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