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 {...@@ -645,17 +645,17 @@ const MachODumper = struct {
645 if (lc.bind_size > 0) {645 if (lc.bind_size > 0) {
646 const data = bytes[lc.bind_off..][0..lc.bind_size];646 const data = bytes[lc.bind_off..][0..lc.bind_size];
647 try writer.writeAll("bind info\n");647 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);
649 }649 }
650 if (lc.weak_bind_size > 0) {650 if (lc.weak_bind_size > 0) {
651 const data = bytes[lc.weak_bind_off..][0..lc.weak_bind_size];651 const data = bytes[lc.weak_bind_off..][0..lc.weak_bind_size];
652 try writer.writeAll("weak bind info\n");652 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);
654 }654 }
655 if (lc.lazy_bind_size > 0) {655 if (lc.lazy_bind_size > 0) {
656 const data = bytes[lc.lazy_bind_off..][0..lc.lazy_bind_size];656 const data = bytes[lc.lazy_bind_off..][0..lc.lazy_bind_size];
657 try writer.writeAll("lazy bind info\n");657 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);
659 }659 }
660 if (lc.export_size > 0) {660 if (lc.export_size > 0) {
661 const data = bytes[lc.export_off..][0..lc.export_size];661 const data = bytes[lc.export_off..][0..lc.export_size];
...@@ -993,7 +993,7 @@ const MachODumper = struct {...@@ -993,7 +993,7 @@ const MachODumper = struct {
993 if (sym.ext()) try writer.writeAll(" external");993 if (sym.ext()) try writer.writeAll(" external");
994 try writer.print(" {s}\n", .{sym_name});994 try writer.print(" {s}\n", .{sym_name});
995 } else if (sym.undf()) {995 } 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);
997 const import_name = blk: {997 const import_name = blk: {
998 if (ordinal <= 0) {998 if (ordinal <= 0) {
999 if (ordinal == macho.BIND_SPECIAL_DYLIB_SELF)999 if (ordinal == macho.BIND_SPECIAL_DYLIB_SELF)
...@@ -1108,7 +1108,8 @@ const MachODumper = struct {...@@ -1108,7 +1108,8 @@ const MachODumper = struct {
1108 const Binding = struct {1108 const Binding = struct {
1109 address: u64,1109 address: u64,
1110 addend: i64,1110 addend: i64,
1111 ordinal: ?u16,1111 ordinal: u16,
1112 tag: Tag,
1112 name: []const u8,1113 name: []const u8,
11131114
1114 fn deinit(binding: *Binding, gpa: Allocator) void {1115 fn deinit(binding: *Binding, gpa: Allocator) void {
...@@ -1119,6 +1120,13 @@ const MachODumper = struct {...@@ -1119,6 +1120,13 @@ const MachODumper = struct {
1119 _ = ctx;1120 _ = ctx;
1120 return lhs.address < rhs.address;1121 return lhs.address < rhs.address;
1121 }1122 }
1123
1124 const Tag = enum {
1125 ord,
1126 self,
1127 exe,
1128 flat,
1129 };
1122 };1130 };
11231131
1124 fn dumpBindInfo(1132 fn dumpBindInfo(
...@@ -1126,7 +1134,6 @@ const MachODumper = struct {...@@ -1126,7 +1134,6 @@ const MachODumper = struct {
1126 data: []const u8,1134 data: []const u8,
1127 segments: []const macho.segment_command_64,1135 segments: []const macho.segment_command_64,
1128 dylibs: []const []const u8,1136 dylibs: []const []const u8,
1129 is_lazy: bool,
1130 writer: anytype,1137 writer: anytype,
1131 ) !void {1138 ) !void {
1132 var bindings = std.ArrayList(Binding).init(gpa);1139 var bindings = std.ArrayList(Binding).init(gpa);
...@@ -1136,14 +1143,18 @@ const MachODumper = struct {...@@ -1136,14 +1143,18 @@ const MachODumper = struct {
1136 }1143 }
1137 bindings.deinit();1144 bindings.deinit();
1138 }1145 }
1139 try parseBindInfo(gpa, data, segments, &bindings, is_lazy);1146 try parseBindInfo(gpa, data, segments, &bindings);
1140 mem.sort(Binding, bindings.items, {}, Binding.lessThan);1147 mem.sort(Binding, bindings.items, {}, Binding.lessThan);
1141 for (bindings.items) |binding| {1148 for (bindings.items) |binding| {
1142 try writer.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });1149 try writer.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });
1143 if (binding.ordinal) |ord| {1150 try writer.writeAll(" (");
1144 try writer.print(" ({s})", .{std.fs.path.basename(dylibs[ord - 1])});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])),
1145 }1156 }
1146 try writer.print(" {s}\n", .{binding.name});1157 try writer.print(") {s}\n", .{binding.name});
1147 }1158 }
1148 }1159 }
11491160
...@@ -1152,14 +1163,14 @@ const MachODumper = struct {...@@ -1152,14 +1163,14 @@ const MachODumper = struct {
1152 data: []const u8,1163 data: []const u8,
1153 segments: []const macho.segment_command_64,1164 segments: []const macho.segment_command_64,
1154 bindings: *std.ArrayList(Binding),1165 bindings: *std.ArrayList(Binding),
1155 lazy_ops: bool,
1156 ) !void {1166 ) !void {
1157 var stream = std.io.fixedBufferStream(data);1167 var stream = std.io.fixedBufferStream(data);
1158 var creader = std.io.countingReader(stream.reader());1168 var creader = std.io.countingReader(stream.reader());
1159 const reader = creader.reader();1169 const reader = creader.reader();
11601170
1161 var seg_id: ?u8 = null;1171 var seg_id: ?u8 = null;
1162 var dylib_id: ?u16 = null;1172 var tag: Binding.Tag = .self;
1173 var ordinal: u16 = 0;
1163 var offset: u64 = 0;1174 var offset: u64 = 0;
1164 var addend: i64 = 0;1175 var addend: i64 = 0;
11651176
...@@ -1171,14 +1182,20 @@ const MachODumper = struct {...@@ -1171,14 +1182,20 @@ const MachODumper = struct {
1171 const opc = byte & macho.BIND_OPCODE_MASK;1182 const opc = byte & macho.BIND_OPCODE_MASK;
1172 const imm = byte & macho.BIND_IMMEDIATE_MASK;1183 const imm = byte & macho.BIND_IMMEDIATE_MASK;
1173 switch (opc) {1184 switch (opc) {
1174 macho.BIND_OPCODE_DONE => {1185 macho.BIND_OPCODE_DONE,
1175 if (!lazy_ops) break;1186 macho.BIND_OPCODE_SET_TYPE_IMM,
1176 },1187 => {},
1177 macho.BIND_OPCODE_SET_TYPE_IMM => {
1178 if (lazy_ops) break;
1179 },
1180 macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM => {1188 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 }
1182 },1199 },
1183 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {1200 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
1184 seg_id = imm;1201 seg_id = imm;
...@@ -1193,7 +1210,6 @@ const MachODumper = struct {...@@ -1193,7 +1210,6 @@ const MachODumper = struct {
1193 addend = try std.leb.readILEB128(i64, reader);1210 addend = try std.leb.readILEB128(i64, reader);
1194 },1211 },
1195 macho.BIND_OPCODE_ADD_ADDR_ULEB => {1212 macho.BIND_OPCODE_ADD_ADDR_ULEB => {
1196 if (lazy_ops) break;
1197 const x = try std.leb.readULEB128(u64, reader);1213 const x = try std.leb.readULEB128(u64, reader);
1198 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));1214 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));
1199 },1215 },
...@@ -1209,15 +1225,12 @@ const MachODumper = struct {...@@ -1209,15 +1225,12 @@ const MachODumper = struct {
1209 switch (opc) {1225 switch (opc) {
1210 macho.BIND_OPCODE_DO_BIND => {},1226 macho.BIND_OPCODE_DO_BIND => {},
1211 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {1227 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {
1212 if (lazy_ops) break;
1213 add_addr = try std.leb.readULEB128(u64, reader);1228 add_addr = try std.leb.readULEB128(u64, reader);
1214 },1229 },
1215 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {1230 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {
1216 if (lazy_ops) break;
1217 add_addr = imm * @sizeOf(u64);1231 add_addr = imm * @sizeOf(u64);
1218 },1232 },
1219 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {1233 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {
1220 if (lazy_ops) break;
1221 count = try std.leb.readULEB128(u64, reader);1234 count = try std.leb.readULEB128(u64, reader);
1222 skip = try std.leb.readULEB128(u64, reader);1235 skip = try std.leb.readULEB128(u64, reader);
1223 },1236 },
...@@ -1231,7 +1244,8 @@ const MachODumper = struct {...@@ -1231,7 +1244,8 @@ const MachODumper = struct {
1231 try bindings.append(.{1244 try bindings.append(.{
1232 .address = addr,1245 .address = addr,
1233 .addend = addend,1246 .addend = addend,
1234 .ordinal = dylib_id,1247 .tag = tag,
1248 .ordinal = ordinal,
1235 .name = try gpa.dupe(u8, name_buf.items),1249 .name = try gpa.dupe(u8, name_buf.items),
1236 });1250 });
1237 offset += skip + @sizeOf(u64) + add_addr;1251 offset += skip + @sizeOf(u64) + add_addr;