From 1f4f9e3d35a2264d86f97dfb6d1e4ccb434f449b Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 14 Nov 2010 04:17:37 +0000 Subject: [PATCH] Handle a peculiar comdat case: Creating a section with an undefined signature symbol causes a local symbol to be created unless there is some other use of the symbol. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119026 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/ELFObjectWriter.cpp | 76 +++++++++++++++++++++++--------------- lib/MC/MCELFStreamer.cpp | 8 ++++ test/MC/ELF/comdat.s | 59 ++++++++++++++++++++++++++--- 3 files changed, 108 insertions(+), 35 deletions(-) diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 085b301b6ec..cd7eb1c6acd 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -285,13 +285,19 @@ namespace { uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, const MCSymbol *S); + // Map from a group section to the signature symbol + typedef DenseMap GroupMapTy; + // Map from a signature symbol to the group section + typedef DenseMap RevGroupMapTy; + /// ComputeSymbolTable - Compute the symbol table data /// /// \param StringTable [out] - The string table data. /// \param StringIndexMap [out] - Map from symbol names to offsets in the /// string table. void ComputeSymbolTable(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap); + const SectionIndexMapTy &SectionIndexMap, + RevGroupMapTy RevGroupMap); void ComputeIndexMap(MCAssembler &Asm, SectionIndexMapTy &SectionIndexMap); @@ -309,10 +315,8 @@ namespace { void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap); - // Map from a group section to the signature symbol - typedef DenseMap GroupMapTy; void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout, - GroupMapTy &GroupMap); + GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap); void ExecutePostLayoutBinding(MCAssembler &Asm); @@ -490,15 +494,6 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { const MCSymbol &Symbol = AliasedSymbol(Alias); MCSymbolData &SD = Asm.getSymbolData(Symbol); - // Undefined symbols are global, but this is the first place we - // are able to set it. - if (Symbol.isUndefined() && !Symbol.isVariable()) { - if (GetBinding(SD) == ELF::STB_LOCAL) { - SetBinding(SD, ELF::STB_GLOBAL); - SetBinding(*it, ELF::STB_GLOBAL); - } - } - // Not an alias. if (&Symbol == &Alias) continue; @@ -904,13 +899,20 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, return true; } -static bool isLocal(const MCSymbolData &Data) { +static bool isLocal(const MCSymbolData &Data, bool isSignature, + bool isUsedInReloc) { if (Data.isExternal()) return false; const MCSymbol &Symbol = Data.getSymbol(); - if (Symbol.isUndefined() && !Symbol.isVariable()) + const MCSymbol &RefSymbol = AliasedSymbol(Symbol); + + if (RefSymbol.isUndefined() && !RefSymbol.isVariable()) { + if (isSignature && !isUsedInReloc) + return true; + return false; + } return true; } @@ -938,7 +940,8 @@ void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, } void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap) { + const SectionIndexMapTy &SectionIndexMap, + RevGroupMapTy RevGroupMap) { // FIXME: Is this the correct place to do this? if (NeedsGOT) { llvm::StringRef Name = "_GLOBAL_OFFSET_TABLE_"; @@ -962,15 +965,26 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, bool Used = UsedInReloc.count(&Symbol); bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol); - if (!isInSymtab(Asm, *it, Used || WeakrefUsed, + bool isSignature = RevGroupMap.count(&Symbol); + + if (!isInSymtab(Asm, *it, + Used || WeakrefUsed || isSignature, Renames.count(&Symbol))) continue; ELFSymbolData MSD; MSD.SymbolData = it; - bool Local = isLocal(*it); const MCSymbol &RefSymbol = AliasedSymbol(Symbol); + // Undefined symbols are global, but this is the first place we + // are able to set it. + bool Local = isLocal(*it, isSignature, Used); + if (!Local && GetBinding(*it) == ELF::STB_LOCAL) { + MCSymbolData &SD = Asm.getSymbolData(RefSymbol); + SetBinding(*it, ELF::STB_GLOBAL); + SetBinding(SD, ELF::STB_GLOBAL); + } + if (RefSymbol.isUndefined() && !Used && WeakrefUsed) SetBinding(*it, ELF::STB_WEAK); @@ -980,7 +994,10 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, } else if (Symbol.isAbsolute() || RefSymbol.isVariable()) { MSD.SectionIndex = ELF::SHN_ABS; } else if (RefSymbol.isUndefined()) { - MSD.SectionIndex = ELF::SHN_UNDEF; + if (isSignature && !Used) + MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap[&Symbol]); + else + MSD.SectionIndex = ELF::SHN_UNDEF; } else { const MCSectionELF &Section = static_cast(RefSymbol.getSection()); @@ -1252,10 +1269,9 @@ bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout, - GroupMapTy &GroupMap) { - typedef DenseMap RevGroupMapTy; + GroupMapTy &GroupMap, + RevGroupMapTy &RevGroupMap) { // Build the groups - RevGroupMapTy Groups; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionELF &Section = @@ -1265,7 +1281,7 @@ void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, const MCSymbol *SignatureSymbol = Section.getGroup(); Asm.getOrCreateSymbolData(*SignatureSymbol); - const MCSectionELF *&Group = Groups[SignatureSymbol]; + const MCSectionELF *&Group = RevGroupMap[SignatureSymbol]; if (!Group) { Group = Asm.getContext().CreateELFGroupSection(); MCSectionData &Data = Asm.getOrCreateSectionData(*Group); @@ -1278,22 +1294,22 @@ void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, // Add sections to the groups unsigned Index = 1; - unsigned NumGroups = Groups.size(); + unsigned NumGroups = RevGroupMap.size(); for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it, ++Index) { const MCSectionELF &Section = static_cast(it->getSection()); if (!(Section.getFlags() & MCSectionELF::SHF_GROUP)) continue; - const MCSectionELF *Group = Groups[Section.getGroup()]; + const MCSectionELF *Group = RevGroupMap[Section.getGroup()]; MCSectionData &Data = Asm.getOrCreateSectionData(*Group); // FIXME: we could use the previous fragment MCDataFragment *F = new MCDataFragment(&Data); String32(*F, NumGroups + Index); } - for (RevGroupMapTy::const_iterator i = Groups.begin(), e = Groups.end(); - i != e; ++i) { + for (RevGroupMapTy::const_iterator i = RevGroupMap.begin(), + e = RevGroupMap.end(); i != e; ++i) { const MCSectionELF *Group = i->second; MCSectionData &Data = Asm.getOrCreateSectionData(*Group); Asm.AddSectionToTheEnd(*this, Data, Layout); @@ -1373,14 +1389,16 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, void ELFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { GroupMapTy GroupMap; - CreateGroupSections(Asm, const_cast(Layout), GroupMap); + RevGroupMapTy RevGroupMap; + CreateGroupSections(Asm, const_cast(Layout), GroupMap, + RevGroupMap); SectionIndexMapTy SectionIndexMap; ComputeIndexMap(Asm, SectionIndexMap); // Compute symbol table information. - ComputeSymbolTable(Asm, SectionIndexMap); + ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap); CreateMetadataSections(const_cast(Asm), const_cast(Layout), diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 830bd4f4ea5..1f4f1461a57 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -84,6 +84,7 @@ public: virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void SwitchSection(const MCSection *Section); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { assert(0 && "ELF doesn't support this directive"); @@ -282,6 +283,13 @@ public: }; } // end anonymous namespace +void MCELFStreamer::SwitchSection(const MCSection *Section) { + const MCSymbol *Grp = static_cast(Section)->getGroup(); + if (Grp) + getAssembler().getOrCreateSymbolData(*Grp); + this->MCObjectStreamer::SwitchSection(Section); +} + void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { getAssembler().getOrCreateSymbolData(*Symbol); MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias); diff --git a/test/MC/ELF/comdat.s b/test/MC/ELF/comdat.s index ba4c9c7abbf..745dfbbdc8b 100644 --- a/test/MC/ELF/comdat.s +++ b/test/MC/ELF/comdat.s @@ -1,31 +1,76 @@ // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck %s -// Test that we produce the two group sections and that they are a the beginning +// Test that we produce the group sections and that they are a the beginning // of the file. // CHECK: # Section 0x00000001 -// CHECK-NEXT: (('sh_name', 0x00000021) # '.group' +// CHECK-NEXT: (('sh_name', 0x00000026) # '.group' // CHECK-NEXT: ('sh_type', 0x00000011) // CHECK-NEXT: ('sh_flags', 0x00000000) // CHECK-NEXT: ('sh_addr', 0x00000000) // CHECK-NEXT: ('sh_offset', 0x00000040) // CHECK-NEXT: ('sh_size', 0x0000000c) -// CHECK-NEXT: ('sh_link', 0x0000000a) +// CHECK-NEXT: ('sh_link', 0x0000000c) // CHECK-NEXT: ('sh_info', 0x00000001) // CHECK-NEXT: ('sh_addralign', 0x00000004) // CHECK-NEXT: ('sh_entsize', 0x00000004) // CHECK-NEXT: ), // CHECK-NEXT: # Section 0x00000002 -// CHECK-NEXT: (('sh_name', 0x00000021) # '.group' +// CHECK-NEXT: (('sh_name', 0x00000026) # '.group' // CHECK-NEXT: ('sh_type', 0x00000011) // CHECK-NEXT: ('sh_flags', 0x00000000) // CHECK-NEXT: ('sh_addr', 0x00000000) // CHECK-NEXT: ('sh_offset', 0x0000004c) // CHECK-NEXT: ('sh_size', 0x00000008) -// CHECK-NEXT: ('sh_link', 0x0000000a) +// CHECK-NEXT: ('sh_link', 0x0000000c) // CHECK-NEXT: ('sh_info', 0x00000002) // CHECK-NEXT: ('sh_addralign', 0x00000004) // CHECK-NEXT: ('sh_entsize', 0x00000004) +// CHECK-NEXT: ), +// CHECK-NEXT: # Section 0x00000003 +// CHECK-NEXT: (('sh_name', 0x00000026) # '.group' +// CHECK-NEXT: ('sh_type', 0x00000011) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000054) +// CHECK-NEXT: ('sh_size', 0x00000008) +// CHECK-NEXT: ('sh_link', 0x0000000c) +// CHECK-NEXT: ('sh_info', 0x0000000d) +// CHECK-NEXT: ('sh_addralign', 0x00000004) +// CHECK-NEXT: ('sh_entsize', 0x00000004) +// CHECK-NEXT: ), + +// Test that g1 and g2 are local, but g3 is an undefined global. + +// CHECK: # Symbol 0x00000001 +// CHECK-NEXT: (('st_name', 0x00000001) # 'g1' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000007) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000002 +// CHECK-NEXT: (('st_name', 0x00000004) # 'g2' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000002) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), + +// CHECK: # Symbol 0x0000000d +// CHECK-NEXT: (('st_name', 0x00000007) # 'g3' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000000) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), + .section .foo,"axG",@progbits,g1,comdat g1: @@ -35,5 +80,7 @@ g1: nop .section .zed,"axG",@progbits,g2,comdat -g2: nop + + .section .baz,"axG",@progbits,g3,comdat + .long g3 -- 2.34.1