/// \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:
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,
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;
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";
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
// Win64 EH directives.
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
bool ParseDirectiveSymIdx(StringRef, SMLoc);
bool parseCOMDATType(COFF::COMDATType &Type);
bool ParseDirectiveLinkOnce(StringRef, SMLoc);
+ bool ParseDirectiveRVA(StringRef, SMLoc);
// Win64 EH directives.
bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
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))
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.
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);
// Test that we produce image-relative relocations (IMAGE_REL_I386_DIR32NB
// and IMAGE_REL_AMD64_ADDR32NB) when accessing foo@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@imgrel
+ .rva .Llabel, .Llabel + 16, foo, .Lother - 3
.text
+.Llabel:
mov foo@IMGREL(%ebx, %ecx, 4), %eax
+.Lother:
mov foo@imgrel(%ebx, %ecx, 4), %eax
// W32: Relocations [
// 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