From 18d49acdab79d6f0966b47182b6c3a2ba3d9f80f Mon Sep 17 00:00:00 2001 From: Nico Rieck Date: Wed, 10 Apr 2013 23:28:17 +0000 Subject: [PATCH] MC: Support COFF image-relative MCSymbolRefs Add support for the COFF relocation types IMAGE_REL_I386_DIR32NB and IMAGE_REL_AMD64_ADDR32NB for 32- and 64-bit respectively. These are similar to normal 4-byte relocations except that they do not include the base address of the image. Image-relative relocations are used for debug information (32-bit) and SEH unwind tables (64-bit). A new MCSymbolRef variant called 'VK_COFF_IMGREL32' is introduced to specify such relocations. For AT&T assembly, this variant can be accessed using the symbol suffix '@imgrel'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179240 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/Extensions.rst | 39 +++++++++++++++++++ docs/index.rst | 4 ++ include/llvm/MC/MCExpr.h | 4 +- include/llvm/MC/MCWinCOFFObjectWriter.h | 6 ++- lib/MC/MCExpr.cpp | 3 ++ lib/MC/WinCOFFObjectWriter.cpp | 9 +---- .../MCTargetDesc/X86WinCOFFObjectWriter.cpp | 18 ++++++++- test/MC/COFF/relocation-imgrel.s | 29 ++++++++++++++ 8 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 docs/Extensions.rst create mode 100644 test/MC/COFF/relocation-imgrel.s diff --git a/docs/Extensions.rst b/docs/Extensions.rst new file mode 100644 index 00000000000..062804a9fc7 --- /dev/null +++ b/docs/Extensions.rst @@ -0,0 +1,39 @@ +=============== +LLVM Extensions +=============== + +.. contents:: + :local: + :depth: 1 + +.. toctree:: + :hidden: + +Introduction +============ + +This document describes extensions to tools and formats LLVM seeks compatibility +with. + +Machine-specific Assembly Syntax +================================ + +X86/COFF-Dependent +------------------ + +The following additional relocation type is 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 +``IMAGE_REL_AMD64_ADDR32NB`` (64-bit). + +.. code-block:: gas + + .text + fun: + mov foo@IMGREL(%ebx, %ecx, 4), %eax + + .section .pdata + .long fun@IMGREL + .long (fun@imgrel + 0x3F) + .long $unwind$fun@imgrel diff --git a/docs/index.rst b/docs/index.rst index c3bb8089da3..6b182dac560 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -160,6 +160,7 @@ For developers of applications which use LLVM as a library. ExtendingLLVM HowToSetUpLLVMStyleRTTI ProgrammersManual + Extensions :doc:`LLVM Language Reference Manual ` Defines the LLVM intermediate representation and the assembly form of the @@ -172,6 +173,9 @@ For developers of applications which use LLVM as a library. Introduction to the general layout of the LLVM sourcebase, important classes and APIs, and some tips & tricks. +:doc:`Extensions` + LLVM-specific extensions to tools and formats LLVM seeks compatibility with. + :doc:`CommandLine` Provides information on using the command line parsing library. diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index b5bfed18eca..a2c5bd3f766 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -216,7 +216,9 @@ public: VK_Mips_GOT_HI16, VK_Mips_GOT_LO16, VK_Mips_CALL_HI16, - VK_Mips_CALL_LO16 + VK_Mips_CALL_LO16, + + VK_COFF_IMGREL32 // symbol@imgrel (image-relative) }; private: diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index 11df5749d45..f13e7d54802 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -11,7 +11,9 @@ #define LLVM_MC_MCWINCOFFOBJECTWRITER_H namespace llvm { + class MCFixup; class MCObjectWriter; + class MCValue; class raw_ostream; class MCWinCOFFObjectTargetWriter { @@ -24,7 +26,9 @@ namespace llvm { virtual ~MCWinCOFFObjectTargetWriter() {} unsigned getMachine() const { return Machine; } - virtual unsigned getRelocType(unsigned FixupKind) const = 0; + virtual unsigned getRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsCrossSection) const = 0; }; /// \brief Construct a new Win COFF writer instance. diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index cd4d144575b..d54c2641834 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -250,6 +250,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_Mips_GOT_LO16: return "GOT_LO16"; case VK_Mips_CALL_HI16: return "CALL_HI16"; case VK_Mips_CALL_LO16: return "CALL_LO16"; + case VK_COFF_IMGREL32: return "IMGREL32"; } llvm_unreachable("Invalid variant kind"); } @@ -285,6 +286,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("dtpoff", VK_DTPOFF) .Case("TLVP", VK_TLVP) .Case("tlvp", VK_TLVP) + .Case("IMGREL", VK_COFF_IMGREL32) + .Case("imgrel", VK_COFF_IMGREL32) .Default(VK_Invalid); } diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 6dffed73dfb..de7e67b4e37 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -689,13 +689,8 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, ++Reloc.Symb->Relocations; Reloc.Data.VirtualAddress += Fixup.getOffset(); - - unsigned FixupKind = Fixup.getKind(); - - if (CrossSection) - FixupKind = FK_PCRel_4; - - Reloc.Data.Type = TargetObjectWriter->getRelocType(FixupKind); + Reloc.Data.Type = TargetObjectWriter->getRelocType(Target, Fixup, + CrossSection); // FIXME: Can anyone explain what this does other than adjust for the size // of the offset? diff --git a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp index bc272efcc9c..ed64a32eeff 100644 --- a/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp @@ -9,6 +9,8 @@ #include "MCTargetDesc/X86FixupKinds.h" #include "MCTargetDesc/X86MCTargetDesc.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCValue.h" #include "llvm/MC/MCWinCOFFObjectWriter.h" #include "llvm/Support/COFF.h" #include "llvm/Support/ErrorHandling.h" @@ -27,7 +29,9 @@ namespace { X86WinCOFFObjectWriter(bool Is64Bit_); ~X86WinCOFFObjectWriter(); - virtual unsigned getRelocType(unsigned FixupKind) const; + virtual unsigned getRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsCrossSection) const LLVM_OVERRIDE; }; } @@ -38,7 +42,14 @@ X86WinCOFFObjectWriter::X86WinCOFFObjectWriter(bool Is64Bit_) X86WinCOFFObjectWriter::~X86WinCOFFObjectWriter() {} -unsigned X86WinCOFFObjectWriter::getRelocType(unsigned FixupKind) const { +unsigned X86WinCOFFObjectWriter::getRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsCrossSection) const { + unsigned FixupKind = IsCrossSection ? FK_PCRel_4 : Fixup.getKind(); + + MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? + MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + switch (FixupKind) { case FK_PCRel_4: case X86::reloc_riprel_4byte: @@ -46,6 +57,9 @@ unsigned X86WinCOFFObjectWriter::getRelocType(unsigned FixupKind) const { return Is64Bit ? COFF::IMAGE_REL_AMD64_REL32 : COFF::IMAGE_REL_I386_REL32; case FK_Data_4: case X86::reloc_signed_4byte: + if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32) + return Is64Bit ? COFF::IMAGE_REL_AMD64_ADDR32NB : + COFF::IMAGE_REL_I386_DIR32NB; return Is64Bit ? COFF::IMAGE_REL_AMD64_ADDR32 : COFF::IMAGE_REL_I386_DIR32; case FK_Data_8: if (Is64Bit) diff --git a/test/MC/COFF/relocation-imgrel.s b/test/MC/COFF/relocation-imgrel.s new file mode 100644 index 00000000000..ccd19ee318b --- /dev/null +++ b/test/MC/COFF/relocation-imgrel.s @@ -0,0 +1,29 @@ +// COFF Image-relative relocations +// +// 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 + +.data +foo: + .long 1 + +.text + mov foo@IMGREL(%ebx, %ecx, 4), %eax + mov foo@imgrel(%ebx, %ecx, 4), %eax + +// W32: Relocations [ +// W32-NEXT: Section (1) .text { +// W32-NEXT: 0x3 IMAGE_REL_I386_DIR32NB foo +// W32-NEXT: 0xA IMAGE_REL_I386_DIR32NB foo +// W32-NEXT: } +// W32-NEXT: ] + +// 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: ]