% cat a.s
.globl _start, foo, bar
.text; _start: movabs $d, %rax
.section .text_foo,"ax"; foo: ret
.section .text_bar,"ax"; bar: nop
% as a.s -o a.o
% ld.bfd a.o --defsym d=foo --gc-sections -o a => .text_foo is retained
% ld.bfd a.o --defsym d=bar --gc-sections -o a => .text_bar is retained
% ld.bfd a.o --defsym d=1 --gc-sections -o a => Neither .text_foo nor
.text_bar is retained
% ld.bfd a.o --defsym c=foo --defsym d=1 --gc-sections -o a => Neither
.text_foo nor .text_bar is retained; lld will retain .text_foo.
For --defsym from=an_expression_with_to, GNU ld appears to add a
reference from 'from' to 'to'. lld's behavior
(https://reviews.llvm.org/D34195) is more conservative.
If we stop treating script->referencedSymbols as GC roots,
instructions like `movabs $d, %rax` will no longer be able to access
the intended section. We can tweak our behavior to be like GNU ld, but
the additional complexity may not be worthwhile.
I think it would be a step too far for defsym symbol=expression to
have no effect on GC. I'd expect that something like defsym foo=bar is
used because some live code refers to foo, but does not refer to bar,
so ideally we'd like defsym foo=bar to keep bar live. I've seen this
idiom used in embedded systems in the presence of binary only
libraries. It is true that the programmer can always go the extra mile
to force bar to be marked live, however I think the expectation would
be defsym foo=bar would do it.
I think the GNU ld behaviour is reasonable. If nothing refers to
either foo or bar then there is no reason to mark them live. On the
implementation cost-benefit trade off I guess we won't know until
there is a prototype, and some idea of what implementing it will save
on a real example.
Peter
Oops, this got buried while I was out. Sorry for the super late reply, and thanks for looking into it in detail. I agree with you that ld’s behavior doesn’t always work correctly either, and implementing something similar in LLD would be tricky. I’ll look into this more if I have a more pressing need for it, but for now I was able to work around it a different way.
Thanks,
Shoaib
.section foo,"a"
.reloc 0,R_X86_64_NONE,bar
.section bar,"a"
--
宋方睿