Recently I have been dealing with a benign multiple definition related to compiler-rt/lib/builtins and rust-lang/compiler-builtins. I need a workaround to convert certain symbols with hidden visibility to default visibility. (If you are curious, see https://discourse.llvm.org/t/relocatable-file-definitions-shared-with-dso/74391 related to an improved linker error --no-allow-shlib-undefined) It appears that objcopy does not provide a direct way to set symbol visibility, but I have found a workaround: objcopy --strip-symbol __udivmodti4 --add-symbol __udivmodti4=.text.__udivmodti4:0,weak udivmodti4.c.o Running this command on an archive will add __udivmodti4 to every archive member, which is not desired. So, I needed to determine which archive member defines __udivmodti4. I ended up implementing something like this in Bazel: """$(AR) x --output=$(@D)/lib $(OUTS) for o in $(@D)/lib/*.o; do $(NM) -gU $$o | grep -qw __udivmodti4 && $(OBJCOPY) --strip-symbol __udivmodti4 --add-symbol __udivmodti4=.text.__udivmodti4:0,weak $$o done $(AR) r $(OUTS) $(@D)/lib/*.o rm -rf $(@D)/lib""" This is cumbersome. Suppose you want to convert a symbol from default visibility to hidden visibility. Unfortunately, I couldn't find a straightforward way to do it. However, llvm-objcopy provides two extension: # objcopy --strip-symbol __udivmodti4 --add-symbol __udivmodti4=.text.__udivmodti4:0,weak,hidden udivmodti4.c.o # unrecognized symbol flag `hidden' llvm-objcopy --strip-symbol __udivmodti4 --add-symbol __udivmodti4=.text.__udivmodti4:0,weak,hidden udivmodti4.c.o llvm-objcopy --strip-symbol __udivmodti4 --add-symbol __udivmodti4=.text.__udivmodti4:0,weak --new-symbol-visibility=hidden udivmodti4.c.o https://llvm.org/docs/CommandGuide/llvm-objcopy.html#cmdoption-llvm-objcopy-new-symbol-visibility --new-symbol-visibility also affects `_binary_*_{start,end,size}` symbols created by llvm-objcopy --new-symbol-visibility hidden -I binary -B i386:x86-64 a.txt a.o This feature request tracks these possible extensions: * 'hidden' in --add-symbol * --new-symbol-visibility=hidden * An option like --set-symbol-flags that can operate on an existing symbol
On the llvm-objcopy side, someone proposes --set-symbol-visibility: https://github.com/llvm/llvm-project/pull/80872
(In reply to Fangrui Song from comment #1) > On the llvm-objcopy side, someone proposes --set-symbol-visibility: > https://github.com/llvm/llvm-project/pull/80872 The proposal looks like: .. option:: --set-symbol-visibility <symbol>=<visibility_type> Change the visibility of a symbol to the specified type. .. option:: --set-symbols-visibility <filename>=<visibility_type> Reads a list of symbols from <filename> and changes their visibility to the specified type. Visibility types: default, internal, hidden, protected. for ELF targets.
(In reply to Fangrui Song from comment #2) > .. option:: --set-symbols-visibility <filename>=<visibility_type> > > Reads a list of symbols from <filename> and changes their visibility to the > specified type. Visibility types: default, internal, hidden, protected. Given the support for "@<file>" for reading in a list of command line options, is the format above really necessary ? Using a file containing lots of: --set-symbol-visibility <symbol>=<vis-type> entries might require a bigger file, but it would also be more flexible, allowing for multiple types of visibility to be set, along with other options as well.
Just wanted to mention that the pull request mentioned above to add this to `llvm-objcopy` was merged, and the options are documented (in the source) at https://github.com/llvm/llvm-project/blob/main/llvm/tools/llvm-objcopy/ObjcopyOpts.td#L102.