diff --git a/llvm/test/tools/llvm-objcopy/ELF/group-reorder.test b/llvm/test/tools/llvm-objcopy/ELF/group-reorder.test --- a/llvm/test/tools/llvm-objcopy/ELF/group-reorder.test +++ b/llvm/test/tools/llvm-objcopy/ELF/group-reorder.test @@ -61,4 +61,5 @@ Section: .bar - Name: bar Type: STT_FUNC + Binding: STB_GLOBAL Section: .foo diff --git a/llvm/test/tools/llvm-objcopy/ELF/group.test b/llvm/test/tools/llvm-objcopy/ELF/group.test --- a/llvm/test/tools/llvm-objcopy/ELF/group.test +++ b/llvm/test/tools/llvm-objcopy/ELF/group.test @@ -78,3 +78,23 @@ ## sh_info fields. # RUN: llvm-objcopy --allow-broken-links -R .symtab %t3 %t4 # RUN: cmp %t3 %t4 + +## The signature symbol is local. Assume the intention is to localize the group. +## Drop GRP_COMDAT so that the linker will suppress deduplication. +# RUN: llvm-objcopy --keep-global-symbol=bar %t %t5 +# RUN: llvm-readelf -s --section-groups %t5 | FileCheck %s --check-prefix=LOCAL-SIG + +# LOCAL-SIG: LOCAL DEFAULT [[#]] foo +# LOCAL-SIG: (unknown) group section [ 1] `.group' [foo] contains 1 sections: + +## The signature symbol is non-local. Keep GRP_COMDAT. +# RUN: llvm-readelf -s --section-groups %t | FileCheck %s --check-prefix=WEAK-SIG + +# WEAK-SIG: WEAK DEFAULT [[#]] foo +# WEAK-SIG: COMDAT group section [ 1] `.group' [foo] contains 1 sections: + +# RUN: llvm-objcopy --globalize-symbol=foo %t %t6 +# RUN: llvm-readelf -s --section-groups %t6 | FileCheck %s --check-prefix=GLOBAL-SIG + +# GLOBAL-SIG: GLOBAL DEFAULT [[#]] foo +# GLOBAL-SIG: COMDAT group section [ 1] `.group' [foo] contains 1 sections: diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-section-in-group.test b/llvm/test/tools/llvm-objcopy/ELF/remove-section-in-group.test --- a/llvm/test/tools/llvm-objcopy/ELF/remove-section-in-group.test +++ b/llvm/test/tools/llvm-objcopy/ELF/remove-section-in-group.test @@ -34,3 +34,4 @@ Symbols: - Name: foo_bar_grp Section: .group + Binding: STB_GLOBAL diff --git a/llvm/test/tools/llvm-objcopy/ELF/strip-dwo-groups.test b/llvm/test/tools/llvm-objcopy/ELF/strip-dwo-groups.test --- a/llvm/test/tools/llvm-objcopy/ELF/strip-dwo-groups.test +++ b/llvm/test/tools/llvm-objcopy/ELF/strip-dwo-groups.test @@ -75,9 +75,11 @@ Symbols: - Name: debug_before Section: .debug_before.dwo + - Name: debug_after + Section: .debug_after.dwo - Name: group2 Section: .text.group2 + Binding: STB_WEAK - Name: group1 Section: .text.group1 - - Name: debug_after - Section: .debug_after.dwo + Binding: STB_WEAK diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -1069,6 +1069,12 @@ void GroupSection::finalize() { this->Info = Sym ? Sym->Index : 0; this->Link = SymTab ? SymTab->Index : 0; + // Linker deduplication for GRP_COMDAT is based on Sym->Name. The local/global + // status is not part of the equation. If Sym is localized, the intention is + // likely to make the group fully localized. Drop GRP_COMDAT to suppress + // deduplication. + if ((FlagWord & GRP_COMDAT) && Sym && Sym->Binding == STB_LOCAL) + this->FlagWord &= ~GRP_COMDAT; } Error GroupSection::removeSectionReferences(