authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-10-20 14:34:09+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-10-22 07:59:24+02:00
log2c2ff4558f83cdf1aacb0a4865389e93af60d2d5
treec325b95fbb4d14dce911a8195b037271f07fa6d0
parent5edb8e0b8ff8ec16fc38af0c9653eee3d4534db0

macho: fix handling of lack of subsections and tracking of inner symbols


4 files changed, 73 insertions(+), 44 deletions(-)

src/link/MachO/Object.zig+11-8
...@@ -316,6 +316,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {...@@ -316,6 +316,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {
316 object_id,316 object_id,
317 sym_index,317 sym_index,
318 0,318 0,
319 0,
319 sect.size,320 sect.size,
320 sect.@"align",321 sect.@"align",
321 out_sect_id,322 out_sect_id,
...@@ -392,6 +393,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {...@@ -392,6 +393,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {
392 object_id,393 object_id,
393 sym_index,394 sym_index,
394 0,395 0,
396 0,
395 atom_size,397 atom_size,
396 sect.@"align",398 sect.@"align",
397 out_sect_id,399 out_sect_id,
...@@ -429,6 +431,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {...@@ -429,6 +431,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {
429 zld,431 zld,
430 object_id,432 object_id,
431 atom_sym_index,433 atom_sym_index,
434 atom_sym_index + 1,
432 nsyms_trailing,435 nsyms_trailing,
433 atom_size,436 atom_size,
434 atom_align,437 atom_align,
...@@ -447,19 +450,17 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {...@@ -447,19 +450,17 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {
447 zld.addAtomToSection(atom_index);450 zld.addAtomToSection(atom_index);
448 }451 }
449 } else {452 } else {
450 const sym_index = self.getSectionAliasSymbolIndex(sect_id);453 const alias_index = self.getSectionAliasSymbolIndex(sect_id);
451 const atom_index = try self.createAtomFromSubsection(454 const atom_index = try self.createAtomFromSubsection(
452 zld,455 zld,
453 object_id,456 object_id,
454 sym_index,457 alias_index,
455 0,458 sect_start_index,
459 sect_loc.len,
456 sect.size,460 sect.size,
457 sect.@"align",461 sect.@"align",
458 out_sect_id,462 out_sect_id,
459 );463 );
460 // If there is no symbol to refer to this atom, we create
461 // a temp one, unless we already did that when working out the relocations
462 // of other atoms.
463 zld.addAtomToSection(atom_index);464 zld.addAtomToSection(atom_index);
464 }465 }
465 }466 }
...@@ -470,7 +471,8 @@ fn createAtomFromSubsection(...@@ -470,7 +471,8 @@ fn createAtomFromSubsection(
470 zld: *Zld,471 zld: *Zld,
471 object_id: u31,472 object_id: u31,
472 sym_index: u32,473 sym_index: u32,
473 nsyms_trailing: u32,474 inner_sym_index: u32,
475 inner_nsyms_trailing: u32,
474 size: u64,476 size: u64,
475 alignment: u32,477 alignment: u32,
476 out_sect_id: u8,478 out_sect_id: u8,
...@@ -478,7 +480,8 @@ fn createAtomFromSubsection(...@@ -478,7 +480,8 @@ fn createAtomFromSubsection(
478 const gpa = zld.gpa;480 const gpa = zld.gpa;
479 const atom_index = try zld.createEmptyAtom(sym_index, size, alignment);481 const atom_index = try zld.createEmptyAtom(sym_index, size, alignment);
480 const atom = zld.getAtomPtr(atom_index);482 const atom = zld.getAtomPtr(atom_index);
481 atom.nsyms_trailing = nsyms_trailing;483 atom.inner_sym_index = inner_sym_index;
484 atom.inner_nsyms_trailing = inner_nsyms_trailing;
482 atom.file = object_id;485 atom.file = object_id;
483 self.symtab[sym_index].n_sect = out_sect_id + 1;486 self.symtab[sym_index].n_sect = out_sect_id + 1;
484487
src/link/MachO/ZldAtom.zig+30-23
...@@ -28,7 +28,8 @@ sym_index: u32,...@@ -28,7 +28,8 @@ sym_index: u32,
28/// If this Atom references a subsection in an Object file, `nsyms_trailing`28/// If this Atom references a subsection in an Object file, `nsyms_trailing`
29/// tells how many symbols trailing `sym_index` fall within this Atom's address29/// tells how many symbols trailing `sym_index` fall within this Atom's address
30/// range.30/// range.
31nsyms_trailing: u32,31inner_sym_index: u32,
32inner_nsyms_trailing: u32,
3233
33/// -1 means symbol defined by the linker.34/// -1 means symbol defined by the linker.
34/// Otherwise, it is the index into appropriate object file.35/// Otherwise, it is the index into appropriate object file.
...@@ -52,7 +53,8 @@ prev_index: ?AtomIndex,...@@ -52,7 +53,8 @@ prev_index: ?AtomIndex,
5253
53pub const empty = Atom{54pub const empty = Atom{
54 .sym_index = 0,55 .sym_index = 0,
55 .nsyms_trailing = 0,56 .inner_sym_index = 0,
57 .inner_nsyms_trailing = 0,
56 .file = -1,58 .file = -1,
57 .size = 0,59 .size = 0,
58 .alignment = 0,60 .alignment = 0,
...@@ -81,9 +83,10 @@ const InnerSymIterator = struct {...@@ -81,9 +83,10 @@ const InnerSymIterator = struct {
8183
82 pub fn next(it: *@This()) ?SymbolWithLoc {84 pub fn next(it: *@This()) ?SymbolWithLoc {
83 if (it.count == 0) return null;85 if (it.count == 0) return null;
86 const res = SymbolWithLoc{ .sym_index = it.sym_index, .file = it.file };
84 it.sym_index += 1;87 it.sym_index += 1;
85 it.count -= 1;88 it.count -= 1;
86 return SymbolWithLoc{ .sym_index = it.sym_index, .file = it.file };89 return res;
87 }90 }
88};91};
8992
...@@ -91,8 +94,8 @@ pub fn getInnerSymbolsIterator(zld: *Zld, atom_index: AtomIndex) InnerSymIterato...@@ -91,8 +94,8 @@ pub fn getInnerSymbolsIterator(zld: *Zld, atom_index: AtomIndex) InnerSymIterato
91 const atom = zld.getAtom(atom_index);94 const atom = zld.getAtom(atom_index);
92 assert(atom.getFile() != null);95 assert(atom.getFile() != null);
93 return .{96 return .{
94 .sym_index = atom.sym_index,97 .sym_index = atom.inner_sym_index,
95 .count = atom.nsyms_trailing,98 .count = atom.inner_nsyms_trailing,
96 .file = atom.file,99 .file = atom.file,
97 };100 };
98}101}
...@@ -123,9 +126,16 @@ pub fn calcInnerSymbolOffset(zld: *Zld, atom_index: AtomIndex, sym_index: u32) u...@@ -123,9 +126,16 @@ pub fn calcInnerSymbolOffset(zld: *Zld, atom_index: AtomIndex, sym_index: u32) u
123 if (atom.sym_index == sym_index) return 0;126 if (atom.sym_index == sym_index) return 0;
124127
125 const object = zld.objects.items[atom.getFile().?];128 const object = zld.objects.items[atom.getFile().?];
126 const source_atom_sym = object.getSourceSymbol(atom.sym_index).?;
127 const source_sym = object.getSourceSymbol(sym_index).?;129 const source_sym = object.getSourceSymbol(sym_index).?;
128 return source_sym.n_value - source_atom_sym.n_value;130 const base_addr = if (object.getSourceSymbol(atom.sym_index)) |sym|
131 sym.n_value
132 else blk: {
133 const nbase = @intCast(u32, object.in_symtab.?.len);
134 const sect_id = @intCast(u16, atom.sym_index - nbase);
135 const source_sect = object.getSourceSection(sect_id);
136 break :blk source_sect.addr;
137 };
138 return source_sym.n_value - base_addr;
129}139}
130140
131pub fn scanAtomRelocs(141pub fn scanAtomRelocs(
...@@ -383,13 +393,13 @@ pub fn resolveRelocs(...@@ -383,13 +393,13 @@ pub fn resolveRelocs(
383 .base_offset = @intCast(i32, source_sym.n_value - source_sect.addr),393 .base_offset = @intCast(i32, source_sym.n_value - source_sect.addr),
384 };394 };
385 }395 }
386 for (object.getSourceSections()) |source_sect, i| {396 const nbase = @intCast(u32, object.in_symtab.?.len);
387 const sym_index = object.getSectionAliasSymbolIndex(@intCast(u8, i));397 const sect_id = @intCast(u16, atom.sym_index - nbase);
388 if (sym_index == atom.sym_index) break :blk .{398 const source_sect = object.getSourceSection(sect_id);
389 .base_addr = source_sect.addr,399 break :blk .{
390 .base_offset = 0,400 .base_addr = source_sect.addr,
391 };401 .base_offset = 0,
392 } else unreachable;402 };
393 };403 };
394404
395 log.debug("resolving relocations in ATOM(%{d}, '{s}')", .{405 log.debug("resolving relocations in ATOM(%{d}, '{s}')", .{
...@@ -918,11 +928,9 @@ pub fn getAtomCode(zld: *Zld, atom_index: AtomIndex) []const u8 {...@@ -918,11 +928,9 @@ pub fn getAtomCode(zld: *Zld, atom_index: AtomIndex) []const u8 {
918 // If there was no matching symbol present in the source symtab, this means928 // If there was no matching symbol present in the source symtab, this means
919 // we are dealing with either an entire section, or part of it, but also929 // we are dealing with either an entire section, or part of it, but also
920 // starting at the beginning.930 // starting at the beginning.
921 const source_sect = for (object.getSourceSections()) |source_sect, sect_id| {931 const nbase = @intCast(u32, object.in_symtab.?.len);
922 const sym_index = object.getSectionAliasSymbolIndex(@intCast(u8, sect_id));932 const sect_id = @intCast(u16, atom.sym_index - nbase);
923 if (sym_index == atom.sym_index) break source_sect;933 const source_sect = object.getSourceSection(sect_id);
924 } else unreachable;
925
926 assert(!source_sect.isZerofill());934 assert(!source_sect.isZerofill());
927 const code = object.getSectionContents(source_sect);935 const code = object.getSectionContents(source_sect);
928 const code_len = @intCast(usize, atom.size);936 const code_len = @intCast(usize, atom.size);
...@@ -949,10 +957,9 @@ pub fn getAtomRelocs(zld: *Zld, atom_index: AtomIndex) []align(1) const macho.re...@@ -949,10 +957,9 @@ pub fn getAtomRelocs(zld: *Zld, atom_index: AtomIndex) []align(1) const macho.re
949 // If there was no matching symbol present in the source symtab, this means957 // If there was no matching symbol present in the source symtab, this means
950 // we are dealing with either an entire section, or part of it, but also958 // we are dealing with either an entire section, or part of it, but also
951 // starting at the beginning.959 // starting at the beginning.
952 const source_sect = for (object.getSourceSections()) |source_sect, sect_id| {960 const nbase = @intCast(u32, object.in_symtab.?.len);
953 const sym_index = object.getSectionAliasSymbolIndex(@intCast(u8, sect_id));961 const sect_id = @intCast(u16, atom.sym_index - nbase);
954 if (sym_index == atom.sym_index) break source_sect;962 const source_sect = object.getSourceSection(sect_id);
955 } else unreachable;
956 assert(!source_sect.isZerofill());963 assert(!source_sect.isZerofill());
957 break :blk source_sect;964 break :blk source_sect;
958 };965 };
src/link/MachO/dead_strip.zig+17-4
...@@ -77,8 +77,15 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {...@@ -77,8 +77,15 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {
77 for (zld.objects.items) |object| {77 for (zld.objects.items) |object| {
78 for (object.atoms.items) |atom_index| {78 for (object.atoms.items) |atom_index| {
79 const atom = zld.getAtom(atom_index);79 const atom = zld.getAtom(atom_index);
80 const source_sym = object.getSourceSymbol(atom.sym_index) orelse continue;80
81 const source_sect = object.getSourceSection(source_sym.n_sect - 1);81 const sect_id = if (object.getSourceSymbol(atom.sym_index)) |source_sym|
82 source_sym.n_sect - 1
83 else blk: {
84 const nbase = @intCast(u32, object.in_symtab.?.len);
85 const sect_id = @intCast(u16, atom.sym_index - nbase);
86 break :blk sect_id;
87 };
88 const source_sect = object.getSourceSection(sect_id);
82 const is_gc_root = blk: {89 const is_gc_root = blk: {
83 if (source_sect.isDontDeadStrip()) break :blk true;90 if (source_sect.isDontDeadStrip()) break :blk true;
84 if (mem.eql(u8, "__StaticInit", source_sect.sectName())) break :blk true;91 if (mem.eql(u8, "__StaticInit", source_sect.sectName())) break :blk true;
...@@ -220,8 +227,14 @@ fn mark(zld: *Zld, roots: AtomTable, alive: *AtomTable, reverse_lookups: [][]u32...@@ -220,8 +227,14 @@ fn mark(zld: *Zld, roots: AtomTable, alive: *AtomTable, reverse_lookups: [][]u32
220 if (alive.contains(atom_index)) continue;227 if (alive.contains(atom_index)) continue;
221228
222 const atom = zld.getAtom(atom_index);229 const atom = zld.getAtom(atom_index);
223 const source_sym = object.getSourceSymbol(atom.sym_index) orelse continue;230 const sect_id = if (object.getSourceSymbol(atom.sym_index)) |source_sym|
224 const source_sect = object.getSourceSection(source_sym.n_sect - 1);231 source_sym.n_sect - 1
232 else blk: {
233 const nbase = @intCast(u32, object.in_symtab.?.len);
234 const sect_id = @intCast(u16, atom.sym_index - nbase);
235 break :blk sect_id;
236 };
237 const source_sect = object.getSourceSection(sect_id);
225238
226 if (source_sect.isDontDeadStripIfReferencesLive()) {239 if (source_sect.isDontDeadStripIfReferencesLive()) {
227 if (try refersLive(zld, atom_index, alive.*, reverse_lookups)) {240 if (try refersLive(zld, atom_index, alive.*, reverse_lookups)) {
src/link/MachO/zld.zig+15-9
...@@ -1911,7 +1911,7 @@ pub const Zld = struct {...@@ -1911,7 +1911,7 @@ pub const Zld = struct {
1911 sym.n_value,1911 sym.n_value,
1912 });1912 });
19131913
1914 if (atom.getFile()) |_| {1914 if (atom.getFile() != null) {
1915 // Update each symbol contained within the atom1915 // Update each symbol contained within the atom
1916 var it = Atom.getInnerSymbolsIterator(self, atom_index);1916 var it = Atom.getInnerSymbolsIterator(self, atom_index);
1917 while (it.next()) |sym_loc| {1917 while (it.next()) |sym_loc| {
...@@ -2160,8 +2160,11 @@ pub const Zld = struct {...@@ -2160,8 +2160,11 @@ pub const Zld = struct {
2160 log.debug(" ATOM({d}, %{d}, '{s}')", .{ atom_index, atom.sym_index, self.getSymbolName(atom.getSymbolWithLoc()) });2160 log.debug(" ATOM({d}, %{d}, '{s}')", .{ atom_index, atom.sym_index, self.getSymbolName(atom.getSymbolWithLoc()) });
21612161
2162 const object = self.objects.items[atom.getFile().?];2162 const object = self.objects.items[atom.getFile().?];
2163 const source_sym = object.getSourceSymbol(atom.sym_index).?;2163 const base_rel_offset: i32 = blk: {
2164 const source_sect = object.getSourceSection(source_sym.n_sect - 1);2164 const source_sym = object.getSourceSymbol(atom.sym_index) orelse break :blk 0;
2165 const source_sect = object.getSourceSection(source_sym.n_sect - 1);
2166 break :blk @intCast(i32, source_sym.n_value - source_sect.addr);
2167 };
2165 const relocs = Atom.getAtomRelocs(self, atom_index);2168 const relocs = Atom.getAtomRelocs(self, atom_index);
21662169
2167 for (relocs) |rel| {2170 for (relocs) |rel| {
...@@ -2180,7 +2183,7 @@ pub const Zld = struct {...@@ -2180,7 +2183,7 @@ pub const Zld = struct {
2180 }2183 }
21812184
2182 const base_offset = @intCast(i32, sym.n_value - segment.vmaddr);2185 const base_offset = @intCast(i32, sym.n_value - segment.vmaddr);
2183 const rel_offset = rel.r_address - @intCast(i32, source_sym.n_value - source_sect.addr);2186 const rel_offset = rel.r_address - base_rel_offset;
2184 const offset = @intCast(u64, base_offset + rel_offset);2187 const offset = @intCast(u64, base_offset + rel_offset);
2185 log.debug(" | rebase at {x}", .{offset});2188 log.debug(" | rebase at {x}", .{offset});
21862189
...@@ -2288,8 +2291,11 @@ pub const Zld = struct {...@@ -2288,8 +2291,11 @@ pub const Zld = struct {
22882291
2289 if (should_bind) {2292 if (should_bind) {
2290 const object = self.objects.items[atom.getFile().?];2293 const object = self.objects.items[atom.getFile().?];
2291 const source_sym = object.getSourceSymbol(atom.sym_index).?;2294 const base_rel_offset: i32 = blk: {
2292 const source_sect = object.getSourceSection(source_sym.n_sect - 1);2295 const source_sym = object.getSourceSymbol(atom.sym_index) orelse break :blk 0;
2296 const source_sect = object.getSourceSection(source_sym.n_sect - 1);
2297 break :blk @intCast(i32, source_sym.n_value - source_sect.addr);
2298 };
2293 const relocs = Atom.getAtomRelocs(self, atom_index);2299 const relocs = Atom.getAtomRelocs(self, atom_index);
22942300
2295 for (relocs) |rel| {2301 for (relocs) |rel| {
...@@ -2313,7 +2319,7 @@ pub const Zld = struct {...@@ -2313,7 +2319,7 @@ pub const Zld = struct {
2313 if (!bind_sym.undf()) continue;2319 if (!bind_sym.undf()) continue;
23142320
2315 const base_offset = @intCast(i32, sym.n_value - segment.vmaddr);2321 const base_offset = @intCast(i32, sym.n_value - segment.vmaddr);
2316 const rel_offset = rel.r_address - @intCast(i32, source_sym.n_value - source_sect.addr);2322 const rel_offset = rel.r_address - base_rel_offset;
2317 const offset = @intCast(u64, base_offset + rel_offset);2323 const offset = @intCast(u64, base_offset + rel_offset);
23182324
2319 const dylib_ordinal = @divTrunc(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER);2325 const dylib_ordinal = @divTrunc(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER);
...@@ -3491,7 +3497,7 @@ pub const Zld = struct {...@@ -3491,7 +3497,7 @@ pub const Zld = struct {
3491 });3497 });
3492 }3498 }
3493 }3499 }
3494 scoped_log.debug(" object(null)", .{});3500 scoped_log.debug(" object(-1)", .{});
3495 for (self.locals.items) |sym, sym_id| {3501 for (self.locals.items) |sym, sym_id| {
3496 if (sym.undf()) continue;3502 if (sym.undf()) continue;
3497 scoped_log.debug(" %{d}: {s} @{x} in sect({d}), {s}", .{3503 scoped_log.debug(" %{d}: {s} @{x} in sect({d}), {s}", .{
...@@ -3635,7 +3641,7 @@ pub const Zld = struct {...@@ -3635,7 +3641,7 @@ pub const Zld = struct {
3635 sym.n_sect,3641 sym.n_sect,
3636 });3642 });
36373643
3638 if (atom.getFile()) |_| {3644 if (atom.getFile() != null) {
3639 var it = Atom.getInnerSymbolsIterator(self, atom_index);3645 var it = Atom.getInnerSymbolsIterator(self, atom_index);
3640 while (it.next()) |sym_loc| {3646 while (it.next()) |sym_loc| {
3641 const inner = self.getSymbol(sym_loc);3647 const inner = self.getSymbol(sym_loc);