diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-03 21:01:12 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-04 13:34:26 +0200 |
| commit | eeec50d2515c5a3b65cab697ba3e28d89cc3b14c (patch) | |
| tree | ec0b7769fa070c189aa605c00015ec943997b6b1 /src | |
| parent | fca92fd7c0a2e1431338ef62440751870563a0e3 (diff) | |
| download | zig-eeec50d2515c5a3b65cab697ba3e28d89cc3b14c.tar.gz zig-eeec50d2515c5a3b65cab697ba3e28d89cc3b14c.zip | |
elf: misc .eh_frame management fixes
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 44 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 1 | ||||
| -rw-r--r-- | src/link/Elf/ZigObject.zig | 12 | ||||
| -rw-r--r-- | src/link/Elf/eh_frame.zig | 18 | ||||
| -rw-r--r-- | src/link/Elf/relocatable.zig | 50 |
5 files changed, 64 insertions, 61 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index d660c48b4b..99ba66e92d 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -621,7 +621,6 @@ pub fn growNonAllocSection( try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); } shdr.sh_size = needed_size; - self.markDirty(shdr_index); } @@ -2895,28 +2894,25 @@ fn initSyntheticSections(self: *Elf) !void { const target = self.getTarget(); const ptr_size = self.ptrWidthBytes(); - const needs_eh_frame = if (self.zigObjectPtr()) |zo| - zo.eh_frame_index != null - else for (self.objects.items) |index| { - if (self.file(index).?.object.cies.items.len > 0) break true; - } else false; + const needs_eh_frame = blk: { + if (self.zigObjectPtr()) |zo| + if (zo.eh_frame_index != null) break :blk true; + break :blk for (self.objects.items) |index| { + if (self.file(index).?.object.cies.items.len > 0) break true; + } else false; + }; if (needs_eh_frame) { if (self.eh_frame_section_index == null) { - self.eh_frame_section_index = blk: { - if (self.zigObjectPtr()) |zo| { - if (zo.eh_frame_index) |idx| break :blk zo.symbol(idx).atom(self).?.output_section_index; - } - break :blk try self.addSection(.{ - .name = try self.insertShString(".eh_frame"), - .type = if (target.cpu.arch == .x86_64) - elf.SHT_X86_64_UNWIND - else - elf.SHT_PROGBITS, - .flags = elf.SHF_ALLOC, - .addralign = ptr_size, - .offset = std.math.maxInt(u64), - }); - }; + self.eh_frame_section_index = self.sectionByName(".eh_frame") orelse try self.addSection(.{ + .name = try self.insertShString(".eh_frame"), + .type = if (target.cpu.arch == .x86_64) + elf.SHT_X86_64_UNWIND + else + elf.SHT_PROGBITS, + .flags = elf.SHF_ALLOC, + .addralign = ptr_size, + .offset = std.math.maxInt(u64), + }); } if (comp.link_eh_frame_hdr) { self.eh_frame_hdr_section_index = try self.addSection(.{ @@ -3591,11 +3587,7 @@ fn updateSectionSizes(self: *Elf) !void { const shdrs = slice.items(.shdr); if (self.eh_frame_section_index) |index| { - shdrs[index].sh_size = existing_size: { - const zo = self.zigObjectPtr() orelse break :existing_size 0; - const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); - break :existing_size sym.atom(self).?.size; - } + try eh_frame.calcEhFrameSize(self); + shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self); } if (self.eh_frame_hdr_section_index) |index| { diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index a72ac697dd..884826d82b 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -1096,6 +1096,7 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void { for (self.atoms_indexes.items) |atom_index| { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; + if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; const shndx = atom_ptr.relocsShndx() orelse continue; const shdr = self.shdrs.items[shndx]; const out_shndx = try elf_file.initOutputSection(.{ diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 8eef1a84e4..416ed06126 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -111,6 +111,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.debug_str_section_dirty = true; self.debug_str_index = try self.addSectionSymbol(gpa, ".debug_str", .@"1", osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_str_index.?).ref; } if (self.debug_info_index == null) { @@ -121,6 +122,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.debug_info_section_dirty = true; self.debug_info_index = try self.addSectionSymbol(gpa, ".debug_info", .@"1", osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_info_index.?).ref; } if (self.debug_abbrev_index == null) { @@ -131,6 +133,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.debug_abbrev_section_dirty = true; self.debug_abbrev_index = try self.addSectionSymbol(gpa, ".debug_abbrev", .@"1", osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_abbrev_index.?).ref; } if (self.debug_aranges_index == null) { @@ -141,6 +144,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.debug_aranges_section_dirty = true; self.debug_aranges_index = try self.addSectionSymbol(gpa, ".debug_aranges", .@"16", osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_aranges_index.?).ref; } if (self.debug_line_index == null) { @@ -151,6 +155,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.debug_line_section_dirty = true; self.debug_line_index = try self.addSectionSymbol(gpa, ".debug_line", .@"1", osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_index.?).ref; } if (self.debug_line_str_index == null) { @@ -163,6 +168,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.debug_line_str_section_dirty = true; self.debug_line_str_index = try self.addSectionSymbol(gpa, ".debug_line_str", .@"1", osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_str_index.?).ref; } if (self.debug_loclists_index == null) { @@ -173,6 +179,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.debug_loclists_section_dirty = true; self.debug_loclists_index = try self.addSectionSymbol(gpa, ".debug_loclists", .@"1", osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_loclists_index.?).ref; } if (self.debug_rnglists_index == null) { @@ -183,6 +190,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.debug_rnglists_section_dirty = true; self.debug_rnglists_index = try self.addSectionSymbol(gpa, ".debug_rnglists", .@"1", osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_rnglists_index.?).ref; } if (self.eh_frame_index == null) { @@ -197,6 +205,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { }); self.eh_frame_section_dirty = true; self.eh_frame_index = try self.addSectionSymbol(gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec); + elf_file.sections.items(.last_atom)[osec] = self.symbol(self.eh_frame_index.?).ref; } try dwarf.initMetadata(); @@ -1116,6 +1125,9 @@ pub fn getOrCreateMetadataForNav( return gop.value_ptr.symbol_index; } +// FIXME: we always create an atom to basically store size and alignment, however, this is only true for +// sections that have a single atom like the debug sections. It would be a better solution to decouple this +// concept from the atom, maybe. fn addSectionSymbol( self: *ZigObject, allocator: Allocator, diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index 54024fa1bb..a9e3e618cb 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -233,7 +233,10 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize { const comp = elf_file.base.comp; const gpa = comp.gpa; - var offset: usize = 0; + var offset: usize = if (elf_file.zigObjectPtr()) |zo| blk: { + const sym = zo.symbol(zo.eh_frame_index orelse break :blk 0); + break :blk sym.atom(elf_file).?.size; + } else 0; var cies = std.ArrayList(Cie).init(gpa); defer cies.deinit(); @@ -423,9 +426,8 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void { } } -fn emitReloc(elf_file: *Elf, base_offset: u64, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela { +fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela { const cpu_arch = elf_file.getTarget().cpu.arch; - const r_offset = base_offset + rel.r_offset; const r_type = rel.r_type(); var r_addend = rel.r_addend; var r_sym: u32 = 0; @@ -467,7 +469,7 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { for (atom_ptr.relocs(elf_file)) |rel| { const ref = zo.resolveSymbol(rel.r_sym(), elf_file); const target = elf_file.symbol(ref).?; - const out_rel = emitReloc(elf_file, 0, target, rel); + const out_rel = emitReloc(elf_file, rel.r_offset, target, rel); try writer.writeStruct(out_rel); } } @@ -480,8 +482,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { for (cie.relocs(elf_file)) |rel| { const ref = object.resolveSymbol(rel.r_sym(), elf_file); const sym = elf_file.symbol(ref).?; - const offset = cie.address(elf_file) - cie.offset; - const out_rel = emitReloc(elf_file, offset, sym, rel); + const r_offset = cie.address(elf_file) + rel.r_offset - cie.offset; + const out_rel = emitReloc(elf_file, r_offset, sym, rel); try writer.writeStruct(out_rel); } } @@ -491,8 +493,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { for (fde.relocs(elf_file)) |rel| { const ref = object.resolveSymbol(rel.r_sym(), elf_file); const sym = elf_file.symbol(ref).?; - const offset = fde.address(elf_file) - fde.offset; - const out_rel = emitReloc(elf_file, offset, sym, rel); + const r_offset = fde.address(elf_file) + rel.r_offset - fde.offset; + const out_rel = emitReloc(elf_file, r_offset, sym, rel); try writer.writeStruct(out_rel); } } diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index e66ae99ad2..9182c06946 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -302,30 +302,29 @@ fn initSections(elf_file: *Elf) !void { try msec.initOutputSection(elf_file); } - const needs_eh_frame = if (elf_file.zigObjectPtr()) |zo| - zo.eh_frame_index != null - else for (elf_file.objects.items) |index| { - if (elf_file.file(index).?.object.cies.items.len > 0) break true; - } else false; + const needs_eh_frame = blk: { + if (elf_file.zigObjectPtr()) |zo| + if (zo.eh_frame_index != null) break :blk true; + break :blk for (elf_file.objects.items) |index| { + if (elf_file.file(index).?.object.cies.items.len > 0) break true; + } else false; + }; if (needs_eh_frame) { if (elf_file.eh_frame_section_index == null) { - elf_file.eh_frame_section_index = blk: { - if (elf_file.zigObjectPtr()) |zo| { - if (zo.eh_frame_index) |idx| break :blk zo.symbol(idx).atom(elf_file).?.output_section_index; - } - break :blk try elf_file.addSection(.{ - .name = try elf_file.insertShString(".eh_frame"), - .type = if (elf_file.getTarget().cpu.arch == .x86_64) - elf.SHT_X86_64_UNWIND - else - elf.SHT_PROGBITS, - .flags = elf.SHF_ALLOC, - .addralign = elf_file.ptrWidthBytes(), - .offset = std.math.maxInt(u64), - }); - }; + elf_file.eh_frame_section_index = elf_file.sectionByName(".eh_frame") orelse + try elf_file.addSection(.{ + .name = try elf_file.insertShString(".eh_frame"), + .type = if (elf_file.getTarget().cpu.arch == .x86_64) + elf.SHT_X86_64_UNWIND + else + elf.SHT_PROGBITS, + .flags = elf.SHF_ALLOC, + .addralign = elf_file.ptrWidthBytes(), + .offset = std.math.maxInt(u64), + }); } - elf_file.eh_frame_rela_section_index = try elf_file.addRelaShdr( + elf_file.eh_frame_rela_section_index = elf_file.sectionByName(".rela.eh_frame") orelse + try elf_file.addRelaShdr( try elf_file.insertShString(".rela.eh_frame"), elf_file.eh_frame_section_index.?, ); @@ -367,6 +366,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { for (slice.items(.shdr), 0..) |*shdr, shndx| { const atom_list = slice.items(.atom_list)[shndx]; if (shdr.sh_type != elf.SHT_RELA) continue; + if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue; for (atom_list.items) |ref| { const atom_ptr = elf_file.atom(ref) orelse continue; if (!atom_ptr.alive) continue; @@ -378,11 +378,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { } if (elf_file.eh_frame_section_index) |index| { - slice.items(.shdr)[index].sh_size = existing_size: { - const zo = elf_file.zigObjectPtr() orelse break :existing_size 0; - const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); - break :existing_size sym.atom(elf_file).?.size; - } + try eh_frame.calcEhFrameSize(elf_file); + slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file); } if (elf_file.eh_frame_rela_section_index) |index| { const shdr = &slice.items(.shdr)[index]; @@ -464,8 +460,8 @@ fn writeSyntheticSections(elf_file: *Elf) !void { for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { if (shdr.sh_type != elf.SHT_RELA) continue; - if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_rela_section_index) continue; if (atom_list.items.len == 0) continue; + if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue; const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse return error.Overflow; |
