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/AArch64MCExpr.h"
     17 #include "MCTargetDesc/AArch64MCTargetDesc.h"
     18 #include "llvm/MC/MCELFObjectWriter.h"
     19 #include "llvm/MC/MCValue.h"
     20 #include "llvm/Support/ErrorHandling.h"
     21 
     22 using namespace llvm;
     23 
     24 namespace {
     25 class AArch64ELFObjectWriter : public MCELFObjectTargetWriter {
     26 public:
     27   AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian);
     28 
     29   virtual ~AArch64ELFObjectWriter();
     30 
     31 protected:
     32   unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
     33                         bool IsPCRel) const override;
     34 
     35 private:
     36 };
     37 }
     38 
     39 AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI,
     40                                                bool IsLittleEndian)
     41     : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64,
     42                               /*HasRelocationAddend*/ true) {}
     43 
     44 AArch64ELFObjectWriter::~AArch64ELFObjectWriter() {}
     45 
     46 unsigned AArch64ELFObjectWriter::GetRelocType(const MCValue &Target,
     47                                             const MCFixup &Fixup,
     48                                             bool IsPCRel) const {
     49   AArch64MCExpr::VariantKind RefKind =
     50       static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
     51   AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
     52   bool IsNC = AArch64MCExpr::isNotChecked(RefKind);
     53 
     54   assert((!Target.getSymA() ||
     55           Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
     56          "Should only be expression-level modifiers here");
     57 
     58   assert((!Target.getSymB() ||
     59           Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
     60          "Should only be expression-level modifiers here");
     61 
     62   if (IsPCRel) {
     63     switch ((unsigned)Fixup.getKind()) {
     64     case FK_Data_2:
     65       return ELF::R_AARCH64_PREL16;
     66     case FK_Data_4:
     67       return ELF::R_AARCH64_PREL32;
     68     case FK_Data_8:
     69       return ELF::R_AARCH64_PREL64;
     70     case AArch64::fixup_aarch64_pcrel_adr_imm21:
     71       assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
     72       return ELF::R_AARCH64_ADR_PREL_LO21;
     73     case AArch64::fixup_aarch64_pcrel_adrp_imm21:
     74       if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
     75         return ELF::R_AARCH64_ADR_PREL_PG_HI21;
     76       if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
     77         return ELF::R_AARCH64_ADR_GOT_PAGE;
     78       if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
     79         return ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
     80       if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
     81         return ELF::R_AARCH64_TLSDESC_ADR_PAGE;
     82       llvm_unreachable("invalid symbol kind for ADRP relocation");
     83     case AArch64::fixup_aarch64_pcrel_branch26:
     84       return ELF::R_AARCH64_JUMP26;
     85     case AArch64::fixup_aarch64_pcrel_call26:
     86       return ELF::R_AARCH64_CALL26;
     87     case AArch64::fixup_aarch64_ldr_pcrel_imm19:
     88       if (SymLoc == AArch64MCExpr::VK_GOTTPREL)
     89         return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19;
     90       return ELF::R_AARCH64_LD_PREL_LO19;
     91     case AArch64::fixup_aarch64_pcrel_branch14:
     92       return ELF::R_AARCH64_TSTBR14;
     93     case AArch64::fixup_aarch64_pcrel_branch19:
     94       return ELF::R_AARCH64_CONDBR19;
     95     default:
     96       llvm_unreachable("Unsupported pc-relative fixup kind");
     97     }
     98   } else {
     99     switch ((unsigned)Fixup.getKind()) {
    100     case FK_Data_2:
    101       return ELF::R_AARCH64_ABS16;
    102     case FK_Data_4:
    103       return ELF::R_AARCH64_ABS32;
    104     case FK_Data_8:
    105       return ELF::R_AARCH64_ABS64;
    106     case AArch64::fixup_aarch64_add_imm12:
    107       if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
    108         return ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12;
    109       if (RefKind == AArch64MCExpr::VK_TPREL_HI12)
    110         return ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12;
    111       if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC)
    112         return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC;
    113       if (RefKind == AArch64MCExpr::VK_DTPREL_LO12)
    114         return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12;
    115       if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC)
    116         return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC;
    117       if (RefKind == AArch64MCExpr::VK_TPREL_LO12)
    118         return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12;
    119       if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
    120         return ELF::R_AARCH64_TLSDESC_ADD_LO12_NC;
    121       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
    122         return ELF::R_AARCH64_ADD_ABS_LO12_NC;
    123 
    124       report_fatal_error("invalid fixup for add (uimm12) instruction");
    125       return 0;
    126     case AArch64::fixup_aarch64_ldst_imm12_scale1:
    127       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
    128         return ELF::R_AARCH64_LDST8_ABS_LO12_NC;
    129       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
    130         return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12;
    131       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
    132         return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC;
    133       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
    134         return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12;
    135       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
    136         return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC;
    137 
    138       report_fatal_error("invalid fixup for 8-bit load/store instruction");
    139       return 0;
    140     case AArch64::fixup_aarch64_ldst_imm12_scale2:
    141       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
    142         return ELF::R_AARCH64_LDST16_ABS_LO12_NC;
    143       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
    144         return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12;
    145       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
    146         return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC;
    147       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
    148         return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12;
    149       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
    150         return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC;
    151 
    152       report_fatal_error("invalid fixup for 16-bit load/store instruction");
    153       return 0;
    154     case AArch64::fixup_aarch64_ldst_imm12_scale4:
    155       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
    156         return ELF::R_AARCH64_LDST32_ABS_LO12_NC;
    157       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
    158         return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12;
    159       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
    160         return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC;
    161       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
    162         return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12;
    163       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
    164         return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC;
    165 
    166       report_fatal_error("invalid fixup for 32-bit load/store instruction");
    167       return 0;
    168     case AArch64::fixup_aarch64_ldst_imm12_scale8:
    169       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
    170         return ELF::R_AARCH64_LDST64_ABS_LO12_NC;
    171       if (SymLoc == AArch64MCExpr::VK_GOT && IsNC)
    172         return ELF::R_AARCH64_LD64_GOT_LO12_NC;
    173       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
    174         return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12;
    175       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
    176         return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC;
    177       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
    178         return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12;
    179       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
    180         return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC;
    181       if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC)
    182         return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
    183       if (SymLoc == AArch64MCExpr::VK_TLSDESC && IsNC)
    184         return ELF::R_AARCH64_TLSDESC_LD64_LO12_NC;
    185 
    186       report_fatal_error("invalid fixup for 64-bit load/store instruction");
    187       return 0;
    188     case AArch64::fixup_aarch64_ldst_imm12_scale16:
    189       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
    190         return ELF::R_AARCH64_LDST128_ABS_LO12_NC;
    191 
    192       report_fatal_error("invalid fixup for 128-bit load/store instruction");
    193       return 0;
    194     case AArch64::fixup_aarch64_movw:
    195       if (RefKind == AArch64MCExpr::VK_ABS_G3)
    196         return ELF::R_AARCH64_MOVW_UABS_G3;
    197       if (RefKind == AArch64MCExpr::VK_ABS_G2)
    198         return ELF::R_AARCH64_MOVW_UABS_G2;
    199       if (RefKind == AArch64MCExpr::VK_ABS_G2_S)
    200         return ELF::R_AARCH64_MOVW_SABS_G2;
    201       if (RefKind == AArch64MCExpr::VK_ABS_G2_NC)
    202         return ELF::R_AARCH64_MOVW_UABS_G2_NC;
    203       if (RefKind == AArch64MCExpr::VK_ABS_G1)
    204         return ELF::R_AARCH64_MOVW_UABS_G1;
    205       if (RefKind == AArch64MCExpr::VK_ABS_G1_S)
    206         return ELF::R_AARCH64_MOVW_SABS_G1;
    207       if (RefKind == AArch64MCExpr::VK_ABS_G1_NC)
    208         return ELF::R_AARCH64_MOVW_UABS_G1_NC;
    209       if (RefKind == AArch64MCExpr::VK_ABS_G0)
    210         return ELF::R_AARCH64_MOVW_UABS_G0;
    211       if (RefKind == AArch64MCExpr::VK_ABS_G0_S)
    212         return ELF::R_AARCH64_MOVW_SABS_G0;
    213       if (RefKind == AArch64MCExpr::VK_ABS_G0_NC)
    214         return ELF::R_AARCH64_MOVW_UABS_G0_NC;
    215       if (RefKind == AArch64MCExpr::VK_DTPREL_G2)
    216         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
    217       if (RefKind == AArch64MCExpr::VK_DTPREL_G1)
    218         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1;
    219       if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC)
    220         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
    221       if (RefKind == AArch64MCExpr::VK_DTPREL_G0)
    222         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0;
    223       if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC)
    224         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC;
    225       if (RefKind == AArch64MCExpr::VK_TPREL_G2)
    226         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
    227       if (RefKind == AArch64MCExpr::VK_TPREL_G1)
    228         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1;
    229       if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC)
    230         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
    231       if (RefKind == AArch64MCExpr::VK_TPREL_G0)
    232         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0;
    233       if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC)
    234         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC;
    235       if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1)
    236         return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
    237       if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC)
    238         return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
    239       report_fatal_error("invalid fixup for movz/movk instruction");
    240       return 0;
    241     case AArch64::fixup_aarch64_tlsdesc_call:
    242       return ELF::R_AARCH64_TLSDESC_CALL;
    243     default:
    244       llvm_unreachable("Unknown ELF relocation type");
    245     }
    246   }
    247 
    248   llvm_unreachable("Unimplemented fixup -> relocation");
    249 }
    250 
    251 MCObjectWriter *llvm::createAArch64ELFObjectWriter(raw_ostream &OS,
    252                                                  uint8_t OSABI,
    253                                                  bool IsLittleEndian) {
    254   MCELFObjectTargetWriter *MOTW =
    255       new AArch64ELFObjectWriter(OSABI, IsLittleEndian);
    256   return createELFObjectWriter(MOTW, OS, IsLittleEndian);
    257 }
    258