Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- AArch64ELFObjectWriter.cpp - AArch64 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 // This file handles ELF-specific object emission, converting LLVM's internal
     11 // fixups into the appropriate relocations.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "MCTargetDesc/AArch64FixupKinds.h"
     16 #include "MCTargetDesc/AArch64MCTargetDesc.h"
     17 #include "llvm/MC/MCELFObjectWriter.h"
     18 #include "llvm/MC/MCValue.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 
     21 using namespace llvm;
     22 
     23 namespace {
     24 class AArch64ELFObjectWriter : public MCELFObjectTargetWriter {
     25 public:
     26   AArch64ELFObjectWriter(uint8_t OSABI);
     27 
     28   virtual ~AArch64ELFObjectWriter();
     29 
     30 protected:
     31   virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
     32                                 bool IsPCRel, bool IsRelocWithSymbol,
     33                                 int64_t Addend) const;
     34 private:
     35 };
     36 }
     37 
     38 AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI)
     39   : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64,
     40                             /*HasRelocationAddend*/ true)
     41 {}
     42 
     43 AArch64ELFObjectWriter::~AArch64ELFObjectWriter()
     44 {}
     45 
     46 unsigned AArch64ELFObjectWriter::GetRelocType(const MCValue &Target,
     47                                               const MCFixup &Fixup,
     48                                               bool IsPCRel,
     49                                               bool IsRelocWithSymbol,
     50                                               int64_t Addend) const {
     51   unsigned Type;
     52   if (IsPCRel) {
     53     switch ((unsigned)Fixup.getKind()) {
     54     default:
     55       llvm_unreachable("Unimplemented fixup -> relocation");
     56     case FK_Data_8:
     57       return ELF::R_AARCH64_PREL64;
     58     case FK_Data_4:
     59       return ELF::R_AARCH64_PREL32;
     60     case FK_Data_2:
     61       return ELF::R_AARCH64_PREL16;
     62     case AArch64::fixup_a64_ld_prel:
     63       Type = ELF::R_AARCH64_LD_PREL_LO19;
     64       break;
     65     case AArch64::fixup_a64_adr_prel:
     66       Type = ELF::R_AARCH64_ADR_PREL_LO21;
     67       break;
     68     case AArch64::fixup_a64_adr_prel_page:
     69       Type = ELF::R_AARCH64_ADR_PREL_PG_HI21;
     70       break;
     71     case AArch64::fixup_a64_adr_prel_got_page:
     72       Type = ELF::R_AARCH64_ADR_GOT_PAGE;
     73       break;
     74     case AArch64::fixup_a64_tstbr:
     75       Type = ELF::R_AARCH64_TSTBR14;
     76       break;
     77     case AArch64::fixup_a64_condbr:
     78       Type = ELF::R_AARCH64_CONDBR19;
     79       break;
     80     case AArch64::fixup_a64_uncondbr:
     81       Type = ELF::R_AARCH64_JUMP26;
     82       break;
     83     case AArch64::fixup_a64_call:
     84       Type = ELF::R_AARCH64_CALL26;
     85       break;
     86     case AArch64::fixup_a64_adr_gottprel_page:
     87       Type = ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
     88       break;
     89     case AArch64::fixup_a64_ld_gottprel_prel19:
     90       Type =  ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19;
     91       break;
     92     case AArch64::fixup_a64_tlsdesc_adr_page:
     93       Type = ELF::R_AARCH64_TLSDESC_ADR_PAGE;
     94       break;
     95     }
     96   } else {
     97     switch ((unsigned)Fixup.getKind()) {
     98     default:
     99       llvm_unreachable("Unimplemented fixup -> relocation");
    100     case FK_Data_8:
    101       return ELF::R_AARCH64_ABS64;
    102     case FK_Data_4:
    103       return ELF::R_AARCH64_ABS32;
    104     case FK_Data_2:
    105       return ELF::R_AARCH64_ABS16;
    106     case AArch64::fixup_a64_add_lo12:
    107       Type = ELF::R_AARCH64_ADD_ABS_LO12_NC;
    108       break;
    109     case AArch64::fixup_a64_ld64_got_lo12_nc:
    110       Type = ELF::R_AARCH64_LD64_GOT_LO12_NC;
    111       break;
    112     case AArch64::fixup_a64_ldst8_lo12:
    113       Type = ELF::R_AARCH64_LDST8_ABS_LO12_NC;
    114       break;
    115     case AArch64::fixup_a64_ldst16_lo12:
    116       Type = ELF::R_AARCH64_LDST16_ABS_LO12_NC;
    117       break;
    118     case AArch64::fixup_a64_ldst32_lo12:
    119       Type = ELF::R_AARCH64_LDST32_ABS_LO12_NC;
    120       break;
    121     case AArch64::fixup_a64_ldst64_lo12:
    122       Type = ELF::R_AARCH64_LDST64_ABS_LO12_NC;
    123       break;
    124     case AArch64::fixup_a64_ldst128_lo12:
    125       Type = ELF::R_AARCH64_LDST128_ABS_LO12_NC;
    126       break;
    127     case AArch64::fixup_a64_movw_uabs_g0:
    128       Type = ELF::R_AARCH64_MOVW_UABS_G0;
    129       break;
    130     case AArch64::fixup_a64_movw_uabs_g0_nc:
    131       Type = ELF::R_AARCH64_MOVW_UABS_G0_NC;
    132       break;
    133     case AArch64::fixup_a64_movw_uabs_g1:
    134       Type = ELF::R_AARCH64_MOVW_UABS_G1;
    135       break;
    136     case AArch64::fixup_a64_movw_uabs_g1_nc:
    137       Type = ELF::R_AARCH64_MOVW_UABS_G1_NC;
    138       break;
    139     case AArch64::fixup_a64_movw_uabs_g2:
    140       Type = ELF::R_AARCH64_MOVW_UABS_G2;
    141       break;
    142     case AArch64::fixup_a64_movw_uabs_g2_nc:
    143       Type = ELF::R_AARCH64_MOVW_UABS_G2_NC;
    144       break;
    145     case AArch64::fixup_a64_movw_uabs_g3:
    146       Type = ELF::R_AARCH64_MOVW_UABS_G3;
    147       break;
    148     case AArch64::fixup_a64_movw_sabs_g0:
    149       Type = ELF::R_AARCH64_MOVW_SABS_G0;
    150       break;
    151     case AArch64::fixup_a64_movw_sabs_g1:
    152       Type = ELF::R_AARCH64_MOVW_SABS_G1;
    153       break;
    154     case AArch64::fixup_a64_movw_sabs_g2:
    155       Type = ELF::R_AARCH64_MOVW_SABS_G2;
    156       break;
    157 
    158     // TLS Local-dynamic block
    159     case AArch64::fixup_a64_movw_dtprel_g2:
    160       Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
    161       break;
    162     case AArch64::fixup_a64_movw_dtprel_g1:
    163       Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1;
    164       break;
    165     case AArch64::fixup_a64_movw_dtprel_g1_nc:
    166       Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
    167       break;
    168     case AArch64::fixup_a64_movw_dtprel_g0:
    169       Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0;
    170       break;
    171     case AArch64::fixup_a64_movw_dtprel_g0_nc:
    172       Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC;
    173       break;
    174     case AArch64::fixup_a64_add_dtprel_hi12:
    175       Type = ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12;
    176       break;
    177     case AArch64::fixup_a64_add_dtprel_lo12:
    178       Type = ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12;
    179       break;
    180     case AArch64::fixup_a64_add_dtprel_lo12_nc:
    181       Type = ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC;
    182       break;
    183     case AArch64::fixup_a64_ldst8_dtprel_lo12:
    184       Type = ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12;
    185       break;
    186     case AArch64::fixup_a64_ldst8_dtprel_lo12_nc:
    187       Type = ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC;
    188       break;
    189     case AArch64::fixup_a64_ldst16_dtprel_lo12:
    190       Type = ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12;
    191       break;
    192     case AArch64::fixup_a64_ldst16_dtprel_lo12_nc:
    193       Type = ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC;
    194       break;
    195     case AArch64::fixup_a64_ldst32_dtprel_lo12:
    196       Type = ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12;
    197       break;
    198     case AArch64::fixup_a64_ldst32_dtprel_lo12_nc:
    199       Type = ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC;
    200       break;
    201     case AArch64::fixup_a64_ldst64_dtprel_lo12:
    202       Type = ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12;
    203       break;
    204     case AArch64::fixup_a64_ldst64_dtprel_lo12_nc:
    205       Type = ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC;
    206       break;
    207 
    208     // TLS initial-exec block
    209     case AArch64::fixup_a64_movw_gottprel_g1:
    210       Type = ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
    211       break;
    212     case AArch64::fixup_a64_movw_gottprel_g0_nc:
    213       Type = ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
    214       break;
    215     case AArch64::fixup_a64_ld64_gottprel_lo12_nc:
    216       Type = ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
    217       break;
    218 
    219     // TLS local-exec block
    220     case AArch64::fixup_a64_movw_tprel_g2:
    221       Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
    222       break;
    223     case AArch64::fixup_a64_movw_tprel_g1:
    224       Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1;
    225       break;
    226     case AArch64::fixup_a64_movw_tprel_g1_nc:
    227       Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
    228       break;
    229     case AArch64::fixup_a64_movw_tprel_g0:
    230       Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0;
    231       break;
    232     case AArch64::fixup_a64_movw_tprel_g0_nc:
    233       Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC;
    234       break;
    235     case AArch64::fixup_a64_add_tprel_hi12:
    236       Type = ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12;
    237       break;
    238     case AArch64::fixup_a64_add_tprel_lo12:
    239       Type = ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12;
    240       break;
    241     case AArch64::fixup_a64_add_tprel_lo12_nc:
    242       Type = ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC;
    243       break;
    244     case AArch64::fixup_a64_ldst8_tprel_lo12:
    245       Type = ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12;
    246       break;
    247     case AArch64::fixup_a64_ldst8_tprel_lo12_nc:
    248       Type = ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC;
    249       break;
    250     case AArch64::fixup_a64_ldst16_tprel_lo12:
    251       Type = ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12;
    252       break;
    253     case AArch64::fixup_a64_ldst16_tprel_lo12_nc:
    254       Type = ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC;
    255       break;
    256     case AArch64::fixup_a64_ldst32_tprel_lo12:
    257       Type = ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12;
    258       break;
    259     case AArch64::fixup_a64_ldst32_tprel_lo12_nc:
    260       Type = ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC;
    261       break;
    262     case AArch64::fixup_a64_ldst64_tprel_lo12:
    263       Type = ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12;
    264       break;
    265     case AArch64::fixup_a64_ldst64_tprel_lo12_nc:
    266       Type = ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC;
    267       break;
    268 
    269     // TLS general-dynamic block
    270     case AArch64::fixup_a64_tlsdesc_adr_page:
    271       Type = ELF::R_AARCH64_TLSDESC_ADR_PAGE;
    272       break;
    273     case AArch64::fixup_a64_tlsdesc_ld64_lo12_nc:
    274       Type = ELF::R_AARCH64_TLSDESC_LD64_LO12_NC;
    275       break;
    276     case AArch64::fixup_a64_tlsdesc_add_lo12_nc:
    277       Type = ELF::R_AARCH64_TLSDESC_ADD_LO12_NC;
    278       break;
    279     case AArch64::fixup_a64_tlsdesc_call:
    280       Type = ELF::R_AARCH64_TLSDESC_CALL;
    281       break;
    282     }
    283   }
    284 
    285   return Type;
    286 }
    287 
    288 MCObjectWriter *llvm::createAArch64ELFObjectWriter(raw_ostream &OS,
    289                                                    uint8_t OSABI) {
    290   MCELFObjectTargetWriter *MOTW = new AArch64ELFObjectWriter(OSABI);
    291   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
    292 }
    293