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