There is some misinformation.
> If different visibility attributes are specified for distinct references to or definitions of a symbol, the most constraining visibility attribute must be propagated to the resolving symbol in the linked object. The attributes, ordered from least to most constraining, are: STV_PROTECTED, STV_HIDDEN, STV_INTERNAL, and STV_EXPORTED.
In GNU ld-compatible linkers, output constrains visibility regardless of -r.
It is incorrect to state that "ET_REL doesn't offer symbol visibility features when processed by ld".
Non-relocatable outputs (ET_EXEC, ET_DYN) additionally convert symbols of hidden visibility to STB_LOCAL binding.
> Similarly to shared objects, static bundle objects will resolve relocations for local symbols, instead of keeping them as possible hook points in the finalized binary
Only a limited set of relocations can actually be resolved in relocatable files.
Specifically, this applies to relocations following the (S-P+A) formula where S refers to a non-ifunc local symbol in the same section as P.
This behavior mirrors assembler fixup resolution (
https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers ):
> Fixup resolution depends on the fixup type:
>
> - PC-relative fixups that describe the symbol itself (the relocation operation looks like S - P + A) resolve to a constant if sym_a is a non-ifunc local symbol defined in the current section.
> - relocation_specifier(S + A) style fixups resolve when S refers to an absolute symbol.
> - Other fixups, including TLS and GOT related ones, remain unresolved.
Many scenarios prevent relocation resolution:
- Cross-section symbol references
- Symbols with STB_WEAK or STB_GLOBAL binding (due to potential symbol interposition in shared libraries and linker script symbol assignments)
- TLS or GOT-related relocations
- Relocations potentially requiring PLT entries or range-extension thunks
---
ET_REL object file already serve different roles.
- Compiler output (e.g. cc -c)
- Relocatable linking output - These files can be:
* Used directly as input for executable linking (ld -r a.o b.o -o ab.o; ld ab.o)
* Loaded by custom loaders (e.g., kernel modules in Linux)
* Merged further with other relocatable files (ld -r a.o b.o -o ab.o; ld -r ab.o c.o -o abc.o)
The proposed static bundle object appears to cover a subset of existing ET_REL use cases while adding a new e_type code. I don't see this as a necessary addition.
---
In the current relocatable linking based approach, we should also consider COMDAT section groups when using C++, which enable name-based deduplication (binding is ignored).
- Compile with hidden symbols by default. Mark necessary symbols as exported
- Run ld -r --force-group-allocation
- Process the output with objcopy --localize-hidden with possibly other options.
objcopy --keep-global-symbols=filename can be utilized as well, similar to how we use a version scriot to create a shared object.
I agree that we might need better integration in tools (including the build system) to produce the kinds of ELF files you want.