diff --git a/docs/Extensions.rst b/docs/Extensions.rst index 9f33d30ac7b..f499bdd57e6 100644 --- a/docs/Extensions.rst +++ b/docs/Extensions.rst @@ -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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 40d90096263..e26b4116bbf 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -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. diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index ca49f8f5908..099ce3048db 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -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(); } diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index d8343a3eea1..cc356c7a174 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -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) { diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 2e1d69b77f6..22e1d47b000 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -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"); } diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index d6b2f2402b5..06c7227e573 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -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(); diff --git a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp index 6da414287cf..31dc1107ecc 100644 --- a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp @@ -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: