Make it possible to set SHF_LINK_ORDER explicitly.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 9 Feb 2017 14:59:20 +0000 (14:59 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 9 Feb 2017 14:59:20 +0000 (14:59 +0000)
This will make it possible to add support for gcing user metadata
(asan for example).

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

docs/Extensions.rst
include/llvm/MC/MCContext.h
lib/MC/ELFObjectWriter.cpp
lib/MC/MCContext.cpp
lib/MC/MCParser/ELFAsmParser.cpp
test/MC/ELF/section-metadata-err1.s [new file with mode: 0644]
test/MC/ELF/section-metadata-err2.s [new file with mode: 0644]
test/MC/ELF/section-metadata-err3.s [new file with mode: 0644]
test/MC/ELF/section-metadata-err4.s [new file with mode: 0644]
test/MC/ELF/section.s

index 56bb279305963a0acfd7c7b99c7ec2e59425030b..782539dda58e115a43845bb27825498707f51ab2 100644 (file)
@@ -204,6 +204,24 @@ For example, the following code creates two sections named ``.text``.
 The unique number is not present in the resulting object at all. It is just used
 in the assembler to differentiate the sections.
 
+The 'm' flag is mapped to SHF_LINK_ORDER. If it is present, a symbol
+must be given that identifies the section to be placed is the
+.sh_link.
+
+.. code-block:: gas
+
+        .section .foo,"a",@progbits
+        .Ltmp:
+        .section .bar,"am",@progbits,.Ltmp
+
+which is equivalent to just
+
+.. code-block:: gas
+
+        .section .foo,"a",@progbits
+        .section .bar,"am",@progbits,.foo
+
+
 Target Specific Behaviour
 =========================
 
index b73c74db5d7d9940734614be9fe70063e6779c18..edfbfaef232ed7a49fd7447fef5d154129125f88 100644 (file)
@@ -357,7 +357,15 @@ namespace llvm {
 
     MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
                                 unsigned Flags, unsigned EntrySize,
-                                const Twine &Group, unsigned UniqueID);
+                                const Twine &Group, unsigned UniqueID) {
+      return getELFSection(Section, Type, Flags, EntrySize, Group, UniqueID,
+                           nullptr);
+    }
+
+    MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
+                                unsigned Flags, unsigned EntrySize,
+                                const Twine &Group, unsigned UniqueID,
+                                const MCSectionELF *Associated);
 
     MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
                                 unsigned Flags, unsigned EntrySize,
index e9f4f1cce3383f1f08c68c033b0600c8179c7b2c..3d1a16c904c9e0bb7edaef836186092cc318ac56 100644 (file)
@@ -1157,8 +1157,7 @@ void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
     break;
   }
 
-  if (TargetObjectWriter->getEMachine() == ELF::EM_ARM &&
-      Section.getType() == ELF::SHT_ARM_EXIDX)
+  if (Section.getFlags() & ELF::SHF_LINK_ORDER)
     sh_link = SectionIndexMap.lookup(Section.getAssociatedSection());
 
   WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()),
index 2bfd8e55cadd22377b777ae5f56c5f4b2e2b5c3f..19aa73efc2156d0dd0040467f01c8f91d6586169 100644 (file)
@@ -358,13 +358,14 @@ MCSectionELF *MCContext::getELFNamedSection(const Twine &Prefix,
 
 MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
                                        unsigned Flags, unsigned EntrySize,
-                                       const Twine &Group, unsigned UniqueID) {
+                                       const Twine &Group, unsigned UniqueID,
+                                       const MCSectionELF *Associated) {
   MCSymbolELF *GroupSym = nullptr;
   if (!Group.isTriviallyEmpty() && !Group.str().empty())
     GroupSym = cast<MCSymbolELF>(getOrCreateSymbol(Group));
 
   return getELFSection(Section, Type, Flags, EntrySize, GroupSym, UniqueID,
-                       nullptr);
+                       Associated);
 }
 
 MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
index 3bee12f68248177c23381b2047a666a635353cc2..b9426566b5c91f93fe6f061450ac68d43328446e 100644 (file)
@@ -157,6 +157,7 @@ private:
   bool maybeParseSectionType(StringRef &TypeName);
   bool parseMergeSize(int64_t &Size);
   bool parseGroup(StringRef &GroupName);
+  bool parseMetadataSym(MCSectionELF *&Associated);
   bool maybeParseUniqueID(int64_t &UniqueID);
 };
 
@@ -297,6 +298,9 @@ static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
     case 'w':
       flags |= ELF::SHF_WRITE;
       break;
+    case 'm':
+      flags |= ELF::SHF_LINK_ORDER;
+      break;
     case 'M':
       flags |= ELF::SHF_MERGE;
       break;
@@ -425,6 +429,21 @@ bool ELFAsmParser::parseGroup(StringRef &GroupName) {
   return false;
 }
 
+bool ELFAsmParser::parseMetadataSym(MCSectionELF *&Associated) {
+  MCAsmLexer &L = getLexer();
+  if (L.isNot(AsmToken::Comma))
+    return TokError("expected metadata symbol");
+  Lex();
+  StringRef Name;
+  if (getParser().parseIdentifier(Name))
+    return true;
+  MCSymbol *Sym = getContext().lookupSymbol(Name);
+  if (!Sym || !Sym->isInSection())
+    return TokError("symbol is not in a section: " + Name);
+  Associated = cast<MCSectionELF>(&Sym->getSection());
+  return false;
+}
+
 bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) {
   MCAsmLexer &L = getLexer();
   if (L.isNot(AsmToken::Comma))
@@ -460,6 +479,7 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
   const MCExpr *Subsection = nullptr;
   bool UseLastGroup = false;
   StringRef UniqueStr;
+  MCSectionELF *Associated = nullptr;
   int64_t UniqueID = ~0;
 
   // Set the defaults first.
@@ -522,6 +542,9 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
     if (Group)
       if (parseGroup(GroupName))
         return true;
+    if (Flags & ELF::SHF_LINK_ORDER)
+      if (parseMetadataSym(Associated))
+        return true;
     if (maybeParseUniqueID(UniqueID))
       return true;
   }
@@ -571,8 +594,8 @@ EndStmt:
       }
   }
 
-  MCSection *ELFSection = getContext().getELFSection(SectionName, Type, Flags,
-                                                     Size, GroupName, UniqueID);
+  MCSection *ELFSection = getContext().getELFSection(
+      SectionName, Type, Flags, Size, GroupName, UniqueID, Associated);
   getStreamer().SwitchSection(ELFSection, Subsection);
 
   if (getContext().getGenDwarfForAssembly()) {
diff --git a/test/MC/ELF/section-metadata-err1.s b/test/MC/ELF/section-metadata-err1.s
new file mode 100644 (file)
index 0000000..eb468f6
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: not llvm-mc -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s
+
+// CHECK: error: symbol is not in a section: foo
+
+        .section .shf_metadata,"am",@progbits,foo
diff --git a/test/MC/ELF/section-metadata-err2.s b/test/MC/ELF/section-metadata-err2.s
new file mode 100644 (file)
index 0000000..032e000
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: not llvm-mc -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s
+
+// CHECK: error: symbol is not in a section: foo
+
+        .quad foo
+        .section .shf_metadata,"am",@progbits,foo
diff --git a/test/MC/ELF/section-metadata-err3.s b/test/MC/ELF/section-metadata-err3.s
new file mode 100644 (file)
index 0000000..4d8d0e2
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: not llvm-mc -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s
+
+// CHECK: error: symbol is not in a section: foo
+
+        foo = 42
+        .section .shf_metadata,"am",@progbits,foo
diff --git a/test/MC/ELF/section-metadata-err4.s b/test/MC/ELF/section-metadata-err4.s
new file mode 100644 (file)
index 0000000..3c843c0
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: not llvm-mc -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s
+
+// CHECK: error: expected metadata symbol
+
+        .section .shf_metadata,"am",@progbits
index 0277be5223617073168f48ed3d953d71529f6e4d..f70139f36ba2931ee2a976fde2f6620ebb65a897 100644 (file)
@@ -149,3 +149,69 @@ bar:
 // CHECK:          Name: bar-"foo"
 // CHECK:        Section {
 // CHECK:          Name: foo
+
+// Test SHF_LINK_ORDER
+
+.section .shf_metadata_target1, "a"
+        .quad 0
+.section .shf_metadata_target2, "a", @progbits, unique, 1
+.Lshf_metadata_target2_1:
+        .quad 0
+.section .shf_metadata_target2, "a", @progbits, unique, 2
+.Lshf_metadata_target2_2:
+        .quad 0
+
+.section .shf_metadata1,"am",@progbits,.Lshf_metadata_target2_1
+.section .shf_metadata2,"am",@progbits,.Lshf_metadata_target2_2
+.section .shf_metadata3,"am",@progbits,.shf_metadata_target1
+
+// CHECK:      Section {
+// CHECK:        Index: 22
+// CHECK-NEXT:   Name: .shf_metadata_target1
+
+// CHECK:      Section {
+// CHECK:        Index: 23
+// CHECK-NEXT:   Name: .shf_metadata_target2
+
+// CHECK:      Section {
+// CHECK:        Index: 24
+// CHECK-NEXT:   Name: .shf_metadata_target2
+
+// CHECK:      Section {
+// CHECK:        Name: .shf_metadata1
+// CHECK-NEXT:   Type: SHT_PROGBITS
+// CHECK-NEXT:   Flags [
+// CHECK-NEXT:     SHF_ALLOC
+// CHECK-NEXT:     SHF_LINK_ORDER
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Address:
+// CHECK-NEXT:   Offset:
+// CHECK-NEXT:   Size:
+// CHECK-NEXT:   Link:    23
+// CHECK-NEXT:   Info:    0
+
+// CHECK:      Section {
+// CHECK:        Name: .shf_metadata2
+// CHECK-NEXT:   Type: SHT_PROGBITS
+// CHECK-NEXT:   Flags [
+// CHECK-NEXT:     SHF_ALLOC
+// CHECK-NEXT:     SHF_LINK_ORDER
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Address:
+// CHECK-NEXT:   Offset:
+// CHECK-NEXT:   Size:
+// CHECK-NEXT:   Link:    24
+// CHECK-NEXT:   Info:    0
+
+// CHECK:      Section {
+// CHECK:        Name: .shf_metadata3
+// CHECK-NEXT:   Type: SHT_PROGBITS
+// CHECK-NEXT:   Flags [
+// CHECK-NEXT:     SHF_ALLOC
+// CHECK-NEXT:     SHF_LINK_ORDER
+// CHECK-NEXT:   ]
+// CHECK-NEXT:   Address:
+// CHECK-NEXT:   Offset:
+// CHECK-NEXT:   Size:
+// CHECK-NEXT:   Link:    22
+// CHECK-NEXT:   Info:    0