Correctly handle references to section symbols.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 15 Oct 2014 18:55:30 +0000 (18:55 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 15 Oct 2014 18:55:30 +0000 (18:55 +0000)
When processing assembly like

.long .text

we were creating a new undefined symbol .text. GAS on the other hand would
handle that as a reference to the .text section.

This patch implements that by creating the section symbols earlier so that
they are visible during asm parsing.

The patch also updates llvm-readobj to print the symbol number in the relocation
dump so that the test can differentiate between two sections with the same name.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219829 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCContext.h
lib/MC/ELFObjectWriter.cpp
lib/MC/MCContext.cpp
lib/MC/MCELFStreamer.cpp
test/MC/ELF/comdat.s
test/MC/ELF/section-sym-err.s [new file with mode: 0644]
test/MC/ELF/section-sym.s [new file with mode: 0644]
tools/llvm-readobj/ELFDumper.cpp

index 69365a3..f209448 100644 (file)
@@ -73,6 +73,10 @@ namespace llvm {
     /// Symbols - Bindings of names to symbols.
     SymbolTable Symbols;
 
+    /// ELF sections can have a corresponding symbol. This maps one to the
+    /// other.
+    DenseMap<const MCSectionELF*, MCSymbol*> SectionSymbols;
+
     /// A maping from a local label number and an instance count to a symbol.
     /// For example, in the assembly
     ///     1:
@@ -231,6 +235,8 @@ namespace llvm {
     MCSymbol *GetOrCreateSymbol(StringRef Name);
     MCSymbol *GetOrCreateSymbol(const Twine &Name);
 
+    MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section);
+
     /// LookupSymbol - Get the symbol for \p Name, or null.
     MCSymbol *LookupSymbol(StringRef Name) const;
     MCSymbol *LookupSymbol(const Twine &Name) const;
index 4577f01..d77f03f 100644 (file)
@@ -81,23 +81,13 @@ public:
 
 struct ELFRelocationEntry {
   uint64_t Offset; // Where is the relocation.
-  bool UseSymbol;  // Relocate with a symbol, not the section.
-  union {
-    const MCSymbol *Symbol;       // The symbol to relocate with.
-    const MCSectionData *Section; // The section to relocate with.
-  };
+  const MCSymbol *Symbol;       // The symbol to relocate with.
   unsigned Type;   // The type of the relocation.
   uint64_t Addend; // The addend to use.
 
   ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type,
                      uint64_t Addend)
-      : Offset(Offset), UseSymbol(true), Symbol(Symbol), Type(Type),
-        Addend(Addend) {}
-
-  ELFRelocationEntry(uint64_t Offset, const MCSectionData *Section,
-                     unsigned Type, uint64_t Addend)
-      : Offset(Offset), UseSymbol(false), Section(Section), Type(Type),
-        Addend(Addend) {}
+      : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
 };
 
 class ELFObjectWriter : public MCObjectWriter {
@@ -137,6 +127,14 @@ class ELFObjectWriter : public MCObjectWriter {
 
       // Support lexicographic sorting.
       bool operator<(const ELFSymbolData &RHS) const {
+        unsigned LHSType = MCELF::GetType(*SymbolData);
+        unsigned RHSType = MCELF::GetType(*RHS.SymbolData);
+        if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION)
+          return false;
+        if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION)
+          return true;
+        if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION)
+          return SectionIndex < RHS.SectionIndex;
         return Name < RHS.Name;
       }
     };
@@ -651,22 +649,6 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF,
     WriteSymbol(Writer, MSD, Layout);
   }
 
-  // Write out a symbol table entry for each regular section.
-  for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e;
-       ++i) {
-    const MCSectionELF &Section =
-      static_cast<const MCSectionELF&>(i->getSection());
-    if (Section.getType() == ELF::SHT_RELA ||
-        Section.getType() == ELF::SHT_REL ||
-        Section.getType() == ELF::SHT_STRTAB ||
-        Section.getType() == ELF::SHT_SYMTAB ||
-        Section.getType() == ELF::SHT_SYMTAB_SHNDX)
-      continue;
-    Writer.writeSymbol(0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT,
-                       SectionIndexMap.lookup(&Section), false);
-    LastLocalSymbolIndex++;
-  }
-
   for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) {
     ELFSymbolData &MSD = ExternalSymbolData[i];
     MCSymbolData &Data = *MSD.SymbolData;
@@ -882,8 +864,11 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
   if (!RelocateWithSymbol) {
     const MCSection *SecA =
         (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
-    const MCSectionData *SecAD = SecA ? &Asm.getSectionData(*SecA) : nullptr;
-    ELFRelocationEntry Rec(FixupOffset, SecAD, Type, Addend);
+    auto *ELFSec = cast_or_null<MCSectionELF>(SecA);
+    MCSymbol *SectionSymbol =
+        ELFSec ? Asm.getContext().GetOrCreateSymbol(ELFSec->getSectionName())
+               : nullptr;
+    ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend);
     Relocations[FixupSection].push_back(Rec);
     return;
   }
@@ -1061,7 +1046,10 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
       Buf += Name.substr(Pos + Skip);
       Name = Buf;
     }
-    MSD.Name = StrTabBuilder.add(Name);
+
+    // Sections have their own string table
+    if (MCELF::GetType(SD) != ELF::STT_SECTION)
+      MSD.Name = StrTabBuilder.add(Name);
 
     if (MSD.SectionIndex == ELF::SHN_UNDEF)
       UndefinedSymbolData.push_back(MSD);
@@ -1079,9 +1067,11 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
   for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i)
     FileSymbolData.push_back(StrTabBuilder.getOffset(*i));
 
-  for (ELFSymbolData& MSD : LocalSymbolData)
-    MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
-  for (ELFSymbolData& MSD : ExternalSymbolData)
+  for (ELFSymbolData &MSD : LocalSymbolData)
+    MSD.StringIndex = MCELF::GetType(*MSD.SymbolData) == ELF::STT_SECTION
+                          ? 0
+                          : StrTabBuilder.getOffset(MSD.Name);
+  for (ELFSymbolData &MSD : ExternalSymbolData)
     MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
   for (ELFSymbolData& MSD : UndefinedSymbolData)
     MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name);
@@ -1097,8 +1087,6 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
   for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
     LocalSymbolData[i].SymbolData->setIndex(Index++);
 
-  Index += NumRegularSections;
-
   for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
     ExternalSymbolData[i].SymbolData->setIndex(Index++);
   for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
@@ -1354,18 +1342,8 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm,
 
   for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
     const ELFRelocationEntry &Entry = Relocs[e - i - 1];
-
-    unsigned Index;
-    if (Entry.UseSymbol) {
-      Index = getSymbolIndexInSymbolTable(Asm, Entry.Symbol);
-    } else {
-      const MCSectionData *Sec = Entry.Section;
-      if (Sec)
-        Index = Sec->getOrdinal() + FileSymbolData.size() +
-                LocalSymbolData.size() + 1;
-      else
-        Index = 0;
-    }
+    unsigned Index =
+        Entry.Symbol ? getSymbolIndexInSymbolTable(Asm, Entry.Symbol) : 0;
 
     if (is64Bit()) {
       write(*F, Entry.Offset);
index 9d8a57e..3ac8d65 100644 (file)
@@ -113,6 +113,23 @@ MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) {
   return Sym;
 }
 
+MCSymbol *MCContext::getOrCreateSectionSymbol(const MCSectionELF &Section) {
+  MCSymbol *&Sym = SectionSymbols[&Section];
+  if (Sym)
+    return Sym;
+
+  StringRef Name = Section.getSectionName();
+  StringMapEntry<bool> *NameEntry = &UsedNames.GetOrCreateValue(Name);
+  NameEntry->setValue(true);
+  Sym = new (*this) MCSymbol(NameEntry->getKey(), /*isTemporary*/ false);
+
+  StringMapEntry<MCSymbol*> &Entry = Symbols.GetOrCreateValue(Name);
+  if (!Entry.getValue())
+    Entry.setValue(Sym);
+
+  return Sym;
+}
+
 MCSymbol *MCContext::CreateSymbol(StringRef Name) {
   // Determine whether this is an assembler temporary or normal label, if used.
   bool isTemporary = false;
index 4ef22d0..bdc4a84 100644 (file)
@@ -92,10 +92,19 @@ void MCELFStreamer::ChangeSection(const MCSection *Section,
   MCSectionData *CurSection = getCurrentSectionData();
   if (CurSection && CurSection->isBundleLocked())
     report_fatal_error("Unterminated .bundle_lock when changing a section");
-  const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup();
+
+  MCAssembler &Asm = getAssembler();
+  auto *SectionELF = static_cast<const MCSectionELF *>(Section);
+  const MCSymbol *Grp = SectionELF->getGroup();
   if (Grp)
-    getAssembler().getOrCreateSymbolData(*Grp);
+    Asm.getOrCreateSymbolData(*Grp);
+
   this->MCObjectStreamer::ChangeSection(Section, Subsection);
+  MCSymbol *SectionSymbol = getContext().getOrCreateSectionSymbol(*SectionELF);
+  if (SectionSymbol->isUndefined()) {
+    EmitLabel(SectionSymbol);
+    MCELF::SetType(Asm.getSymbolData(*SectionSymbol), ELF::STT_SECTION);
+  }
 }
 
 void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
index ae2cc6b..4796675 100644 (file)
@@ -41,7 +41,7 @@
 // CHECK-NEXT:     Offset: 0x54
 // CHECK-NEXT:     Size: 12
 // CHECK-NEXT:     Link: 13
-// CHECK-NEXT:     Info: 13
+// CHECK-NEXT:     Info: 10
 // CHECK-NEXT:     AddressAlignment: 4
 // CHECK-NEXT:     EntrySize: 4
 // CHECK-NEXT:   }
diff --git a/test/MC/ELF/section-sym-err.s b/test/MC/ELF/section-sym-err.s
new file mode 100644 (file)
index 0000000..789fee7
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o 2>&1 | FileCheck %s
+
+.section foo
+foo:
+
+// CHECK: error: invalid symbol redefinition
diff --git a/test/MC/ELF/section-sym.s b/test/MC/ELF/section-sym.s
new file mode 100644 (file)
index 0000000..3b76d81
--- /dev/null
@@ -0,0 +1,91 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -s -t -r --expand-relocs | FileCheck %s
+
+.section foo, "aG", @progbits, f1, comdat
+.section foo, "G", @progbits, f2, comdat
+.section bar
+.long foo
+
+// Test that the relocation points to the first section foo.
+
+// The first seciton foo has index 6
+// CHECK:      Section {
+// CHECK:        Index:   6
+// CHECK-NEXT:   Name:    foo (28)
+// CHECK-NEXT:   Type:    SHT_PROGBITS (0x1)
+// CHECK-NEXT:   Flags [ (0x202)
+// CHECK-NEXT:     SHF_ALLOC (0x2)
+// CHECK-NEXT:     SHF_GROUP (0x200)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Address:         0x0
+// CHECK-NEXT:   Offset:  0x50
+// CHECK-NEXT:   Size:    0
+// CHECK-NEXT:   Link:    0
+// CHECK-NEXT:   Info:    0
+// CHECK-NEXT:   AddressAlignment:        1
+// CHECK-NEXT:   EntrySize:       0
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT:   Index:   7
+// CHECK-NEXT:   Name:    foo (28)
+// CHECK-NEXT:   Type:    SHT_PROGBITS (0x1)
+// CHECK-NEXT:   Flags [ (0x200)
+// CHECK-NEXT:     SHF_GROUP (0x200)
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Address:         0x0
+// CHECK-NEXT:   Offset:  0x50
+// CHECK-NEXT:   Size:    0
+// CHECK-NEXT:   Link:    0
+// CHECK-NEXT:   Info:    0
+// CHECK-NEXT:   AddressAlignment:        1
+// CHECK-NEXT:   EntrySize:       0
+// CHECK-NEXT: }
+
+// The relocation points to symbol 6
+// CHECK:      Relocations [
+// CHECK-NEXT:   Section (9) .relabar {
+// CHECK-NEXT:     Relocation {
+// CHECK-NEXT:       Offset:  0x0
+// CHECK-NEXT:       Type:    R_X86_64_32 (10)
+// CHECK-NEXT:       Symbol:  foo (6)
+// CHECK-NEXT:       Addend:  0x0
+// CHECK-NEXT:     }
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
+
+
+// The symbol 6 corresponds section 6
+// CHECK: Symbols [
+
+// symbol 0
+// CHECK-NOT: Name
+// CHECK: Name:
+
+// symbol 1
+// CHECK-NOT: Name
+// CHECK: Name:    f1
+
+// symbol 2
+// CHECK-NOT: Name
+// CHECK: Name:    f2
+
+// symbol 3
+// CHECK-NOT: Name
+// CHECK: Name:    .text
+
+// symbol 4
+// CHECK-NOT: Name
+// CHECK: Name:    .data
+
+// symbol 5
+// CHECK-NOT: Name
+// CHECK: Name:    .bss
+
+// symbol 6
+// CHECK-NOT: Name
+// CHECK: Name:    foo
+// CHECK: Section: foo (0x6)
+
+// symbol 7
+// CHECK-NOT: Name
+// CHECK: Name:    foo
+// CHECK: Section: foo (0x7)
index 6da3318..d68c786 100644 (file)
@@ -676,7 +676,8 @@ void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec,
     DictScope Group(W, "Relocation");
     W.printHex("Offset", Rel.r_offset);
     W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
-    W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-");
+    W.printNumber("Symbol", SymbolName.size() > 0 ? SymbolName : "-",
+                  Rel.getSymbol(Obj->isMips64EL()));
     W.printHex("Addend", Rel.r_addend);
   } else {
     raw_ostream& OS = W.startLine();