authorgravatar for loic@gregoire.devLoïc Grégoire <loic@gregoire.dev> 2026-10-12 14:29:40-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-16 12:41:30+01:00
log6c1a5a1e5b12e775552e1e3ff52daa6576789487
tree019523796ece7d65c76abb8ec0e52c5ada41768f
parent626381706712eb593bcf0c843dd2275d71cf41da
signature Commit is signed but in an unrecognized format.

Elf2: allow custom NOBITS sections in objects

Elf2 previously was failing on objects with sections such as '.bss.something', now preserve those sections for ET_REL output and merge them into their respective .bss/.tbss for other output types.

1 files changed, 17 insertions(+), 17 deletions(-)

src/link/Elf2.zig+17-17
...@@ -7090,7 +7090,7 @@ fn mapInputSection(elf: *Elf, opts: struct {...@@ -7090,7 +7090,7 @@ fn mapInputSection(elf: *Elf, opts: struct {
7090 .type = switch (opts.type) {7090 .type = switch (opts.type) {
7091 .PROGBITS => .NULL, // size is 07091 .PROGBITS => .NULL, // size is 0
7092 .X86_64_UNWIND => .X86_64_UNWIND,7092 .X86_64_UNWIND => .X86_64_UNWIND,
7093 .NOBITS => return error.UnsupportedNobitsSection,7093 .NOBITS => if (elf.ehdrType() == .REL) .NOBITS else return error.UnsupportedNobitsSection,
7094 else => unreachable,7094 else => unreachable,
7095 },7095 },
7096 .flags = flags: {7096 .flags = flags: {
...@@ -7568,10 +7568,8 @@ fn loadObject(...@@ -7568,10 +7568,8 @@ fn loadObject(
7568 shdr: ElfN.Shdr,7568 shdr: ElfN.Shdr,
7569 placement: union(enum) {7569 placement: union(enum) {
7570 progbits: InputSection.Index,7570 progbits: InputSection.Index,
7571 bss: struct {7571 nobits: struct {
7572 offset: u64,7572 shndx: Section.Index,
7573 },
7574 tbss: struct {
7575 offset: u64,7573 offset: u64,
7576 },7574 },
7577 none,7575 none,
...@@ -7743,14 +7741,16 @@ fn loadObject(...@@ -7743,14 +7741,16 @@ fn loadObject(
7743 },7741 },
7744 };7742 };
77457743
7744 section.placement = .{ .nobits = .{
7745 .shndx = opts.shndx,
7746 .offset = offset,
7747 } };
7746 if (opts.shndx == elf.shndx.bss) {7748 if (opts.shndx == elf.shndx.bss) {
7747 section.placement = .{ .bss = .{ .offset = offset } };
7748 input_has_bss = true;7749 input_has_bss = true;
7749 } else if (opts.shndx == elf.shndx.tbss) {7750 } else if (opts.shndx == elf.shndx.tbss) {
7750 section.placement = .{ .tbss = .{ .offset = offset } };
7751 input_has_tbss = true;7751 input_has_tbss = true;
7752 } else {7752 } else {
7753 unreachable;7753 assert(elf.ehdrType() == .REL);
7754 }7754 }
77557755
7756 continue;7756 continue;
...@@ -7882,15 +7882,15 @@ fn loadObject(...@@ -7882,15 +7882,15 @@ fn loadObject(
7882 elf.getNodeShndx(isi.node(elf)),7882 elf.getNodeShndx(isi.node(elf)),
7883 input_sym.value,7883 input_sym.value,
7884 },7884 },
7885 .bss => |bss| .{7885 .nobits => |nobits| .{
7886 .none,
7887 elf.shndx.bss,
7888 elf.shndx.bss.vaddr(elf) + bss.offset + input_sym.value,
7889 },
7890 .tbss => |tbss| .{
7891 .none,7886 .none,
7892 elf.shndx.tbss,7887 nobits.shndx,
7893 elf.tbssBaseOffset() + tbss.offset + input_sym.value,7888 (if (elf.ehdrType() == .REL)
7889 @as(u64, 0)
7890 else if (nobits.shndx.flags(elf).TLS)
7891 elf.tbssBaseOffset()
7892 else
7893 nobits.shndx.vaddr(elf)) + nobits.offset + input_sym.value,
7894 },7894 },
7895 .none => unreachable,7895 .none => unreachable,
7896 };7896 };
...@@ -7960,7 +7960,7 @@ fn loadObject(...@@ -7960,7 +7960,7 @@ fn loadObject(
7960 const loc_node = switch (loc_sec.placement) {7960 const loc_node = switch (loc_sec.placement) {
7961 .none => continue,7961 .none => continue,
7962 .progbits => |isi| isi.node(elf),7962 .progbits => |isi| isi.node(elf),
7963 .bss, .tbss => return diags.failParse(7963 .nobits => return diags.failParse(
7964 path,7964 path,
7965 "relocations applying to BSS (SHT_NOBITS) sections are unsupported",7965 "relocations applying to BSS (SHT_NOBITS) sections are unsupported",
7966 .{},7966 .{},