| ... | @@ -590,6 +590,17 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { | ... | @@ -590,6 +590,17 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { |
| 590 | const syms = self.symtab.items(.nlist); | 590 | const syms = self.symtab.items(.nlist); |
| 591 | const sym_lookup = SymbolLookup{ .ctx = self, .entries = nlists }; | 591 | const sym_lookup = SymbolLookup{ .ctx = self, .entries = nlists }; |
| 592 | | 592 | |
| | 593 | // We need to cache nlists by name so that we can properly resolve local N_GSYM stabs. |
| | 594 | // What happens is `ld -r` will emit an N_GSYM stab for a symbol that may be either an |
| | 595 | // external or private external. |
| | 596 | var addr_lookup = std.StringHashMap(u64).init(gpa); |
| | 597 | defer addr_lookup.deinit(); |
| | 598 | for (syms) |sym| { |
| | 599 | if (sym.sect() and (sym.ext() or sym.pext())) { |
| | 600 | try addr_lookup.putNoClobber(self.getString(sym.n_strx), sym.n_value); |
| | 601 | } |
| | 602 | } |
| | 603 | |
| 593 | var i: u32 = start; | 604 | var i: u32 = start; |
| 594 | while (i < end) : (i += 1) { | 605 | while (i < end) : (i += 1) { |
| 595 | const open = syms[i]; | 606 | const open = syms[i]; |
| ... | @@ -611,17 +622,17 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { | ... | @@ -611,17 +622,17 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { |
| 611 | var stab: StabFile.Stab = .{}; | 622 | var stab: StabFile.Stab = .{}; |
| 612 | switch (nlist.n_type) { | 623 | switch (nlist.n_type) { |
| 613 | macho.N_BNSYM => { | 624 | macho.N_BNSYM => { |
| 614 | stab.tag = .func; | 625 | stab.is_func = true; |
| 615 | stab.symbol = sym_lookup.find(nlist.n_value); | 626 | stab.symbol = sym_lookup.find(nlist.n_value); |
| 616 | // TODO validate | 627 | // TODO validate |
| 617 | i += 3; | 628 | i += 3; |
| 618 | }, | 629 | }, |
| 619 | macho.N_GSYM => { | 630 | macho.N_GSYM => { |
| 620 | stab.tag = .global; | 631 | stab.is_func = false; |
| 621 | stab.symbol = macho_file.getGlobalByName(self.getString(nlist.n_strx)); | 632 | stab.symbol = sym_lookup.find(addr_lookup.get(self.getString(nlist.n_strx)).?); |
| 622 | }, | 633 | }, |
| 623 | macho.N_STSYM => { | 634 | macho.N_STSYM => { |
| 624 | stab.tag = .static; | 635 | stab.is_func = false; |
| 625 | stab.symbol = sym_lookup.find(nlist.n_value); | 636 | stab.symbol = sym_lookup.find(nlist.n_value); |
| 626 | }, | 637 | }, |
| 627 | else => { | 638 | else => { |
| ... | @@ -1421,11 +1432,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { | ... | @@ -1421,11 +1432,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { |
| 1421 | const file = sym.getFile(macho_file).?; | 1432 | const file = sym.getFile(macho_file).?; |
| 1422 | if (file.getIndex() != self.index) continue; | 1433 | if (file.getIndex() != self.index) continue; |
| 1423 | if (!sym.flags.output_symtab) continue; | 1434 | if (!sym.flags.output_symtab) continue; |
| 1424 | const nstabs: u32 = switch (stab.tag) { | 1435 | const nstabs: u32 = if (stab.is_func) 4 else 1; |
| 1425 | .func => 4, // N_BNSYM, N_FUN, N_FUN, N_ENSYM | | |
| 1426 | .global => 1, // N_GSYM | | |
| 1427 | .static => 1, // N_STSYM | | |
| 1428 | }; | | |
| 1429 | self.output_symtab_ctx.nstabs += nstabs; | 1436 | self.output_symtab_ctx.nstabs += nstabs; |
| 1430 | } | 1437 | } |
| 1431 | } | 1438 | } |
| ... | @@ -1654,31 +1661,27 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO, ctx: anytype) error{O | ... | @@ -1654,31 +1661,27 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO, ctx: anytype) error{O |
| 1654 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; | 1661 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; |
| 1655 | const sym_n_value = sym.getAddress(.{}, macho_file); | 1662 | const sym_n_value = sym.getAddress(.{}, macho_file); |
| 1656 | const sym_size = sym.getSize(macho_file); | 1663 | const sym_size = sym.getSize(macho_file); |
| 1657 | switch (stab.tag) { | 1664 | if (stab.is_func) { |
| 1658 | .func => { | 1665 | writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx); |
| 1659 | writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx); | 1666 | index += 4; |
| 1660 | index += 4; | 1667 | } else if (sym.visibility == .global) { |
| 1661 | }, | 1668 | ctx.symtab.items[index] = .{ |
| 1662 | .global => { | 1669 | .n_strx = sym_n_strx, |
| 1663 | ctx.symtab.items[index] = .{ | 1670 | .n_type = macho.N_GSYM, |
| 1664 | .n_strx = sym_n_strx, | 1671 | .n_sect = sym_n_sect, |
| 1665 | .n_type = macho.N_GSYM, | 1672 | .n_desc = 0, |
| 1666 | .n_sect = sym_n_sect, | 1673 | .n_value = 0, |
| 1667 | .n_desc = 0, | 1674 | }; |
| 1668 | .n_value = 0, | 1675 | index += 1; |
| 1669 | }; | 1676 | } else { |
| 1670 | index += 1; | 1677 | ctx.symtab.items[index] = .{ |
| 1671 | }, | 1678 | .n_strx = sym_n_strx, |
| 1672 | .static => { | 1679 | .n_type = macho.N_STSYM, |
| 1673 | ctx.symtab.items[index] = .{ | 1680 | .n_sect = sym_n_sect, |
| 1674 | .n_strx = sym_n_strx, | 1681 | .n_desc = 0, |
| 1675 | .n_type = macho.N_STSYM, | 1682 | .n_value = sym_n_value, |
| 1676 | .n_sect = sym_n_sect, | 1683 | }; |
| 1677 | .n_desc = 0, | 1684 | index += 1; |
| 1678 | .n_value = sym_n_value, | | |
| 1679 | }; | | |
| 1680 | index += 1; | | |
| 1681 | }, | | |
| 1682 | } | 1685 | } |
| 1683 | } | 1686 | } |
| 1684 | | 1687 | |
| ... | @@ -1976,7 +1979,7 @@ const StabFile = struct { | ... | @@ -1976,7 +1979,7 @@ const StabFile = struct { |
| 1976 | } | 1979 | } |
| 1977 | | 1980 | |
| 1978 | const Stab = struct { | 1981 | const Stab = struct { |
| 1979 | tag: enum { func, global, static } = .func, | 1982 | is_func: bool = true, |
| 1980 | symbol: ?Symbol.Index = null, | 1983 | symbol: ?Symbol.Index = null, |
| 1981 | | 1984 | |
| 1982 | fn getSymbol(stab: Stab, macho_file: *MachO) ?*Symbol { | 1985 | fn getSymbol(stab: Stab, macho_file: *MachO) ?*Symbol { |