authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-03 21:01:12+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 13:34:26+02:00
logeeec50d2515c5a3b65cab697ba3e28d89cc3b14c
treeec0b7769fa070c189aa605c00015ec943997b6b1
parentfca92fd7c0a2e1431338ef62440751870563a0e3

elf: misc .eh_frame management fixes


5 files changed, 64 insertions(+), 61 deletions(-)

src/link/Elf.zig+18-26
...@@ -621,7 +621,6 @@ pub fn growNonAllocSection(...@@ -621,7 +621,6 @@ pub fn growNonAllocSection(
621 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);621 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);
622 }622 }
623 shdr.sh_size = needed_size;623 shdr.sh_size = needed_size;
624
625 self.markDirty(shdr_index);624 self.markDirty(shdr_index);
626}625}
627626
...@@ -2895,28 +2894,25 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2895,28 +2894,25 @@ fn initSyntheticSections(self: *Elf) !void {
2895 const target = self.getTarget();2894 const target = self.getTarget();
2896 const ptr_size = self.ptrWidthBytes();2895 const ptr_size = self.ptrWidthBytes();
28972896
2898 const needs_eh_frame = if (self.zigObjectPtr()) |zo|2897 const needs_eh_frame = blk: {
2899 zo.eh_frame_index != null2898 if (self.zigObjectPtr()) |zo|
2900 else for (self.objects.items) |index| {2899 if (zo.eh_frame_index != null) break :blk true;
2901 if (self.file(index).?.object.cies.items.len > 0) break true;2900 break :blk for (self.objects.items) |index| {
2902 } else false;2901 if (self.file(index).?.object.cies.items.len > 0) break true;
2902 } else false;
2903 };
2903 if (needs_eh_frame) {2904 if (needs_eh_frame) {
2904 if (self.eh_frame_section_index == null) {2905 if (self.eh_frame_section_index == null) {
2905 self.eh_frame_section_index = blk: {2906 self.eh_frame_section_index = self.sectionByName(".eh_frame") orelse try self.addSection(.{
2906 if (self.zigObjectPtr()) |zo| {2907 .name = try self.insertShString(".eh_frame"),
2907 if (zo.eh_frame_index) |idx| break :blk zo.symbol(idx).atom(self).?.output_section_index;2908 .type = if (target.cpu.arch == .x86_64)
2908 }2909 elf.SHT_X86_64_UNWIND
2909 break :blk try self.addSection(.{2910 else
2910 .name = try self.insertShString(".eh_frame"),2911 elf.SHT_PROGBITS,
2911 .type = if (target.cpu.arch == .x86_64)2912 .flags = elf.SHF_ALLOC,
2912 elf.SHT_X86_64_UNWIND2913 .addralign = ptr_size,
2913 else2914 .offset = std.math.maxInt(u64),
2914 elf.SHT_PROGBITS,2915 });
2915 .flags = elf.SHF_ALLOC,
2916 .addralign = ptr_size,
2917 .offset = std.math.maxInt(u64),
2918 });
2919 };
2920 }2916 }
2921 if (comp.link_eh_frame_hdr) {2917 if (comp.link_eh_frame_hdr) {
2922 self.eh_frame_hdr_section_index = try self.addSection(.{2918 self.eh_frame_hdr_section_index = try self.addSection(.{
...@@ -3591,11 +3587,7 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -3591,11 +3587,7 @@ fn updateSectionSizes(self: *Elf) !void {
35913587
3592 const shdrs = slice.items(.shdr);3588 const shdrs = slice.items(.shdr);
3593 if (self.eh_frame_section_index) |index| {3589 if (self.eh_frame_section_index) |index| {
3594 shdrs[index].sh_size = existing_size: {3590 shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self);
3595 const zo = self.zigObjectPtr() orelse break :existing_size 0;
3596 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);
3597 break :existing_size sym.atom(self).?.size;
3598 } + try eh_frame.calcEhFrameSize(self);
3599 }3591 }
36003592
3601 if (self.eh_frame_hdr_section_index) |index| {3593 if (self.eh_frame_hdr_section_index) |index| {
src/link/Elf/Object.zig+1
...@@ -1096,6 +1096,7 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {...@@ -1096,6 +1096,7 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
1096 for (self.atoms_indexes.items) |atom_index| {1096 for (self.atoms_indexes.items) |atom_index| {
1097 const atom_ptr = self.atom(atom_index) orelse continue;1097 const atom_ptr = self.atom(atom_index) orelse continue;
1098 if (!atom_ptr.alive) continue;1098 if (!atom_ptr.alive) continue;
1099 if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue;
1099 const shndx = atom_ptr.relocsShndx() orelse continue;1100 const shndx = atom_ptr.relocsShndx() orelse continue;
1100 const shdr = self.shdrs.items[shndx];1101 const shdr = self.shdrs.items[shndx];
1101 const out_shndx = try elf_file.initOutputSection(.{1102 const out_shndx = try elf_file.initOutputSection(.{
src/link/Elf/ZigObject.zig+12
...@@ -111,6 +111,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -111,6 +111,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
111 });111 });
112 self.debug_str_section_dirty = true;112 self.debug_str_section_dirty = true;
113 self.debug_str_index = try self.addSectionSymbol(gpa, ".debug_str", .@"1", osec);113 self.debug_str_index = try self.addSectionSymbol(gpa, ".debug_str", .@"1", osec);
114 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_str_index.?).ref;
114 }115 }
115116
116 if (self.debug_info_index == null) {117 if (self.debug_info_index == null) {
...@@ -121,6 +122,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -121,6 +122,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
121 });122 });
122 self.debug_info_section_dirty = true;123 self.debug_info_section_dirty = true;
123 self.debug_info_index = try self.addSectionSymbol(gpa, ".debug_info", .@"1", osec);124 self.debug_info_index = try self.addSectionSymbol(gpa, ".debug_info", .@"1", osec);
125 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_info_index.?).ref;
124 }126 }
125127
126 if (self.debug_abbrev_index == null) {128 if (self.debug_abbrev_index == null) {
...@@ -131,6 +133,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -131,6 +133,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
131 });133 });
132 self.debug_abbrev_section_dirty = true;134 self.debug_abbrev_section_dirty = true;
133 self.debug_abbrev_index = try self.addSectionSymbol(gpa, ".debug_abbrev", .@"1", osec);135 self.debug_abbrev_index = try self.addSectionSymbol(gpa, ".debug_abbrev", .@"1", osec);
136 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_abbrev_index.?).ref;
134 }137 }
135138
136 if (self.debug_aranges_index == null) {139 if (self.debug_aranges_index == null) {
...@@ -141,6 +144,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -141,6 +144,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
141 });144 });
142 self.debug_aranges_section_dirty = true;145 self.debug_aranges_section_dirty = true;
143 self.debug_aranges_index = try self.addSectionSymbol(gpa, ".debug_aranges", .@"16", osec);146 self.debug_aranges_index = try self.addSectionSymbol(gpa, ".debug_aranges", .@"16", osec);
147 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_aranges_index.?).ref;
144 }148 }
145149
146 if (self.debug_line_index == null) {150 if (self.debug_line_index == null) {
...@@ -151,6 +155,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -151,6 +155,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
151 });155 });
152 self.debug_line_section_dirty = true;156 self.debug_line_section_dirty = true;
153 self.debug_line_index = try self.addSectionSymbol(gpa, ".debug_line", .@"1", osec);157 self.debug_line_index = try self.addSectionSymbol(gpa, ".debug_line", .@"1", osec);
158 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_index.?).ref;
154 }159 }
155160
156 if (self.debug_line_str_index == null) {161 if (self.debug_line_str_index == null) {
...@@ -163,6 +168,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -163,6 +168,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
163 });168 });
164 self.debug_line_str_section_dirty = true;169 self.debug_line_str_section_dirty = true;
165 self.debug_line_str_index = try self.addSectionSymbol(gpa, ".debug_line_str", .@"1", osec);170 self.debug_line_str_index = try self.addSectionSymbol(gpa, ".debug_line_str", .@"1", osec);
171 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_str_index.?).ref;
166 }172 }
167173
168 if (self.debug_loclists_index == null) {174 if (self.debug_loclists_index == null) {
...@@ -173,6 +179,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -173,6 +179,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
173 });179 });
174 self.debug_loclists_section_dirty = true;180 self.debug_loclists_section_dirty = true;
175 self.debug_loclists_index = try self.addSectionSymbol(gpa, ".debug_loclists", .@"1", osec);181 self.debug_loclists_index = try self.addSectionSymbol(gpa, ".debug_loclists", .@"1", osec);
182 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_loclists_index.?).ref;
176 }183 }
177184
178 if (self.debug_rnglists_index == null) {185 if (self.debug_rnglists_index == null) {
...@@ -183,6 +190,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -183,6 +190,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
183 });190 });
184 self.debug_rnglists_section_dirty = true;191 self.debug_rnglists_section_dirty = true;
185 self.debug_rnglists_index = try self.addSectionSymbol(gpa, ".debug_rnglists", .@"1", osec);192 self.debug_rnglists_index = try self.addSectionSymbol(gpa, ".debug_rnglists", .@"1", osec);
193 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_rnglists_index.?).ref;
186 }194 }
187195
188 if (self.eh_frame_index == null) {196 if (self.eh_frame_index == null) {
...@@ -197,6 +205,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -197,6 +205,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
197 });205 });
198 self.eh_frame_section_dirty = true;206 self.eh_frame_section_dirty = true;
199 self.eh_frame_index = try self.addSectionSymbol(gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec);207 self.eh_frame_index = try self.addSectionSymbol(gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec);
208 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.eh_frame_index.?).ref;
200 }209 }
201210
202 try dwarf.initMetadata();211 try dwarf.initMetadata();
...@@ -1116,6 +1125,9 @@ pub fn getOrCreateMetadataForNav(...@@ -1116,6 +1125,9 @@ pub fn getOrCreateMetadataForNav(
1116 return gop.value_ptr.symbol_index;1125 return gop.value_ptr.symbol_index;
1117}1126}
11181127
1128// FIXME: we always create an atom to basically store size and alignment, however, this is only true for
1129// sections that have a single atom like the debug sections. It would be a better solution to decouple this
1130// concept from the atom, maybe.
1119fn addSectionSymbol(1131fn addSectionSymbol(
1120 self: *ZigObject,1132 self: *ZigObject,
1121 allocator: Allocator,1133 allocator: Allocator,
src/link/Elf/eh_frame.zig+10-8
...@@ -233,7 +233,10 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize {...@@ -233,7 +233,10 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize {
233 const comp = elf_file.base.comp;233 const comp = elf_file.base.comp;
234 const gpa = comp.gpa;234 const gpa = comp.gpa;
235235
236 var offset: usize = 0;236 var offset: usize = if (elf_file.zigObjectPtr()) |zo| blk: {
237 const sym = zo.symbol(zo.eh_frame_index orelse break :blk 0);
238 break :blk sym.atom(elf_file).?.size;
239 } else 0;
237240
238 var cies = std.ArrayList(Cie).init(gpa);241 var cies = std.ArrayList(Cie).init(gpa);
239 defer cies.deinit();242 defer cies.deinit();
...@@ -423,9 +426,8 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void {...@@ -423,9 +426,8 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void {
423 }426 }
424}427}
425428
426fn emitReloc(elf_file: *Elf, base_offset: u64, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {429fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {
427 const cpu_arch = elf_file.getTarget().cpu.arch;430 const cpu_arch = elf_file.getTarget().cpu.arch;
428 const r_offset = base_offset + rel.r_offset;
429 const r_type = rel.r_type();431 const r_type = rel.r_type();
430 var r_addend = rel.r_addend;432 var r_addend = rel.r_addend;
431 var r_sym: u32 = 0;433 var r_sym: u32 = 0;
...@@ -467,7 +469,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {...@@ -467,7 +469,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
467 for (atom_ptr.relocs(elf_file)) |rel| {469 for (atom_ptr.relocs(elf_file)) |rel| {
468 const ref = zo.resolveSymbol(rel.r_sym(), elf_file);470 const ref = zo.resolveSymbol(rel.r_sym(), elf_file);
469 const target = elf_file.symbol(ref).?;471 const target = elf_file.symbol(ref).?;
470 const out_rel = emitReloc(elf_file, 0, target, rel);472 const out_rel = emitReloc(elf_file, rel.r_offset, target, rel);
471 try writer.writeStruct(out_rel);473 try writer.writeStruct(out_rel);
472 }474 }
473 }475 }
...@@ -480,8 +482,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {...@@ -480,8 +482,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
480 for (cie.relocs(elf_file)) |rel| {482 for (cie.relocs(elf_file)) |rel| {
481 const ref = object.resolveSymbol(rel.r_sym(), elf_file);483 const ref = object.resolveSymbol(rel.r_sym(), elf_file);
482 const sym = elf_file.symbol(ref).?;484 const sym = elf_file.symbol(ref).?;
483 const offset = cie.address(elf_file) - cie.offset;485 const r_offset = cie.address(elf_file) + rel.r_offset - cie.offset;
484 const out_rel = emitReloc(elf_file, offset, sym, rel);486 const out_rel = emitReloc(elf_file, r_offset, sym, rel);
485 try writer.writeStruct(out_rel);487 try writer.writeStruct(out_rel);
486 }488 }
487 }489 }
...@@ -491,8 +493,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {...@@ -491,8 +493,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
491 for (fde.relocs(elf_file)) |rel| {493 for (fde.relocs(elf_file)) |rel| {
492 const ref = object.resolveSymbol(rel.r_sym(), elf_file);494 const ref = object.resolveSymbol(rel.r_sym(), elf_file);
493 const sym = elf_file.symbol(ref).?;495 const sym = elf_file.symbol(ref).?;
494 const offset = fde.address(elf_file) - fde.offset;496 const r_offset = fde.address(elf_file) + rel.r_offset - fde.offset;
495 const out_rel = emitReloc(elf_file, offset, sym, rel);497 const out_rel = emitReloc(elf_file, r_offset, sym, rel);
496 try writer.writeStruct(out_rel);498 try writer.writeStruct(out_rel);
497 }499 }
498 }500 }
src/link/Elf/relocatable.zig+23-27
...@@ -302,30 +302,29 @@ fn initSections(elf_file: *Elf) !void {...@@ -302,30 +302,29 @@ fn initSections(elf_file: *Elf) !void {
302 try msec.initOutputSection(elf_file);302 try msec.initOutputSection(elf_file);
303 }303 }
304304
305 const needs_eh_frame = if (elf_file.zigObjectPtr()) |zo|305 const needs_eh_frame = blk: {
306 zo.eh_frame_index != null306 if (elf_file.zigObjectPtr()) |zo|
307 else for (elf_file.objects.items) |index| {307 if (zo.eh_frame_index != null) break :blk true;
308 if (elf_file.file(index).?.object.cies.items.len > 0) break true;308 break :blk for (elf_file.objects.items) |index| {
309 } else false;309 if (elf_file.file(index).?.object.cies.items.len > 0) break true;
310 } else false;
311 };
310 if (needs_eh_frame) {312 if (needs_eh_frame) {
311 if (elf_file.eh_frame_section_index == null) {313 if (elf_file.eh_frame_section_index == null) {
312 elf_file.eh_frame_section_index = blk: {314 elf_file.eh_frame_section_index = elf_file.sectionByName(".eh_frame") orelse
313 if (elf_file.zigObjectPtr()) |zo| {315 try elf_file.addSection(.{
314 if (zo.eh_frame_index) |idx| break :blk zo.symbol(idx).atom(elf_file).?.output_section_index;316 .name = try elf_file.insertShString(".eh_frame"),
315 }317 .type = if (elf_file.getTarget().cpu.arch == .x86_64)
316 break :blk try elf_file.addSection(.{318 elf.SHT_X86_64_UNWIND
317 .name = try elf_file.insertShString(".eh_frame"),319 else
318 .type = if (elf_file.getTarget().cpu.arch == .x86_64)320 elf.SHT_PROGBITS,
319 elf.SHT_X86_64_UNWIND321 .flags = elf.SHF_ALLOC,
320 else322 .addralign = elf_file.ptrWidthBytes(),
321 elf.SHT_PROGBITS,323 .offset = std.math.maxInt(u64),
322 .flags = elf.SHF_ALLOC,324 });
323 .addralign = elf_file.ptrWidthBytes(),
324 .offset = std.math.maxInt(u64),
325 });
326 };
327 }325 }
328 elf_file.eh_frame_rela_section_index = try elf_file.addRelaShdr(326 elf_file.eh_frame_rela_section_index = elf_file.sectionByName(".rela.eh_frame") orelse
327 try elf_file.addRelaShdr(
329 try elf_file.insertShString(".rela.eh_frame"),328 try elf_file.insertShString(".rela.eh_frame"),
330 elf_file.eh_frame_section_index.?,329 elf_file.eh_frame_section_index.?,
331 );330 );
...@@ -367,6 +366,7 @@ fn updateSectionSizes(elf_file: *Elf) !void {...@@ -367,6 +366,7 @@ fn updateSectionSizes(elf_file: *Elf) !void {
367 for (slice.items(.shdr), 0..) |*shdr, shndx| {366 for (slice.items(.shdr), 0..) |*shdr, shndx| {
368 const atom_list = slice.items(.atom_list)[shndx];367 const atom_list = slice.items(.atom_list)[shndx];
369 if (shdr.sh_type != elf.SHT_RELA) continue;368 if (shdr.sh_type != elf.SHT_RELA) continue;
369 if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue;
370 for (atom_list.items) |ref| {370 for (atom_list.items) |ref| {
371 const atom_ptr = elf_file.atom(ref) orelse continue;371 const atom_ptr = elf_file.atom(ref) orelse continue;
372 if (!atom_ptr.alive) continue;372 if (!atom_ptr.alive) continue;
...@@ -378,11 +378,7 @@ fn updateSectionSizes(elf_file: *Elf) !void {...@@ -378,11 +378,7 @@ fn updateSectionSizes(elf_file: *Elf) !void {
378 }378 }
379379
380 if (elf_file.eh_frame_section_index) |index| {380 if (elf_file.eh_frame_section_index) |index| {
381 slice.items(.shdr)[index].sh_size = existing_size: {381 slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file);
382 const zo = elf_file.zigObjectPtr() orelse break :existing_size 0;
383 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);
384 break :existing_size sym.atom(elf_file).?.size;
385 } + try eh_frame.calcEhFrameSize(elf_file);
386 }382 }
387 if (elf_file.eh_frame_rela_section_index) |index| {383 if (elf_file.eh_frame_rela_section_index) |index| {
388 const shdr = &slice.items(.shdr)[index];384 const shdr = &slice.items(.shdr)[index];
...@@ -464,8 +460,8 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -464,8 +460,8 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
464460
465 for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {461 for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {
466 if (shdr.sh_type != elf.SHT_RELA) continue;462 if (shdr.sh_type != elf.SHT_RELA) continue;
467 if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_rela_section_index) continue;
468 if (atom_list.items.len == 0) continue;463 if (atom_list.items.len == 0) continue;
464 if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue;
469465
470 const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse466 const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse
471 return error.Overflow;467 return error.Overflow;