Comment 1 for bug 1902760

Revision history for this message
In , D-i-j (d-i-j) wrote :

This can be reproduced with clang 10 (likely also 9; and all master commits before https://reviews.llvm.org/D83967 ). LLVMgold.so is needed.

% cat a.c
int main() {}
% /tmp/Debug/bin/clang -fuse-ld=bfd -fprofile-generate -flto a.c -Wl,-plugin-opt=save-temps -Wl,-y,__llvm_profile_raw_version -Wl,-plugin-opt=save-temps
/usr/bin/ld.bfd: /tmp/a-e575a9.o (symbol from plugin): definition of __llvm_profile_raw_version
/usr/bin/ld.bfd: /tmp/Debug/lib/clang/12.0.0/lib/linux/libclang_rt.profile-x86_64.a(InstrProfiling.c.o): definition of __llvm_profile_raw_version

/tmp/a-e575a9.o (symbol from plugin) provides a definition in a prevailing comdat group.
libclang_rt.profile-x86_64.a(InstrProfiling.c.o) is an weak definition which should not override the IR definition.

% cat a.out.resolution.txt
/tmp/a-e575a9.o
-r=/tmp/a-e575a9.o,main,plx
-r=/tmp/a-e575a9.o,__llvm_profile_raw_version,l # should be 'plx' instead of 'l'
-r=/tmp/a-e575a9.o,__llvm_profile_filename,plx

Gold and LLD are correct.

% /tmp/Debug/bin/clang -fuse-ld=gold -fprofile-generate -flto a.c -Wl,-plugin-opt=save-temps -Wl,-y,__llvm_profile_raw_version
/tmp/a-668c9c.o: definition of __llvm_profile_raw_version
/tmp/Debug/lib/clang/12.0.0/lib/linux/libclang_rt.profile-x86_64.a(InstrProfiling.c.o): definition of __llvm_profile_raw_version
a.out.o: definition of __llvm_profile_raw_version
% cat a.out.resolution.txt
/tmp/a-668c9c.o
-r=/tmp/a-668c9c.o,main,plx
-r=/tmp/a-668c9c.o,__llvm_profile_raw_version,plx
-r=/tmp/a-668c9c.o,__llvm_profile_filename,plx

% /tmp/Debug/bin/clang -fuse-ld=lld -fprofile-generate -flto a.c -Wl,-plugin-opt=save-temps -Wl,-y,__llvm_profile_raw_version
/tmp/a-afb841.o: definition of __llvm_profile_raw_version
<internal>: reference to __llvm_profile_raw_version
lto.tmp: definition of __llvm_profile_raw_version
% cat a.out.resolution.txt
/tmp/a-afb841.o
-r=/tmp/a-afb841.o,main,plx
-r=/tmp/a-afb841.o,__llvm_profile_raw_version,plx
-r=/tmp/a-afb841.o,__llvm_profile_filename,plx

The ld bug is in ld/plugin.c:plugin_notice . ld somehow drops bfd_link_hash_defined (provided by "/tmp/a-e575a9.o (symbol from plugin)") in favor of bfd_link_hash_undefweak. Then bfd_link_hash_undefweak is overridden by the weak definition in libclang_rt.profile-x86_64.a(InstrProfiling.c.o)

      /* Otherwise, it must be a new def.
  Ensure any symbol defined in an IR dummy BFD takes on a
  new value from a real BFD. Weak symbols are not normally
  overridden by a new weak definition, and strong symbols
  will normally cause multiple definition errors. Avoid
  this by making the symbol appear to be undefined. */
      else if (((h->type == bfd_link_hash_defweak
   || h->type == bfd_link_hash_defined)
  && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
        || (h->type == bfd_link_hash_common
     && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
 {
   h->type = bfd_link_hash_undefweak;
   h->u.undef.abfd = sym_bfd;
 }

The intended behavior is to let "/tmp/a-e575a9.o (symbol from plugin)" provide the definition.