authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-10-21 23:20:34+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-10-22 07:59:24+02:00
log086cee844a082bab82dba9e7422067f644930309
tree290f75decc67ffa008cfb4e5680c0ff730768778
parent0cc4d54781ca3835e2f83c8ce93b485366a52b2a

macho: refactor dead code stripping conditions

1. If an object file was not compiled with `MH_SUBSECTIONS_VIA_SYMBOLS` such a hand-written ASM on x86_64, treat the entire object file as not suitable for dead code stripping aka a GC root. 2. If there are non-extern relocs within a section, treat the entire section as a root, at least temporarily until we work out the exact conditions for marking the atoms live.

4 files changed, 129 insertions(+), 108 deletions(-)

src/link/MachO/ZldAtom.zig+12-22
...@@ -165,7 +165,7 @@ pub fn parseRelocTarget(...@@ -165,7 +165,7 @@ pub fn parseRelocTarget(
165 atom_index: AtomIndex,165 atom_index: AtomIndex,
166 rel: macho.relocation_info,166 rel: macho.relocation_info,
167 reverse_lookup: []u32,167 reverse_lookup: []u32,
168) !SymbolWithLoc {168) SymbolWithLoc {
169 const atom = zld.getAtom(atom_index);169 const atom = zld.getAtom(atom_index);
170 const object = &zld.objects.items[atom.getFile().?];170 const object = &zld.objects.items[atom.getFile().?];
171171
...@@ -429,15 +429,17 @@ pub fn getRelocTargetAddress(zld: *Zld, rel: macho.relocation_info, target: Symb...@@ -429,15 +429,17 @@ pub fn getRelocTargetAddress(zld: *Zld, rel: macho.relocation_info, target: Symb
429 zld.getSymbolName(target_atom.getSymbolWithLoc()),429 zld.getSymbolName(target_atom.getSymbolWithLoc()),
430 target_atom.file,430 target_atom.file,
431 });431 });
432 // If `target` is contained within the target atom, pull its address value.432
433 const target_sym = zld.getSymbol(target_atom.getSymbolWithLoc());433 const target_sym = zld.getSymbol(target_atom.getSymbolWithLoc());
434 assert(target_sym.n_desc != @import("zld.zig").N_DEAD);
435
436 // If `target` is contained within the target atom, pull its address value.
434 const offset = if (target_atom.getFile() != null) blk: {437 const offset = if (target_atom.getFile() != null) blk: {
435 const object = zld.objects.items[target_atom.getFile().?];438 const object = zld.objects.items[target_atom.getFile().?];
436 break :blk if (object.getSourceSymbol(target.sym_index)) |_|439 break :blk if (object.getSourceSymbol(target.sym_index)) |_|
437 Atom.calcInnerSymbolOffset(zld, target_atom_index, target.sym_index)440 Atom.calcInnerSymbolOffset(zld, target_atom_index, target.sym_index)
438 else441 else
439 0; // section alias442 0; // section alias
440
441 } else 0;443 } else 0;
442 const base_address: u64 = if (is_tlv) base_address: {444 const base_address: u64 = if (is_tlv) base_address: {
443 // For TLV relocations, the value specified as a relocation is the displacement from the445 // For TLV relocations, the value specified as a relocation is the displacement from the
...@@ -498,20 +500,13 @@ fn resolveRelocsArm64(...@@ -498,20 +500,13 @@ fn resolveRelocsArm64(
498 atom.file,500 atom.file,
499 });501 });
500502
501 const sym_index = reverse_lookup[rel.r_symbolnum];503 subtractor = parseRelocTarget(zld, atom_index, rel, reverse_lookup);
502 const sym_loc = SymbolWithLoc{
503 .sym_index = sym_index,
504 .file = atom.file,
505 };
506 const sym = zld.getSymbol(sym_loc);
507 assert(sym.sect());
508 subtractor = sym_loc;
509 continue;504 continue;
510 },505 },
511 else => {},506 else => {},
512 }507 }
513508
514 const target = try parseRelocTarget(zld, atom_index, rel, reverse_lookup);509 const target = parseRelocTarget(zld, atom_index, rel, reverse_lookup);
515 const rel_offset = @intCast(u32, rel.r_address - context.base_offset);510 const rel_offset = @intCast(u32, rel.r_address - context.base_offset);
516511
517 log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{512 log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{
...@@ -784,20 +779,13 @@ fn resolveRelocsX86(...@@ -784,20 +779,13 @@ fn resolveRelocsX86(
784 atom.file,779 atom.file,
785 });780 });
786781
787 const sym_index = reverse_lookup[rel.r_symbolnum];782 subtractor = parseRelocTarget(zld, atom_index, rel, reverse_lookup);
788 const sym_loc = SymbolWithLoc{
789 .sym_index = sym_index,
790 .file = atom.file,
791 };
792 const sym = zld.getSymbol(sym_loc);
793 assert(sym.sect());
794 subtractor = sym_loc;
795 continue;783 continue;
796 },784 },
797 else => {},785 else => {},
798 }786 }
799787
800 const target = try parseRelocTarget(zld, atom_index, rel, reverse_lookup);788 const target = parseRelocTarget(zld, atom_index, rel, reverse_lookup);
801 const rel_offset = @intCast(u32, rel.r_address - context.base_offset);789 const rel_offset = @intCast(u32, rel.r_address - context.base_offset);
802790
803 log.debug(" RELA({s}) @ {x} => %{d} in object({?})", .{791 log.debug(" RELA({s}) @ {x} => %{d} in object({?})", .{
...@@ -816,10 +804,11 @@ fn resolveRelocsX86(...@@ -816,10 +804,11 @@ fn resolveRelocsX86(
816 const header = zld.sections.items(.header)[source_sym.n_sect - 1];804 const header = zld.sections.items(.header)[source_sym.n_sect - 1];
817 break :is_tlv header.@"type"() == macho.S_THREAD_LOCAL_VARIABLES;805 break :is_tlv header.@"type"() == macho.S_THREAD_LOCAL_VARIABLES;
818 };806 };
819 const target_addr = try getRelocTargetAddress(zld, rel, target, is_tlv);
820807
821 log.debug(" | source_addr = 0x{x}", .{source_addr});808 log.debug(" | source_addr = 0x{x}", .{source_addr});
822809
810 const target_addr = try getRelocTargetAddress(zld, rel, target, is_tlv);
811
823 switch (rel_type) {812 switch (rel_type) {
824 .X86_64_RELOC_BRANCH => {813 .X86_64_RELOC_BRANCH => {
825 const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]);814 const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]);
...@@ -878,6 +867,7 @@ fn resolveRelocsX86(...@@ -878,6 +867,7 @@ fn resolveRelocsX86(
878 }867 }
879868
880 const adjusted_target_addr = @intCast(u64, @intCast(i64, target_addr) + addend);869 const adjusted_target_addr = @intCast(u64, @intCast(i64, target_addr) + addend);
870
881 log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr});871 log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr});
882872
883 const disp = try calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, correction);873 const disp = try calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, correction);
src/link/MachO/dead_strip.zig+102-81
...@@ -42,8 +42,12 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {...@@ -42,8 +42,12 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {
42 const object = zld.objects.items[global.getFile().?];42 const object = zld.objects.items[global.getFile().?];
43 const atom_index = object.getAtomIndexForSymbol(global.sym_index).?; // panic here means fatal error43 const atom_index = object.getAtomIndexForSymbol(global.sym_index).?; // panic here means fatal error
44 _ = try roots.getOrPut(atom_index);44 _ = try roots.getOrPut(atom_index);
45 log.debug("adding root", .{});45
46 zld.logAtom(atom_index, log);46 log.debug("root(ATOM({d}, %{d}, {d}))", .{
47 atom_index,
48 zld.getAtom(atom_index).sym_index,
49 zld.getAtom(atom_index).file,
50 });
47 },51 },
48 else => |other| {52 else => |other| {
49 assert(other == .Lib);53 assert(other == .Lib);
...@@ -55,8 +59,12 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {...@@ -55,8 +59,12 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {
55 const object = zld.objects.items[global.getFile().?];59 const object = zld.objects.items[global.getFile().?];
56 const atom_index = object.getAtomIndexForSymbol(global.sym_index).?; // panic here means fatal error60 const atom_index = object.getAtomIndexForSymbol(global.sym_index).?; // panic here means fatal error
57 _ = try roots.getOrPut(atom_index);61 _ = try roots.getOrPut(atom_index);
58 log.debug("adding root", .{});62
59 zld.logAtom(atom_index, log);63 log.debug("root(ATOM({d}, %{d}, {d}))", .{
64 atom_index,
65 zld.getAtom(atom_index).sym_index,
66 zld.getAtom(atom_index).file,
67 });
60 }68 }
61 },69 },
62 }70 }
...@@ -67,28 +75,36 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {...@@ -67,28 +75,36 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {
67 const object = zld.objects.items[global.getFile().?];75 const object = zld.objects.items[global.getFile().?];
68 if (object.getAtomIndexForSymbol(global.sym_index)) |atom_index| {76 if (object.getAtomIndexForSymbol(global.sym_index)) |atom_index| {
69 _ = try roots.getOrPut(atom_index);77 _ = try roots.getOrPut(atom_index);
70 log.debug("adding root", .{});78
71 zld.logAtom(atom_index, log);79 log.debug("root(ATOM({d}, %{d}, {d}))", .{
80 atom_index,
81 zld.getAtom(atom_index).sym_index,
82 zld.getAtom(atom_index).file,
83 });
72 }84 }
73 break;85 break;
74 }86 }
75 }87 }
7688
77 for (zld.objects.items) |object| {89 for (zld.objects.items) |object| {
78 for (object.atoms.items) |atom_index| {90 const has_subsections = object.header.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0;
79 const atom = zld.getAtom(atom_index);
8091
81 const sect_id = if (object.getSourceSymbol(atom.sym_index)) |source_sym|92 for (object.atoms.items) |atom_index| {
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);
89 const is_gc_root = blk: {93 const is_gc_root = blk: {
94 // Modelled after ld64 which treats each object file compiled without MH_SUBSECTIONS_VIA_SYMBOLS
95 // as a root.
96 if (!has_subsections) break :blk true;
97
98 const atom = zld.getAtom(atom_index);
99 const sect_id = if (object.getSourceSymbol(atom.sym_index)) |source_sym|
100 source_sym.n_sect - 1
101 else sect_id: {
102 const nbase = @intCast(u32, object.in_symtab.?.len);
103 const sect_id = @intCast(u16, atom.sym_index - nbase);
104 break :sect_id sect_id;
105 };
106 const source_sect = object.getSourceSection(sect_id);
90 if (source_sect.isDontDeadStrip()) break :blk true;107 if (source_sect.isDontDeadStrip()) break :blk true;
91 if (mem.eql(u8, "__StaticInit", source_sect.sectName())) break :blk true;
92 switch (source_sect.@"type"()) {108 switch (source_sect.@"type"()) {
93 macho.S_MOD_INIT_FUNC_POINTERS,109 macho.S_MOD_INIT_FUNC_POINTERS,
94 macho.S_MOD_TERM_FUNC_POINTERS,110 macho.S_MOD_TERM_FUNC_POINTERS,
...@@ -96,10 +112,15 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {...@@ -96,10 +112,15 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {
96 else => break :blk false,112 else => break :blk false,
97 }113 }
98 };114 };
115
99 if (is_gc_root) {116 if (is_gc_root) {
100 try roots.putNoClobber(atom_index, {});117 try roots.putNoClobber(atom_index, {});
101 log.debug("adding root", .{});118
102 zld.logAtom(atom_index, log);119 log.debug("root(ATOM({d}, %{d}, {d}))", .{
120 atom_index,
121 zld.getAtom(atom_index).sym_index,
122 zld.getAtom(atom_index).file,
123 });
103 }124 }
104 }125 }
105 }126 }
...@@ -111,17 +132,17 @@ fn markLive(...@@ -111,17 +132,17 @@ fn markLive(
111 alive: *AtomTable,132 alive: *AtomTable,
112 reverse_lookups: [][]u32,133 reverse_lookups: [][]u32,
113) anyerror!void {134) anyerror!void {
114 log.debug("mark(ATOM({d}))", .{atom_index});
115
116 if (alive.contains(atom_index)) return;135 if (alive.contains(atom_index)) return;
117136
118 alive.putAssumeCapacityNoClobber(atom_index, {});137 const atom = zld.getAtom(atom_index);
138 const sym_loc = atom.getSymbolWithLoc();
139
140 log.debug("mark(ATOM({d}, %{d}, {d}))", .{ atom_index, sym_loc.sym_index, sym_loc.file });
119141
120 zld.logAtom(atom_index, log);142 alive.putAssumeCapacityNoClobber(atom_index, {});
121143
122 const cpu_arch = zld.options.target.cpu.arch;144 const cpu_arch = zld.options.target.cpu.arch;
123145
124 const atom = zld.getAtom(atom_index);
125 const sym = zld.getSymbol(atom.getSymbolWithLoc());146 const sym = zld.getSymbol(atom.getSymbolWithLoc());
126 const header = zld.sections.items(.header)[sym.n_sect - 1];147 const header = zld.sections.items(.header)[sym.n_sect - 1];
127 if (header.isZerofill()) return;148 if (header.isZerofill()) return;
...@@ -130,37 +151,30 @@ fn markLive(...@@ -130,37 +151,30 @@ fn markLive(
130 const reverse_lookup = reverse_lookups[atom.getFile().?];151 const reverse_lookup = reverse_lookups[atom.getFile().?];
131 for (relocs) |rel| {152 for (relocs) |rel| {
132 const target = switch (cpu_arch) {153 const target = switch (cpu_arch) {
133 .aarch64 => blk: {154 .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) {
134 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);155 .ARM64_RELOC_ADDEND => continue,
135 switch (rel_type) {156 else => Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup),
136 .ARM64_RELOC_ADDEND => continue,
137 .ARM64_RELOC_SUBTRACTOR => {
138 const sym_index = reverse_lookup[rel.r_symbolnum];
139 break :blk SymbolWithLoc{
140 .sym_index = sym_index,
141 .file = atom.file,
142 };
143 },
144 else => break :blk try Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup),
145 }
146 },
147 .x86_64 => blk: {
148 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);
149 switch (rel_type) {
150 .X86_64_RELOC_SUBTRACTOR => {
151 const sym_index = reverse_lookup[rel.r_symbolnum];
152 break :blk SymbolWithLoc{
153 .sym_index = sym_index,
154 .file = atom.file,
155 };
156 },
157 else => break :blk try Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup),
158 }
159 },157 },
158 .x86_64 => Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup),
160 else => unreachable,159 else => unreachable,
161 };160 };
162
163 const target_sym = zld.getSymbol(target);161 const target_sym = zld.getSymbol(target);
162
163 if (rel.r_extern == 0) {
164 // We are pessimistic and mark all atoms within the target section as live.
165 // TODO: this can be improved by marking only the relevant atoms.
166 const sect_id = target_sym.n_sect;
167 const object = zld.objects.items[target.getFile().?];
168 for (object.atoms.items) |other_atom_index| {
169 const other_atom = zld.getAtom(other_atom_index);
170 const other_sym = zld.getSymbol(other_atom.getSymbolWithLoc());
171 if (other_sym.n_sect == sect_id) {
172 try markLive(zld, other_atom_index, alive, reverse_lookups);
173 }
174 }
175 continue;
176 }
177
164 if (target_sym.undf()) continue;178 if (target_sym.undf()) continue;
165 if (target.getFile() == null) {179 if (target.getFile() == null) {
166 const target_sym_name = zld.getSymbolName(target);180 const target_sym_name = zld.getSymbolName(target);
...@@ -172,51 +186,51 @@ fn markLive(...@@ -172,51 +186,51 @@ fn markLive(
172186
173 const object = zld.objects.items[target.getFile().?];187 const object = zld.objects.items[target.getFile().?];
174 const target_atom_index = object.getAtomIndexForSymbol(target.sym_index).?;188 const target_atom_index = object.getAtomIndexForSymbol(target.sym_index).?;
175 log.debug(" following ATOM({d})", .{target_atom_index});189 log.debug(" following ATOM({d}, %{d}, {d})", .{
190 target_atom_index,
191 zld.getAtom(target_atom_index).sym_index,
192 zld.getAtom(target_atom_index).file,
193 });
176194
177 try markLive(zld, target_atom_index, alive, reverse_lookups);195 try markLive(zld, target_atom_index, alive, reverse_lookups);
178 }196 }
179}197}
180198
181fn refersLive(zld: *Zld, atom_index: AtomIndex, alive: AtomTable, reverse_lookups: [][]u32) !bool {199fn refersLive(zld: *Zld, atom_index: AtomIndex, alive: AtomTable, reverse_lookups: [][]u32) !bool {
182 log.debug("refersLive(ATOM({d}))", .{atom_index});200 const atom = zld.getAtom(atom_index);
201 const sym_loc = atom.getSymbolWithLoc();
202
203 log.debug("refersLive(ATOM({d}, %{d}, {d}))", .{ atom_index, sym_loc.sym_index, sym_loc.file });
183204
184 const cpu_arch = zld.options.target.cpu.arch;205 const cpu_arch = zld.options.target.cpu.arch;
185206
186 const atom = zld.getAtom(atom_index);207 const sym = zld.getSymbol(sym_loc);
187 const sym = zld.getSymbol(atom.getSymbolWithLoc());
188 const header = zld.sections.items(.header)[sym.n_sect - 1];208 const header = zld.sections.items(.header)[sym.n_sect - 1];
189 if (header.isZerofill()) return false;209 assert(!header.isZerofill());
190210
191 const relocs = Atom.getAtomRelocs(zld, atom_index);211 const relocs = Atom.getAtomRelocs(zld, atom_index);
192 const reverse_lookup = reverse_lookups[atom.getFile().?];212 const reverse_lookup = reverse_lookups[atom.getFile().?];
193 for (relocs) |rel| {213 for (relocs) |rel| {
194 switch (cpu_arch) {214 const target = switch (cpu_arch) {
195 .aarch64 => {215 .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) {
196 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);216 .ARM64_RELOC_ADDEND => continue,
197 switch (rel_type) {217 else => Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup),
198 .ARM64_RELOC_ADDEND, .ARM64_RELOC_SUBTRACTOR => continue,
199 else => {},
200 }
201 },
202 .x86_64 => {
203 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);
204 switch (rel_type) {
205 .X86_64_RELOC_SUBTRACTOR => continue,
206 else => {},
207 }
208 },218 },
219 .x86_64 => Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup),
209 else => unreachable,220 else => unreachable,
210 }221 };
211222
212 const target = try Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup);
213 const object = zld.objects.items[target.getFile().?];223 const object = zld.objects.items[target.getFile().?];
214 const target_atom_index = object.getAtomIndexForSymbol(target.sym_index) orelse {224 const target_atom_index = object.getAtomIndexForSymbol(target.sym_index) orelse {
215 log.debug("atom for symbol '{s}' not found; skipping...", .{zld.getSymbolName(target)});225 log.debug("atom for symbol '{s}' not found; skipping...", .{zld.getSymbolName(target)});
216 continue;226 continue;
217 };227 };
218 if (alive.contains(target_atom_index)) {228 if (alive.contains(target_atom_index)) {
219 log.debug(" refers live ATOM({d})", .{target_atom_index});229 log.debug(" refers live ATOM({d}, %{d}, {d})", .{
230 target_atom_index,
231 zld.getAtom(target_atom_index).sym_index,
232 zld.getAtom(target_atom_index).file,
233 });
220 return true;234 return true;
221 }235 }
222 }236 }
...@@ -270,10 +284,16 @@ fn prune(zld: *Zld, alive: AtomTable) !void {...@@ -270,10 +284,16 @@ fn prune(zld: *Zld, alive: AtomTable) !void {
270 continue;284 continue;
271 }285 }
272286
273 zld.logAtom(atom_index, log);
274
275 const atom = zld.getAtom(atom_index);287 const atom = zld.getAtom(atom_index);
276 const sym_loc = atom.getSymbolWithLoc();288 const sym_loc = atom.getSymbolWithLoc();
289
290 log.debug("prune(ATOM({d}, %{d}, {d}))", .{
291 atom_index,
292 sym_loc.sym_index,
293 sym_loc.file,
294 });
295 log.debug(" {s} in {s}", .{ zld.getSymbolName(sym_loc), object.name });
296
277 const sym = zld.getSymbolPtr(sym_loc);297 const sym = zld.getSymbolPtr(sym_loc);
278 const sect_id = sym.n_sect - 1;298 const sect_id = sym.n_sect - 1;
279 var section = zld.sections.get(sect_id);299 var section = zld.sections.get(sect_id);
...@@ -303,16 +323,17 @@ fn prune(zld: *Zld, alive: AtomTable) !void {...@@ -303,16 +323,17 @@ fn prune(zld: *Zld, alive: AtomTable) !void {
303 zld.sections.set(sect_id, section);323 zld.sections.set(sect_id, section);
304 _ = object.atoms.swapRemove(i);324 _ = object.atoms.swapRemove(i);
305325
306 if (sym.ext()) {326 sym.n_desc = N_DEAD;
307 sym.n_desc = N_DEAD;
308 }
309327
310 var inner_sym_it = Atom.getInnerSymbolsIterator(zld, atom_index);328 var inner_sym_it = Atom.getInnerSymbolsIterator(zld, atom_index);
311 while (inner_sym_it.next()) |inner| {329 while (inner_sym_it.next()) |inner| {
312 const inner_sym = zld.getSymbolPtr(inner);330 const inner_sym = zld.getSymbolPtr(inner);
313 if (inner_sym.ext()) {331 inner_sym.n_desc = N_DEAD;
314 inner_sym.n_desc = N_DEAD;332 }
315 }333
334 if (Atom.getSectionAlias(zld, atom_index)) |alias| {
335 const alias_sym = zld.getSymbolPtr(alias);
336 alias_sym.n_desc = N_DEAD;
316 }337 }
317 }338 }
318 }339 }
src/link/MachO/thunks.zig+1-1
...@@ -224,7 +224,7 @@ fn scanRelocs(...@@ -224,7 +224,7 @@ fn scanRelocs(
224 for (relocs) |rel| {224 for (relocs) |rel| {
225 if (!relocNeedsThunk(rel)) continue;225 if (!relocNeedsThunk(rel)) continue;
226226
227 const target = Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup) catch unreachable;227 const target = Atom.parseRelocTarget(zld, atom_index, rel, reverse_lookup);
228 if (isReachable(zld, atom_index, rel, base_offset, target, allocated)) continue;228 if (isReachable(zld, atom_index, rel, base_offset, target, allocated)) continue;
229229
230 log.debug("{x}: source = {s}@{x}, target = {s}@{x} unreachable", .{230 log.debug("{x}: source = {s}@{x}, target = {s}@{x} unreachable", .{
src/link/MachO/zld.zig+14-4
...@@ -2313,7 +2313,7 @@ pub const Zld = struct {...@@ -2313,7 +2313,7 @@ pub const Zld = struct {
2313 else => unreachable,2313 else => unreachable,
2314 }2314 }
23152315
2316 const global = try Atom.parseRelocTarget(self, atom_index, rel, reverse_lookups[atom.getFile().?]);2316 const global = Atom.parseRelocTarget(self, atom_index, rel, reverse_lookups[atom.getFile().?]);
2317 const bind_sym_name = self.getSymbolName(global);2317 const bind_sym_name = self.getSymbolName(global);
2318 const bind_sym = self.getSymbol(global);2318 const bind_sym = self.getSymbol(global);
2319 if (!bind_sym.undf()) continue;2319 if (!bind_sym.undf()) continue;
...@@ -2750,14 +2750,20 @@ pub const Zld = struct {...@@ -2750,14 +2750,20 @@ pub const Zld = struct {
2750 continue;2750 continue;
2751 }2751 }
27522752
2753 const source_sym = object.getSourceSymbol(atom.sym_index) orelse continue;2753 const source_addr = if (object.getSourceSymbol(atom.sym_index)) |source_sym|
2754 const source_addr = math.cast(u32, source_sym.n_value) orelse return error.Overflow;2754 source_sym.n_value
2755 else blk: {
2756 const nbase = @intCast(u32, object.in_symtab.?.len);
2757 const source_sect_id = @intCast(u16, atom.sym_index - nbase);
2758 break :blk object.getSourceSection(source_sect_id).addr;
2759 };
2755 const filtered_dice = filterDataInCode(dice, source_addr, source_addr + atom.size);2760 const filtered_dice = filterDataInCode(dice, source_addr, source_addr + atom.size);
2756 const base = math.cast(u32, sym.n_value - text_sect_header.addr + text_sect_header.offset) orelse2761 const base = math.cast(u32, sym.n_value - text_sect_header.addr + text_sect_header.offset) orelse
2757 return error.Overflow;2762 return error.Overflow;
27582763
2759 for (filtered_dice) |single| {2764 for (filtered_dice) |single| {
2760 const offset = single.offset - source_addr + base;2765 const offset = math.cast(u32, single.offset - source_addr + base) orelse
2766 return error.Overflow;
2761 out_dice.appendAssumeCapacity(.{2767 out_dice.appendAssumeCapacity(.{
2762 .offset = offset,2768 .offset = offset,
2763 .length = single.length,2769 .length = single.length,
...@@ -4305,6 +4311,10 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -4305,6 +4311,10 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
4305 const physical_zerofill_size = math.cast(usize, linkedit.fileoff - physical_zerofill_start) orelse4311 const physical_zerofill_size = math.cast(usize, linkedit.fileoff - physical_zerofill_start) orelse
4306 return error.Overflow;4312 return error.Overflow;
4307 if (physical_zerofill_size > 0) {4313 if (physical_zerofill_size > 0) {
4314 log.debug("zeroing out zerofill area of length {x} at {x}", .{
4315 physical_zerofill_size,
4316 physical_zerofill_start,
4317 });
4308 var padding = try zld.gpa.alloc(u8, physical_zerofill_size);4318 var padding = try zld.gpa.alloc(u8, physical_zerofill_size);
4309 defer zld.gpa.free(padding);4319 defer zld.gpa.free(padding);
4310 mem.set(u8, padding, 0);4320 mem.set(u8, padding, 0);