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