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.