[llvm] r338063 - [MC] Add support for the .rva assembler directive for COFF targets

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 26 13:11:26 PDT 2018


Author: mstorsjo
Date: Thu Jul 26 13:11:26 2018
New Revision: 338063

URL: http://llvm.org/viewvc/llvm-project?rev=338063&view=rev
Log:
[MC] Add support for the .rva assembler directive for COFF targets

Even though gas doesn't document it, it has been supported there for
a very long time.

This produces the 32 bit relative virtual address (aka image relative
address) for a given symbol. ".rva foo" is essentially equal to
".long foo at imgrel".

Differential Revision: https://reviews.llvm.org/D49821

Modified:
    llvm/trunk/include/llvm/MC/MCStreamer.h
    llvm/trunk/include/llvm/MC/MCWinCOFFStreamer.h
    llvm/trunk/lib/MC/MCAsmStreamer.cpp
    llvm/trunk/lib/MC/MCParser/COFFAsmParser.cpp
    llvm/trunk/lib/MC/MCStreamer.cpp
    llvm/trunk/lib/MC/MCWinCOFFStreamer.cpp
    llvm/trunk/test/MC/COFF/relocation-imgrel.s

Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=338063&r1=338062&r2=338063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Thu Jul 26 13:11:26 2018
@@ -522,6 +522,11 @@ public:
   /// \param Symbol - Symbol the section relative relocation should point to.
   virtual void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset);
 
+  /// Emits a COFF image relative relocation.
+  ///
+  /// \param Symbol - Symbol the image relative relocation should point to.
+  virtual void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset);
+
   /// Emit an ELF .size directive.
   ///
   /// This corresponds to an assembler statement such as:

Modified: llvm/trunk/include/llvm/MC/MCWinCOFFStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCWinCOFFStreamer.h?rev=338063&r1=338062&r2=338063&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCWinCOFFStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCWinCOFFStreamer.h Thu Jul 26 13:11:26 2018
@@ -54,6 +54,7 @@ public:
   void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
   void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
   void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
+  void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
   void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         unsigned ByteAlignment) override;
   void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,

Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=338063&r1=338062&r2=338063&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Thu Jul 26 13:11:26 2018
@@ -165,6 +165,7 @@ public:
   void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
   void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
   void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
+  void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
   void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         unsigned ByteAlignment) override;
@@ -706,6 +707,16 @@ void MCAsmStreamer::EmitCOFFSecRel32(MCS
   EmitEOL();
 }
 
+void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
+  OS << "\t.rva\t";
+  Symbol->print(OS, MAI);
+  if (Offset > 0)
+    OS << '+' << Offset;
+  else if (Offset < 0)
+    OS << '-' << -Offset;
+  EmitEOL();
+}
+
 void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
   assert(MAI->hasDotTypeDotSizeDirective());
   OS << "\t.size\t";

Modified: llvm/trunk/lib/MC/MCParser/COFFAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/COFFAsmParser.cpp?rev=338063&r1=338062&r2=338063&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/COFFAsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/COFFAsmParser.cpp Thu Jul 26 13:11:26 2018
@@ -69,6 +69,7 @@ class COFFAsmParser : public MCAsmParser
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
     addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
+    addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
 
     // Win64 EH directives.
     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
@@ -134,6 +135,7 @@ class COFFAsmParser : public MCAsmParser
   bool ParseDirectiveSymIdx(StringRef, SMLoc);
   bool parseCOMDATType(COFF::COMDATType &Type);
   bool ParseDirectiveLinkOnce(StringRef, SMLoc);
+  bool ParseDirectiveRVA(StringRef, SMLoc);
 
   // Win64 EH directives.
   bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
@@ -492,6 +494,37 @@ bool COFFAsmParser::ParseDirectiveSecRel
   return false;
 }
 
+bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
+  auto parseOp = [&]() -> bool {
+    StringRef SymbolID;
+    if (getParser().parseIdentifier(SymbolID))
+      return TokError("expected identifier in directive");
+
+    int64_t Offset = 0;
+    SMLoc OffsetLoc;
+    if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
+      OffsetLoc = getLexer().getLoc();
+      if (getParser().parseAbsoluteExpression(Offset))
+        return true;
+    }
+
+    if (Offset < std::numeric_limits<int32_t>::min() ||
+        Offset > std::numeric_limits<int32_t>::max())
+      return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
+                              "than -2147483648 or greater than "
+                              "2147483647");
+
+    MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
+
+    getStreamer().EmitCOFFImgRel32(Symbol, Offset);
+    return false;
+  };
+
+  if (getParser().parseMany(parseOp))
+    return addErrorSuffix(" in directive");
+  return false;
+}
+
 bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
   StringRef SymbolID;
   if (getParser().parseIdentifier(SymbolID))

Modified: llvm/trunk/lib/MC/MCStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=338063&r1=338062&r2=338063&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCStreamer.cpp Thu Jul 26 13:11:26 2018
@@ -830,6 +830,8 @@ void MCStreamer::EmitCOFFSectionIndex(MC
 
 void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
 
+void MCStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}
+
 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
 /// the specified string in the output .s file.  This capability is
 /// indicated by the hasRawTextSupport() predicate.

Modified: llvm/trunk/lib/MC/MCWinCOFFStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCWinCOFFStreamer.cpp?rev=338063&r1=338062&r2=338063&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCWinCOFFStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCWinCOFFStreamer.cpp Thu Jul 26 13:11:26 2018
@@ -232,6 +232,25 @@ void MCWinCOFFStreamer::EmitCOFFSecRel32
   DF->getContents().resize(DF->getContents().size() + 4, 0);
 }
 
+void MCWinCOFFStreamer::EmitCOFFImgRel32(const MCSymbol *Symbol,
+                                         int64_t Offset) {
+  visitUsedSymbol(*Symbol);
+  MCDataFragment *DF = getOrCreateDataFragment();
+  // Create Symbol A for the relocation relative reference.
+  const MCExpr *MCE = MCSymbolRefExpr::create(
+      Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
+  // Add the constant offset, if given.
+  if (Offset)
+    MCE = MCBinaryExpr::createAdd(
+        MCE, MCConstantExpr::create(Offset, getContext()), getContext());
+  // Build the imgrel relocation.
+  MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
+  // Record the relocation.
+  DF->getFixups().push_back(Fixup);
+  // Emit 4 bytes (zeros) to the object file.
+  DF->getContents().resize(DF->getContents().size() + 4, 0);
+}
+
 void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
                                          unsigned ByteAlignment) {
   auto *Symbol = cast<MCSymbolCOFF>(S);

Modified: llvm/trunk/test/MC/COFF/relocation-imgrel.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/relocation-imgrel.s?rev=338063&r1=338062&r2=338063&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/relocation-imgrel.s (original)
+++ llvm/trunk/test/MC/COFF/relocation-imgrel.s Thu Jul 26 13:11:26 2018
@@ -3,15 +3,23 @@
 // Test that we produce image-relative relocations (IMAGE_REL_I386_DIR32NB
 // and IMAGE_REL_AMD64_ADDR32NB) when accessing foo at imgrel.
 
-// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s | llvm-readobj -r | FileCheck --check-prefix=W32 %s
-// RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s | llvm-readobj -r | FileCheck --check-prefix=W64 %s
+// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s > %t.w32.obj
+// RUN: llvm-readobj -r %t.w32.obj | FileCheck --check-prefix=W32 %s
+// RUN: llvm-objdump -s %t.w32.obj | FileCheck --check-prefix=W32OBJ %s
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s > %t.w64.obj
+// RUN: llvm-readobj -r %t.w64.obj | FileCheck --check-prefix=W64 %s
+// RUN: llvm-objdump -s %t.w64.obj | FileCheck --check-prefix=W64OBJ %s
 
 .data
 foo:
     .long 1
+    .long .Llabel at imgrel
+    .rva .Llabel, .Llabel + 16, foo, .Lother - 3
 
 .text
+.Llabel:
     mov foo at IMGREL(%ebx, %ecx, 4), %eax
+.Lother:
     mov foo at imgrel(%ebx, %ecx, 4), %eax
 
 // W32:      Relocations [
@@ -19,11 +27,33 @@ foo:
 // W32-NEXT:     0x3 IMAGE_REL_I386_DIR32NB foo
 // W32-NEXT:     0xA IMAGE_REL_I386_DIR32NB foo
 // W32-NEXT:   }
+// W32-NEXT:   Section (2) .data {
+// W32-NEXT:     0x4 IMAGE_REL_I386_DIR32NB .Llabel
+// W32-NEXT:     0x8 IMAGE_REL_I386_DIR32NB .Llabel
+// W32-NEXT:     0xC IMAGE_REL_I386_DIR32NB .Llabel
+// W32-NEXT:     0x10 IMAGE_REL_I386_DIR32NB foo
+// W32-NEXT:     0x14 IMAGE_REL_I386_DIR32NB .Lother
+// W32-NEXT:   }
 // W32-NEXT: ]
 
+// W32OBJ:      Contents of section .data:
+// W32OBJ-NEXT:  0000 01000000 00000000 00000000 10000000
+// W32OBJ-NEXT:  0010 00000000 fdffffff
+
 // W64:      Relocations [
 // W64-NEXT:   Section (1) .text {
 // W64-NEXT:     0x4 IMAGE_REL_AMD64_ADDR32NB foo
 // W64-NEXT:     0xC IMAGE_REL_AMD64_ADDR32NB foo
 // W64-NEXT:   }
+// W64-NEXT:   Section (2) .data {
+// W64-NEXT:     0x4 IMAGE_REL_AMD64_ADDR32NB .text
+// W64-NEXT:     0x8 IMAGE_REL_AMD64_ADDR32NB .text
+// W64-NEXT:     0xC IMAGE_REL_AMD64_ADDR32NB .text
+// W64-NEXT:     0x10 IMAGE_REL_AMD64_ADDR32NB foo
+// W64-NEXT:     0x14 IMAGE_REL_AMD64_ADDR32NB .text
+// W64-NEXT:   }
 // W64-NEXT: ]
+
+// W64OBJ:      Contents of section .data:
+// W64OBJ-NEXT:  0000 01000000 00000000 00000000 10000000
+// W64OBJ-NEXT:  0010 00000000 05000000




More information about the llvm-commits mailing list