Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- PPCELFObjectWriter.cpp - PPC 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/PPCMCTargetDesc.h"
     11 #include "MCTargetDesc/PPCFixupKinds.h"
     12 #include "MCTargetDesc/PPCMCExpr.h"
     13 #include "llvm/ADT/STLExtras.h"
     14 #include "llvm/MC/MCELF.h"
     15 #include "llvm/MC/MCELFObjectWriter.h"
     16 #include "llvm/MC/MCExpr.h"
     17 #include "llvm/MC/MCValue.h"
     18 #include "llvm/Support/ErrorHandling.h"
     19 
     20 using namespace llvm;
     21 
     22 namespace {
     23   class PPCELFObjectWriter : public MCELFObjectTargetWriter {
     24   public:
     25     PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
     26 
     27   protected:
     28     unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
     29                           bool IsPCRel) const override;
     30 
     31     bool needsRelocateWithSymbol(const MCSymbolData &SD,
     32                                  unsigned Type) const override;
     33   };
     34 }
     35 
     36 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
     37   : MCELFObjectTargetWriter(Is64Bit, OSABI,
     38                             Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,
     39                             /*HasRelocationAddend*/ true) {}
     40 
     41 static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
     42                                                      const MCFixup &Fixup) {
     43   const MCExpr *Expr = Fixup.getValue();
     44 
     45   if (Expr->getKind() != MCExpr::Target)
     46     return Target.getAccessVariant();
     47 
     48   switch (cast<PPCMCExpr>(Expr)->getKind()) {
     49   case PPCMCExpr::VK_PPC_None:
     50     return MCSymbolRefExpr::VK_None;
     51   case PPCMCExpr::VK_PPC_LO:
     52     return MCSymbolRefExpr::VK_PPC_LO;
     53   case PPCMCExpr::VK_PPC_HI:
     54     return MCSymbolRefExpr::VK_PPC_HI;
     55   case PPCMCExpr::VK_PPC_HA:
     56     return MCSymbolRefExpr::VK_PPC_HA;
     57   case PPCMCExpr::VK_PPC_HIGHERA:
     58     return MCSymbolRefExpr::VK_PPC_HIGHERA;
     59   case PPCMCExpr::VK_PPC_HIGHER:
     60     return MCSymbolRefExpr::VK_PPC_HIGHER;
     61   case PPCMCExpr::VK_PPC_HIGHEST:
     62     return MCSymbolRefExpr::VK_PPC_HIGHEST;
     63   case PPCMCExpr::VK_PPC_HIGHESTA:
     64     return MCSymbolRefExpr::VK_PPC_HIGHESTA;
     65   }
     66   llvm_unreachable("unknown PPCMCExpr kind");
     67 }
     68 
     69 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
     70                                           const MCFixup &Fixup,
     71                                           bool IsPCRel) const {
     72   MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
     73 
     74   // determine the type of the relocation
     75   unsigned Type;
     76   if (IsPCRel) {
     77     switch ((unsigned)Fixup.getKind()) {
     78     default:
     79       llvm_unreachable("Unimplemented");
     80     case PPC::fixup_ppc_br24:
     81     case PPC::fixup_ppc_br24abs:
     82       switch (Modifier) {
     83       default: llvm_unreachable("Unsupported Modifier");
     84       case MCSymbolRefExpr::VK_None:
     85         Type = ELF::R_PPC_REL24;
     86         break;
     87       case MCSymbolRefExpr::VK_PLT:
     88         Type = ELF::R_PPC_PLTREL24;
     89         break;
     90       case MCSymbolRefExpr::VK_PPC_LOCAL:
     91         Type = ELF::R_PPC_LOCAL24PC;
     92         break;
     93       }
     94       break;
     95     case PPC::fixup_ppc_brcond14:
     96     case PPC::fixup_ppc_brcond14abs:
     97       Type = ELF::R_PPC_REL14;
     98       break;
     99     case PPC::fixup_ppc_half16:
    100       switch (Modifier) {
    101       default: llvm_unreachable("Unsupported Modifier");
    102       case MCSymbolRefExpr::VK_None:
    103         Type = ELF::R_PPC_REL16;
    104         break;
    105       case MCSymbolRefExpr::VK_PPC_LO:
    106         Type = ELF::R_PPC_REL16_LO;
    107         break;
    108       case MCSymbolRefExpr::VK_PPC_HI:
    109         Type = ELF::R_PPC_REL16_HI;
    110         break;
    111       case MCSymbolRefExpr::VK_PPC_HA:
    112         Type = ELF::R_PPC_REL16_HA;
    113         break;
    114       }
    115       break;
    116     case FK_Data_4:
    117     case FK_PCRel_4:
    118       Type = ELF::R_PPC_REL32;
    119       break;
    120     case FK_Data_8:
    121     case FK_PCRel_8:
    122       Type = ELF::R_PPC64_REL64;
    123       break;
    124     }
    125   } else {
    126     switch ((unsigned)Fixup.getKind()) {
    127       default: llvm_unreachable("invalid fixup kind!");
    128     case PPC::fixup_ppc_br24abs:
    129       Type = ELF::R_PPC_ADDR24;
    130       break;
    131     case PPC::fixup_ppc_brcond14abs:
    132       Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
    133       break;
    134     case PPC::fixup_ppc_half16:
    135       switch (Modifier) {
    136       default: llvm_unreachable("Unsupported Modifier");
    137       case MCSymbolRefExpr::VK_None:
    138         Type = ELF::R_PPC_ADDR16;
    139         break;
    140       case MCSymbolRefExpr::VK_PPC_LO:
    141         Type = ELF::R_PPC_ADDR16_LO;
    142         break;
    143       case MCSymbolRefExpr::VK_PPC_HI:
    144         Type = ELF::R_PPC_ADDR16_HI;
    145         break;
    146       case MCSymbolRefExpr::VK_PPC_HA:
    147         Type = ELF::R_PPC_ADDR16_HA;
    148         break;
    149       case MCSymbolRefExpr::VK_PPC_HIGHER:
    150         Type = ELF::R_PPC64_ADDR16_HIGHER;
    151         break;
    152       case MCSymbolRefExpr::VK_PPC_HIGHERA:
    153         Type = ELF::R_PPC64_ADDR16_HIGHERA;
    154         break;
    155       case MCSymbolRefExpr::VK_PPC_HIGHEST:
    156         Type = ELF::R_PPC64_ADDR16_HIGHEST;
    157         break;
    158       case MCSymbolRefExpr::VK_PPC_HIGHESTA:
    159         Type = ELF::R_PPC64_ADDR16_HIGHESTA;
    160         break;
    161       case MCSymbolRefExpr::VK_GOT:
    162         Type = ELF::R_PPC_GOT16;
    163         break;
    164       case MCSymbolRefExpr::VK_PPC_GOT_LO:
    165         Type = ELF::R_PPC_GOT16_LO;
    166         break;
    167       case MCSymbolRefExpr::VK_PPC_GOT_HI:
    168         Type = ELF::R_PPC_GOT16_HI;
    169         break;
    170       case MCSymbolRefExpr::VK_PPC_GOT_HA:
    171         Type = ELF::R_PPC_GOT16_HA;
    172         break;
    173       case MCSymbolRefExpr::VK_PPC_TOC:
    174         Type = ELF::R_PPC64_TOC16;
    175         break;
    176       case MCSymbolRefExpr::VK_PPC_TOC_LO:
    177         Type = ELF::R_PPC64_TOC16_LO;
    178         break;
    179       case MCSymbolRefExpr::VK_PPC_TOC_HI:
    180         Type = ELF::R_PPC64_TOC16_HI;
    181         break;
    182       case MCSymbolRefExpr::VK_PPC_TOC_HA:
    183         Type = ELF::R_PPC64_TOC16_HA;
    184         break;
    185       case MCSymbolRefExpr::VK_PPC_TPREL:
    186         Type = ELF::R_PPC_TPREL16;
    187         break;
    188       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
    189         Type = ELF::R_PPC_TPREL16_LO;
    190         break;
    191       case MCSymbolRefExpr::VK_PPC_TPREL_HI:
    192         Type = ELF::R_PPC_TPREL16_HI;
    193         break;
    194       case MCSymbolRefExpr::VK_PPC_TPREL_HA:
    195         Type = ELF::R_PPC_TPREL16_HA;
    196         break;
    197       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
    198         Type = ELF::R_PPC64_TPREL16_HIGHER;
    199         break;
    200       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
    201         Type = ELF::R_PPC64_TPREL16_HIGHERA;
    202         break;
    203       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
    204         Type = ELF::R_PPC64_TPREL16_HIGHEST;
    205         break;
    206       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
    207         Type = ELF::R_PPC64_TPREL16_HIGHESTA;
    208         break;
    209       case MCSymbolRefExpr::VK_PPC_DTPREL:
    210         Type = ELF::R_PPC64_DTPREL16;
    211         break;
    212       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
    213         Type = ELF::R_PPC64_DTPREL16_LO;
    214         break;
    215       case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
    216         Type = ELF::R_PPC64_DTPREL16_HI;
    217         break;
    218       case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
    219         Type = ELF::R_PPC64_DTPREL16_HA;
    220         break;
    221       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
    222         Type = ELF::R_PPC64_DTPREL16_HIGHER;
    223         break;
    224       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
    225         Type = ELF::R_PPC64_DTPREL16_HIGHERA;
    226         break;
    227       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
    228         Type = ELF::R_PPC64_DTPREL16_HIGHEST;
    229         break;
    230       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
    231         Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
    232         break;
    233       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
    234         if (is64Bit())
    235           Type = ELF::R_PPC64_GOT_TLSGD16;
    236         else
    237           Type = ELF::R_PPC_GOT_TLSGD16;
    238         break;
    239       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
    240         Type = ELF::R_PPC64_GOT_TLSGD16_LO;
    241         break;
    242       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
    243         Type = ELF::R_PPC64_GOT_TLSGD16_HI;
    244         break;
    245       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
    246         Type = ELF::R_PPC64_GOT_TLSGD16_HA;
    247         break;
    248       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
    249         if (is64Bit())
    250           Type = ELF::R_PPC64_GOT_TLSLD16;
    251         else
    252           Type = ELF::R_PPC_GOT_TLSLD16;
    253         break;
    254       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
    255         Type = ELF::R_PPC64_GOT_TLSLD16_LO;
    256         break;
    257       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
    258         Type = ELF::R_PPC64_GOT_TLSLD16_HI;
    259         break;
    260       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
    261         Type = ELF::R_PPC64_GOT_TLSLD16_HA;
    262         break;
    263       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
    264         /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
    265            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
    266         Type = ELF::R_PPC64_GOT_TPREL16_DS;
    267         break;
    268       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
    269         /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
    270            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
    271         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
    272         break;
    273       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
    274         Type = ELF::R_PPC64_GOT_TPREL16_HI;
    275         break;
    276       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
    277         /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
    278            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
    279         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
    280         break;
    281       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
    282         /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
    283            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
    284         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
    285         break;
    286       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
    287         Type = ELF::R_PPC64_GOT_TPREL16_HA;
    288         break;
    289       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
    290         Type = ELF::R_PPC64_GOT_DTPREL16_HI;
    291         break;
    292       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
    293         Type = ELF::R_PPC64_GOT_DTPREL16_HA;
    294         break;
    295       }
    296       break;
    297     case PPC::fixup_ppc_half16ds:
    298       switch (Modifier) {
    299       default: llvm_unreachable("Unsupported Modifier");
    300       case MCSymbolRefExpr::VK_None:
    301         Type = ELF::R_PPC64_ADDR16_DS;
    302         break;
    303       case MCSymbolRefExpr::VK_PPC_LO:
    304         Type = ELF::R_PPC64_ADDR16_LO_DS;
    305         break;
    306       case MCSymbolRefExpr::VK_GOT:
    307         Type = ELF::R_PPC64_GOT16_DS;
    308 	break;
    309       case MCSymbolRefExpr::VK_PPC_GOT_LO:
    310         Type = ELF::R_PPC64_GOT16_LO_DS;
    311         break;
    312       case MCSymbolRefExpr::VK_PPC_TOC:
    313         Type = ELF::R_PPC64_TOC16_DS;
    314 	break;
    315       case MCSymbolRefExpr::VK_PPC_TOC_LO:
    316         Type = ELF::R_PPC64_TOC16_LO_DS;
    317         break;
    318       case MCSymbolRefExpr::VK_PPC_TPREL:
    319         Type = ELF::R_PPC64_TPREL16_DS;
    320         break;
    321       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
    322         Type = ELF::R_PPC64_TPREL16_LO_DS;
    323         break;
    324       case MCSymbolRefExpr::VK_PPC_DTPREL:
    325         Type = ELF::R_PPC64_DTPREL16_DS;
    326         break;
    327       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
    328         Type = ELF::R_PPC64_DTPREL16_LO_DS;
    329         break;
    330       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
    331         Type = ELF::R_PPC64_GOT_TPREL16_DS;
    332         break;
    333       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
    334         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
    335         break;
    336       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
    337         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
    338         break;
    339       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
    340         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
    341         break;
    342       }
    343       break;
    344     case PPC::fixup_ppc_nofixup:
    345       switch (Modifier) {
    346       default: llvm_unreachable("Unsupported Modifier");
    347       case MCSymbolRefExpr::VK_PPC_TLSGD:
    348         if (is64Bit())
    349           Type = ELF::R_PPC64_TLSGD;
    350         else
    351           Type = ELF::R_PPC_TLSGD;
    352         break;
    353       case MCSymbolRefExpr::VK_PPC_TLSLD:
    354         if (is64Bit())
    355           Type = ELF::R_PPC64_TLSLD;
    356         else
    357           Type = ELF::R_PPC_TLSLD;
    358         break;
    359       case MCSymbolRefExpr::VK_PPC_TLS:
    360         if (is64Bit())
    361           Type = ELF::R_PPC64_TLS;
    362         else
    363           Type = ELF::R_PPC_TLS;
    364         break;
    365       }
    366       break;
    367     case FK_Data_8:
    368       switch (Modifier) {
    369       default: llvm_unreachable("Unsupported Modifier");
    370       case MCSymbolRefExpr::VK_PPC_TOCBASE:
    371         Type = ELF::R_PPC64_TOC;
    372         break;
    373       case MCSymbolRefExpr::VK_None:
    374         Type = ELF::R_PPC64_ADDR64;
    375 	break;
    376       case MCSymbolRefExpr::VK_PPC_DTPMOD:
    377         Type = ELF::R_PPC64_DTPMOD64;
    378 	break;
    379       case MCSymbolRefExpr::VK_PPC_TPREL:
    380         Type = ELF::R_PPC64_TPREL64;
    381 	break;
    382       case MCSymbolRefExpr::VK_PPC_DTPREL:
    383         Type = ELF::R_PPC64_DTPREL64;
    384 	break;
    385       }
    386       break;
    387     case FK_Data_4:
    388       Type = ELF::R_PPC_ADDR32;
    389       break;
    390     case FK_Data_2:
    391       Type = ELF::R_PPC_ADDR16;
    392       break;
    393     }
    394   }
    395   return Type;
    396 }
    397 
    398 bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD,
    399                                                  unsigned Type) const {
    400   switch (Type) {
    401     default:
    402       return false;
    403 
    404     case ELF::R_PPC_REL24:
    405       // If the target symbol has a local entry point, we must keep the
    406       // target symbol to preserve that information for the linker.
    407       // The "other" values are stored in the last 6 bits of the second byte.
    408       // The traditional defines for STO values assume the full byte and thus
    409       // the shift to pack it.
    410       unsigned Other = MCELF::getOther(SD) << 2;
    411       return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
    412   }
    413 }
    414 
    415 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_pwrite_stream &OS,
    416                                                bool Is64Bit,
    417                                                bool IsLittleEndian,
    418                                                uint8_t OSABI) {
    419   MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
    420   return createELFObjectWriter(MOTW, OS, IsLittleEndian);
    421 }
    422