Skip to content

Proposal: expose lld's "orphan handling" option #8261

@kivikakk

Description

@kivikakk

Last night I ran into a familiar problem --- it turns out that, on RISC-V, some globals are put in an .sbss section. I was using a linker script patterned from my ARM64 one, which doesn't use that. This lead to some headscratching as some globals were being placed after the "end" pointer I'd put in the linker script. objdump showed me that there were some sections that had been put there by default.

Today in #zig-help @rgreenblatt happened to hit something that sounded familiar: this time the presentation was __zig_probe_stack being placed at the end of their loaded data. It was the same thing; he had loaded *(.text) in the linker script, but the probe stack function was placed in a section called .text.__zig_probe_stack, so it just got put at the end too.

TIL these are called orphaned sections, and LLD has a parameter --orphan-handling=error which causes it to error out if any sections are unnamed by the linker script. Access to this would be very helpful for embedded, since the "helpful" behaviour of just putting them at the end is actually kinda dangerous and leads to lots of confusion.

diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 314e443f3..0d4a817b4 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1462,6 +1462,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
         }

         try argv.appendSlice(self.base.options.extra_lld_args);
+        try argv.append("--orphan-handling=error");

         if (self.base.options.z_nodelete) {
             try argv.append("-z");

I used this to minimally test that it works as expected, and it does. The thing is, the "default" linker script seems to actually orphan everything, letting the linker just drop every section in as an orphan. Here's a demo with the change:

$ cat test.zig
pub fn main() void {}
$ zig build-exe test.zig -target aarch64-linux-musl
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.text) is being placed in '.text'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.rodata) is being placed in '.rodata'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.rodata.cst16) is being placed in '.rodata'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.rodata.cst8) is being placed in '.rodata'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.rodata.str1.1) is being placed in '.rodata'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.bss) is being placed in '.bss'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.tbss) is being placed in '.tbss'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.data) is being placed in '.data'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.rodata.cst4) is being placed in '.rodata'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.rodata.cst32) is being placed in '.rodata'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_loc) is being placed in '.debug_loc'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_abbrev) is being placed in '.debug_abbrev'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_info) is being placed in '.debug_info'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_ranges) is being placed in '.debug_ranges'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_str) is being placed in '.debug_str'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_pubnames) is being placed in '.debug_pubnames'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_pubtypes) is being placed in '.debug_pubtypes'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_frame) is being placed in '.debug_frame'
ld.lld: error: zig-cache/o/30d7afa88b192b441a081997e43a357b/test.o:(.debug_line) is being placed in '.debug_line'
ld.lld: error: /Users/kameliya/.cache/zig/o/ab2c2add6c0ae640490aa3cbc70de91c/libc.a(/Users/kameliya/.cache/zig/o/ab2c2add6c0ae640490aa3cbc70de91c/c.o):(.text.memset) is being placed in '
.text'
ld.lld: error: /Users/kameliya/.cache/zig/o/ab2c2add6c0ae640490aa3cbc70de91c/libc.a(/Users/kameliya/.cache/zig/o/ab2c2add6c0ae640490aa3cbc70de91c/c.o):(.text.memcpy) is being placed in '
.text'
ld.lld: error: /Users/kameliya/.cache/zig/o/57ca96a87c228d21d399eedec4c2db72/libcompiler_rt.a(/Users/kameliya/.cache/zig/o/57ca96a87c228d21d399eedec4c2db72/compiler_rt.o):(.text.__divti3
) is being placed in '.text'
ld.lld: error: /Users/kameliya/.cache/zig/o/57ca96a87c228d21d399eedec4c2db72/libcompiler_rt.a(/Users/kameliya/.cache/zig/o/57ca96a87c228d21d399eedec4c2db72/compiler_rt.o):(.text.compiler
_rt.udivmod.udivmod.65) is being placed in '.text'
ld.lld: error: /Users/kameliya/.cache/zig/o/57ca96a87c228d21d399eedec4c2db72/libcompiler_rt.a(/Users/kameliya/.cache/zig/o/57ca96a87c228d21d399eedec4c2db72/compiler_rt.o):(.text.__udivti
3) is being placed in '.text'
ld.lld: error: /Users/kameliya/.cache/zig/o/57ca96a87c228d21d399eedec4c2db72/libcompiler_rt.a(/Users/kameliya/.cache/zig/o/57ca96a87c228d21d399eedec4c2db72/compiler_rt.o):(.text.__muloti
4) is being placed in '.text'
ld.lld: error: <internal>:(.comment) is being placed in '.comment'
ld.lld: error: <internal>:(.got) is being placed in '.got'
ld.lld: error: <internal>:(.symtab) is being placed in '.symtab'
ld.lld: error: <internal>:(.shstrtab) is being placed in '.shstrtab'
ld.lld: error: <internal>:(.strtab) is being placed in '.strtab'
panic: attempt to unwrap error: LLDReportedFailure
/Users/kameliya/Code/zig/lib/std/heap.zig:142:46: 0x1042c73b7 in std.heap.CAllocator.resize (zig1)
            const full_len = alignedAllocSize(buf.ptr);

So we may want to only expose an option for this, letting embedded developers opt-in, so they can then choose to include or ignore what they like.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSolving this issue will likely involve adding new logic or components to the codebase.linking

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions