[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