diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -193,21 +193,27 @@ /// The Compile Unit ID that we are currently processing. unsigned DwarfCompileUnitID = 0; + // Sections are differentiated by the quadruple (section_name, group_name, + // unique_id, link_to_symbol_name). Sections sharing the same quadruple are + // combined into one section. struct ELFSectionKey { std::string SectionName; StringRef GroupName; + StringRef LinkedToName; unsigned UniqueID; ELFSectionKey(StringRef SectionName, StringRef GroupName, - unsigned UniqueID) - : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) { - } + StringRef LinkedToName, unsigned UniqueID) + : SectionName(SectionName), GroupName(GroupName), + LinkedToName(LinkedToName), UniqueID(UniqueID) {} bool operator<(const ELFSectionKey &Other) const { if (SectionName != Other.SectionName) return SectionName < Other.SectionName; if (GroupName != Other.GroupName) return GroupName < Other.GroupName; + if (int O = LinkedToName.compare(Other.LinkedToName)) + return O < 0; return UniqueID < Other.UniqueID; } }; diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -316,12 +316,14 @@ if (const MCSymbol *Group = Section->getGroup()) GroupName = Group->getName(); + // This function is only used by .debug*, which should not have the + // SHF_LINK_ORDER flag. unsigned UniqueID = Section->getUniqueID(); ELFUniquingMap.erase( - ELFSectionKey{Section->getSectionName(), GroupName, UniqueID}); - auto I = ELFUniquingMap.insert(std::make_pair( - ELFSectionKey{Name, GroupName, UniqueID}, - Section)) + ELFSectionKey{Section->getSectionName(), GroupName, "", UniqueID}); + auto I = ELFUniquingMap + .insert(std::make_pair( + ELFSectionKey{Name, GroupName, "", UniqueID}, Section)) .first; StringRef CachedName = I->first.SectionName; const_cast(Section)->setSectionName(CachedName); @@ -404,8 +406,10 @@ if (GroupSym) Group = GroupSym->getName(); // Do the lookup, if we have a hit, return it. - auto IterBool = ELFUniquingMap.insert( - std::make_pair(ELFSectionKey{Section.str(), Group, UniqueID}, nullptr)); + auto IterBool = ELFUniquingMap.insert(std::make_pair( + ELFSectionKey{Section.str(), Group, + LinkedToSym ? LinkedToSym->getName() : "", UniqueID}, + nullptr)); auto &Entry = *IterBool.first; if (!IterBool.second) return Entry.second; diff --git a/llvm/test/MC/ELF/comdat-dup-group-name.s b/llvm/test/MC/ELF/comdat-dup-group-name.s deleted file mode 100644 --- a/llvm/test/MC/ELF/comdat-dup-group-name.s +++ /dev/null @@ -1,32 +0,0 @@ -// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -S --symbols | FileCheck %s - -// Test that we produce two foo sections, each in separate groups - -// CHECK: Index: 3 -// CHECK-NEXT: Name: .group - -// CHECK: Index: 4 -// CHECK-NEXT: Name: .foo - -// CHECK: Index: 5 -// CHECK-NEXT: Name: .group - -// CHECK: Index: 6 -// CHECK-NEXT: Name: .foo - -// CHECK: Symbols [ - -// CHECK: Name: f1 -// CHECK-NOT: } -// CHECK: Section: .group (0x3) - -// CHECK: Name: f2 -// CHECK-NOT: } -// CHECK: Section: .group (0x5) - - .section .foo,"axG",@progbits,f1,comdat - nop - - .section .foo,"axG",@progbits,f2,comdat - nop - diff --git a/llvm/test/MC/ELF/section-combine.s b/llvm/test/MC/ELF/section-combine.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ELF/section-combine.s @@ -0,0 +1,48 @@ +## Sections are differentiated by the quadruple +## (section_name, group_name, unique_id, link_to_symbol_name). +## Sections sharing the same quadruple are combined into one section. + +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t +# RUN: llvm-readelf -x .foo %t | FileCheck %s + +# CHECK: Hex dump of section '.foo': +# CHECK-NEXT: 0x00000000 00 +# CHECK: Hex dump of section '.foo': +# CHECK-NEXT: 0x00000000 0102 +# CHECK: Hex dump of section '.foo': +# CHECK-NEXT: 0x00000000 03 +# CHECK: Hex dump of section '.foo': +# CHECK-NEXT: 0x00000000 0405 +# CHECK: Hex dump of section '.foo': +# CHECK-NEXT: 0x00000000 06 +# CHECK: Hex dump of section '.foo': +# CHECK-NEXT: 0x00000000 0708 + +foo: +bar: + +## foo and bar are in the same section. However, a section referencing foo +## is considered different from a section referencing bar. +.section .foo,"o",@progbits,foo +.byte 0 + +.section .foo,"o",@progbits,bar +.byte 1 +.section .foo,"o",@progbits,bar +.byte 2 + +.section .foo,"o",@progbits,bar,unique,0 +.byte 3 + +.section .foo,"o",@progbits,bar,unique,1 +.byte 4 +.section .foo,"o",@progbits,bar,unique,1 +.byte 5 + +.section .foo,"Go",@progbits,comdat0,comdat,bar,unique,1 +.byte 6 + +.section .foo,"Go",@progbits,comdat1,comdat,bar,unique,1 +.byte 7 +.section .foo,"Go",@progbits,comdat1,comdat,bar,unique,1 +.byte 8