authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-10-04 12:46:57+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-09 12:38:53-07:00
loge448fb960137e5aa83a1e7c2e6cbbf688f4fce05
tree1ffad6ca3fe35659df183971fdc9c2bc85d835ac
parentc92c72d08cfb102206594d723e29dd0616290d31

elf: change how we manage debug atoms in Dwarf linker


5 files changed, 97 insertions(+), 97 deletions(-)

src/link/Dwarf.zig+26-18
......@@ -389,14 +389,20 @@ pub const Section = struct {
389389 if (dwarf.bin_file.cast(.elf)) |elf_file| {
390390 const zo = elf_file.zigObjectPtr().?;
391391 const atom = zo.symbol(sec.index).atom(elf_file).?;
392 const shndx = atom.output_section_index;
393 const needed_size = len;
394 const min_alignment = sec.alignment.toByteUnits().?;
395 try elf_file.growSection(shndx, needed_size, min_alignment);
396 const shdr = elf_file.sections.items(.shdr)[shndx];
397 atom.size = needed_size;
398 atom.alignment = InternPool.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
399 sec.len = needed_size;
392 const old_size = atom.size;
393 atom.size = len;
394 atom.alignment = sec.alignment;
395 sec.len = len;
396 if (old_size > 0) {
397 if (!atom.alignment.check(@intCast(atom.value)) or atom.size > atom.fileCapacity(elf_file)) {
398 try zo.allocateAtom(atom, false, elf_file);
399 } else {
400 const shdr = &elf_file.sections.items(.shdr)[atom.output_section_index];
401 shdr.sh_size = (shdr.sh_size - old_size) + atom.size;
402 }
403 } else {
404 try zo.allocateAtom(atom, false, elf_file);
405 }
400406 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
401407 const header = if (macho_file.d_sym) |*d_sym| header: {
402408 try d_sym.growSection(@intCast(sec.index), len, true, macho_file);
......@@ -417,11 +423,15 @@ pub const Section = struct {
417423 if (dwarf.bin_file.cast(.elf)) |elf_file| {
418424 const zo = elf_file.zigObjectPtr().?;
419425 const atom = zo.symbol(sec.index).atom(elf_file).?;
420 const shndx = atom.output_section_index;
421 const shdr = &elf_file.sections.items(.shdr)[shndx];
422 atom.size = sec.len;
423 shdr.sh_offset += len;
424 shdr.sh_size = sec.len;
426 if (atom.prevAtom(elf_file)) |_| {
427 // FIXME:JK trimming/shrinking has to be reworked on ZigObject/Elf level
428 atom.value += len;
429 } else {
430 const shdr = &elf_file.sections.items(.shdr)[atom.output_section_index];
431 shdr.sh_offset += len;
432 atom.value = 0;
433 }
434 atom.size -= len;
425435 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
426436 const header = if (macho_file.d_sym) |*d_sym|
427437 &d_sym.sections.items[sec.index]
......@@ -910,11 +920,9 @@ const Entry = struct {
910920 if (std.debug.runtime_safety) {
911921 log.err("missing {} from {s}", .{
912922 @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)),
913 std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file| sh_name: {
914 const zo = elf_file.zigObjectPtr().?;
915 const shndx = zo.symbol(sec.index).atom(elf_file).?.output_section_index;
916 break :sh_name elf_file.shstrtab.items[elf_file.sections.items(.shdr)[shndx].sh_name..];
917 } else if (dwarf.bin_file.cast(.macho)) |macho_file|
923 std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file|
924 elf_file.zigObjectPtr().?.symbol(sec.index).name(elf_file)
925 else if (dwarf.bin_file.cast(.macho)) |macho_file|
918926 if (macho_file.d_sym) |*d_sym|
919927 &d_sym.sections.items[sec.index].segname
920928 else
src/link/Elf.zig+23-30
......@@ -573,10 +573,10 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment:
573573 // Must move the entire section.
574574 const new_offset = try self.findFreeSpace(needed_size, min_alignment);
575575
576 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
576 log.debug("moving '{s}' from 0x{x} to 0x{x}", .{
577577 self.getShString(shdr.sh_name),
578 shdr.sh_offset,
578579 new_offset,
579 new_offset + existing_size,
580580 });
581581
582582 const amt = try self.base.file.?.copyRangeAll(
......@@ -691,13 +691,6 @@ pub fn allocateChunk(self: *Elf, args: struct {
691691 }
692692 };
693693
694 log.debug("allocated chunk (size({x}),align({x})) at 0x{x} (file(0x{x}))", .{
695 args.size,
696 args.alignment.toByteUnits().?,
697 shdr.sh_addr + res.value,
698 shdr.sh_offset + res.value,
699 });
700
701694 const expand_section = if (self.atom(res.placement)) |placement_atom|
702695 placement_atom.nextAtom(self) == null
703696 else
......@@ -707,6 +700,18 @@ pub fn allocateChunk(self: *Elf, args: struct {
707700 try self.growSection(args.shndx, needed_size, args.alignment.toByteUnits().?);
708701 }
709702
703 log.debug("allocated chunk (size({x}),align({x})) in {s} at 0x{x} (file(0x{x}))", .{
704 args.size,
705 args.alignment.toByteUnits().?,
706 self.getShString(shdr.sh_name),
707 shdr.sh_addr + res.value,
708 shdr.sh_offset + res.value,
709 });
710 log.debug(" placement {}, {s}", .{
711 res.placement,
712 if (self.atom(res.placement)) |atom_ptr| atom_ptr.name(self) else "",
713 });
714
710715 return res;
711716}
712717
......@@ -1796,6 +1801,7 @@ pub fn initOutputSection(self: *Elf, args: struct {
17961801 .type = @"type",
17971802 .flags = flags,
17981803 .name = try self.insertShString(name),
1804 .offset = std.math.maxInt(u64),
17991805 });
18001806 return out_shndx;
18011807}
......@@ -3898,27 +3904,14 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
38983904 shdr.sh_size = 0;
38993905 const new_offset = try self.findFreeSpace(needed_size, shdr.sh_addralign);
39003906
3901 if (self.zigObjectPtr()) |zo| blk: {
3902 const existing_size = for ([_]?Symbol.Index{
3903 zo.debug_info_index,
3904 zo.debug_abbrev_index,
3905 zo.debug_aranges_index,
3906 zo.debug_str_index,
3907 zo.debug_line_index,
3908 zo.debug_line_str_index,
3909 zo.debug_loclists_index,
3910 zo.debug_rnglists_index,
3911 }) |maybe_sym_index| {
3912 const sym_index = maybe_sym_index orelse continue;
3913 const sym = zo.symbol(sym_index);
3914 const atom_ptr = sym.atom(self).?;
3915 if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
3916 } else break :blk;
3917 log.debug("moving {s} from 0x{x} to 0x{x}", .{
3918 self.getShString(shdr.sh_name),
3919 shdr.sh_offset,
3920 new_offset,
3921 });
3907 log.debug("moving {s} from 0x{x} to 0x{x}", .{
3908 self.getShString(shdr.sh_name),
3909 shdr.sh_offset,
3910 new_offset,
3911 });
3912
3913 if (shdr.sh_offset > 0) {
3914 const existing_size = self.sectionSize(@intCast(shndx));
39223915 const amt = try self.base.file.?.copyRangeAll(
39233916 shdr.sh_offset,
39243917 self.base.file.?,
src/link/Elf/Atom.zig+10-1
......@@ -118,10 +118,19 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 {
118118 return @intCast(next_addr - self.address(elf_file));
119119}
120120
121pub fn fileCapacity(self: Atom, elf_file: *Elf) u64 {
122 const self_off = self.offset(elf_file);
123 const next_off = if (self.nextAtom(elf_file)) |next_atom|
124 next_atom.offset(elf_file)
125 else
126 self_off + elf_file.allocatedSize(self_off);
127 return @intCast(next_off - self_off);
128}
129
121130pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
122131 // No need to keep a free list node for the last block.
123132 const next = self.nextAtom(elf_file) orelse return false;
124 const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file));
133 const cap: u64 = @intCast(next.value - self.value);
125134 const ideal_cap = Elf.padToIdeal(self.size);
126135 if (cap <= ideal_cap) return false;
127136 const surplus = cap - ideal_cap;
src/link/Elf/ZigObject.zig+30-30
......@@ -130,10 +130,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
130130 .entsize = 1,
131131 .type = elf.SHT_PROGBITS,
132132 .addralign = 1,
133 .offset = std.math.maxInt(u64),
133134 });
134135 self.debug_str_section_dirty = true;
135136 self.debug_str_index = try addSectionSymbolWithAtom(self, gpa, ".debug_str", .@"1", osec);
136 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_str_index.?).ref;
137137 }
138138
139139 if (self.debug_info_index == null) {
......@@ -141,10 +141,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
141141 .name = try elf_file.insertShString(".debug_info"),
142142 .type = elf.SHT_PROGBITS,
143143 .addralign = 1,
144 .offset = std.math.maxInt(u64),
144145 });
145146 self.debug_info_section_dirty = true;
146147 self.debug_info_index = try addSectionSymbolWithAtom(self, gpa, ".debug_info", .@"1", osec);
147 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_info_index.?).ref;
148148 }
149149
150150 if (self.debug_abbrev_index == null) {
......@@ -152,10 +152,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
152152 .name = try elf_file.insertShString(".debug_abbrev"),
153153 .type = elf.SHT_PROGBITS,
154154 .addralign = 1,
155 .offset = std.math.maxInt(u64),
155156 });
156157 self.debug_abbrev_section_dirty = true;
157158 self.debug_abbrev_index = try addSectionSymbolWithAtom(self, gpa, ".debug_abbrev", .@"1", osec);
158 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_abbrev_index.?).ref;
159159 }
160160
161161 if (self.debug_aranges_index == null) {
......@@ -163,10 +163,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
163163 .name = try elf_file.insertShString(".debug_aranges"),
164164 .type = elf.SHT_PROGBITS,
165165 .addralign = 16,
166 .offset = std.math.maxInt(u64),
166167 });
167168 self.debug_aranges_section_dirty = true;
168169 self.debug_aranges_index = try addSectionSymbolWithAtom(self, gpa, ".debug_aranges", .@"16", osec);
169 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_aranges_index.?).ref;
170170 }
171171
172172 if (self.debug_line_index == null) {
......@@ -174,10 +174,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
174174 .name = try elf_file.insertShString(".debug_line"),
175175 .type = elf.SHT_PROGBITS,
176176 .addralign = 1,
177 .offset = std.math.maxInt(u64),
177178 });
178179 self.debug_line_section_dirty = true;
179180 self.debug_line_index = try addSectionSymbolWithAtom(self, gpa, ".debug_line", .@"1", osec);
180 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_index.?).ref;
181181 }
182182
183183 if (self.debug_line_str_index == null) {
......@@ -187,10 +187,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
187187 .entsize = 1,
188188 .type = elf.SHT_PROGBITS,
189189 .addralign = 1,
190 .offset = std.math.maxInt(u64),
190191 });
191192 self.debug_line_str_section_dirty = true;
192193 self.debug_line_str_index = try addSectionSymbolWithAtom(self, gpa, ".debug_line_str", .@"1", osec);
193 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_str_index.?).ref;
194194 }
195195
196196 if (self.debug_loclists_index == null) {
......@@ -198,10 +198,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
198198 .name = try elf_file.insertShString(".debug_loclists"),
199199 .type = elf.SHT_PROGBITS,
200200 .addralign = 1,
201 .offset = std.math.maxInt(u64),
201202 });
202203 self.debug_loclists_section_dirty = true;
203204 self.debug_loclists_index = try addSectionSymbolWithAtom(self, gpa, ".debug_loclists", .@"1", osec);
204 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_loclists_index.?).ref;
205205 }
206206
207207 if (self.debug_rnglists_index == null) {
......@@ -209,10 +209,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
209209 .name = try elf_file.insertShString(".debug_rnglists"),
210210 .type = elf.SHT_PROGBITS,
211211 .addralign = 1,
212 .offset = std.math.maxInt(u64),
212213 });
213214 self.debug_rnglists_section_dirty = true;
214215 self.debug_rnglists_index = try addSectionSymbolWithAtom(self, gpa, ".debug_rnglists", .@"1", osec);
215 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_rnglists_index.?).ref;
216216 }
217217
218218 if (self.eh_frame_index == null) {
......@@ -224,10 +224,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
224224 elf.SHT_PROGBITS,
225225 .flags = elf.SHF_ALLOC,
226226 .addralign = ptr_size,
227 .offset = std.math.maxInt(u64),
227228 });
228229 self.eh_frame_section_dirty = true;
229230 self.eh_frame_index = try addSectionSymbolWithAtom(self, gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec);
230 elf_file.sections.items(.last_atom)[osec] = self.symbol(self.eh_frame_index.?).ref;
231231 }
232232
233233 try dwarf.initMetadata();
......@@ -1318,7 +1318,7 @@ fn updateNavCode(
13181318 const capacity = atom_ptr.capacity(elf_file);
13191319 const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value));
13201320 if (need_realloc) {
1321 try self.growAtom(atom_ptr, elf_file);
1321 try self.allocateAtom(atom_ptr, true, elf_file);
13221322 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });
13231323 if (old_vaddr != atom_ptr.value) {
13241324 sym.value = 0;
......@@ -1328,7 +1328,7 @@ fn updateNavCode(
13281328 // TODO shrink section size
13291329 }
13301330 } else {
1331 try self.allocateAtom(atom_ptr, elf_file);
1331 try self.allocateAtom(atom_ptr, true, elf_file);
13321332 errdefer self.freeNavMetadata(elf_file, sym_index);
13331333 sym.value = 0;
13341334 esym.st_value = 0;
......@@ -1403,7 +1403,7 @@ fn updateTlv(
14031403 const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);
14041404 assert(!gop.found_existing); // TODO incremental updates
14051405
1406 try self.allocateAtom(atom_ptr, elf_file);
1406 try self.allocateAtom(atom_ptr, true, elf_file);
14071407 sym.value = 0;
14081408 esym.st_value = 0;
14091409
......@@ -1729,7 +1729,7 @@ fn updateLazySymbol(
17291729 atom_ptr.size = code.len;
17301730 atom_ptr.output_section_index = output_section_index;
17311731
1732 try self.allocateAtom(atom_ptr, elf_file);
1732 try self.allocateAtom(atom_ptr, true, elf_file);
17331733 errdefer self.freeNavMetadata(elf_file, symbol_index);
17341734
17351735 local_sym.value = 0;
......@@ -1784,7 +1784,7 @@ fn lowerConst(
17841784 atom_ptr.size = code.len;
17851785 atom_ptr.output_section_index = output_section_index;
17861786
1787 try self.allocateAtom(atom_ptr, elf_file);
1787 try self.allocateAtom(atom_ptr, true, elf_file);
17881788 errdefer self.freeNavMetadata(elf_file, sym_index);
17891789
17901790 try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
......@@ -1981,17 +1981,27 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
19811981 }
19821982}
19831983
1984fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
1984pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, elf_file: *Elf) !void {
1985 const slice = elf_file.sections.slice();
1986 const shdr = &slice.items(.shdr)[atom_ptr.output_section_index];
1987 const last_atom_ref = &slice.items(.last_atom)[atom_ptr.output_section_index];
1988
1989 // FIXME:JK this only works if this atom is the only atom in the output section
1990 // In every other case, we need to redo the prev/next links
1991 if (last_atom_ref.eql(atom_ptr.ref())) last_atom_ref.* = .{};
1992
19851993 const alloc_res = try elf_file.allocateChunk(.{
19861994 .shndx = atom_ptr.output_section_index,
19871995 .size = atom_ptr.size,
19881996 .alignment = atom_ptr.alignment,
1997 .requires_padding = requires_padding,
19891998 });
19901999 atom_ptr.value = @intCast(alloc_res.value);
1991
1992 const slice = elf_file.sections.slice();
1993 const shdr = &slice.items(.shdr)[atom_ptr.output_section_index];
1994 const last_atom_ref = &slice.items(.last_atom)[atom_ptr.output_section_index];
2000 log.debug("allocated {s} at {x}\n placement {?}", .{
2001 atom_ptr.name(elf_file),
2002 atom_ptr.offset(elf_file),
2003 alloc_res.placement,
2004 });
19952005
19962006 const expand_section = if (elf_file.atom(alloc_res.placement)) |placement_atom|
19972007 placement_atom.nextAtom(elf_file) == null
......@@ -2013,12 +2023,6 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
20132023 }
20142024 shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits().?);
20152025
2016 if (self.sectionSymbol(atom_ptr.output_section_index, elf_file)) |sym| {
2017 assert(sym.atom(elf_file) == null and sym.mergeSubsection(elf_file) == null);
2018 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
2019 esym.st_size += atom_ptr.size + Elf.padToIdeal(atom_ptr.size);
2020 }
2021
20222026 // This function can also reallocate an atom.
20232027 // In this case we need to "unplug" it from its previous location before
20242028 // plugging it in to its new location.
......@@ -2037,12 +2041,8 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
20372041 atom_ptr.prev_atom_ref = .{ .index = 0, .file = 0 };
20382042 atom_ptr.next_atom_ref = .{ .index = 0, .file = 0 };
20392043 }
2040}
20412044
2042fn growAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
2043 if (!atom_ptr.alignment.check(@intCast(atom_ptr.value)) or atom_ptr.size > atom_ptr.capacity(elf_file)) {
2044 try self.allocateAtom(atom_ptr, elf_file);
2045 }
2045 log.debug(" prev {?}, next {?}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref });
20462046}
20472047
20482048pub fn resetShdrIndexes(self: *ZigObject, backlinks: anytype) void {
src/link/Elf/relocatable.zig+8-18
......@@ -394,24 +394,14 @@ fn allocateAllocSections(elf_file: *Elf) !void {
394394 shdr.sh_size = 0;
395395 const new_offset = try elf_file.findFreeSpace(needed_size, shdr.sh_addralign);
396396
397 if (elf_file.zigObjectPtr()) |zo| blk: {
398 const existing_size = for ([_]?Symbol.Index{
399 zo.text_index,
400 zo.rodata_index,
401 zo.data_relro_index,
402 zo.data_index,
403 zo.tdata_index,
404 zo.eh_frame_index,
405 }) |maybe_sym_index| {
406 const sect_sym_index = maybe_sym_index orelse continue;
407 const sect_atom_ptr = zo.symbol(sect_sym_index).atom(elf_file).?;
408 if (sect_atom_ptr.output_section_index == shndx) break sect_atom_ptr.size;
409 } else break :blk;
410 log.debug("moving {s} from 0x{x} to 0x{x}", .{
411 elf_file.getShString(shdr.sh_name),
412 shdr.sh_offset,
413 new_offset,
414 });
397 log.debug("moving {s} from 0x{x} to 0x{x}", .{
398 elf_file.getShString(shdr.sh_name),
399 shdr.sh_offset,
400 new_offset,
401 });
402
403 if (shdr.sh_offset > 0) {
404 const existing_size = elf_file.sectionSize(@intCast(shndx));
415405 const amt = try elf_file.base.file.?.copyRangeAll(
416406 shdr.sh_offset,
417407 elf_file.base.file.?,