authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-08-31 21:07:34-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 12:59:38-04:00
log00116e2c7d68d35284c8e671d7d00d59f76149bd
tree4b59ffac464e0a2a5b34c4b59bcebc0f964fdf36
parent566b6a6ec0ac2aa847fc3c8572c2404dcb67b51e

Elf2: use footer nodes to ensure space for trailing padding

This avoids needing to call `ensureMinimumSize` manually.

3 files changed, 146 insertions(+), 88 deletions(-)

src/link/Dwarf2.zig+6
......@@ -31,6 +31,7 @@ pub const Unit = struct {
3131 cie_ni: MappedFile.Node.Index.Optional,
3232 debug_info_ni: MappedFile.Node.Index.Optional,
3333 debug_info_header_ni: MappedFile.Node.Index.Optional,
34 debug_info_footer_ni: MappedFile.Node.Index.Optional,
3435 debug_line_ni: MappedFile.Node.Index.Optional,
3536 debug_line_header_ni: MappedFile.Node.Index.Optional,
3637 debug_line_header_changed: bool,
......@@ -1339,6 +1340,7 @@ pub fn initUnits(dwarf: *Dwarf, gpa: std.mem.Allocator, units_len: usize) std.me
13391340 .cie_ni = .none,
13401341 .debug_info_ni = .none,
13411342 .debug_info_header_ni = .none,
1343 .debug_info_footer_ni = .none,
13421344 .debug_line_ni = .none,
13431345 .debug_line_header_ni = .none,
13441346 .debug_line_header_changed = false,
......@@ -1944,6 +1946,7 @@ pub fn updateComptimeNav(
19441946 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
19451947 break :done;
19461948 }
1949 return;
19471950 },
19481951 .enum_type => {
19491952 const loaded_enum = ip.loadEnumType(nav_val.toIntern());
......@@ -1951,6 +1954,7 @@ pub fn updateComptimeNav(
19511954 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
19521955 break :done;
19531956 }
1957 return;
19541958 },
19551959 .union_type => {
19561960 const loaded_union = ip.loadUnionType(nav_val.toIntern());
......@@ -1958,6 +1962,7 @@ pub fn updateComptimeNav(
19581962 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
19591963 break :done;
19601964 }
1965 return;
19611966 },
19621967 .opaque_type => {
19631968 const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern());
......@@ -1965,6 +1970,7 @@ pub fn updateComptimeNav(
19651970 _ = try dwarf.const_pool.get(pt, .{ .elf2 = dwarf.lf.cast(.elf2).? }, nav_val.toIntern());
19661971 break :done;
19671972 }
1973 return;
19681974 },
19691975 .func => |func| if (func.owner_nav == nav_index and func.generic_owner == .none) {
19701976 const fi = try dwarf.getFunc(func.owner_nav);
src/link/Elf2.zig+136-88
......@@ -287,11 +287,13 @@ const Node = union(enum) {
287287 lazy_const_data: LazyMapRef.Index(.const_data),
288288
289289 debug_shared: Dwarf.SharedSection,
290 eh_frame_footer,
290291 unit_padding,
291292 unit_frame: Dwarf.Unit.Index,
292293 unit_frame_cie: Dwarf.Unit.Index,
293294 unit_debug_info: Dwarf.Unit.Index,
294295 unit_debug_info_header: Dwarf.Unit.Index,
296 unit_debug_info_footer: Dwarf.Unit.Index,
295297 unit_debug_line: Dwarf.Unit.Index,
296298 unit_debug_line_header: Dwarf.Unit.Index,
297299 unit_debug_rnglists: Dwarf.Unit.Index,
......@@ -564,8 +566,8 @@ const Section = struct {
564566 std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(reserve(sec)),
565567 };
566568 }
567 pub fn toSection(s: Index) ?std.elf.Section {
568 return switch (@backingInt(s)) {
569 pub fn toSection(shndx: Index) ?std.elf.Section {
570 return switch (@backingInt(shndx)) {
569571 std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => |sec| @intCast(sec),
570572 std.elf.SHN_LORESERVE...reserve(std.elf.SHN_LORESERVE) - 1 => null,
571573 reserve(std.elf.SHN_LORESERVE)...reserve(std.elf.SHN_HIRESERVE) => |sec| @intCast(
......@@ -574,28 +576,40 @@ const Section = struct {
574576 };
575577 }
576578
577 fn get(s: Index, elf: *Elf) *Section {
578 return &elf.shdrs.items[@backingInt(s) - 1]; // overflow means you tried to get the `.UNDEF` section
579 fn get(shndx: Index, elf: *Elf) *Section {
580 return &elf.shdrs.items[@backingInt(shndx) - 1]; // overflow means you tried to get the `.UNDEF` section
579581 }
580582
581 fn name(s: Index, elf: *Elf) String(.shstrtab) {
582 return switch (elf.shdrPtr(s)) {
583 fn name(shndx: Index, elf: *Elf) String(.shstrtab) {
584 return switch (elf.shdrPtr(shndx)) {
583585 inline else => |shdr| @fromBackingInt(elf.targetLoad(&shdr.name)),
584586 };
585587 }
586588
587 fn vaddr(s: Index, elf: *Elf) u64 {
588 return switch (elf.shdrPtr(s)) {
589 fn vaddr(shndx: Index, elf: *Elf) u64 {
590 return switch (elf.shdrPtr(shndx)) {
589591 inline else => |shdr| elf.targetLoad(&shdr.addr),
590592 };
591593 }
592594
593 fn size(s: Index, elf: *Elf) u64 {
594 return switch (elf.shdrPtr(s)) {
595 fn size(shndx: Index, elf: *Elf) u64 {
596 return switch (elf.shdrPtr(shndx)) {
595597 inline else => |shdr| elf.targetLoad(&shdr.size),
596598 };
597599 }
598600
601 fn setSize(shndx: Index, elf: *Elf, new_size: u64) void {
602 return switch (elf.shdrPtr(shndx)) {
603 inline else => |shdr| {
604 elf.targetStore(&shdr.type, switch (new_size) {
605 0 => .NULL,
606 else => .PROGBITS,
607 });
608 elf.targetStore(&shdr.size, @intCast(new_size));
609 },
610 };
611 }
612
599613 fn flags(s: Index, elf: *Elf) std.elf.SHF {
600614 return switch (elf.shdrPtr(s)) {
601615 inline else => |shdr| elf.targetLoad(&shdr.flags).shf,
......@@ -853,6 +867,15 @@ const Section = struct {
853867 }
854868 };
855869};
870fn debugFrameFooterSize(elf: *Elf, frame_format: Dwarf.Frame.Format) usize {
871 return switch (frame_format) {
872 .eh_frame => switch (elf.ehdrType()) {
873 .REL => 0,
874 .EXEC, .DYN => 4,
875 },
876 .debug_frame => 0,
877 };
878}
856879
857880const dwarf_relocs = struct {
858881 const Shared = struct {
......@@ -3324,11 +3347,13 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId {
33243347 .input_section,
33253348 .copied_global,
33263349 .debug_shared,
3350 .eh_frame_footer,
33273351 .unit_padding,
33283352 .unit_frame,
33293353 .unit_frame_cie,
33303354 .unit_debug_info,
33313355 .unit_debug_info_header,
3356 .unit_debug_info_footer,
33323357 .unit_debug_line,
33333358 .unit_debug_line_header,
33343359 .unit_debug_rnglists,
......@@ -4074,7 +4099,8 @@ fn initHeaders(
40744099 const expected_nodes_len = @as(usize, if (is_archive) 3 else 0) + // .archive, .archive_header, .archive_elf_member_header
40754100 3 + // `.elf`, `.ehdr`, and `.shdr` nodes
40764101 (shnum - 1) + // -1 because the SHN_UNDEF shdr does not have a `.section` node
4077 (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node
4102 (phnum -| 1) + // -1 because the GNU_STACK phdr does not have a `.segment` node
4103 @intFromBool(have_eh_frame and @"type" != .REL); // eh_frame_footer
40784104
40794105 try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
40804106 try elf.shdrs.ensureTotalCapacity(gpa, shnum - 1); // -1 to exclude SHN_UNDEF
......@@ -4841,7 +4867,7 @@ fn initHeaders(
48414867 }
48424868 }
48434869 if (have_eh_frame) {
4844 elf.ni.gnu_eh_frame = .wrap(elf.addNodeAssumeCapacity(
4870 const gnu_eh_frame = elf.addNodeAssumeCapacity(
48454871 try elf.ni.rodata.addFloatingChild(gpa, &elf.mf, .{
48464872 .size = @sizeOf(Dwarf.EhFrameHdr),
48474873 .alignment = .@"4",
......@@ -4849,10 +4875,11 @@ fn initHeaders(
48494875 .bubbles_moved = false,
48504876 }),
48514877 .{ .segment = phndx.gnu_eh_frame },
4852 ));
4878 );
4879 elf.ni.gnu_eh_frame = .wrap(gnu_eh_frame);
48534880 elf.phdrs.items[phndx.gnu_eh_frame] = elf.ni.gnu_eh_frame;
48544881
4855 elf.shndx.eh_frame_hdr = try elf.addSection(elf.ni.gnu_eh_frame.unwrap().?, .{
4882 elf.shndx.eh_frame_hdr = try elf.addSection(gnu_eh_frame, .{
48564883 .name = ".eh_frame_hdr",
48574884 .type = .PROGBITS,
48584885 .flags = .{ .ALLOC = true },
......@@ -4864,7 +4891,9 @@ fn initHeaders(
48644891 .flags = .{ .ALLOC = true },
48654892 .addralign = addr_align,
48664893 .node_align = elf.mf.flags.block_size,
4894 .manual_size = true,
48674895 });
4896
48684897 const eh_frame_hdr_ni = elf.shndx.eh_frame_hdr.get(elf).ni;
48694898 elf.eh_frame_hdr_first_symbol_reloc =
48704899 @fromBackingInt(@intCast(elf.symbol_relocs.items.len));
......@@ -4873,6 +4902,13 @@ fn initHeaders(
48734902 @ptrCast(@alignCast(eh_frame_hdr_ni.slice(&elf.mf))),
48744903 Symbol.Id.local(elf.shndx.eh_frame.get(elf).lsi).toTypeErased(),
48754904 );
4905 _ = elf.addNodeAssumeCapacity(
4906 try elf.shndx.eh_frame.get(elf).ni.addOnlyFooterChild(gpa, &elf.mf, .{
4907 .size = addr_align.forward(4),
4908 .alignment = addr_align,
4909 }),
4910 .eh_frame_footer,
4911 );
48764912 }
48774913
48784914 // Populate reserved GOT words.
......@@ -5057,6 +5093,7 @@ fn initHeaders(
50575093 .flags = .{ .ALLOC = true },
50585094 .addralign = addr_align,
50595095 .node_align = elf.mf.flags.block_size,
5096 .manual_size = true,
50605097 });
50615098 }
50625099 if (elf.ni.tls.unwrap()) |tls_segment_ni| elf.shndx.tdata = try elf.addSection(tls_segment_ni, .{
......@@ -5072,6 +5109,7 @@ fn initHeaders(
50725109 .name = ".debug_frame",
50735110 .addralign = addr_align,
50745111 .node_align = elf.mf.flags.block_size,
5112 .manual_size = true,
50755113 });
50765114 elf.shndx.debug_info = try elf.addSection(elf.ni.elf, .{
50775115 .name = ".debug_info",
......@@ -5189,14 +5227,19 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
51895227 .lazy_code,
51905228 .lazy_const_data,
51915229 .debug_shared,
5230 .eh_frame_footer,
51925231 .unit_padding,
51935232 .unit_frame,
51945233 .unit_debug_info,
51955234 .unit_debug_line,
51965235 .unit_debug_rnglists,
5197 => elf.getNode(ni.parent(&elf.mf).unwrap().?).section,
5236 => switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) {
5237 else => unreachable,
5238 .section, .section_manual_size => |shndx| shndx,
5239 },
51985240 .unit_frame_cie,
51995241 .unit_debug_info_header,
5242 .unit_debug_info_footer,
52005243 .unit_debug_line_header,
52015244 .const_debug_info,
52025245 .global_debug_info,
......@@ -5204,7 +5247,10 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index {
52045247 .func_debug_info,
52055248 .func_debug_line,
52065249 .decl_debug_info,
5207 => elf.getNode(ni.parent(&elf.mf).unwrap().?.parent(&elf.mf).unwrap().?).section,
5250 => switch (elf.getNode(ni.parent(&elf.mf).unwrap().?.parent(&elf.mf).unwrap().?)) {
5251 else => unreachable,
5252 .section, .section_manual_size => |shndx| shndx,
5253 },
52085254 };
52095255}
52105256fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
......@@ -5228,11 +5274,13 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
52285274 .lazy_const_data,
52295275 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
52305276 .debug_shared,
5277 .eh_frame_footer,
52315278 .unit_padding,
52325279 .unit_frame,
52335280 .unit_frame_cie,
52345281 .unit_debug_info,
52355282 .unit_debug_info_header,
5283 .unit_debug_info_footer,
52365284 .unit_debug_line,
52375285 .unit_debug_line_header,
52385286 .unit_debug_rnglists,
......@@ -5266,14 +5314,14 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
52665314 .lazy_code,
52675315 .lazy_const_data,
52685316 => |i| Symbol.Id.local(i.symbol(elf)).value(elf),
5269 .debug_shared, .unit_padding => unreachable,
5317 .debug_shared, .eh_frame_footer, .unit_padding => unreachable,
52705318 .unit_frame, .unit_debug_info, .unit_debug_line => {
5271 const section_ni = parent_ni.parent(&elf.mf).unwrap().?;
52725319 const section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
5273 break :parent_vaddr elf.getNode(section_ni).section.vaddr(elf) + section_offset;
5320 break :parent_vaddr elf.getNodeShndx(parent_ni).vaddr(elf) + section_offset;
52745321 },
52755322 .unit_frame_cie,
52765323 .unit_debug_info_header,
5324 .unit_debug_info_footer,
52775325 .unit_debug_line_header,
52785326 .unit_debug_rnglists,
52795327 .const_debug_info,
......@@ -5303,13 +5351,14 @@ fn computeNodeSectionOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 {
53035351 .section, .section_manual_size => 0,
53045352 .input_section, .copied_global => unreachable,
53055353 .nav, .uav, .lazy_code, .lazy_const_data => unreachable,
5306 .debug_shared, .unit_padding => unreachable,
5354 .debug_shared, .eh_frame_footer, .unit_padding => unreachable,
53075355 .unit_frame, .unit_debug_info, .unit_debug_line => {
53085356 const parent_section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
53095357 break :parent_section_offset parent_section_offset;
53105358 },
53115359 .unit_frame_cie,
53125360 .unit_debug_info_header,
5361 .unit_debug_info_footer,
53135362 .unit_debug_line_header,
53145363 .unit_debug_rnglists,
53155364 .const_debug_info,
......@@ -5351,6 +5400,7 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
53515400 .segment,
53525401 .copied_global,
53535402 .debug_shared,
5403 .eh_frame_footer,
53545404 .unit_padding,
53555405 .unit_frame,
53565406 .unit_frame_cie,
......@@ -5378,10 +5428,11 @@ pub fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void {
53785428 .unit_debug_info_header => |ui| .{
53795429 .first_node_reloc = &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_node_reloc,
53805430 },
5431 .unit_debug_info_footer => unreachable, // cannot contain relocs
53815432 .unit_debug_line_header => |ui| .{
53825433 .first_node_reloc = &elf.dwarf_units[@backingInt(ui)].debug_line_header_first_node_reloc,
53835434 },
5384 .unit_debug_rnglists => unreachable, // unsupported
5435 .unit_debug_rnglists => unreachable, // cannot contain relocs
53855436 .const_debug_info => |cpi| .{
53865437 .first_symbol_reloc = &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_symbol_reloc,
53875438 .first_node_reloc = &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_node_reloc,
......@@ -6049,7 +6100,7 @@ fn uavMapIndex(
60496100 elf.pending_uavs.appendAssumeCapacity(umi);
60506101 } else {
60516102 const node = uav_gop.value_ptr.lsi.index().ptr(elf).node.unwrap().?;
6052 const shndx = elf.getNode(node.parent(&elf.mf).unwrap().?).section;
6103 const shndx = elf.getNodeShndx(node);
60536104 try shndx.ensureAligned(elf, resolved_align);
60546105 if (resolved_align.order(node.alignment(&elf.mf)).compare(.gt)) {
60556106 try node.realign(gpa, &elf.mf, resolved_align);
......@@ -7261,13 +7312,17 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
72617312 unit.debug_info_ni = .wrap(debug_info_ni);
72627313 break :debug_info_ni debug_info_ni;
72637314 };
7264
72657315 if (unit.debug_info_header_ni == .none) unit.debug_info_header_ni = .wrap(
72667316 elf.addNodeAssumeCapacity(try debug_info_ni.addOnlyHeaderChild(gpa, &elf.mf, .{
72677317 .next_moved = true,
72687318 .enable_next_moved = true,
72697319 }), .{ .unit_debug_info_header = ui }),
72707320 );
7321 if (unit.debug_info_footer_ni == .none) unit.debug_info_footer_ni = .wrap(
7322 elf.addNodeAssumeCapacity(try debug_info_ni.addOnlyFooterChild(gpa, &elf.mf, .{
7323 .size = comptime Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) * 2,
7324 }), .{ .unit_debug_info_footer = ui }),
7325 );
72717326 },
72727327 }
72737328 switch (elf.shndx.debug_line) {
......@@ -7284,7 +7339,6 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void {
72847339 unit.debug_line_ni = .wrap(debug_line_ni);
72857340 break :debug_line_ni debug_line_ni;
72867341 };
7287
72887342 if (unit.debug_line_header_ni == .none) unit.debug_line_header_ni = .wrap(
72897343 elf.addNodeAssumeCapacity(try debug_line_ni.addOnlyHeaderChild(gpa, &elf.mf, .{
72907344 // Idle tasks are going to try to keep this up to date before we are able to
......@@ -8264,11 +8318,13 @@ fn addGotRelocAssumeCapacity(
82648318 .segment,
82658319 .copied_global,
82668320 .debug_shared,
8321 .eh_frame_footer,
82678322 .unit_padding,
82688323 .unit_frame,
82698324 .unit_frame_cie,
82708325 .unit_debug_info,
82718326 .unit_debug_info_header,
8327 .unit_debug_info_footer,
82728328 .unit_debug_line,
82738329 .unit_debug_line_header,
82748330 .unit_debug_rnglists,
......@@ -8601,6 +8657,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
86018657
86028658 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.
86038659 try elf.genPending(pt);
8660 try elf.dwarf.const_pool.flushPending(pt, .{ .elf2 = elf });
86048661}
86058662
86068663pub fn updateContainerType(
......@@ -8932,33 +8989,12 @@ fn updateFuncInner(
89328989 switch (elf.symPtr(nmi.symbol(elf).index())) {
89338990 inline else => |sym| elf.targetStore(&sym.size, @intCast(func_length)),
89348991 }
8935 debug_output: switch (debug_output) {
8992 switch (debug_output) {
89368993 .dwarf => unreachable,
8937 .eh_frame => |wip_nav| {
8938 wip_nav.finishDebugFrameFde(func_length);
8939 const frame_ni = switch (wip_nav.frame_format) {
8940 .debug_frame => elf.shndx.debug_frame,
8941 .eh_frame => elf.shndx.eh_frame,
8942 }.get(elf).ni;
8943 switch (wip_nav.frame_format) {
8944 .debug_frame => {},
8945 .eh_frame => {
8946 const last_offset, const last_size =
8947 frame_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);
8948 try frame_ni.ensureMinimumSize(gpa, &elf.mf, last_offset + last_size + 4);
8949 },
8950 }
8951 },
8994 .eh_frame => |wip_nav| wip_nav.finishDebugFrameFde(func_length),
89528995 .dwarf2 => |debug| {
89538996 try debug.finishFunc(func_length);
89548997 const unit = debug.wip_nav.unit.get(debug.wip_nav.dwarf);
8955 {
8956 const debug_info_ni = unit.debug_info_ni.unwrap().?;
8957 const last_offset, const last_size =
8958 debug_info_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf);
8959 try debug_info_ni.ensureMinimumSize(gpa, &elf.mf, last_offset + last_size +
8960 comptime Dwarf.uleb128Size(@backingInt(Dwarf.AbbrevCode.null)) * 2);
8961 }
89628998 {
89638999 var dr_nw: MappedFile.Node.Writer = undefined;
89649000 unit.debug_rnglists_ni.unwrap().?.writer(gpa, &elf.mf, &dr_nw);
......@@ -8983,7 +9019,7 @@ fn updateFuncInner(
89839019 {},
89849020 );
89859021 }
8986 continue :debug_output .{ .eh_frame = &debug.wip_nav };
9022 debug.wip_nav.finishDebugFrameFde(func_length);
89879023 },
89889024 .none => {},
89899025 }
......@@ -8991,6 +9027,7 @@ fn updateFuncInner(
89919027
89929028 // The NAV's node is done---now generate any UAVs or lazy code/data which the NAV needs.
89939029 try elf.genPending(pt);
9030 try elf.dwarf.const_pool.flushPending(pt, .{ .elf2 = elf });
89949031}
89959032
89969033pub fn updateLineNumber(
......@@ -9297,7 +9334,7 @@ fn idleProgNode(
92979334 break :name std.mem.print(&name, "{f}{f} {s}", .{
92989335 ii.path(elf).fmtEscapeString(),
92999336 fmtMemberString(ii.member(elf)),
9300 elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf),
9337 elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf),
93019338 }) catch &name;
93029339 },
93039340 .nav => |nmi| {
......@@ -9316,6 +9353,7 @@ fn idleProgNode(
93169353 .unit_frame_cie,
93179354 .unit_debug_info,
93189355 .unit_debug_info_header,
9356 .unit_debug_info_footer,
93199357 .unit_debug_line,
93209358 .unit_debug_line_header,
93219359 .unit_debug_rnglists,
......@@ -9323,7 +9361,11 @@ fn idleProgNode(
93239361 switch (tag) {
93249362 else => unreachable,
93259363 .unit_frame, .unit_frame_cie => "unwind",
9326 .unit_debug_info, .unit_debug_info_header, .unit_debug_rnglists => "debug",
9364 .unit_debug_info,
9365 .unit_debug_info_header,
9366 .unit_debug_info_footer,
9367 .unit_debug_rnglists,
9368 => "debug",
93279369 .unit_debug_line, .unit_debug_line_header => "line",
93289370 },
93299371 ui.mod(&elf.dwarf).fully_qualified_name,
......@@ -9393,7 +9435,6 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) link.Error!void {
93939435 elf.resetNodeRelocs(debug_info_ni);
93949436 try elf.dwarf.genDecl(pt, &di_nw, pending.instance_val);
93959437 }
9396 try elf.dwarf.const_pool.flushPending(pt, .{ .elf2 = elf });
93979438 },
93989439 .code_view => unreachable,
93999440 }
......@@ -9555,7 +9596,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
95559596 fr.seekTo(file_loc.offset) catch |err| switch (err) {
95569597 error.Canceled => |e| return e,
95579598 else => |e| return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{
9558 elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf),
9599 elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf),
95599600 path.fmtEscapeString(),
95609601 fmtMemberString(ii.member(elf)),
95619602 e,
......@@ -9566,7 +9607,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
95669607 defer nw.deinit();
95679608 const n_bytes = nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) catch |err| switch (err) {
95689609 error.ReadFailed => return diags.fail("failed to read input section '{s}' from \"{f}{f}\": {t}", .{
9569 elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf),
9610 elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf),
95709611 path.fmtEscapeString(),
95719612 fmtMemberString(ii.member(elf)),
95729613 fr.err orelse (fr.seek_err orelse fr.size_err.?),
......@@ -9574,7 +9615,7 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void {
95749615 error.WriteFailed => return nw.err.?,
95759616 };
95769617 if (n_bytes != file_loc.size) return diags.fail("failed to read input section '{s}' from \"{f}{f}\": unexpected eof", .{
9577 elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf),
9618 elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf),
95789619 path.fmtEscapeString(),
95799620 fmtMemberString(ii.member(elf)),
95809621 });
......@@ -9797,7 +9838,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
97979838 target_ri = target_reloc.next;
97989839 }
97999840 },
9800 .unit_padding, .unit_frame, .unit_debug_info, .unit_debug_line => {},
9841 .eh_frame_footer, .unit_padding, .unit_frame, .unit_debug_info, .unit_debug_line => {},
98019842 .unit_frame_cie => |ui| {
98029843 const target_section_offset = elf.computeNodeSectionOffset(ni);
98039844 var target_ri = elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc;
......@@ -9822,6 +9863,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
98229863 .first_node_reloc = dwarf_unit.debug_info_header_first_node_reloc,
98239864 });
98249865 },
9866 .unit_debug_info_footer => {},
98259867 .unit_debug_line_header => |ui| {
98269868 const dwarf_unit = &elf.dwarf_units[@backingInt(ui)];
98279869 const target_section_offset = elf.computeNodeSectionOffset(ni);
......@@ -10179,11 +10221,13 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
1017910221 .lazy_code,
1018010222 .lazy_const_data,
1018110223 .debug_shared,
10224 .eh_frame_footer,
1018210225 .unit_padding,
1018310226 .unit_frame,
1018410227 .unit_frame_cie,
1018510228 .unit_debug_info,
1018610229 .unit_debug_info_header,
10230 .unit_debug_info_footer,
1018710231 .unit_debug_line,
1018810232 .unit_debug_line_header,
1018910233 .unit_debug_rnglists,
......@@ -10219,6 +10263,8 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1021910263 .lazy_code,
1022010264 .lazy_const_data,
1022110265 .debug_shared,
10266 .eh_frame_footer,
10267 .unit_debug_info_footer,
1022210268 => unreachable,
1022310269
1022410270 .archive_header => {
......@@ -10261,7 +10307,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1026110307 => |_, tag| {
1026210308 const offset, const size = ni.location(&elf.mf).resolve(&elf.mf);
1026310309 const parent_ni = ni.parent(&elf.mf).unwrap().?;
10264 const slice = if (ni.next(&elf.mf).unwrap()) |next_ni| slice: {
10310 const slice = if (ni.next(&elf.mf).ifPos(&elf.mf, .floating).unwrap()) |next_ni| slice: {
1026510311 const parent_slice = parent_ni.slicePadding(&elf.mf);
1026610312 const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf);
1026710313 break :slice parent_slice[@intCast(offset)..@intCast(next_offset)];
......@@ -10269,40 +10315,35 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1026910315 else => unreachable,
1027010316 .unit_padding, .unit_debug_rnglists => {
1027110317 const parent_slice = parent_ni.slicePadding(&elf.mf);
10272 switch (elf.getNode(parent_ni).section.debugFrameFormat(elf) orelse .debug_frame) {
10273 .eh_frame => {
10274 const end = parent_slice.len - 4;
10275 std.mem.writeInt(u32, parent_slice[end..][0..4], 0, elf.dwarf.endian);
10276 break :slice parent_slice[@intCast(offset)..end];
10277 },
10278 .debug_frame => break :slice parent_slice[@intCast(offset)..],
10279 }
10318 const frame_shndx = elf.getNodeShndx(parent_ni);
10319 const frame_format = frame_shndx.debugFrameFormat(elf) orelse
10320 break :slice parent_slice[@intCast(offset)..];
10321 const footer_size = elf.debugFrameFooterSize(frame_format);
10322 @memset(parent_slice[@intCast(offset + size)..][0..footer_size], 0);
10323 frame_shndx.setSize(elf, offset + size + footer_size);
10324 break :slice parent_slice[@intCast(offset)..][0..@intCast(size)];
1028010325 },
1028110326 .unit_frame_cie, .func_frame_fde => {
1028210327 const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
1028310328 const frame_ni = parent_ni.parent(&elf.mf).unwrap().?;
1028410329 const frame_slice = frame_ni.slicePadding(&elf.mf);
10285 const frame_format = elf.getNode(frame_ni).section.debugFrameFormat(elf);
10286 const slice = frame_slice[@intCast(parent_offset + offset)..if (parent_ni.next(&elf.mf).unwrap()) |parent_next_ni| frame_end: {
10330 const frame_shndx = elf.getNode(frame_ni).section_manual_size;
10331 const frame_format = frame_shndx.debugFrameFormat(elf).?;
10332 if (parent_ni.next(&elf.mf).ifPos(&elf.mf, .floating).unwrap()) |parent_next_ni| {
1028710333 const parent_next_offset, _ = parent_next_ni.location(&elf.mf).resolve(&elf.mf);
10288 break :frame_end @intCast(parent_next_offset);
10289 } else frame_end: switch (frame_format orelse .debug_frame) {
10290 .eh_frame => {
10291 const frame_end = frame_slice.len - 4;
10292 std.mem.writeInt(u32, frame_slice[frame_end..][0..4], 0, elf.dwarf.endian);
10293 break :frame_end frame_end;
10294 },
10295 .debug_frame => frame_slice.len,
10296 }];
10297 var fw: Io.Writer = .fixed(slice[@intCast(size)..]);
10298 (if (frame_format) |format|
10299 elf.dwarf.genDebugFrameCie(&fw, null, format)
10300 else
10301 elf.dwarf.genUnitPadding(&fw)) catch |err| switch (err) {
10302 error.WriteFailed => break :slice slice,
10303 };
10304 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
10305 break :slice slice[0..@intCast(size)];
10334 const slice =
10335 frame_slice[@intCast(parent_offset + offset)..@intCast(parent_next_offset)];
10336 var fw: Io.Writer = .fixed(slice[@intCast(size)..]);
10337 elf.dwarf.genDebugFrameCie(&fw, null, frame_format) catch |err| switch (err) {
10338 error.WriteFailed => break :slice slice,
10339 };
10340 elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len);
10341 break :slice slice[0..@intCast(size)];
10342 }
10343 const footer_size = elf.debugFrameFooterSize(frame_format);
10344 @memset(frame_slice[@intCast(parent_offset + offset + size)..][0..footer_size], 0);
10345 frame_shndx.setSize(elf, parent_offset + offset + size + footer_size);
10346 break :slice frame_slice[@intCast(parent_offset + offset)..][0..@intCast(size)];
1030610347 },
1030710348 .unit_debug_info_header,
1030810349 .unit_debug_line_header,
......@@ -10315,7 +10356,9 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1031510356 const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf);
1031610357 const debug_ni = parent_ni.parent(&elf.mf).unwrap().?;
1031710358 const debug_slice = debug_ni.slicePadding(&elf.mf);
10318 var fw: Io.Writer = .fixed(debug_slice[@intCast(parent_offset)..if (parent_ni.next(&elf.mf).unwrap()) |parent_next_ni| debug_end: {
10359 var fw: Io.Writer = .fixed(debug_slice[@intCast(parent_offset)..if (parent_ni
10360 .next(&elf.mf).ifPos(&elf.mf, .floating).unwrap()) |parent_next_ni|
10361 debug_end: {
1031910362 const parent_next_offset, _ = parent_next_ni.location(&elf.mf).resolve(&elf.mf);
1032010363 break :debug_end @intCast(parent_next_offset);
1032110364 } else debug_slice.len]);
......@@ -10383,8 +10426,12 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!
1038310426 },
1038410427 }
1038510428 },
10386 .unit_frame, .unit_debug_info, .unit_debug_line => if (ni.last(&elf.mf).unwrap()) |last_ni|
10387 try last_ni.nextMoved(elf.base.comp.gpa, &elf.mf),
10429 .unit_frame, .unit_debug_info, .unit_debug_line => {
10430 var last_ni = ni.last(&elf.mf).unwrap() orelse return;
10431 while (last_ni.position(&elf.mf) == .footer)
10432 last_ni = last_ni.prev(&elf.mf).unwrap() orelse return;
10433 try last_ni.nextMoved(elf.base.comp.gpa, &elf.mf);
10434 },
1038810435 }
1038910436}
1039010437
......@@ -10877,7 +10924,7 @@ pub fn printNode(
1087710924 try w.print("({f}{f}, {s})", .{
1087810925 ii.path(elf).fmtEscapeString(),
1087910926 fmtMemberString(ii.member(elf)),
10880 elf.getNode(isi.node(elf).parent(&elf.mf).unwrap().?).section.name(elf).slice(elf),
10927 elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf),
1088110928 });
1088210929 },
1088310930 .copied_global => |name| try w.print("(copy:{s})", .{name.slice(elf)}),
......@@ -10909,6 +10956,7 @@ pub fn printNode(
1090910956 .unit_frame_cie,
1091010957 .unit_debug_info,
1091110958 .unit_debug_info_header,
10959 .unit_debug_info_footer,
1091210960 .unit_debug_line,
1091310961 .unit_debug_line_header,
1091410962 .unit_debug_rnglists,
src/link/MappedFile.zig+4
......@@ -355,6 +355,10 @@ pub const Node = extern struct {
355355 assert(oi != .none);
356356 return oi;
357357 }
358
359 pub fn ifPos(oi: Optional, mf: *const MappedFile, pos: Node.Position) Optional {
360 return if ((oi.unwrap() orelse return .none).position(mf) == pos) oi else .none;
361 }
358362 };
359363
360364 fn get(ni: Node.Index, mf: *const MappedFile) *Node {