Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- ARMELFObjectWriter.cpp - ARM 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/ARMMCTargetDesc.h"
     11 #include "MCTargetDesc/ARMFixupKinds.h"
     12 #include "llvm/ADT/Statistic.h"
     13 #include "llvm/ADT/StringSwitch.h"
     14 #include "llvm/MC/MCELFObjectWriter.h"
     15 #include "llvm/MC/MCExpr.h"
     16 #include "llvm/MC/MCSectionELF.h"
     17 #include "llvm/MC/MCValue.h"
     18 #include "llvm/Support/Debug.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 
     22 using namespace llvm;
     23 
     24 namespace {
     25   class ARMELFObjectWriter : public MCELFObjectTargetWriter {
     26     enum { DefaultEABIVersion = 0x05000000U };
     27     unsigned GetRelocTypeInner(const MCValue &Target,
     28                                const MCFixup &Fixup,
     29                                bool IsPCRel) const;
     30 
     31 
     32   public:
     33     ARMELFObjectWriter(uint8_t OSABI);
     34 
     35     virtual ~ARMELFObjectWriter();
     36 
     37     unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
     38                           bool IsPCRel) const override;
     39 
     40     bool needsRelocateWithSymbol(unsigned Type) const override;
     41   };
     42 }
     43 
     44 ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
     45   : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
     46                             ELF::EM_ARM,
     47                             /*HasRelocationAddend*/ false) {}
     48 
     49 ARMELFObjectWriter::~ARMELFObjectWriter() {}
     50 
     51 bool ARMELFObjectWriter::needsRelocateWithSymbol(unsigned Type) const {
     52   // FIXME: This is extremelly conservative. This really needs to use a
     53   // whitelist with a clear explanation for why each realocation needs to
     54   // point to the symbol, not to the section.
     55   switch (Type) {
     56   default:
     57     return true;
     58 
     59   case ELF::R_ARM_PREL31:
     60   case ELF::R_ARM_ABS32:
     61     return false;
     62   }
     63 }
     64 
     65 // Need to examine the Fixup when determining whether to
     66 // emit the relocation as an explicit symbol or as a section relative
     67 // offset
     68 unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
     69                                           const MCFixup &Fixup,
     70                                           bool IsPCRel) const {
     71   return GetRelocTypeInner(Target, Fixup, IsPCRel);
     72 }
     73 
     74 unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
     75                                                const MCFixup &Fixup,
     76                                                bool IsPCRel) const  {
     77   MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
     78 
     79   unsigned Type = 0;
     80   if (IsPCRel) {
     81     switch ((unsigned)Fixup.getKind()) {
     82     default: llvm_unreachable("Unimplemented");
     83     case FK_Data_4:
     84       switch (Modifier) {
     85       default: llvm_unreachable("Unsupported Modifier");
     86       case MCSymbolRefExpr::VK_None:
     87         Type = ELF::R_ARM_REL32;
     88         break;
     89       case MCSymbolRefExpr::VK_TLSGD:
     90         llvm_unreachable("unimplemented");
     91       case MCSymbolRefExpr::VK_GOTTPOFF:
     92         Type = ELF::R_ARM_TLS_IE32;
     93         break;
     94       case MCSymbolRefExpr::VK_GOTPCREL:
     95         Type = ELF::R_ARM_GOT_PREL;
     96         break;
     97       }
     98       break;
     99     case ARM::fixup_arm_blx:
    100     case ARM::fixup_arm_uncondbl:
    101       switch (Modifier) {
    102       case MCSymbolRefExpr::VK_PLT:
    103         Type = ELF::R_ARM_PLT32;
    104         break;
    105       case MCSymbolRefExpr::VK_ARM_TLSCALL:
    106         Type = ELF::R_ARM_TLS_CALL;
    107         break;
    108       default:
    109         Type = ELF::R_ARM_CALL;
    110         break;
    111       }
    112       break;
    113     case ARM::fixup_arm_condbl:
    114     case ARM::fixup_arm_condbranch:
    115     case ARM::fixup_arm_uncondbranch:
    116       Type = ELF::R_ARM_JUMP24;
    117       break;
    118     case ARM::fixup_t2_condbranch:
    119     case ARM::fixup_t2_uncondbranch:
    120       Type = ELF::R_ARM_THM_JUMP24;
    121       break;
    122     case ARM::fixup_arm_movt_hi16:
    123       Type = ELF::R_ARM_MOVT_PREL;
    124       break;
    125     case ARM::fixup_arm_movw_lo16:
    126       Type = ELF::R_ARM_MOVW_PREL_NC;
    127       break;
    128     case ARM::fixup_t2_movt_hi16:
    129       Type = ELF::R_ARM_THM_MOVT_PREL;
    130       break;
    131     case ARM::fixup_t2_movw_lo16:
    132       Type = ELF::R_ARM_THM_MOVW_PREL_NC;
    133       break;
    134     case ARM::fixup_arm_thumb_bl:
    135     case ARM::fixup_arm_thumb_blx:
    136       switch (Modifier) {
    137       case MCSymbolRefExpr::VK_ARM_TLSCALL:
    138         Type = ELF::R_ARM_THM_TLS_CALL;
    139         break;
    140       default:
    141         Type = ELF::R_ARM_THM_CALL;
    142         break;
    143       }
    144       break;
    145     }
    146   } else {
    147     switch ((unsigned)Fixup.getKind()) {
    148     default: llvm_unreachable("invalid fixup kind!");
    149     case FK_Data_4:
    150       switch (Modifier) {
    151       default: llvm_unreachable("Unsupported Modifier");
    152       case MCSymbolRefExpr::VK_ARM_NONE:
    153         Type = ELF::R_ARM_NONE;
    154         break;
    155       case MCSymbolRefExpr::VK_GOT:
    156         Type = ELF::R_ARM_GOT_BREL;
    157         break;
    158       case MCSymbolRefExpr::VK_TLSGD:
    159         Type = ELF::R_ARM_TLS_GD32;
    160         break;
    161       case MCSymbolRefExpr::VK_TPOFF:
    162         Type = ELF::R_ARM_TLS_LE32;
    163         break;
    164       case MCSymbolRefExpr::VK_GOTTPOFF:
    165         Type = ELF::R_ARM_TLS_IE32;
    166         break;
    167       case MCSymbolRefExpr::VK_None:
    168         Type = ELF::R_ARM_ABS32;
    169         break;
    170       case MCSymbolRefExpr::VK_GOTOFF:
    171         Type = ELF::R_ARM_GOTOFF32;
    172         break;
    173       case MCSymbolRefExpr::VK_GOTPCREL:
    174         Type = ELF::R_ARM_GOT_PREL;
    175         break;
    176       case MCSymbolRefExpr::VK_ARM_TARGET1:
    177         Type = ELF::R_ARM_TARGET1;
    178         break;
    179       case MCSymbolRefExpr::VK_ARM_TARGET2:
    180         Type = ELF::R_ARM_TARGET2;
    181         break;
    182       case MCSymbolRefExpr::VK_ARM_PREL31:
    183         Type = ELF::R_ARM_PREL31;
    184         break;
    185       case MCSymbolRefExpr::VK_ARM_TLSLDO:
    186         Type = ELF::R_ARM_TLS_LDO32;
    187         break;
    188       case MCSymbolRefExpr::VK_ARM_TLSCALL:
    189         Type = ELF::R_ARM_TLS_CALL;
    190         break;
    191       case MCSymbolRefExpr::VK_ARM_TLSDESC:
    192         Type = ELF::R_ARM_TLS_GOTDESC;
    193         break;
    194       case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
    195         Type = ELF::R_ARM_TLS_DESCSEQ;
    196         break;
    197       }
    198       break;
    199     case ARM::fixup_arm_ldst_pcrel_12:
    200     case ARM::fixup_arm_pcrel_10:
    201     case ARM::fixup_arm_adr_pcrel_12:
    202     case ARM::fixup_arm_thumb_bl:
    203     case ARM::fixup_arm_thumb_cb:
    204     case ARM::fixup_arm_thumb_cp:
    205     case ARM::fixup_arm_thumb_br:
    206       llvm_unreachable("Unimplemented");
    207     case ARM::fixup_arm_condbranch:
    208     case ARM::fixup_arm_uncondbranch:
    209       Type = ELF::R_ARM_JUMP24;
    210       break;
    211     case ARM::fixup_arm_movt_hi16:
    212       Type = ELF::R_ARM_MOVT_ABS;
    213       break;
    214     case ARM::fixup_arm_movw_lo16:
    215       Type = ELF::R_ARM_MOVW_ABS_NC;
    216       break;
    217     case ARM::fixup_t2_movt_hi16:
    218       Type = ELF::R_ARM_THM_MOVT_ABS;
    219       break;
    220     case ARM::fixup_t2_movw_lo16:
    221       Type = ELF::R_ARM_THM_MOVW_ABS_NC;
    222       break;
    223     }
    224   }
    225 
    226   return Type;
    227 }
    228 
    229 MCObjectWriter *llvm::createARMELFObjectWriter(raw_ostream &OS,
    230                                                uint8_t OSABI,
    231                                                bool IsLittleEndian) {
    232   MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI);
    233   return createELFObjectWriter(MOTW, OS, IsLittleEndian);
    234 }
    235