authorgravatar for abbix@riseup.netlg <abbix@riseup.net> 2026-09-01 17:18:16-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-16 12:41:30+01:00
log7a6eb167bcde3ed8fdc81f88bd683b30b6290e45
tree4e5ececf03ca85a23941bf73ad2c9d1fb253c82e
parente03ff669f56421a13760356c9fbb979c74c65622
signature Commit is signed but in an unrecognized format.

Elf2: clean things up

As per review: - Don't allow non-bss NOBITS sections (which simplifies the code quite a bit). - Remove duplicated and superfluous code. - General style improvements.

1 files changed, 102 insertions(+), 101 deletions(-)

src/link/Elf2.zig+102-101
...@@ -6381,11 +6381,11 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {...@@ -6381,11 +6381,11 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
6381 };6381 };
6382}6382}
63836383
6384fn tbssSegmentOffset(elf: *Elf) u64 {6384fn tbssBaseOffset(elf: *Elf) u64 {
6385 const tbss_addr = elf.shndx.tbss.vaddr(elf);6385 const tbss_addr = elf.shndx.tbss.vaddr(elf);
63866386
6387 // Hasn't been laid out yet.6387 // Hasn't been laid out yet.
6388 if (tbss_addr == 0) return 0;6388 if (tbss_addr == 0 or elf.ehdrType() == .REL) return 0;
63896389
6390 const tls_ni = elf.ni.tls.unwrap().?;6390 const tls_ni = elf.ni.tls.unwrap().?;
6391 const tls_phndx = elf.getNode(tls_ni).segment;6391 const tls_phndx = elf.getNode(tls_ni).segment;
...@@ -7016,6 +7016,7 @@ fn mapInputSection(elf: *Elf, opts: struct {...@@ -7016,6 +7016,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
7016 StripSection,7016 StripSection,
7017 SectionFlagsConflict,7017 SectionFlagsConflict,
7018 SectionTypeConflict,7018 SectionTypeConflict,
7019 UnsupportedNobitsSection,
7019})!Section.Index {7020})!Section.Index {
7020 const gpa = elf.base.comp.gpa;7021 const gpa = elf.base.comp.gpa;
7021 if (opts.flags.INFO_LINK or7022 if (opts.flags.INFO_LINK or
...@@ -7073,7 +7074,8 @@ fn mapInputSection(elf: *Elf, opts: struct {...@@ -7073,7 +7074,8 @@ fn mapInputSection(elf: *Elf, opts: struct {
7073 .name = name,7074 .name = name,
7074 .type = switch (opts.type) {7075 .type = switch (opts.type) {
7075 .PROGBITS => .NULL, // size is 07076 .PROGBITS => .NULL, // size is 0
7076 .NOBITS => .NOBITS,7077 .X86_64_UNWIND => .X86_64_UNWIND,
7078 .NOBITS => return error.UnsupportedNobitsSection,
7077 else => unreachable,7079 else => unreachable,
7078 },7080 },
7079 .flags = flags: {7081 .flags = flags: {
...@@ -7099,7 +7101,7 @@ fn mapInputSection(elf: *Elf, opts: struct {...@@ -7099,7 +7101,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
7099 const existing_type = elf.targetLoad(&shdr.type);7101 const existing_type = elf.targetLoad(&shdr.type);
71007102
7101 switch (opts.type) {7103 switch (opts.type) {
7102 .PROGBITS => switch (existing_type) {7104 .PROGBITS, .X86_64_UNWIND => switch (existing_type) {
7103 .NULL, .PROGBITS, .X86_64_UNWIND => {},7105 .NULL, .PROGBITS, .X86_64_UNWIND => {},
7104 else => return error.SectionTypeConflict,7106 else => return error.SectionTypeConflict,
7105 },7107 },
...@@ -7157,6 +7159,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node...@@ -7157,6 +7159,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node
7157 error.UnsupportedSectionFlags,7159 error.UnsupportedSectionFlags,
7158 error.SectionTypeConflict,7160 error.SectionTypeConflict,
7159 error.SectionFlagsConflict,7161 error.SectionFlagsConflict,
7162 error.UnsupportedNobitsSection,
7160 => {}, // fall back to default behavior below7163 => {}, // fall back to default behavior below
71617164
7162 }7165 }
...@@ -7548,16 +7551,15 @@ fn loadObject(...@@ -7548,16 +7551,15 @@ fn loadObject(
75487551
7549 const sections = try gpa.alloc(struct {7552 const sections = try gpa.alloc(struct {
7550 shdr: ElfN.Shdr,7553 shdr: ElfN.Shdr,
7551 placement: ?union(enum) {7554 placement: union(enum) {
7552 progbits: InputSection.Index,7555 progbits: InputSection.Index,
7553 bss: struct {7556 bss: struct {
7554 shndx: Section.Index,
7555 offset: u64,7557 offset: u64,
7556 },7558 },
7557 tbss: struct {7559 tbss: struct {
7558 shndx: Section.Index,
7559 offset: u64,7560 offset: u64,
7560 },7561 },
7562 none,
7561 },7563 },
7562 }, ehdr.shnum);7564 }, ehdr.shnum);
75637565
...@@ -7566,7 +7568,7 @@ fn loadObject(...@@ -7566,7 +7568,7 @@ fn loadObject(
7566 for (sections) |*section| {7568 for (sections) |*section| {
7567 section.* = .{7569 section.* = .{
7568 .shdr = try r.peekStruct(ElfN.Shdr, target_endian),7570 .shdr = try r.peekStruct(ElfN.Shdr, target_endian),
7569 .placement = null,7571 .placement = .none,
7570 };7572 };
7571 try r.discardAll(ehdr.shentsize);7573 try r.discardAll(ehdr.shentsize);
7572 switch (section.shdr.type) {7574 switch (section.shdr.type) {
...@@ -7594,10 +7596,6 @@ fn loadObject(...@@ -7594,10 +7596,6 @@ fn loadObject(
7594 const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0);7596 const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0);
7595 if (!comp.config.any_unwind_tables and std.mem.eql(u8, name, ".eh_frame")) continue;7597 if (!comp.config.any_unwind_tables and std.mem.eql(u8, name, ".eh_frame")) continue;
7596 const sect_type = section.shdr.type;7598 const sect_type = section.shdr.type;
7597 const is_bss = (std.mem.startsWith(u8, name, ".bss.") or
7598 std.mem.eql(u8, name, ".bss")) and sect_type == .NOBITS;
7599 const is_tbss = (std.mem.startsWith(u8, name, ".tbss.") or
7600 std.mem.eql(u8, name, ".tbss")) and sect_type == .NOBITS;
7601 const opts: struct {7599 const opts: struct {
7602 shndx: Section.Index,7600 shndx: Section.Index,
7603 node_fixed: bool,7601 node_fixed: bool,
...@@ -7608,7 +7606,7 @@ fn loadObject(...@@ -7608,7 +7606,7 @@ fn loadObject(
7608 .name = name,7606 .name = name,
7609 .flags = section.shdr.flags.shf,7607 .flags = section.shdr.flags.shf,
7610 .entsize = section.shdr.entsize,7608 .entsize = section.shdr.entsize,
7611 .type = if (is_bss or is_tbss) .NOBITS else .PROGBITS,7609 .type = section.shdr.type,
7612 }) catch |err| switch (err) {7610 }) catch |err| switch (err) {
7613 else => |e| return e,7611 else => |e| return e,
7614 error.StripSection => continue,7612 error.StripSection => continue,
...@@ -7641,6 +7639,11 @@ fn loadObject(...@@ -7641,6 +7639,11 @@ fn loadObject(
7641 "flags of section '{s}' conflict with other inputs",7639 "flags of section '{s}' conflict with other inputs",
7642 .{name},7640 .{name},
7643 ),7641 ),
7642 error.UnsupportedNobitsSection => return diags.failParse(
7643 path,
7644 "unsupported section type SHT_NOBITS for non-bss section '{s}'",
7645 .{name},
7646 ),
7644 };7647 };
7645 if (section.shdr.flags.shf.COMPRESSED) {7648 if (section.shdr.flags.shf.COMPRESSED) {
7646 // SHF_COMPRESSED is only allowed on non-alloc sections.7649 // SHF_COMPRESSED is only allowed on non-alloc sections.
...@@ -7664,8 +7667,7 @@ fn loadObject(...@@ -7664,8 +7667,7 @@ fn loadObject(
7664 shndx != .rodata and7667 shndx != .rodata and
7665 shndx != .data and7668 shndx != .data and
7666 shndx != .data_rel_ro and7669 shndx != .data_rel_ro and
7667 shndx != elf.shndx.tdata and7670 shndx != elf.shndx.tdata,
7668 shndx != elf.shndx.tbss,
7669 };7671 };
7670 },7672 },
7671 inline .INIT_ARRAY, .FINI_ARRAY, .PREINIT_ARRAY => |@"type"| .{7673 inline .INIT_ARRAY, .FINI_ARRAY, .PREINIT_ARRAY => |@"type"| .{
...@@ -7711,35 +7713,25 @@ fn loadObject(...@@ -7711,35 +7713,25 @@ fn loadObject(
77117713
7712 try opts.shndx.ensureAligned(elf, need_align);7714 try opts.shndx.ensureAligned(elf, need_align);
77137715
7714 if (is_bss or is_tbss) {7716 if (sect_type == .NOBITS) {
7715 const offset: u64 = offset: {7717 const offset: u64 = switch (elf.shdrPtr(opts.shndx)) {
7716 switch (elf.shdrPtr(opts.shndx)) {7718 inline else => |shdr| offset: {
7717 inline else => |shdr| {7719 // Bump our BSS output section size
7718 // Bump our BSS output section size.7720 const old_size: u64 = elf.targetLoad(&shdr.size);
7719 const old_size: u64 = elf.targetLoad(&shdr.size);7721 const offset = need_align.forward(old_size);
7720 const offset = need_align.forward(old_size);7722 elf.targetStore(&shdr.size, @intCast(offset + section.shdr.size));
7721 const new_size = offset + section.shdr.size;7723 break :offset offset;
7722 elf.targetStore(&shdr.size, @intCast(new_size));7724 },
7723 break :offset offset;
7724 },
7725 }
7726 };7725 };
77277726
7728 if (is_bss) {7727 if (opts.shndx == elf.shndx.bss) {
7729 section.placement = .{ .bss = .{7728 section.placement = .{ .bss = .{ .offset = offset } };
7730 .shndx = opts.shndx,
7731 .offset = offset,
7732 } };
7733 input_has_bss = true;7729 input_has_bss = true;
7734 continue;7730 } else if (opts.shndx == elf.shndx.tbss) {
7735 }7731 section.placement = .{ .tbss = .{ .offset = offset } };
7736
7737 if (is_tbss) {
7738 section.placement = .{ .tbss = .{
7739 .shndx = opts.shndx,
7740 .offset = offset,
7741 } };
7742 input_has_tbss = true;7732 input_has_tbss = true;
7733 } else {
7734 unreachable;
7743 }7735 }
77447736
7745 continue;7737 continue;
...@@ -7861,8 +7853,9 @@ fn loadObject(...@@ -7861,8 +7853,9 @@ fn loadObject(
7861 },7853 },
7862 };7854 };
78637855
7864 const placement =7856 const placement = sections[input_sym.shndx].placement;
7865 sections[input_sym.shndx].placement orelse continue;7857
7858 if (placement == .none) continue;
78667859
7867 const symbol_oni: MappedFile.Node.Index.Optional, const output_shndx, const symbol_value = switch (placement) {7860 const symbol_oni: MappedFile.Node.Index.Optional, const output_shndx, const symbol_value = switch (placement) {
7868 .progbits => |isi| .{7861 .progbits => |isi| .{
...@@ -7871,20 +7864,16 @@ fn loadObject(...@@ -7871,20 +7864,16 @@ fn loadObject(
7871 input_sym.value,7864 input_sym.value,
7872 },7865 },
7873 .bss => |bss| .{7866 .bss => |bss| .{
7874 bss.shndx.get(elf).ni,7867 .none,
7875 bss.shndx,7868 elf.shndx.bss,
7876 bss.shndx.vaddr(elf) + bss.offset + input_sym.value,7869 elf.shndx.bss.vaddr(elf) + bss.offset + input_sym.value,
7877 },7870 },
7878 .tbss => |tbss| .{7871 .tbss => |tbss| .{
7879 tbss.shndx.get(elf).ni,7872 .none,
7880 tbss.shndx,7873 elf.shndx.tbss,
7881 switch (elf.ehdrType()) {7874 elf.tbssBaseOffset() + tbss.offset + input_sym.value,
7882 .REL => tbss.offset + input_sym.value,
7883 .EXEC, .DYN => elf.tbssSegmentOffset() +
7884 tbss.offset +
7885 input_sym.value,
7886 },
7887 },7875 },
7876 .none => unreachable,
7888 };7877 };
78897878
7890 switch (input_sym.info.bind) {7879 switch (input_sym.info.bind) {
...@@ -7949,7 +7938,8 @@ fn loadObject(...@@ -7949,7 +7938,8 @@ fn loadObject(
7949 return diags.failParse(path, "unsupported rel entsize", .{});7938 return diags.failParse(path, "unsupported rel entsize", .{});
79507939
7951 const loc_sec = &sections[rel_sec.shdr.info];7940 const loc_sec = &sections[rel_sec.shdr.info];
7952 const loc_node = switch (loc_sec.placement orelse continue) {7941 const loc_node = switch (loc_sec.placement) {
7942 .none => continue,
7953 .progbits => |isi| isi.node(elf),7943 .progbits => |isi| isi.node(elf),
7954 .bss, .tbss => return diags.failParse(7944 .bss, .tbss => return diags.failParse(
7955 path,7945 path,
...@@ -9007,6 +8997,8 @@ fn flushDynamic(elf: *Elf) void {...@@ -9007,6 +8997,8 @@ fn flushDynamic(elf: *Elf) void {
90078997
9008fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {8998fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
9009 name: []const u8 = "",8999 name: []const u8 = "",
9000 /// If this is `.NOBITS`, then the section's address is initialized to 0, and it is the caller's
9001 /// responsibility to populate it.
9010 type: std.elf.SHT = .NULL,9002 type: std.elf.SHT = .NULL,
9011 flags: std.elf.SHF = .{},9003 flags: std.elf.SHF = .{},
9012 size: std.elf.Xword = 0,9004 size: std.elf.Xword = 0,
...@@ -11229,7 +11221,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -11229,7 +11221,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
11229 },11221 },
1123011222
11231 .TLS => {11223 .TLS => {
11232 const tbss_base = elf.tbssSegmentOffset();11224 const tbss_base = elf.tbssBaseOffset();
11233 const new_vaddr = elf.computeNodeVAddr(ni);11225 const new_vaddr = elf.computeNodeVAddr(ni);
11234 const tls_offset = elf.targetLoad(&ph.offset);11226 const tls_offset = elf.targetLoad(&ph.offset);
11235 const tls_filesz = elf.targetLoad(&ph.filesz);11227 const tls_filesz = elf.targetLoad(&ph.filesz);
...@@ -11237,16 +11229,17 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void...@@ -11237,16 +11229,17 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void
11237 elf.targetStore(&ph.vaddr, @intCast(new_vaddr));11229 elf.targetStore(&ph.vaddr, @intCast(new_vaddr));
11238 elf.targetStore(&ph.paddr, @intCast(new_vaddr));11230 elf.targetStore(&ph.paddr, @intCast(new_vaddr));
1123911231
11240 // This may seem like a no-op since we're moving to and fro the same base,11232 const tbss_shndx = elf.shndx.tbss;
11241 // but we also need to update the section STT_SECTION symbol, which this11233 const tbss_addr = new_vaddr + tbss_base;
11242 // function will conveniently do for us.11234 switch (elf.shdrPtr(tbss_shndx)) {
11243 elf.updateNobitsAddress(11235 inline else => |shdr| {
11244 elf.shndx.tbss,11236 elf.targetStore(&shdr.addr, @intCast(tbss_addr));
11245 new_vaddr + tbss_base,11237 elf.targetStore(&shdr.offset, @intCast(tls_offset + tls_filesz));
11246 tls_offset + tls_filesz,11238 },
11247 tbss_base,11239 }
11248 tbss_base,11240 Symbol.Id.local(tbss_shndx.get(elf).lsi).flushMoved(
11249 elf.tbss_inputs.items,11241 elf,
11242 tbss_addr,
11250 );11243 );
11251 },11244 },
11252 }11245 }
...@@ -11651,6 +11644,34 @@ fn updateNobitsAddress(...@@ -11651,6 +11644,34 @@ fn updateNobitsAddress(
11651 );11644 );
11652}11645}
1165311646
11647fn loadSegmentChildrenMoved(
11648 elf: *Elf,
11649 segment_ni: MappedFile.Node.Index,
11650 old_vaddr: u64,
11651 new_vaddr: u64,
11652 offset: u64,
11653 filesz: u64,
11654) std.mem.Allocator.Error!void {
11655 if (segment_ni == elf.ni.data and elf.shndx.bss != .UNDEF) {
11656 const bss_shndx = elf.shndx.bss;
11657 const old_bss_addr = bss_shndx.vaddr(elf);
11658 const new_bss_addr = new_vaddr + filesz;
11659
11660 elf.updateNobitsAddress(
11661 bss_shndx,
11662 new_bss_addr,
11663 offset + filesz,
11664 old_bss_addr,
11665 new_bss_addr,
11666 elf.bss_inputs.items,
11667 );
11668 }
11669
11670 if (old_vaddr != new_vaddr) {
11671 try segment_ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
11672 }
11673}
11674
11654/// Given the index of a `PT_LOAD`/`PT_NULL` segment, assumes that the phdr's `offset` and `filesz`11675/// Given the index of a `PT_LOAD`/`PT_NULL` segment, assumes that the phdr's `offset` and `filesz`
11655/// have been updated as needed by the caller, and updates the `@"align"`, `vaddr`, `paddr`, and11676/// have been updated as needed by the caller, and updates the `@"align"`, `vaddr`, `paddr`, and
11656/// `memsz` fields of the segment, in order to place it at a valid virtual address.11677/// `memsz` fields of the segment, in order to place it at a valid virtual address.
...@@ -11693,6 +11714,8 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro...@@ -11693,6 +11714,8 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro
11693 var vaddr: u64 = orig_vaddr;11714 var vaddr: u64 = orig_vaddr;
1169411715
11695 elf.targetStore(&phdr[orig_phndx].@"align", @intCast(ph_align.toByteUnits()));11716 elf.targetStore(&phdr[orig_phndx].@"align", @intCast(ph_align.toByteUnits()));
11717 elf.targetStore(&phdr[orig_phndx].memsz, @intCast(memsz));
11718 elf.targetStore(&phdr[orig_phndx].type, if (memsz > 0) .LOAD else .NULL);
1169611719
11697 // First, we will shift the virtual address as needed in order to maintain the required11720 // First, we will shift the virtual address as needed in order to maintain the required
11698 // property that vaddr is congruent to offset modulo the phdr alignment.11721 // property that vaddr is congruent to offset modulo the phdr alignment.
...@@ -11770,22 +11793,15 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro...@@ -11770,22 +11793,15 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro
11770 elf.targetStore(&next_ph.vaddr, @intCast(next_new_vaddr));11793 elf.targetStore(&next_ph.vaddr, @intCast(next_new_vaddr));
11771 elf.targetStore(&next_ph.paddr, @intCast(next_new_vaddr));11794 elf.targetStore(&next_ph.paddr, @intCast(next_new_vaddr));
1177211795
11773 const bss_shndx = elf.shndx.bss;
11774 const next_filesz = elf.targetLoad(&next_ph.filesz);11796 const next_filesz = elf.targetLoad(&next_ph.filesz);
11775 const old_bss_addr = bss_shndx.vaddr(elf);11797 try elf.loadSegmentChildrenMoved(
11776 const new_bss_addr = next_new_vaddr + next_filesz;11798 next_ni,
1177711799 next_vaddr,
11778 elf.updateNobitsAddress(11800 next_new_vaddr,
11779 bss_shndx,11801 next_offset,
11780 new_bss_addr,11802 next_filesz,
11781 next_offset + next_filesz,
11782 old_bss_addr,
11783 new_bss_addr,
11784 elf.bss_inputs.items,
11785 );11803 );
1178611804
11787 try next_ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
11788
11789 break;11805 break;
11790 },11806 },
11791 }11807 }
...@@ -11809,29 +11825,15 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro...@@ -11809,29 +11825,15 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro
11809 if (vaddr != orig_vaddr) {11825 if (vaddr != orig_vaddr) {
11810 elf.targetStore(&phdr[phndx].vaddr, @intCast(vaddr));11826 elf.targetStore(&phdr[phndx].vaddr, @intCast(vaddr));
11811 elf.targetStore(&phdr[phndx].paddr, @intCast(vaddr));11827 elf.targetStore(&phdr[phndx].paddr, @intCast(vaddr));
11812 try segment_ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
11813 }11828 }
1181411829
11815 const ph = &phdr[phndx];11830 try elf.loadSegmentChildrenMoved(
1181611831 segment_ni,
11817 elf.targetStore(&ph.memsz, @intCast(memsz));11832 orig_vaddr,
11818 elf.targetStore(&ph.type, if (memsz > 0) .LOAD else .NULL);11833 vaddr,
1181911834 offset,
11820 if (segment_ni == elf.ni.data and elf.shndx.bss != .UNDEF) {11835 filesz,
11821 const bss_shndx = elf.shndx.bss;11836 );
11822
11823 const old_bss_addr = bss_shndx.vaddr(elf);
11824 const new_bss_addr = vaddr + filesz;
11825
11826 elf.updateNobitsAddress(
11827 bss_shndx,
11828 new_bss_addr,
11829 offset + filesz,
11830 old_bss_addr,
11831 new_bss_addr,
11832 elf.bss_inputs.items,
11833 );
11834 }
11835 },11837 },
11836 }11838 }
11837}11839}
...@@ -11867,7 +11869,6 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo...@@ -11867,7 +11869,6 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
11867 switch (elf.targetLoad(&ph.type)) {11869 switch (elf.targetLoad(&ph.type)) {
11868 else => unreachable,11870 else => unreachable,
11869 .NULL, .LOAD => {11871 .NULL, .LOAD => {
11870 elf.targetStore(&ph.type, if (size > 0) .LOAD else .NULL);
11871 try elf.allocateSegmentLoadAddress(phndx);11872 try elf.allocateSegmentLoadAddress(phndx);
11872 },11873 },
11873 .DYNAMIC, .INTERP, .PHDR, .GNU_EH_FRAME, .GNU_RELRO => {11874 .DYNAMIC, .INTERP, .PHDR, .GNU_EH_FRAME, .GNU_RELRO => {
...@@ -11876,7 +11877,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo...@@ -11876,7 +11877,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
11876 .TLS => {11877 .TLS => {
11877 const tls_filesz: u64 = size;11878 const tls_filesz: u64 = size;
1187811879
11879 const old_tbss_base = elf.tbssSegmentOffset();11880 const old_tbss_base = elf.tbssBaseOffset();
11880 const new_tbss_base = tls_filesz;11881 const new_tbss_base = tls_filesz;
11881 const tbss_size = elf.shndx.tbss.size(elf);11882 const tbss_size = elf.shndx.tbss.size(elf);
11882 const tls_vaddr = elf.targetLoad(&ph.vaddr);11883 const tls_vaddr = elf.targetLoad(&ph.vaddr);