Pre-link static binaries/remove
Simon Richter
Simon.Richter@hogyros.de
Tue Nov 11 14:32:57 GMT 2025
Hi,
On 11/11/25 9:22 PM, Thomas Richter wrote:
> Clearly, as long as a.o and b.o exist as independent objects in the
> final library, bar() cannot be removed. It will be removed in the final
> step when creating a .so. However, would it be possible to merge a.o and
> b.o into "merged.o" - a single unit - and by doing so, resolve the call
> of "bar()" already by replacing it by a "relative branch" from one part
> of the unit to another.
You can merge all the objects of a shared library into one, e.g.
$ ld -o /tmp/test.o -r --whole-archive /lib/x86_64-linux-gnu/libc.a
but this does not resolve any relocations because that doesn't really
gain us anything. The pass that replaces jump/call instructions with
shorter forms ("linker relaxation") needs to be able to adjust any
relocations that cross a relocation it performs, so we cannot remove the
relocation information yet. If we were to "pre-link" and relax some of
the calls, a later linking step could still make a relocation possible,
e.g. assuming 16 bit opcodes and 32 bit operands:
a:
call hidden_b -- 6 bytes
call ext_a -- 6 bytes
jmp a -- 6 bytes
hidden_b:
ret -- 2 bytes
replacing this with
a:
call pc+10 -- 2 bytes
call ext_a -- 6 bytes
jmp pc-8 -- 2 bytes
ret -- 2 bytes
would mean that if we link "ext_a" directly behind it, we can no longer
replace the 6-byte "call ext_a" with a shorter form, because we need to
adjust the offsets in the first call and the jmp instruction again here.
In principle, we could partially relax here and replace the relocation:
a:
1:
call 2f -- 2 bytes
call ext_a -- 6 bytes
jmp 1b -- 2 bytes
2:
ret -- 2 bytes
but all we've gained here is to make the symbol local. Final relocation
will still only happen during final linking, and we need a relaxation
pass there anyway to replace the second call instruction.
If you want to turn the hidden symbols local, there is objcopy
$ objcopy --localize-hidden test.o test2.o
That will still not resolve these symbols or apply relaxations, but that
is fine, all of that is handled during final link.
For more aggressive optimization, use -flto to link before compiling. I
think it should be possible to combine that with "ld -r" and "objcopy
--localize-hidden", and it should also remove unused functions.
Simon
More information about the Binutils
mailing list