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: Type = ELF::R_X86_64_64; break;
    105       case X86::reloc_signed_4byte:
    106         switch (Modifier) {
    107         default:
    108           llvm_unreachable("Unimplemented");
    109         case MCSymbolRefExpr::VK_None:
    110           Type = ELF::R_X86_64_32S;
    111           break;
    112         case MCSymbolRefExpr::VK_GOT:
    113           Type = ELF::R_X86_64_GOT32;
    114           break;
    115         case MCSymbolRefExpr::VK_GOTPCREL:
    116           Type = ELF::R_X86_64_GOTPCREL;
    117           break;
    118         case MCSymbolRefExpr::VK_TPOFF:
    119           Type = ELF::R_X86_64_TPOFF32;
    120           break;
    121         case MCSymbolRefExpr::VK_DTPOFF:
    122           Type = ELF::R_X86_64_DTPOFF32;
    123           break;
    124         }
    125         break;
    126       case FK_Data_4:
    127         Type = ELF::R_X86_64_32;
    128         break;
    129       case FK_Data_2: Type = ELF::R_X86_64_16; break;
    130       case FK_PCRel_1:
    131       case FK_Data_1: Type = ELF::R_X86_64_8; break;
    132       }
    133     }
    134   } else if (getEMachine() == ELF::EM_386) {
    135     if (IsPCRel) {
    136       switch ((unsigned)Fixup.getKind()) {
    137       default: llvm_unreachable("invalid fixup kind!");
    138 
    139       case X86::reloc_global_offset_table:
    140         Type = ELF::R_386_GOTPC;
    141         break;
    142 
    143       case X86::reloc_signed_4byte:
    144       case FK_PCRel_4:
    145       case FK_Data_4:
    146         switch (Modifier) {
    147         default:
    148           llvm_unreachable("Unimplemented");
    149         case MCSymbolRefExpr::VK_None:
    150           Type = ELF::R_386_PC32;
    151           break;
    152         case MCSymbolRefExpr::VK_PLT:
    153           Type = ELF::R_386_PLT32;
    154           break;
    155         }
    156         break;
    157       }
    158     } else {
    159       switch ((unsigned)Fixup.getKind()) {
    160       default: llvm_unreachable("invalid fixup kind!");
    161 
    162       case X86::reloc_global_offset_table:
    163         Type = ELF::R_386_GOTPC;
    164         break;
    165 
    166       // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
    167       // instead?
    168       case X86::reloc_signed_4byte:
    169       case FK_PCRel_4:
    170       case FK_Data_4:
    171         switch (Modifier) {
    172         default:
    173           llvm_unreachable("Unimplemented");
    174         case MCSymbolRefExpr::VK_None:
    175           Type = ELF::R_386_32;
    176           break;
    177         case MCSymbolRefExpr::VK_GOT:
    178           Type = ELF::R_386_GOT32;
    179           break;
    180         case MCSymbolRefExpr::VK_GOTOFF:
    181           Type = ELF::R_386_GOTOFF;
    182           break;
    183         case MCSymbolRefExpr::VK_TLSGD:
    184           Type = ELF::R_386_TLS_GD;
    185           break;
    186         case MCSymbolRefExpr::VK_TPOFF:
    187           Type = ELF::R_386_TLS_LE_32;
    188           break;
    189         case MCSymbolRefExpr::VK_INDNTPOFF:
    190           Type = ELF::R_386_TLS_IE;
    191           break;
    192         case MCSymbolRefExpr::VK_NTPOFF:
    193           Type = ELF::R_386_TLS_LE;
    194           break;
    195         case MCSymbolRefExpr::VK_GOTNTPOFF:
    196           Type = ELF::R_386_TLS_GOTIE;
    197           break;
    198         case MCSymbolRefExpr::VK_TLSLDM:
    199           Type = ELF::R_386_TLS_LDM;
    200           break;
    201         case MCSymbolRefExpr::VK_DTPOFF:
    202           Type = ELF::R_386_TLS_LDO_32;
    203           break;
    204         case MCSymbolRefExpr::VK_GOTTPOFF:
    205           Type = ELF::R_386_TLS_IE_32;
    206           break;
    207         }
    208         break;
    209       case FK_Data_2: Type = ELF::R_386_16; break;
    210       case FK_PCRel_1:
    211       case FK_Data_1: Type = ELF::R_386_8; break;
    212       }
    213     }
    214   } else
    215     llvm_unreachable("Unsupported ELF machine type.");
    216 
    217   return Type;
    218 }
    219 
    220 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
    221                                                bool IsELF64,
    222                                                uint8_t OSABI,
    223                                                uint16_t EMachine) {
    224   MCELFObjectTargetWriter *MOTW =
    225     new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
    226   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
    227 }
    228