Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- X86ELFObjectWriter.cpp - X86 ELF Writer ---------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "MCTargetDesc/X86FixupKinds.h"
     11 #include "MCTargetDesc/X86MCTargetDesc.h"
     12 #include "llvm/MC/MCELFObjectWriter.h"
     13 #include "llvm/MC/MCExpr.h"
     14 #include "llvm/MC/MCValue.h"
     15 #include "llvm/Support/ELF.h"
     16 #include "llvm/Support/ErrorHandling.h"
     17 
     18 using namespace llvm;
     19 
     20 namespace {
     21   class X86ELFObjectWriter : public MCELFObjectTargetWriter {
     22   public:
     23     X86ELFObjectWriter(bool is64Bit, uint8_t OSABI);
     24 
     25     virtual ~X86ELFObjectWriter();
     26   protected:
     27     virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
     28                                   bool IsPCRel, bool IsRelocWithSymbol,
     29                                   int64_t Addend) const;
     30   };
     31 }
     32 
     33 X86ELFObjectWriter::X86ELFObjectWriter(bool Is64Bit, uint8_t OSABI)
     34   : MCELFObjectTargetWriter(Is64Bit, OSABI,
     35                             Is64Bit ?  ELF::EM_X86_64 : ELF::EM_386,
     36                             /*HasRelocationAddend*/ Is64Bit) {}
     37 
     38 X86ELFObjectWriter::~X86ELFObjectWriter()
     39 {}
     40 
     41 unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
     42                                           const MCFixup &Fixup,
     43                                           bool IsPCRel,
     44                                           bool IsRelocWithSymbol,
     45                                           int64_t Addend) const {
     46   // determine the type of the relocation
     47 
     48   MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
     49     MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
     50   unsigned Type;
     51   if (is64Bit()) {
     52     if (IsPCRel) {
     53       switch ((unsigned)Fixup.getKind()) {
     54       default: llvm_unreachable("invalid fixup kind!");
     55 
     56       case FK_Data_8: Type = ELF::R_X86_64_PC64; break;
     57       case FK_Data_4: Type = ELF::R_X86_64_PC32; break;
     58       case FK_Data_2: Type = ELF::R_X86_64_PC16; break;
     59 
     60       case FK_PCRel_8:
     61         assert(Modifier == MCSymbolRefExpr::VK_None);
     62         Type = ELF::R_X86_64_PC64;
     63         break;
     64       case X86::reloc_signed_4byte:
     65       case X86::reloc_riprel_4byte_movq_load:
     66       case X86::reloc_riprel_4byte:
     67       case FK_PCRel_4:
     68         switch (Modifier) {
     69         default:
     70           llvm_unreachable("Unimplemented");
     71         case MCSymbolRefExpr::VK_None:
     72           Type = ELF::R_X86_64_PC32;
     73           break;
     74         case MCSymbolRefExpr::VK_PLT:
     75           Type = ELF::R_X86_64_PLT32;
     76           break;
     77         case MCSymbolRefExpr::VK_GOTPCREL:
     78           Type = ELF::R_X86_64_GOTPCREL;
     79           break;
     80         case MCSymbolRefExpr::VK_GOTTPOFF:
     81           Type = ELF::R_X86_64_GOTTPOFF;
     82         break;
     83         case MCSymbolRefExpr::VK_TLSGD:
     84           Type = ELF::R_X86_64_TLSGD;
     85           break;
     86         case MCSymbolRefExpr::VK_TLSLD:
     87           Type = ELF::R_X86_64_TLSLD;
     88           break;
     89         }
     90         break;
     91       case FK_PCRel_2:
     92         assert(Modifier == MCSymbolRefExpr::VK_None);
     93         Type = ELF::R_X86_64_PC16;
     94         break;
     95       case FK_PCRel_1:
     96         assert(Modifier == MCSymbolRefExpr::VK_None);
     97         Type = ELF::R_X86_64_PC8;
     98         break;
     99       }
    100     } else {
    101       switch ((unsigned)Fixup.getKind()) {
    102       default: llvm_unreachable("invalid fixup kind!");
    103       case FK_Data_8: Type = ELF::R_X86_64_64; break;
    104       case X86::reloc_signed_4byte:
    105         switch (Modifier) {
    106         default:
    107           llvm_unreachable("Unimplemented");
    108         case MCSymbolRefExpr::VK_None:
    109           Type = ELF::R_X86_64_32S;
    110           break;
    111         case MCSymbolRefExpr::VK_GOT:
    112           Type = ELF::R_X86_64_GOT32;
    113           break;
    114         case MCSymbolRefExpr::VK_GOTPCREL:
    115           Type = ELF::R_X86_64_GOTPCREL;
    116           break;
    117         case MCSymbolRefExpr::VK_TPOFF:
    118           Type = ELF::R_X86_64_TPOFF32;
    119           break;
    120         case MCSymbolRefExpr::VK_DTPOFF:
    121           Type = ELF::R_X86_64_DTPOFF32;
    122           break;
    123         }
    124         break;
    125       case FK_Data_4:
    126         Type = ELF::R_X86_64_32;
    127         break;
    128       case FK_Data_2: Type = ELF::R_X86_64_16; break;
    129       case FK_PCRel_1:
    130       case FK_Data_1: Type = ELF::R_X86_64_8; break;
    131       }
    132     }
    133   } else {
    134     if (IsPCRel) {
    135       switch ((unsigned)Fixup.getKind()) {
    136       default: llvm_unreachable("invalid fixup kind!");
    137 
    138       case X86::reloc_global_offset_table:
    139         Type = ELF::R_386_GOTPC;
    140         break;
    141 
    142       case X86::reloc_signed_4byte:
    143       case FK_PCRel_4:
    144       case FK_Data_4:
    145         switch (Modifier) {
    146         default:
    147           llvm_unreachable("Unimplemented");
    148         case MCSymbolRefExpr::VK_None:
    149           Type = ELF::R_386_PC32;
    150           break;
    151         case MCSymbolRefExpr::VK_PLT:
    152           Type = ELF::R_386_PLT32;
    153           break;
    154         }
    155         break;
    156       }
    157     } else {
    158       switch ((unsigned)Fixup.getKind()) {
    159       default: llvm_unreachable("invalid fixup kind!");
    160 
    161       case X86::reloc_global_offset_table:
    162         Type = ELF::R_386_GOTPC;
    163         break;
    164 
    165       // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
    166       // instead?
    167       case X86::reloc_signed_4byte:
    168       case FK_PCRel_4:
    169       case FK_Data_4:
    170         switch (Modifier) {
    171         default:
    172           llvm_unreachable("Unimplemented");
    173         case MCSymbolRefExpr::VK_None:
    174           Type = ELF::R_386_32;
    175           break;
    176         case MCSymbolRefExpr::VK_GOT:
    177           Type = ELF::R_386_GOT32;
    178           break;
    179         case MCSymbolRefExpr::VK_GOTOFF:
    180           Type = ELF::R_386_GOTOFF;
    181           break;
    182         case MCSymbolRefExpr::VK_TLSGD:
    183           Type = ELF::R_386_TLS_GD;
    184           break;
    185         case MCSymbolRefExpr::VK_TPOFF:
    186           Type = ELF::R_386_TLS_LE_32;
    187           break;
    188         case MCSymbolRefExpr::VK_INDNTPOFF:
    189           Type = ELF::R_386_TLS_IE;
    190           break;
    191         case MCSymbolRefExpr::VK_NTPOFF:
    192           Type = ELF::R_386_TLS_LE;
    193           break;
    194         case MCSymbolRefExpr::VK_GOTNTPOFF:
    195           Type = ELF::R_386_TLS_GOTIE;
    196           break;
    197         case MCSymbolRefExpr::VK_TLSLDM:
    198           Type = ELF::R_386_TLS_LDM;
    199           break;
    200         case MCSymbolRefExpr::VK_DTPOFF:
    201           Type = ELF::R_386_TLS_LDO_32;
    202           break;
    203         case MCSymbolRefExpr::VK_GOTTPOFF:
    204           Type = ELF::R_386_TLS_IE_32;
    205           break;
    206         }
    207         break;
    208       case FK_Data_2: Type = ELF::R_386_16; break;
    209       case FK_PCRel_1:
    210       case FK_Data_1: Type = ELF::R_386_8; break;
    211       }
    212     }
    213   }
    214 
    215   return Type;
    216 }
    217 
    218 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
    219                                                bool Is64Bit,
    220                                                uint8_t OSABI) {
    221   MCELFObjectTargetWriter *MOTW =
    222     new X86ELFObjectWriter(Is64Bit, OSABI);
    223   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
    224 }
    225