This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Suppress "duplicate symbol" when resolving STB_WEAK and STB_GNU_UNIQUE in different COMDATs
ClosedPublic

Authored by MaskRay on Oct 20 2022, 2:23 PM.

Details

Summary
template <typename T> struct A {
  A() {}
  int value = 0;
};

template <typename Value> struct B {
  static A<int> a;
};

template <typename Value> A<int> B<Value>::a;

inline int foo() {
  return B<int>::a.value;
}
clang++ -c -fno-pic a.cc -o weak.o
g++ -c -fno-pic a.cc -o unique.o  # --enable-gnu-unique-object

# Duplicate symbol error. In postParse, we do not check `sym.binding`
ld.lld -e 0 weak.o unique.o

Mixing GCC and Clang object files in this case is not ideal. .bss._ZGVN1BIiE1aE
has different COMDAT groups. It appears to work in practice because the guard
variable prevents harm due to double initialization.

For the linker, we just stick with the rule that a weak binding does not cause
"duplicate symbol" errors.

Close https://github.com/llvm/llvm-project/issues/58232

Diff Detail

Event Timeline

MaskRay created this revision.Oct 20 2022, 2:23 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 20 2022, 2:23 PM
MaskRay requested review of this revision.Oct 20 2022, 2:23 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 20 2022, 2:23 PM
MaskRay edited the summary of this revision. (Show Details)Oct 20 2022, 2:30 PM
peter.smith accepted this revision.Oct 21 2022, 4:22 AM

Is this symptomatic of a problem in Clang or GCC? It looks like they are not generating the same groups for the same source file which I would expect considering that both claim to implement the itanium ABI. I couldn't understand at first why the STB_GNU_UNIQUE symbols were not getting discarded as part of a non-prevailing group, however the clang and gcc (I used aarch64-none-linux-gnu-g++ (fsf-10.39) 10.1.1 20200629) generated groups have different signatures so we end up with two groups with one STB_GNU_UNIQUE and one STB_WEAK.

I've approved as the groups are different even when -fno-gnu-unique is used for GCC so it makes sense to treat STB_GNU_WEAK and STB_GNU_UNIQUE the same way. However this does feel less than ideal. We end up with sections from both groups in the ELF file but only one set of symbols. Probably the job of the compiler to fix, not sure there is much we can do at link time.

lld/test/ELF/comdat-binding2.s
33

Can we add to the comment as I found it difficult to spot.

  1. Note the different group signature for the second group.
This revision is now accepted and ready to land.Oct 21 2022, 4:22 AM
MaskRay marked an inline comment as done.Oct 21 2022, 9:38 AM

Is this symptomatic of a problem in Clang or GCC? It looks like they are not generating the same groups for the same source file which I would expect considering that both claim to implement the itanium ABI. I couldn't understand at first why the STB_GNU_UNIQUE symbols were not getting discarded as part of a non-prevailing group, however the clang and gcc (I used aarch64-none-linux-gnu-g++ (fsf-10.39) 10.1.1 20200629) generated groups have different signatures so we end up with two groups with one STB_GNU_UNIQUE and one STB_WEAK.

I need to do some research. I suspect GCC's scheme isn't ideal as generally we want to make related symbols in one comdat instead of two.

I've approved as the groups are different even when -fno-gnu-unique is used for GCC so it makes sense to treat STB_GNU_WEAK and STB_GNU_UNIQUE the same way. However this does feel less than ideal. We end up with sections from both groups in the ELF file but only one set of symbols. Probably the job of the compiler to fix, not sure there is much we can do at link time.

The mix is not ideal but appear to work fine in practice because the guard variable prevents harm due to double initialization....
For the linker we just stick with the rule that a weak binding does not cause duplicate symbol error.

MaskRay updated this revision to Diff 469662.Oct 21 2022, 9:39 AM
MaskRay edited the summary of this revision. (Show Details)

add comment

This revision was landed with ongoing or failed builds.Oct 21 2022, 9:43 AM
This revision was automatically updated to reflect the committed changes.