| author | |
| committer | |
| log | 51df63a44e6d6f78676e0d43b6723d21e1cb9235 |
| tree | 603cb1f5d80a01b11fea21365a9a8b61c5210364 |
| parent | 2873e19366400b2f11d3a99b10ea17e4f06c6b4b |
| parent | 28623544ce78c5c559af8a47c62e688db9ce5e4a |
| signature |
macos: fix stack traces for Zig linked with any linker including Apple's ld646 files changed, 212 insertions(+), 134 deletions(-)
lib/std/debug.zig+142-62| ... | ... | @@ -559,7 +559,7 @@ pub const TTY = struct { |
| 559 | 559 | |
| 560 | 560 | fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol { |
| 561 | 561 | var min: usize = 0; |
| 562 | var max: usize = symbols.len - 1; // Exclude sentinel. | |
| 562 | var max: usize = symbols.len; | |
| 563 | 563 | while (min < max) { |
| 564 | 564 | const mid = min + (max - min) / 2; |
| 565 | 565 | const curr = &symbols[mid]; |
| ... | ... | @@ -850,51 +850,91 @@ fn readMachODebugInfo(allocator: *mem.Allocator, macho_file: File) !ModuleDebugI |
| 850 | 850 | } else { |
| 851 | 851 | return error.MissingDebugInfo; |
| 852 | 852 | }; |
| 853 | const syms = @ptrCast([*]const macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff))[0..symtab.nsyms]; | |
| 853 | const syms = @ptrCast( | |
| 854 | [*]const macho.nlist_64, | |
| 855 | @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff), | |
| 856 | )[0..symtab.nsyms]; | |
| 854 | 857 | const strings = @ptrCast([*]const u8, hdr_base + symtab.stroff)[0 .. symtab.strsize - 1 :0]; |
| 855 | 858 | |
| 856 | 859 | const symbols_buf = try allocator.alloc(MachoSymbol, syms.len); |
| 857 | 860 | |
| 858 | var ofile: ?*const macho.nlist_64 = null; | |
| 859 | var reloc: u64 = 0; | |
| 861 | var ofile: u32 = undefined; | |
| 862 | var last_sym: MachoSymbol = undefined; | |
| 860 | 863 | var symbol_index: usize = 0; |
| 861 | var last_len: u64 = 0; | |
| 864 | var state: enum { | |
| 865 | init, | |
| 866 | oso_open, | |
| 867 | oso_close, | |
| 868 | bnsym, | |
| 869 | fun_strx, | |
| 870 | fun_size, | |
| 871 | ensym, | |
| 872 | } = .init; | |
| 873 | ||
| 862 | 874 | for (syms) |*sym| { |
| 863 | if (sym.n_type & std.macho.N_STAB != 0) { | |
| 864 | switch (sym.n_type) { | |
| 865 | std.macho.N_OSO => { | |
| 866 | ofile = sym; | |
| 867 | reloc = 0; | |
| 868 | }, | |
| 869 | std.macho.N_FUN => { | |
| 870 | if (sym.n_sect == 0) { | |
| 871 | last_len = sym.n_value; | |
| 872 | } else { | |
| 873 | symbols_buf[symbol_index] = MachoSymbol{ | |
| 874 | .nlist = sym, | |
| 875 | if (!sym.stab()) continue; | |
| 876 | ||
| 877 | // TODO handle globals N_GSYM, and statics N_STSYM | |
| 878 | switch (sym.n_type) { | |
| 879 | macho.N_OSO => { | |
| 880 | switch (state) { | |
| 881 | .init, .oso_close => { | |
| 882 | state = .oso_open; | |
| 883 | ofile = sym.n_strx; | |
| 884 | }, | |
| 885 | else => return error.InvalidDebugInfo, | |
| 886 | } | |
| 887 | }, | |
| 888 | macho.N_BNSYM => { | |
| 889 | switch (state) { | |
| 890 | .oso_open, .ensym => { | |
| 891 | state = .bnsym; | |
| 892 | last_sym = .{ | |
| 893 | .strx = 0, | |
| 894 | .addr = sym.n_value, | |
| 895 | .size = 0, | |
| 875 | 896 | .ofile = ofile, |
| 876 | .reloc = reloc, | |
| 877 | 897 | }; |
| 898 | }, | |
| 899 | else => return error.InvalidDebugInfo, | |
| 900 | } | |
| 901 | }, | |
| 902 | macho.N_FUN => { | |
| 903 | switch (state) { | |
| 904 | .bnsym => { | |
| 905 | state = .fun_strx; | |
| 906 | last_sym.strx = sym.n_strx; | |
| 907 | }, | |
| 908 | .fun_strx => { | |
| 909 | state = .fun_size; | |
| 910 | last_sym.size = @intCast(u32, sym.n_value); | |
| 911 | }, | |
| 912 | else => return error.InvalidDebugInfo, | |
| 913 | } | |
| 914 | }, | |
| 915 | macho.N_ENSYM => { | |
| 916 | switch (state) { | |
| 917 | .fun_size => { | |
| 918 | state = .ensym; | |
| 919 | symbols_buf[symbol_index] = last_sym; | |
| 878 | 920 | symbol_index += 1; |
| 879 | } | |
| 880 | }, | |
| 881 | std.macho.N_BNSYM => { | |
| 882 | if (reloc == 0) { | |
| 883 | reloc = sym.n_value; | |
| 884 | } | |
| 885 | }, | |
| 886 | else => continue, | |
| 887 | } | |
| 921 | }, | |
| 922 | else => return error.InvalidDebugInfo, | |
| 923 | } | |
| 924 | }, | |
| 925 | macho.N_SO => { | |
| 926 | switch (state) { | |
| 927 | .init, .oso_close => {}, | |
| 928 | .oso_open, .ensym => { | |
| 929 | state = .oso_close; | |
| 930 | }, | |
| 931 | else => return error.InvalidDebugInfo, | |
| 932 | } | |
| 933 | }, | |
| 934 | else => {}, | |
| 888 | 935 | } |
| 889 | 936 | } |
| 890 | const sentinel = try allocator.create(macho.nlist_64); | |
| 891 | sentinel.* = macho.nlist_64{ | |
| 892 | .n_strx = 0, | |
| 893 | .n_type = 36, | |
| 894 | .n_sect = 0, | |
| 895 | .n_desc = 0, | |
| 896 | .n_value = symbols_buf[symbol_index - 1].nlist.n_value + last_len, | |
| 897 | }; | |
| 937 | assert(state == .oso_close); | |
| 898 | 938 | |
| 899 | 939 | const symbols = allocator.shrink(symbols_buf, symbol_index); |
| 900 | 940 | |
| ... | ... | @@ -946,18 +986,19 @@ fn printLineFromFileAnyOs(out_stream: anytype, line_info: LineInfo) !void { |
| 946 | 986 | } |
| 947 | 987 | |
| 948 | 988 | const MachoSymbol = struct { |
| 949 | nlist: *const macho.nlist_64, | |
| 950 | ofile: ?*const macho.nlist_64, | |
| 951 | reloc: u64, | |
| 989 | strx: u32, | |
| 990 | addr: u64, | |
| 991 | size: u32, | |
| 992 | ofile: u32, | |
| 952 | 993 | |
| 953 | 994 | /// Returns the address from the macho file |
| 954 | 995 | fn address(self: MachoSymbol) u64 { |
| 955 | return self.nlist.n_value; | |
| 996 | return self.addr; | |
| 956 | 997 | } |
| 957 | 998 | |
| 958 | 999 | fn addressLessThan(context: void, lhs: MachoSymbol, rhs: MachoSymbol) bool { |
| 959 | 1000 | _ = context; |
| 960 | return lhs.address() < rhs.address(); | |
| 1001 | return lhs.addr < rhs.addr; | |
| 961 | 1002 | } |
| 962 | 1003 | }; |
| 963 | 1004 | |
| ... | ... | @@ -1231,13 +1272,17 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1231 | 1272 | strings: [:0]const u8, |
| 1232 | 1273 | ofiles: OFileTable, |
| 1233 | 1274 | |
| 1234 | const OFileTable = std.StringHashMap(DW.DwarfInfo); | |
| 1275 | const OFileTable = std.StringHashMap(OFileInfo); | |
| 1276 | const OFileInfo = struct { | |
| 1277 | di: DW.DwarfInfo, | |
| 1278 | addr_table: std.StringHashMap(u64), | |
| 1279 | }; | |
| 1235 | 1280 | |
| 1236 | 1281 | pub fn allocator(self: @This()) *mem.Allocator { |
| 1237 | 1282 | return self.ofiles.allocator; |
| 1238 | 1283 | } |
| 1239 | 1284 | |
| 1240 | fn loadOFile(self: *@This(), o_file_path: []const u8) !DW.DwarfInfo { | |
| 1285 | fn loadOFile(self: *@This(), o_file_path: []const u8) !OFileInfo { | |
| 1241 | 1286 | const o_file = try fs.cwd().openFile(o_file_path, .{ .intended_io_mode = .blocking }); |
| 1242 | 1287 | const mapped_mem = try mapWholeFile(o_file); |
| 1243 | 1288 | |
| ... | ... | @@ -1250,22 +1295,54 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1250 | 1295 | |
| 1251 | 1296 | const hdr_base = @ptrCast([*]const u8, hdr); |
| 1252 | 1297 | var ptr = hdr_base + @sizeOf(macho.mach_header_64); |
| 1298 | var segptr = ptr; | |
| 1253 | 1299 | var ncmd: u32 = hdr.ncmds; |
| 1254 | const segcmd = while (ncmd != 0) : (ncmd -= 1) { | |
| 1300 | var segcmd: ?*const macho.segment_command_64 = null; | |
| 1301 | var symtabcmd: ?*const macho.symtab_command = null; | |
| 1302 | ||
| 1303 | while (ncmd != 0) : (ncmd -= 1) { | |
| 1255 | 1304 | const lc = @ptrCast(*const std.macho.load_command, ptr); |
| 1256 | 1305 | switch (lc.cmd) { |
| 1257 | 1306 | std.macho.LC_SEGMENT_64 => { |
| 1258 | break @ptrCast( | |
| 1307 | segcmd = @ptrCast( | |
| 1259 | 1308 | *const std.macho.segment_command_64, |
| 1260 | 1309 | @alignCast(@alignOf(std.macho.segment_command_64), ptr), |
| 1261 | 1310 | ); |
| 1311 | segptr = ptr; | |
| 1312 | }, | |
| 1313 | std.macho.LC_SYMTAB => { | |
| 1314 | symtabcmd = @ptrCast( | |
| 1315 | *const std.macho.symtab_command, | |
| 1316 | @alignCast(@alignOf(std.macho.symtab_command), ptr), | |
| 1317 | ); | |
| 1262 | 1318 | }, |
| 1263 | 1319 | else => {}, |
| 1264 | 1320 | } |
| 1265 | 1321 | ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize); |
| 1266 | } else { | |
| 1267 | return error.MissingDebugInfo; | |
| 1268 | }; | |
| 1322 | } | |
| 1323 | ||
| 1324 | if (segcmd == null or symtabcmd == null) return error.MissingDebugInfo; | |
| 1325 | ||
| 1326 | // Parse symbols | |
| 1327 | const strtab = @ptrCast( | |
| 1328 | [*]const u8, | |
| 1329 | hdr_base + symtabcmd.?.stroff, | |
| 1330 | )[0 .. symtabcmd.?.strsize - 1 :0]; | |
| 1331 | const symtab = @ptrCast( | |
| 1332 | [*]const macho.nlist_64, | |
| 1333 | @alignCast(@alignOf(macho.nlist_64), hdr_base + symtabcmd.?.symoff), | |
| 1334 | )[0..symtabcmd.?.nsyms]; | |
| 1335 | ||
| 1336 | // TODO handle tentative (common) symbols | |
| 1337 | var addr_table = std.StringHashMap(u64).init(self.allocator()); | |
| 1338 | try addr_table.ensureTotalCapacity(@intCast(u32, symtab.len)); | |
| 1339 | for (symtab) |sym| { | |
| 1340 | if (sym.n_strx == 0) continue; | |
| 1341 | if (sym.undf() or sym.tentative() or sym.abs()) continue; | |
| 1342 | const sym_name = mem.sliceTo(strtab[sym.n_strx..], 0); | |
| 1343 | // TODO is it possible to have a symbol collision? | |
| 1344 | addr_table.putAssumeCapacityNoClobber(sym_name, sym.n_value); | |
| 1345 | } | |
| 1269 | 1346 | |
| 1270 | 1347 | var opt_debug_line: ?*const macho.section_64 = null; |
| 1271 | 1348 | var opt_debug_info: ?*const macho.section_64 = null; |
| ... | ... | @@ -1275,8 +1352,8 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1275 | 1352 | |
| 1276 | 1353 | const sections = @ptrCast( |
| 1277 | 1354 | [*]const macho.section_64, |
| 1278 | @alignCast(@alignOf(macho.section_64), ptr + @sizeOf(std.macho.segment_command_64)), | |
| 1279 | )[0..segcmd.nsects]; | |
| 1355 | @alignCast(@alignOf(macho.section_64), segptr + @sizeOf(std.macho.segment_command_64)), | |
| 1356 | )[0..segcmd.?.nsects]; | |
| 1280 | 1357 | for (sections) |*sect| { |
| 1281 | 1358 | // The section name may not exceed 16 chars and a trailing null may |
| 1282 | 1359 | // not be present |
| ... | ... | @@ -1320,34 +1397,34 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1320 | 1397 | }; |
| 1321 | 1398 | |
| 1322 | 1399 | try DW.openDwarfDebugInfo(&di, self.allocator()); |
| 1400 | var info = OFileInfo{ | |
| 1401 | .di = di, | |
| 1402 | .addr_table = addr_table, | |
| 1403 | }; | |
| 1323 | 1404 | |
| 1324 | 1405 | // Add the debug info to the cache |
| 1325 | try self.ofiles.putNoClobber(o_file_path, di); | |
| 1406 | try self.ofiles.putNoClobber(o_file_path, info); | |
| 1326 | 1407 | |
| 1327 | return di; | |
| 1408 | return info; | |
| 1328 | 1409 | } |
| 1329 | 1410 | |
| 1330 | 1411 | pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { |
| 1331 | 1412 | nosuspend { |
| 1332 | 1413 | // Translate the VA into an address into this object |
| 1333 | 1414 | const relocated_address = address - self.base_address; |
| 1334 | assert(relocated_address >= 0x100000000); | |
| 1335 | 1415 | |
| 1336 | 1416 | // Find the .o file where this symbol is defined |
| 1337 | 1417 | const symbol = machoSearchSymbols(self.symbols, relocated_address) orelse |
| 1338 | 1418 | return SymbolInfo{}; |
| 1419 | const addr_off = relocated_address - symbol.addr; | |
| 1339 | 1420 | |
| 1340 | 1421 | // Take the symbol name from the N_FUN STAB entry, we're going to |
| 1341 | 1422 | // use it if we fail to find the DWARF infos |
| 1342 | const stab_symbol = mem.sliceTo(self.strings[symbol.nlist.n_strx..], 0); | |
| 1343 | ||
| 1344 | if (symbol.ofile == null) | |
| 1345 | return SymbolInfo{ .symbol_name = stab_symbol }; | |
| 1346 | ||
| 1347 | const o_file_path = mem.sliceTo(self.strings[symbol.ofile.?.n_strx..], 0); | |
| 1423 | const stab_symbol = mem.sliceTo(self.strings[symbol.strx..], 0); | |
| 1424 | const o_file_path = mem.sliceTo(self.strings[symbol.ofile..], 0); | |
| 1348 | 1425 | |
| 1349 | 1426 | // Check if its debug infos are already in the cache |
| 1350 | var o_file_di = self.ofiles.get(o_file_path) orelse | |
| 1427 | var o_file_info = self.ofiles.get(o_file_path) orelse | |
| 1351 | 1428 | (self.loadOFile(o_file_path) catch |err| switch (err) { |
| 1352 | 1429 | error.FileNotFound, |
| 1353 | 1430 | error.MissingDebugInfo, |
| ... | ... | @@ -1357,19 +1434,22 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1357 | 1434 | }, |
| 1358 | 1435 | else => return err, |
| 1359 | 1436 | }); |
| 1437 | const o_file_di = &o_file_info.di; | |
| 1360 | 1438 | |
| 1361 | 1439 | // Translate again the address, this time into an address inside the |
| 1362 | 1440 | // .o file |
| 1363 | const relocated_address_o = relocated_address - symbol.reloc; | |
| 1441 | const relocated_address_o = o_file_info.addr_table.get(stab_symbol) orelse return SymbolInfo{ | |
| 1442 | .symbol_name = "???", | |
| 1443 | }; | |
| 1364 | 1444 | |
| 1365 | 1445 | if (o_file_di.findCompileUnit(relocated_address_o)) |compile_unit| { |
| 1366 | 1446 | return SymbolInfo{ |
| 1367 | 1447 | .symbol_name = o_file_di.getSymbolName(relocated_address_o) orelse "???", |
| 1368 | .compile_unit_name = compile_unit.die.getAttrString(&o_file_di, DW.AT.name) catch |err| switch (err) { | |
| 1448 | .compile_unit_name = compile_unit.die.getAttrString(o_file_di, DW.AT.name) catch |err| switch (err) { | |
| 1369 | 1449 | error.MissingDebugInfo, error.InvalidDebugInfo => "???", |
| 1370 | 1450 | else => return err, |
| 1371 | 1451 | }, |
| 1372 | .line_info = o_file_di.getLineNumberInfo(compile_unit.*, relocated_address_o) catch |err| switch (err) { | |
| 1452 | .line_info = o_file_di.getLineNumberInfo(compile_unit.*, relocated_address_o + addr_off) catch |err| switch (err) { | |
| 1373 | 1453 | error.MissingDebugInfo, error.InvalidDebugInfo => null, |
| 1374 | 1454 | else => return err, |
| 1375 | 1455 | }, |
lib/std/macho.zig+49| ... | ... | @@ -744,6 +744,55 @@ pub const nlist_64 = extern struct { |
| 744 | 744 | n_sect: u8, |
| 745 | 745 | n_desc: u16, |
| 746 | 746 | n_value: u64, |
| 747 | ||
| 748 | pub fn stab(sym: nlist_64) bool { | |
| 749 | return (N_STAB & sym.n_type) != 0; | |
| 750 | } | |
| 751 | ||
| 752 | pub fn pext(sym: nlist_64) bool { | |
| 753 | return (N_PEXT & sym.n_type) != 0; | |
| 754 | } | |
| 755 | ||
| 756 | pub fn ext(sym: nlist_64) bool { | |
| 757 | return (N_EXT & sym.n_type) != 0; | |
| 758 | } | |
| 759 | ||
| 760 | pub fn sect(sym: nlist_64) bool { | |
| 761 | const type_ = N_TYPE & sym.n_type; | |
| 762 | return type_ == N_SECT; | |
| 763 | } | |
| 764 | ||
| 765 | pub fn undf(sym: nlist_64) bool { | |
| 766 | const type_ = N_TYPE & sym.n_type; | |
| 767 | return type_ == N_UNDF; | |
| 768 | } | |
| 769 | ||
| 770 | pub fn indr(sym: nlist_64) bool { | |
| 771 | const type_ = N_TYPE & sym.n_type; | |
| 772 | return type_ == N_INDR; | |
| 773 | } | |
| 774 | ||
| 775 | pub fn abs(sym: nlist_64) bool { | |
| 776 | const type_ = N_TYPE & sym.n_type; | |
| 777 | return type_ == N_ABS; | |
| 778 | } | |
| 779 | ||
| 780 | pub fn weakDef(sym: nlist_64) bool { | |
| 781 | return (sym.n_desc & N_WEAK_DEF) != 0; | |
| 782 | } | |
| 783 | ||
| 784 | pub fn weakRef(sym: nlist_64) bool { | |
| 785 | return (sym.n_desc & N_WEAK_REF) != 0; | |
| 786 | } | |
| 787 | ||
| 788 | pub fn discarded(sym: nlist_64) bool { | |
| 789 | return (sym.n_desc & N_DESC_DISCARDED) != 0; | |
| 790 | } | |
| 791 | ||
| 792 | pub fn tentative(sym: nlist_64) bool { | |
| 793 | if (!sym.undf()) return false; | |
| 794 | return sym.n_value != 0; | |
| 795 | } | |
| 747 | 796 | }; |
| 748 | 797 | |
| 749 | 798 | /// Format of a relocation entry of a Mach-O file. Modified from the 4.3BSD |
src/link/MachO.zig+15-66| ... | ... | @@ -885,7 +885,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 885 | 885 | const sym_name = self.getString(sym.n_strx); |
| 886 | 886 | const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable; |
| 887 | 887 | |
| 888 | if (symbolIsDiscarded(sym.*)) { | |
| 888 | if (sym.discarded()) { | |
| 889 | 889 | sym.* = .{ |
| 890 | 890 | .n_strx = 0, |
| 891 | 891 | .n_type = macho.N_UNDF, |
| ... | ... | @@ -2445,21 +2445,21 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2445 | 2445 | const sym_id = @intCast(u32, id); |
| 2446 | 2446 | const sym_name = object.getString(sym.n_strx); |
| 2447 | 2447 | |
| 2448 | if (symbolIsStab(sym)) { | |
| 2448 | if (sym.stab()) { | |
| 2449 | 2449 | log.err("unhandled symbol type: stab", .{}); |
| 2450 | 2450 | log.err(" symbol '{s}'", .{sym_name}); |
| 2451 | 2451 | log.err(" first definition in '{s}'", .{object.name}); |
| 2452 | 2452 | return error.UnhandledSymbolType; |
| 2453 | 2453 | } |
| 2454 | 2454 | |
| 2455 | if (symbolIsIndr(sym)) { | |
| 2455 | if (sym.indr()) { | |
| 2456 | 2456 | log.err("unhandled symbol type: indirect", .{}); |
| 2457 | 2457 | log.err(" symbol '{s}'", .{sym_name}); |
| 2458 | 2458 | log.err(" first definition in '{s}'", .{object.name}); |
| 2459 | 2459 | return error.UnhandledSymbolType; |
| 2460 | 2460 | } |
| 2461 | 2461 | |
| 2462 | if (symbolIsAbs(sym)) { | |
| 2462 | if (sym.abs()) { | |
| 2463 | 2463 | log.err("unhandled symbol type: absolute", .{}); |
| 2464 | 2464 | log.err(" symbol '{s}'", .{sym_name}); |
| 2465 | 2465 | log.err(" first definition in '{s}'", .{object.name}); |
| ... | ... | @@ -2467,7 +2467,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2467 | 2467 | } |
| 2468 | 2468 | |
| 2469 | 2469 | const n_strx = try self.makeString(sym_name); |
| 2470 | if (symbolIsSect(sym)) { | |
| 2470 | if (sym.sect()) { | |
| 2471 | 2471 | // Defined symbol regardless of scope lands in the locals symbol table. |
| 2472 | 2472 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 2473 | 2473 | try self.locals.append(self.base.allocator, .{ |
| ... | ... | @@ -2482,7 +2482,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2482 | 2482 | |
| 2483 | 2483 | // If the symbol's scope is not local aka translation unit, then we need work out |
| 2484 | 2484 | // if we should save the symbol as a global, or potentially flag the error. |
| 2485 | if (!symbolIsExt(sym)) continue; | |
| 2485 | if (!sym.ext()) continue; | |
| 2486 | 2486 | |
| 2487 | 2487 | const local = self.locals.items[local_sym_index]; |
| 2488 | 2488 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { |
| ... | ... | @@ -2507,18 +2507,16 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2507 | 2507 | .global => { |
| 2508 | 2508 | const global = &self.globals.items[resolv.where_index]; |
| 2509 | 2509 | |
| 2510 | if (symbolIsTentative(global.*)) { | |
| 2510 | if (global.tentative()) { | |
| 2511 | 2511 | assert(self.tentatives.swapRemove(resolv.where_index)); |
| 2512 | } else if (!(symbolIsWeakDef(sym) or symbolIsPext(sym)) and | |
| 2513 | !(symbolIsWeakDef(global.*) or symbolIsPext(global.*))) | |
| 2514 | { | |
| 2512 | } else if (!(sym.weakDef() or sym.pext()) and !(global.weakDef() or global.pext())) { | |
| 2515 | 2513 | log.err("symbol '{s}' defined multiple times", .{sym_name}); |
| 2516 | 2514 | if (resolv.file) |file| { |
| 2517 | 2515 | log.err(" first definition in '{s}'", .{self.objects.items[file].name}); |
| 2518 | 2516 | } |
| 2519 | 2517 | log.err(" next definition in '{s}'", .{object.name}); |
| 2520 | 2518 | return error.MultipleSymbolDefinitions; |
| 2521 | } else if (symbolIsWeakDef(sym) or symbolIsPext(sym)) continue; // Current symbol is weak, so skip it. | |
| 2519 | } else if (sym.weakDef() or sym.pext()) continue; // Current symbol is weak, so skip it. | |
| 2522 | 2520 | |
| 2523 | 2521 | // Otherwise, update the resolver and the global symbol. |
| 2524 | 2522 | global.n_type = sym.n_type; |
| ... | ... | @@ -2554,7 +2552,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2554 | 2552 | .local_sym_index = local_sym_index, |
| 2555 | 2553 | .file = object_id, |
| 2556 | 2554 | }; |
| 2557 | } else if (symbolIsTentative(sym)) { | |
| 2555 | } else if (sym.tentative()) { | |
| 2558 | 2556 | // Symbol is a tentative definition. |
| 2559 | 2557 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { |
| 2560 | 2558 | const global_sym_index = @intCast(u32, self.globals.items.len); |
| ... | ... | @@ -2577,7 +2575,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2577 | 2575 | switch (resolv.where) { |
| 2578 | 2576 | .global => { |
| 2579 | 2577 | const global = &self.globals.items[resolv.where_index]; |
| 2580 | if (!symbolIsTentative(global.*)) continue; | |
| 2578 | if (!global.tentative()) continue; | |
| 2581 | 2579 | if (global.n_value >= sym.n_value) continue; |
| 2582 | 2580 | |
| 2583 | 2581 | global.n_desc = sym.n_desc; |
| ... | ... | @@ -3575,9 +3573,9 @@ pub fn updateDeclExports( |
| 3575 | 3573 | |
| 3576 | 3574 | const sym = &self.globals.items[resolv.where_index]; |
| 3577 | 3575 | |
| 3578 | if (symbolIsTentative(sym.*)) { | |
| 3576 | if (sym.tentative()) { | |
| 3579 | 3577 | assert(self.tentatives.swapRemove(resolv.where_index)); |
| 3580 | } else if (!is_weak and !(symbolIsWeakDef(sym.*) or symbolIsPext(sym.*))) { | |
| 3578 | } else if (!is_weak and !(sym.weakDef() or sym.pext())) { | |
| 3581 | 3579 | _ = try module.failed_exports.put( |
| 3582 | 3580 | module.gpa, |
| 3583 | 3581 | exp, |
| ... | ... | @@ -5316,58 +5314,9 @@ pub fn getString(self: *MachO, off: u32) []const u8 { |
| 5316 | 5314 | return mem.sliceTo(@ptrCast([*:0]const u8, self.strtab.items.ptr + off), 0); |
| 5317 | 5315 | } |
| 5318 | 5316 | |
| 5319 | pub fn symbolIsStab(sym: macho.nlist_64) bool { | |
| 5320 | return (macho.N_STAB & sym.n_type) != 0; | |
| 5321 | } | |
| 5322 | ||
| 5323 | pub fn symbolIsPext(sym: macho.nlist_64) bool { | |
| 5324 | return (macho.N_PEXT & sym.n_type) != 0; | |
| 5325 | } | |
| 5326 | ||
| 5327 | pub fn symbolIsExt(sym: macho.nlist_64) bool { | |
| 5328 | return (macho.N_EXT & sym.n_type) != 0; | |
| 5329 | } | |
| 5330 | ||
| 5331 | pub fn symbolIsSect(sym: macho.nlist_64) bool { | |
| 5332 | const type_ = macho.N_TYPE & sym.n_type; | |
| 5333 | return type_ == macho.N_SECT; | |
| 5334 | } | |
| 5335 | ||
| 5336 | pub fn symbolIsUndf(sym: macho.nlist_64) bool { | |
| 5337 | const type_ = macho.N_TYPE & sym.n_type; | |
| 5338 | return type_ == macho.N_UNDF; | |
| 5339 | } | |
| 5340 | ||
| 5341 | pub fn symbolIsIndr(sym: macho.nlist_64) bool { | |
| 5342 | const type_ = macho.N_TYPE & sym.n_type; | |
| 5343 | return type_ == macho.N_INDR; | |
| 5344 | } | |
| 5345 | ||
| 5346 | pub fn symbolIsAbs(sym: macho.nlist_64) bool { | |
| 5347 | const type_ = macho.N_TYPE & sym.n_type; | |
| 5348 | return type_ == macho.N_ABS; | |
| 5349 | } | |
| 5350 | ||
| 5351 | pub fn symbolIsWeakDef(sym: macho.nlist_64) bool { | |
| 5352 | return (sym.n_desc & macho.N_WEAK_DEF) != 0; | |
| 5353 | } | |
| 5354 | ||
| 5355 | pub fn symbolIsWeakRef(sym: macho.nlist_64) bool { | |
| 5356 | return (sym.n_desc & macho.N_WEAK_REF) != 0; | |
| 5357 | } | |
| 5358 | ||
| 5359 | pub fn symbolIsDiscarded(sym: macho.nlist_64) bool { | |
| 5360 | return (sym.n_desc & macho.N_DESC_DISCARDED) != 0; | |
| 5361 | } | |
| 5362 | ||
| 5363 | pub fn symbolIsTentative(sym: macho.nlist_64) bool { | |
| 5364 | if (!symbolIsUndf(sym)) return false; | |
| 5365 | return sym.n_value != 0; | |
| 5366 | } | |
| 5367 | ||
| 5368 | 5317 | pub fn symbolIsTemp(sym: macho.nlist_64, sym_name: []const u8) bool { |
| 5369 | if (!symbolIsSect(sym)) return false; | |
| 5370 | if (symbolIsExt(sym)) return false; | |
| 5318 | if (!sym.sect()) return false; | |
| 5319 | if (sym.ext()) return false; | |
| 5371 | 5320 | return mem.startsWith(u8, sym_name, "l") or mem.startsWith(u8, sym_name, "L"); |
| 5372 | 5321 | } |
| 5373 | 5322 |
src/link/MachO/Atom.zig+2-2| ... | ... | @@ -295,7 +295,7 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC |
| 295 | 295 | |
| 296 | 296 | assert(subtractor == null); |
| 297 | 297 | const sym = context.object.symtab.items[rel.r_symbolnum]; |
| 298 | if (MachO.symbolIsSect(sym) and !MachO.symbolIsExt(sym)) { | |
| 298 | if (sym.sect() and !sym.ext()) { | |
| 299 | 299 | subtractor = context.object.symbol_mapping.get(rel.r_symbolnum).?; |
| 300 | 300 | } else { |
| 301 | 301 | const sym_name = context.object.getString(sym.n_strx); |
| ... | ... | @@ -362,7 +362,7 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC |
| 362 | 362 | const sym = context.object.symtab.items[rel.r_symbolnum]; |
| 363 | 363 | const sym_name = context.object.getString(sym.n_strx); |
| 364 | 364 | |
| 365 | if (MachO.symbolIsSect(sym) and !MachO.symbolIsExt(sym)) { | |
| 365 | if (sym.sect() and !sym.ext()) { | |
| 366 | 366 | const sym_index = context.object.symbol_mapping.get(rel.r_symbolnum) orelse unreachable; |
| 367 | 367 | break :target Relocation.Target{ .local = sym_index }; |
| 368 | 368 | } |
src/link/MachO/Dylib.zig+1-1| ... | ... | @@ -226,7 +226,7 @@ fn parseSymbols(self: *Dylib, allocator: *Allocator) !void { |
| 226 | 226 | _ = try self.file.preadAll(strtab, symtab_cmd.stroff + self.library_offset); |
| 227 | 227 | |
| 228 | 228 | for (slice) |sym| { |
| 229 | const add_to_symtab = MachO.symbolIsExt(sym) and (MachO.symbolIsSect(sym) or MachO.symbolIsIndr(sym)); | |
| 229 | const add_to_symtab = sym.ext() and (sym.sect() or sym.indr()); | |
| 230 | 230 | |
| 231 | 231 | if (!add_to_symtab) continue; |
| 232 | 232 |
src/link/MachO/Object.zig+3-3| ... | ... | @@ -338,8 +338,8 @@ const NlistWithIndex = struct { |
| 338 | 338 | // afterwards by address in each group. Normally, dysymtab should |
| 339 | 339 | // be enough to guarantee the sort, but turns out not every compiler |
| 340 | 340 | // is kind enough to specify the symbols in the correct order. |
| 341 | if (MachO.symbolIsSect(lhs.nlist)) { | |
| 342 | if (MachO.symbolIsSect(rhs.nlist)) { | |
| 341 | if (lhs.nlist.sect()) { | |
| 342 | if (rhs.nlist.sect()) { | |
| 343 | 343 | // Same group, sort by address. |
| 344 | 344 | return lhs.nlist.n_value < rhs.nlist.n_value; |
| 345 | 345 | } else { |
| ... | ... | @@ -414,7 +414,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: *Allocator, macho_file: *MachO) |
| 414 | 414 | var iundefsym: usize = sorted_all_nlists.items.len; |
| 415 | 415 | while (iundefsym > 0) : (iundefsym -= 1) { |
| 416 | 416 | const nlist = sorted_all_nlists.items[iundefsym]; |
| 417 | if (MachO.symbolIsSect(nlist.nlist)) break; | |
| 417 | if (nlist.nlist.sect()) break; | |
| 418 | 418 | } |
| 419 | 419 | break :blk iundefsym; |
| 420 | 420 | }; |