[COFF] Add support for the .secidx directive
authorTimur Iskhodzhanov <timurrrr@google.com>
Fri, 20 Dec 2013 18:15:00 +0000 (18:15 +0000)
committerTimur Iskhodzhanov <timurrrr@google.com>
Fri, 20 Dec 2013 18:15:00 +0000 (18:15 +0000)
Reviewed at http://llvm-reviews.chandlerc.com/D2445

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

docs/Extensions.rst
include/llvm/MC/MCStreamer.h
lib/MC/MCAsmStreamer.cpp
lib/MC/MCParser/COFFAsmParser.cpp
lib/MC/MCStreamer.cpp
lib/MC/WinCOFFStreamer.cpp
lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp

index 9f33d30ac7b5b607baa3713670c7404a0fce6181..f499bdd57e6ef823af9abfaa9e07b2ab67e9f977 100644 (file)
@@ -37,7 +37,7 @@ X86/COFF-Dependent
 Relocations
 ^^^^^^^^^^^
 
-The following additional relocation type is supported:
+The following additional relocation types are supported:
 
 **@IMGREL** (AT&T syntax only) generates an image-relative relocation that
 corresponds to the COFF relocation types ``IMAGE_REL_I386_DIR32NB`` (32-bit) or
@@ -54,6 +54,22 @@ corresponds to the COFF relocation types ``IMAGE_REL_I386_DIR32NB`` (32-bit) or
     .long (fun@imgrel + 0x3F)
     .long $unwind$fun@imgrel
 
+**.secrel32** generates a relocation that corresponds to the COFF relocation
+types ``IMAGE_REL_I386_SECREL`` (32-bit) or ``IMAGE_REL_AMD64_SECREL`` (64-bit).
+
+**.secidx** relocation generates an index of the section that contains
+the target.  It corresponds to the COFF relocation types
+``IMAGE_REL_I386_SECTION`` (32-bit) or ``IMAGE_REL_AMD64_SECTION`` (64-bit).
+
+.. code-block:: gas
+
+  .section .debug$S,"rn"
+    .long 4
+    .long 242
+    .long 40
+    .secrel32 _function_name
+    .secidx   _function_name
+    ...
 
 ``.linkonce`` Directive
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 40d90096263f16919ac1b90b2ff184b8c8c0b942..e26b4116bbf1dab5adcd857150b6ed6ef97c248f 100644 (file)
@@ -411,6 +411,11 @@ public:
   /// EndCOFFSymbolDef - Marks the end of the symbol definition.
   virtual void EndCOFFSymbolDef() = 0;
 
+  /// EmitCOFFSectionIndex - Emits a COFF section index.
+  ///
+  /// @param Symbol - Symbol the section number relocation should point to.
+  virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol);
+
   /// EmitCOFFSecRel32 - Emits a COFF section relative relocation.
   ///
   /// @param Symbol - Symbol the section relative relocation should point to.
index ca49f8f5908e077bc2270cab4f67c65942704e9b..099ce3048db408182e664cb48a82882c5453bda0 100644 (file)
@@ -160,6 +160,7 @@ public:
   virtual void EmitCOFFSymbolStorageClass(int StorageClass);
   virtual void EmitCOFFSymbolType(int Type);
   virtual void EndCOFFSymbolDef();
+  virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol);
   virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
   virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@@ -505,8 +506,13 @@ void MCAsmStreamer::EndCOFFSymbolDef() {
   EmitEOL();
 }
 
+void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
+  OS << "\t.secidx\t" << *Symbol;
+  EmitEOL();
+}
+
 void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
-  OS << "\t.secrel32\t" << *Symbol << '\n';
+  OS << "\t.secrel32\t" << *Symbol;
   EmitEOL();
 }
 
index d8343a3eea1b67a6368e7311d829692185beb608..cc356c7a1748482c19b41baa61e24e5fc60f8b20 100644 (file)
@@ -55,6 +55,7 @@ class COFFAsmParser : public MCAsmParserExtension {
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
+    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
 
     // Win64 EH directives.
@@ -115,6 +116,7 @@ class COFFAsmParser : public MCAsmParserExtension {
   bool ParseDirectiveType(StringRef, SMLoc);
   bool ParseDirectiveEndef(StringRef, SMLoc);
   bool ParseDirectiveSecRel32(StringRef, SMLoc);
+  bool ParseDirectiveSecIdx(StringRef, SMLoc);
   bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
                                const MCSectionCOFF *&Assoc);
   bool ParseDirectiveLinkOnce(StringRef, SMLoc);
@@ -432,7 +434,7 @@ bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
 bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
   StringRef SymbolID;
   if (getParser().parseIdentifier(SymbolID))
-    return true;
+    return TokError("expected identifier in directive");
 
   if (getLexer().isNot(AsmToken::EndOfStatement))
     return TokError("unexpected token in directive");
@@ -444,6 +446,21 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
   return false;
 }
 
+bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
+  StringRef SymbolID;
+  if (getParser().parseIdentifier(SymbolID))
+    return TokError("expected identifier in directive");
+
+  if (getLexer().isNot(AsmToken::EndOfStatement))
+    return TokError("unexpected token in directive");
+
+  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
+
+  Lex();
+  getStreamer().EmitCOFFSectionIndex(Symbol);
+  return false;
+}
+
 /// ::= [ identifier [ identifier ] ]
 bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
                                             const MCSectionCOFF *&Assoc) {
index 2e1d69b77f6f0cb8d5a7745e744aa1fdf8d6049e..22e1d47b000005b1912eaeb4e8e4bec9c63d61c8 100644 (file)
@@ -566,6 +566,10 @@ void MCStreamer::EmitWin64EHEndProlog() {
   EmitLabel(CurFrame->PrologEnd);
 }
 
+void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
+  llvm_unreachable("This file format doesn't support this directive");
+}
+
 void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
   llvm_unreachable("This file format doesn't support this directive");
 }
index d6b2f2402b54221ff6fdbeb69340850f466b6661..06c7227e573a5fa2d85dde99d9f895b6c11fec89 100644 (file)
@@ -61,6 +61,7 @@ public:
   virtual void EmitCOFFSymbolStorageClass(int StorageClass);
   virtual void EmitCOFFSymbolType(int Type);
   virtual void EndCOFFSymbolDef();
+  virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol);
   virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
   virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@@ -249,6 +250,17 @@ void WinCOFFStreamer::EndCOFFSymbolDef() {
   CurSymbol = NULL;
 }
 
+void WinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol)
+{
+  MCDataFragment *DF = getOrCreateDataFragment();
+
+  DF->getFixups().push_back(
+      MCFixup::Create(DF->getContents().size(),
+                      MCSymbolRefExpr::Create (Symbol, getContext ()),
+                      FK_SecRel_2));
+  DF->getContents().resize(DF->getContents().size() + 4, 0);
+}
+
 void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol)
 {
   MCDataFragment *DF = getOrCreateDataFragment();
index 6da414287cfcb57ea7ca911e59050c63503f7ddb..31dc1107eccfddf5147d69aa6e0ed1b17b5776d0 100644 (file)
@@ -65,6 +65,9 @@ unsigned X86WinCOFFObjectWriter::getRelocType(const MCValue &Target,
     if (Is64Bit)
       return COFF::IMAGE_REL_AMD64_ADDR64;
     llvm_unreachable("unsupported relocation type");
+  case FK_SecRel_2:
+    return Is64Bit ? COFF::IMAGE_REL_AMD64_SECTION
+                   : COFF::IMAGE_REL_I386_SECTION;
   case FK_SecRel_4:
     return Is64Bit ? COFF::IMAGE_REL_AMD64_SECREL : COFF::IMAGE_REL_I386_SECREL;
   default: