This is an archive of the discontinued LLVM Phabricator instance.

[Driver] Pass -X to ld for riscv*-{elf,freebsd,linux}
ClosedPublic

Authored by MaskRay on Jun 14 2022, 11:48 PM.

Details

Summary

GNU ld has a hack that defaults to -X (--discard-locals) in the emulation file
riscvelf.em. The recommended way, as gcc/config/arm does, is to let the
compiler driver pass -X to ld.
(The motivation is likely to discard a plethora of .L symbols due to
linker relaxation.)

lld default to --discard-none. To make clang+lld use match GNU ld's behavior,
pass -X to ld.

Note: GNU ld has a special rule to treat ld -r -s as ld -r -S -x. With -X, driver -r -Wl,-s
will behave as ld -r -S -X. This removes fewer symbols than -r -S -x but is safe.

Diff Detail

Event Timeline

MaskRay created this revision.Jun 14 2022, 11:48 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 14 2022, 11:48 PM
MaskRay requested review of this revision.Jun 14 2022, 11:48 PM
kito-cheng accepted this revision.Jun 16 2022, 9:12 PM

ld's help message just confused me, that say -X is default, but actually default action is Discard local temporary symbols in SEC_MERGE sections. which is no option can enable that but default.

$ ld.bfd --help
...
  -x, --discard-all           Discard all local symbols
  -X, --discard-locals        Discard temporary local symbols (default)
  --discard-none              Don't discard any local symbols
...

Anyway, back to the RISC-V part, that set -X (--discard-locals) IF discard policy is default, which match the behavior of emultempl/riscvelf.em, however I've little concern about that might change the behavior for ld.bfd when we try to link with clang -target riscv64 -Wl,-r -Wl,-s: ld will treat ld -r -s as ld -r -S -x, but this change changed this behavior because we always append a -X here, so it the behavior is become treat ld -r -s as ld -r -S, but I must say I really not sure how important of this behavior - the behavior here is over 20 years[2, 3] and I didn't found any document to describe why.

But generally I believe discard fewer symbol isn't harmful - just made the object file fatter little bit, so I give a LGTM here.

[1] https://github.com/bminor/binutils-gdb/blob/master/ld/emultempl/riscvelf.em#L34

[2] https://github.com/bminor/binutils-gdb/blob/252b5132c753830d5fd56823373aed85f2a0db63/ld/ldmain.c#L272
[3] https://github.com/bminor/binutils-gdb/commit/f5fa8ca231d47662321addbfbde105e2bed0be07#diff-3b7cfc539d765310991a11f7f328f095fc6f9e17fea1a8510c949c210804deb5R281

/* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols).  I
   don't see how else this can be handled, since in this case we
   must preserve all externally visible symbols.  */
if (bfd_link_relocatable (&link_info) && link_info.strip == strip_all)
  {    
    link_info.strip = strip_debugger;
    if (link_info.discard == discard_sec_merge)
      link_info.discard = discard_all;
  }
This revision is now accepted and ready to land.Jun 16 2022, 9:12 PM

Thanks for the archaeology!

ld will treat ld -r -s as ld -r -S -x,

This seems really weird... I agree that using driver-passed -X instead of the implied -x is safe.

MaskRay added a subscriber: dim.Jun 16 2022, 11:23 PM
MaskRay added inline comments.
clang/lib/Driver/ToolChains/FreeBSD.cpp
226

@dim FYI

MaskRay edited the summary of this revision. (Show Details)Jun 16 2022, 11:27 PM
MaskRay edited the summary of this revision. (Show Details)Jun 16 2022, 11:33 PM
This revision was landed with ongoing or failed builds.Jun 16 2022, 11:34 PM
This revision was automatically updated to reflect the committed changes.
brad added a subscriber: brad.Jun 18 2022, 6:26 PM

This should probably be applied to Fuchsia and NetBSD as well.