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 IsELF64, uint8_t OSABI, uint16_t EMachine);
     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 IsELF64, uint8_t OSABI,
     34                                        uint16_t EMachine)
     35   : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
     36                             // Only i386 uses Rel instead of RelA.
     37                             /*HasRelocationAddend*/ EMachine != ELF::EM_386) {}
     38 
     39 X86ELFObjectWriter::~X86ELFObjectWriter()
     40 {}
     41 
     42 unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
     43                                           const MCFixup &Fixup,
     44                                           bool IsPCRel,
     45                                           bool IsRelocWithSymbol,
     46                                           int64_t Addend) const {
     47   // determine the type of the relocation
     48 
     49   MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
     50     MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
     51   unsigned Type;
     52   if (getEMachine() == ELF::EM_X86_64) {
     53     if (IsPCRel) {
     54       switch ((unsigned)Fixup.getKind()) {
     55       default: llvm_unreachable("invalid fixup kind!");
     56 
     57       case FK_Data_8: Type = ELF::R_X86_64_PC64; break;
     58       case FK_Data_4: Type = ELF::R_X86_64_PC32; break;
     59       case FK_Data_2: Type = ELF::R_X86_64_PC16; break;
     60 
     61       case FK_PCRel_8:
     62         assert(Modifier == MCSymbolRefExpr::VK_None);
     63         Type = ELF::R_X86_64_PC64;
     64         break;
     65       case X86::reloc_signed_4byte:
     66       case X86::reloc_riprel_4byte_movq_load:
     67       case X86::reloc_riprel_4byte:
     68       case FK_PCRel_4:
     69         switch (Modifier) {
     70         default:
     71           llvm_unreachable("Unimplemented");
     72         case MCSymbolRefExpr::VK_None:
     73           Type = ELF::R_X86_64_PC32;
     74           break;
     75         case MCSymbolRefExpr::VK_PLT:
     76           Type = ELF::R_X86_64_PLT32;
     77           break;
     78         case MCSymbolRefExpr::VK_GOTPCREL:
     79           Type = ELF::R_X86_64_GOTPCREL;
     80           break;
     81         case MCSymbolRefExpr::VK_GOTTPOFF:
     82           Type = ELF::R_X86_64_GOTTPOFF;
     83         break;
     84         case MCSymbolRefExpr::VK_TLSGD:
     85           Type = ELF::R_X86_64_TLSGD;
     86           break;
     87         case MCSymbolRefExpr::VK_TLSLD:
     88           Type = ELF::R_X86_64_TLSLD;
     89           break;
     90         }
     91         break;
     92       case FK_PCRel_2:
     93         assert(Modifier == MCSymbolRefExpr::VK_None);
     94         Type = ELF::R_X86_64_PC16;
     95         break;
     96       case FK_PCRel_1:
     97         assert(Modifier == MCSymbolRefExpr::VK_None);
     98         Type = ELF::R_X86_64_PC8;
     99         break;
    100       }
    101     } else {
    102       switch ((unsigned)Fixup.getKind()) {
    103       default: llvm_unreachable("invalid fixup kind!");
    104       case FK_Data_8:
    105         switch (Modifier) {
    106         default:
    107           llvm_unreachable("Unimplemented");
    108         case MCSymbolRefExpr::VK_None:
    109           Type = ELF::R_X86_64_64;
    110           break;
    111         case MCSymbolRefExpr::VK_DTPOFF:
    112           Type = ELF::R_X86_64_DTPOFF64;
    113           break;
    114         }
    115         break;
    116       case X86::reloc_signed_4byte:
    117         switch (Modifier) {
    118         default:
    119           llvm_unreachable("Unimplemented");
    120         case MCSymbolRefExpr::VK_None:
    121           Type = ELF::R_X86_64_32S;
    122           break;
    123         case MCSymbolRefExpr::VK_GOT:
    124           Type = ELF::R_X86_64_GOT32;
    125           break;
    126         case MCSymbolRefExpr::VK_GOTPCREL:
    127           Type = ELF::R_X86_64_GOTPCREL;
    128           break;
    129         case MCSymbolRefExpr::VK_TPOFF:
    130           Type = ELF::R_X86_64_TPOFF32;
    131           break;
    132         case MCSymbolRefExpr::VK_DTPOFF:
    133           Type = ELF::R_X86_64_DTPOFF32;
    134           break;
    135         }
    136         break;
    137       case FK_Data_4:
    138         Type = ELF::R_X86_64_32;
    139         break;
    140       case FK_Data_2: Type = ELF::R_X86_64_16; break;
    141       case FK_PCRel_1:
    142       case FK_Data_1: Type = ELF::R_X86_64_8; break;
    143       }
    144     }
    145   } else if (getEMachine() == ELF::EM_386) {
    146     if (IsPCRel) {
    147       switch ((unsigned)Fixup.getKind()) {
    148       default: llvm_unreachable("invalid fixup kind!");
    149 
    150       case X86::reloc_global_offset_table:
    151         Type = ELF::R_386_GOTPC;
    152         break;
    153 
    154       case X86::reloc_signed_4byte:
    155       case FK_PCRel_4:
    156       case FK_Data_4:
    157         switch (Modifier) {
    158         default:
    159           llvm_unreachable("Unimplemented");
    160         case MCSymbolRefExpr::VK_None:
    161           Type = ELF::R_386_PC32;
    162           break;
    163         case MCSymbolRefExpr::VK_PLT:
    164           Type = ELF::R_386_PLT32;
    165           break;
    166         }
    167         break;
    168       }
    169     } else {
    170       switch ((unsigned)Fixup.getKind()) {
    171       default: llvm_unreachable("invalid fixup kind!");
    172 
    173       case X86::reloc_global_offset_table:
    174         Type = ELF::R_386_GOTPC;
    175         break;
    176 
    177       // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
    178       // instead?
    179       case X86::reloc_signed_4byte:
    180       case FK_PCRel_4:
    181       case FK_Data_4:
    182         switch (Modifier) {
    183         default:
    184           llvm_unreachable("Unimplemented");
    185         case MCSymbolRefExpr::VK_None:
    186           Type = ELF::R_386_32;
    187           break;
    188         case MCSymbolRefExpr::VK_GOT:
    189           Type = ELF::R_386_GOT32;
    190           break;
    191         case MCSymbolRefExpr::VK_GOTOFF:
    192           Type = ELF::R_386_GOTOFF;
    193           break;
    194         case MCSymbolRefExpr::VK_TLSGD:
    195           Type = ELF::R_386_TLS_GD;
    196           break;
    197         case MCSymbolRefExpr::VK_TPOFF:
    198           Type = ELF::R_386_TLS_LE_32;
    199           break;
    200         case MCSymbolRefExpr::VK_INDNTPOFF:
    201           Type = ELF::R_386_TLS_IE;
    202           break;
    203         case MCSymbolRefExpr::VK_NTPOFF:
    204           Type = ELF::R_386_TLS_LE;
    205           break;
    206         case MCSymbolRefExpr::VK_GOTNTPOFF:
    207           Type = ELF::R_386_TLS_GOTIE;
    208           break;
    209         case MCSymbolRefExpr::VK_TLSLDM:
    210           Type = ELF::R_386_TLS_LDM;
    211           break;
    212         case MCSymbolRefExpr::VK_DTPOFF:
    213           Type = ELF::R_386_TLS_LDO_32;
    214           break;
    215         case MCSymbolRefExpr::VK_GOTTPOFF:
    216           Type = ELF::R_386_TLS_IE_32;
    217           break;
    218         }
    219         break;
    220       case FK_Data_2: Type = ELF::R_386_16; break;
    221       case FK_PCRel_1:
    222       case FK_Data_1: Type = ELF::R_386_8; break;
    223       }
    224     }
    225   } else
    226     llvm_unreachable("Unsupported ELF machine type.");
    227 
    228   return Type;
    229 }
    230 
    231 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
    232                                                bool IsELF64,
    233                                                uint8_t OSABI,
    234                                                uint16_t EMachine) {
    235   MCELFObjectTargetWriter *MOTW =
    236     new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
    237   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
    238 }
    239