authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-12-12 20:52:28+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-12-13 01:29:01+01:00
loga38af5f542199378483aba9f4598634ebf012b7b
tree962a1de712121ed3f7780b094c56b746784b4439
parent37458cc886f8c6347b0e3e58965637656d86f9f9

lib/std/Build/CheckObject: fix parsing and dumping special dylib lookup values


1 files changed, 38 insertions(+), 24 deletions(-)

lib/std/Build/Step/CheckObject.zig+38-24
......@@ -645,17 +645,17 @@ const MachODumper = struct {
645645 if (lc.bind_size > 0) {
646646 const data = bytes[lc.bind_off..][0..lc.bind_size];
647647 try writer.writeAll("bind info\n");
648 try dumpBindInfo(gpa, data, segments.items, imports.items, false, writer);
648 try dumpBindInfo(gpa, data, segments.items, imports.items, writer);
649649 }
650650 if (lc.weak_bind_size > 0) {
651651 const data = bytes[lc.weak_bind_off..][0..lc.weak_bind_size];
652652 try writer.writeAll("weak bind info\n");
653 try dumpBindInfo(gpa, data, segments.items, imports.items, false, writer);
653 try dumpBindInfo(gpa, data, segments.items, imports.items, writer);
654654 }
655655 if (lc.lazy_bind_size > 0) {
656656 const data = bytes[lc.lazy_bind_off..][0..lc.lazy_bind_size];
657657 try writer.writeAll("lazy bind info\n");
658 try dumpBindInfo(gpa, data, segments.items, imports.items, true, writer);
658 try dumpBindInfo(gpa, data, segments.items, imports.items, writer);
659659 }
660660 if (lc.export_size > 0) {
661661 const data = bytes[lc.export_off..][0..lc.export_size];
......@@ -993,7 +993,7 @@ const MachODumper = struct {
993993 if (sym.ext()) try writer.writeAll(" external");
994994 try writer.print(" {s}\n", .{sym_name});
995995 } else if (sym.undf()) {
996 const ordinal = @divTrunc(@as(i16, @bitCast(sym.n_desc)), macho.N_SYMBOL_RESOLVER);
996 const ordinal = @divFloor(@as(i16, @bitCast(sym.n_desc)), macho.N_SYMBOL_RESOLVER);
997997 const import_name = blk: {
998998 if (ordinal <= 0) {
999999 if (ordinal == macho.BIND_SPECIAL_DYLIB_SELF)
......@@ -1108,7 +1108,8 @@ const MachODumper = struct {
11081108 const Binding = struct {
11091109 address: u64,
11101110 addend: i64,
1111 ordinal: ?u16,
1111 ordinal: u16,
1112 tag: Tag,
11121113 name: []const u8,
11131114
11141115 fn deinit(binding: *Binding, gpa: Allocator) void {
......@@ -1119,6 +1120,13 @@ const MachODumper = struct {
11191120 _ = ctx;
11201121 return lhs.address < rhs.address;
11211122 }
1123
1124 const Tag = enum {
1125 ord,
1126 self,
1127 exe,
1128 flat,
1129 };
11221130 };
11231131
11241132 fn dumpBindInfo(
......@@ -1126,7 +1134,6 @@ const MachODumper = struct {
11261134 data: []const u8,
11271135 segments: []const macho.segment_command_64,
11281136 dylibs: []const []const u8,
1129 is_lazy: bool,
11301137 writer: anytype,
11311138 ) !void {
11321139 var bindings = std.ArrayList(Binding).init(gpa);
......@@ -1136,14 +1143,18 @@ const MachODumper = struct {
11361143 }
11371144 bindings.deinit();
11381145 }
1139 try parseBindInfo(gpa, data, segments, &bindings, is_lazy);
1146 try parseBindInfo(gpa, data, segments, &bindings);
11401147 mem.sort(Binding, bindings.items, {}, Binding.lessThan);
11411148 for (bindings.items) |binding| {
11421149 try writer.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });
1143 if (binding.ordinal) |ord| {
1144 try writer.print(" ({s})", .{std.fs.path.basename(dylibs[ord - 1])});
1150 try writer.writeAll(" (");
1151 switch (binding.tag) {
1152 .self => try writer.writeAll("self"),
1153 .exe => try writer.writeAll("main executable"),
1154 .flat => try writer.writeAll("flat lookup"),
1155 .ord => try writer.writeAll(std.fs.path.basename(dylibs[binding.ordinal - 1])),
11451156 }
1146 try writer.print(" {s}\n", .{binding.name});
1157 try writer.print(") {s}\n", .{binding.name});
11471158 }
11481159 }
11491160
......@@ -1152,14 +1163,14 @@ const MachODumper = struct {
11521163 data: []const u8,
11531164 segments: []const macho.segment_command_64,
11541165 bindings: *std.ArrayList(Binding),
1155 lazy_ops: bool,
11561166 ) !void {
11571167 var stream = std.io.fixedBufferStream(data);
11581168 var creader = std.io.countingReader(stream.reader());
11591169 const reader = creader.reader();
11601170
11611171 var seg_id: ?u8 = null;
1162 var dylib_id: ?u16 = null;
1172 var tag: Binding.Tag = .self;
1173 var ordinal: u16 = 0;
11631174 var offset: u64 = 0;
11641175 var addend: i64 = 0;
11651176
......@@ -1171,14 +1182,20 @@ const MachODumper = struct {
11711182 const opc = byte & macho.BIND_OPCODE_MASK;
11721183 const imm = byte & macho.BIND_IMMEDIATE_MASK;
11731184 switch (opc) {
1174 macho.BIND_OPCODE_DONE => {
1175 if (!lazy_ops) break;
1176 },
1177 macho.BIND_OPCODE_SET_TYPE_IMM => {
1178 if (lazy_ops) break;
1179 },
1185 macho.BIND_OPCODE_DONE,
1186 macho.BIND_OPCODE_SET_TYPE_IMM,
1187 => {},
11801188 macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM => {
1181 dylib_id = imm;
1189 tag = .ord;
1190 ordinal = imm;
1191 },
1192 macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM => {
1193 switch (imm) {
1194 0 => tag = .self,
1195 0xf => tag = .exe,
1196 0xe => tag = .flat,
1197 else => unreachable,
1198 }
11821199 },
11831200 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
11841201 seg_id = imm;
......@@ -1193,7 +1210,6 @@ const MachODumper = struct {
11931210 addend = try std.leb.readILEB128(i64, reader);
11941211 },
11951212 macho.BIND_OPCODE_ADD_ADDR_ULEB => {
1196 if (lazy_ops) break;
11971213 const x = try std.leb.readULEB128(u64, reader);
11981214 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));
11991215 },
......@@ -1209,15 +1225,12 @@ const MachODumper = struct {
12091225 switch (opc) {
12101226 macho.BIND_OPCODE_DO_BIND => {},
12111227 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {
1212 if (lazy_ops) break;
12131228 add_addr = try std.leb.readULEB128(u64, reader);
12141229 },
12151230 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {
1216 if (lazy_ops) break;
12171231 add_addr = imm * @sizeOf(u64);
12181232 },
12191233 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {
1220 if (lazy_ops) break;
12211234 count = try std.leb.readULEB128(u64, reader);
12221235 skip = try std.leb.readULEB128(u64, reader);
12231236 },
......@@ -1231,7 +1244,8 @@ const MachODumper = struct {
12311244 try bindings.append(.{
12321245 .address = addr,
12331246 .addend = addend,
1234 .ordinal = dylib_id,
1247 .tag = tag,
1248 .ordinal = ordinal,
12351249 .name = try gpa.dupe(u8, name_buf.items),
12361250 });
12371251 offset += skip + @sizeOf(u64) + add_addr;