[PATCH] D73230: [X86][ELF] Prefer to lower MC_GlobalAddress operands to .Lfoo$local

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 10 12:23:51 PDT 2020


MaskRay added a comment.

In D73230#2207735 <https://reviews.llvm.org/D73230#2207735>, @bd1976llvm wrote:

> In D73230#2207634 <https://reviews.llvm.org/D73230#2207634>, @MaskRay wrote:
>
>> In D73230#2207477 <https://reviews.llvm.org/D73230#2207477>, @bd1976llvm wrote:
>>
>>> So, clang's behavior has changed so that --wrap no longer wraps symbol definitions for default symbols + -fpic + -fno-semantic-interposition (-fno-semantic-interposition is the default); however, you can restore the old behavior via -fsemantic-interposition. For hidden symbols + -fpic --wrap no longer wraps symbol definitions and there is no way to restore the old definition wrapping behavior.
>>
>> I think the summary is correct. -fvisibility=hidden nullifies -fsemantic-interposition when the definition is available in the same translation unit. Given how GCC and GNU ld handle/document it, I'd say the previous `hidden` clang behavior working with -Wl,--wrap=foo is accidental rather than intentional. If you don't pass explicit -fsemantic-interposition, in -fPIC mode clang can freely inline foo into call sites, which will also defeat the intended -Wl,--wrap=foo behavior.
>>
>>> Any undefined reference to symbol will be resolved to "__wrap_symbol".
>>
>> I think the reasonably portable approach making the wrapping scheme work is `__attribute__((weak))`. An alternative is to move the definitions to a separate translation unit (it does not work with -r or GCC LTO, though).
>
> .. but now we have this difference in behaviour for -normal vs flto links:
>
>   ben at ben-VirtualBox:~/tests/wrap$ cat smaller.c 
>   void __wrap_foo () {
>   	puts ("__wrap_foo");
>   	__real_foo();
>   }
>   
>   void foo () { puts("foo()"); }
>   
>   int main() { foo(); }
>   ben at ben-VirtualBox:~/tests/wrap$ clang smaller.c -Wno-implicit-function-declaration -fpic -ffunction-sections -Wl,--wrap=foo -o old.elf -fvisibility=hidden -fuse-ld=lld
>   ben at ben-VirtualBox:~/tests/wrap$ ./old.elf
>   __wrap_foo
>   foo()
>   ben at ben-VirtualBox:~/tests/wrap$ clang smaller.c -Wno-implicit-function-declaration -fpic -ffunction-sections -Wl,--wrap=foo -o old_lto.elf -fvisibility=hidden -fuse-ld=lld -flto
>   ben at ben-VirtualBox:~/tests/wrap$ ./old_lto.elf
>   __wrap_foo
>   foo()
>   ben at ben-VirtualBox:~/tests/wrap$ ~/u/build/bin/clang smaller.c -Wno-implicit-function-declaration -fpic -ffunction-sections -Wl,--wrap=foo -o new.elf -fvisibility=hidden -fuse-ld=lld
>   ben at ben-VirtualBox:~/tests/wrap$ ./new.elf
>   foo()
>   ben at ben-VirtualBox:~/tests/wrap$ ~/u/build/bin/clang smaller.c -Wno-implicit-function-declaration -fpic -ffunction-sections -Wl,--wrap=foo -o new_lto.elf -fvisibility=hidden -fuse-ld=lld -flto
>   ben at ben-VirtualBox:~/tests/wrap$ ./new_lto.elf
>   __wrap_foo
>   foo()
>
> ... and the same will be true for default symbols + -fpic when we enable -fno-semantic-interposition by default for -fpic :(

I think the non-LTO vs Full LTO difference is due to the way we implement --wrap for LTO: D33621 <https://reviews.llvm.org/D33621>.
It adds WeakAny linkage which obtains wrapping behavior.

`clang -fuse-ld=lld smaller.c -Wno-implicit-function-declaration -fpic -ffunction-sections -Wl,--wrap=foo -fvisibility=hidden -flto -Wl,--save-temps`

  % llvm-dis < a.out.0.0.preopt.bc
  ...
  define weak hidden void @foo() #0 {  # Note the weakany linkage
  ...


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73230/new/

https://reviews.llvm.org/D73230



More information about the llvm-commits mailing list