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/MCELFObjectWriter.h"
     15 #include "llvm/MC/MCExpr.h"
     16 #include "llvm/MC/MCSymbolELF.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 MCSymbol &Sym,
     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 PPC::fixup_ppc_half16ds:
    117       Target.print(errs());
    118       errs() << '\n';
    119       report_fatal_error("Invalid PC-relative half16ds relocation");
    120     case FK_Data_4:
    121     case FK_PCRel_4:
    122       Type = ELF::R_PPC_REL32;
    123       break;
    124     case FK_Data_8:
    125     case FK_PCRel_8:
    126       Type = ELF::R_PPC64_REL64;
    127       break;
    128     }
    129   } else {
    130     switch ((unsigned)Fixup.getKind()) {
    131       default: llvm_unreachable("invalid fixup kind!");
    132     case PPC::fixup_ppc_br24abs:
    133       Type = ELF::R_PPC_ADDR24;
    134       break;
    135     case PPC::fixup_ppc_brcond14abs:
    136       Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
    137       break;
    138     case PPC::fixup_ppc_half16:
    139       switch (Modifier) {
    140       default: llvm_unreachable("Unsupported Modifier");
    141       case MCSymbolRefExpr::VK_None:
    142         Type = ELF::R_PPC_ADDR16;
    143         break;
    144       case MCSymbolRefExpr::VK_PPC_LO:
    145         Type = ELF::R_PPC_ADDR16_LO;
    146         break;
    147       case MCSymbolRefExpr::VK_PPC_HI:
    148         Type = ELF::R_PPC_ADDR16_HI;
    149         break;
    150       case MCSymbolRefExpr::VK_PPC_HA:
    151         Type = ELF::R_PPC_ADDR16_HA;
    152         break;
    153       case MCSymbolRefExpr::VK_PPC_HIGHER:
    154         Type = ELF::R_PPC64_ADDR16_HIGHER;
    155         break;
    156       case MCSymbolRefExpr::VK_PPC_HIGHERA:
    157         Type = ELF::R_PPC64_ADDR16_HIGHERA;
    158         break;
    159       case MCSymbolRefExpr::VK_PPC_HIGHEST:
    160         Type = ELF::R_PPC64_ADDR16_HIGHEST;
    161         break;
    162       case MCSymbolRefExpr::VK_PPC_HIGHESTA:
    163         Type = ELF::R_PPC64_ADDR16_HIGHESTA;
    164         break;
    165       case MCSymbolRefExpr::VK_GOT:
    166         Type = ELF::R_PPC_GOT16;
    167         break;
    168       case MCSymbolRefExpr::VK_PPC_GOT_LO:
    169         Type = ELF::R_PPC_GOT16_LO;
    170         break;
    171       case MCSymbolRefExpr::VK_PPC_GOT_HI:
    172         Type = ELF::R_PPC_GOT16_HI;
    173         break;
    174       case MCSymbolRefExpr::VK_PPC_GOT_HA:
    175         Type = ELF::R_PPC_GOT16_HA;
    176         break;
    177       case MCSymbolRefExpr::VK_PPC_TOC:
    178         Type = ELF::R_PPC64_TOC16;
    179         break;
    180       case MCSymbolRefExpr::VK_PPC_TOC_LO:
    181         Type = ELF::R_PPC64_TOC16_LO;
    182         break;
    183       case MCSymbolRefExpr::VK_PPC_TOC_HI:
    184         Type = ELF::R_PPC64_TOC16_HI;
    185         break;
    186       case MCSymbolRefExpr::VK_PPC_TOC_HA:
    187         Type = ELF::R_PPC64_TOC16_HA;
    188         break;
    189       case MCSymbolRefExpr::VK_PPC_TPREL:
    190         Type = ELF::R_PPC_TPREL16;
    191         break;
    192       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
    193         Type = ELF::R_PPC_TPREL16_LO;
    194         break;
    195       case MCSymbolRefExpr::VK_PPC_TPREL_HI:
    196         Type = ELF::R_PPC_TPREL16_HI;
    197         break;
    198       case MCSymbolRefExpr::VK_PPC_TPREL_HA:
    199         Type = ELF::R_PPC_TPREL16_HA;
    200         break;
    201       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
    202         Type = ELF::R_PPC64_TPREL16_HIGHER;
    203         break;
    204       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
    205         Type = ELF::R_PPC64_TPREL16_HIGHERA;
    206         break;
    207       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
    208         Type = ELF::R_PPC64_TPREL16_HIGHEST;
    209         break;
    210       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
    211         Type = ELF::R_PPC64_TPREL16_HIGHESTA;
    212         break;
    213       case MCSymbolRefExpr::VK_PPC_DTPREL:
    214         Type = ELF::R_PPC64_DTPREL16;
    215         break;
    216       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
    217         Type = ELF::R_PPC64_DTPREL16_LO;
    218         break;
    219       case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
    220         Type = ELF::R_PPC64_DTPREL16_HI;
    221         break;
    222       case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
    223         Type = ELF::R_PPC64_DTPREL16_HA;
    224         break;
    225       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
    226         Type = ELF::R_PPC64_DTPREL16_HIGHER;
    227         break;
    228       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
    229         Type = ELF::R_PPC64_DTPREL16_HIGHERA;
    230         break;
    231       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
    232         Type = ELF::R_PPC64_DTPREL16_HIGHEST;
    233         break;
    234       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
    235         Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
    236         break;
    237       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
    238         if (is64Bit())
    239           Type = ELF::R_PPC64_GOT_TLSGD16;
    240         else
    241           Type = ELF::R_PPC_GOT_TLSGD16;
    242         break;
    243       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
    244         Type = ELF::R_PPC64_GOT_TLSGD16_LO;
    245         break;
    246       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
    247         Type = ELF::R_PPC64_GOT_TLSGD16_HI;
    248         break;
    249       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
    250         Type = ELF::R_PPC64_GOT_TLSGD16_HA;
    251         break;
    252       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
    253         if (is64Bit())
    254           Type = ELF::R_PPC64_GOT_TLSLD16;
    255         else
    256           Type = ELF::R_PPC_GOT_TLSLD16;
    257         break;
    258       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
    259         Type = ELF::R_PPC64_GOT_TLSLD16_LO;
    260         break;
    261       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
    262         Type = ELF::R_PPC64_GOT_TLSLD16_HI;
    263         break;
    264       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
    265         Type = ELF::R_PPC64_GOT_TLSLD16_HA;
    266         break;
    267       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
    268         /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
    269            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
    270         Type = ELF::R_PPC64_GOT_TPREL16_DS;
    271         break;
    272       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
    273         /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
    274            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
    275         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
    276         break;
    277       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
    278         Type = ELF::R_PPC64_GOT_TPREL16_HI;
    279         break;
    280       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
    281         /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
    282            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
    283         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
    284         break;
    285       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
    286         /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
    287            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
    288         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
    289         break;
    290       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
    291         Type = ELF::R_PPC64_GOT_TPREL16_HA;
    292         break;
    293       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
    294         Type = ELF::R_PPC64_GOT_DTPREL16_HI;
    295         break;
    296       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
    297         Type = ELF::R_PPC64_GOT_DTPREL16_HA;
    298         break;
    299       }
    300       break;
    301     case PPC::fixup_ppc_half16ds:
    302       switch (Modifier) {
    303       default: llvm_unreachable("Unsupported Modifier");
    304       case MCSymbolRefExpr::VK_None:
    305         Type = ELF::R_PPC64_ADDR16_DS;
    306         break;
    307       case MCSymbolRefExpr::VK_PPC_LO:
    308         Type = ELF::R_PPC64_ADDR16_LO_DS;
    309         break;
    310       case MCSymbolRefExpr::VK_GOT:
    311         Type = ELF::R_PPC64_GOT16_DS;
    312         break;
    313       case MCSymbolRefExpr::VK_PPC_GOT_LO:
    314         Type = ELF::R_PPC64_GOT16_LO_DS;
    315         break;
    316       case MCSymbolRefExpr::VK_PPC_TOC:
    317         Type = ELF::R_PPC64_TOC16_DS;
    318         break;
    319       case MCSymbolRefExpr::VK_PPC_TOC_LO:
    320         Type = ELF::R_PPC64_TOC16_LO_DS;
    321         break;
    322       case MCSymbolRefExpr::VK_PPC_TPREL:
    323         Type = ELF::R_PPC64_TPREL16_DS;
    324         break;
    325       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
    326         Type = ELF::R_PPC64_TPREL16_LO_DS;
    327         break;
    328       case MCSymbolRefExpr::VK_PPC_DTPREL:
    329         Type = ELF::R_PPC64_DTPREL16_DS;
    330         break;
    331       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
    332         Type = ELF::R_PPC64_DTPREL16_LO_DS;
    333         break;
    334       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
    335         Type = ELF::R_PPC64_GOT_TPREL16_DS;
    336         break;
    337       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
    338         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
    339         break;
    340       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
    341         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
    342         break;
    343       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
    344         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
    345         break;
    346       }
    347       break;
    348     case PPC::fixup_ppc_nofixup:
    349       switch (Modifier) {
    350       default: llvm_unreachable("Unsupported Modifier");
    351       case MCSymbolRefExpr::VK_PPC_TLSGD:
    352         if (is64Bit())
    353           Type = ELF::R_PPC64_TLSGD;
    354         else
    355           Type = ELF::R_PPC_TLSGD;
    356         break;
    357       case MCSymbolRefExpr::VK_PPC_TLSLD:
    358         if (is64Bit())
    359           Type = ELF::R_PPC64_TLSLD;
    360         else
    361           Type = ELF::R_PPC_TLSLD;
    362         break;
    363       case MCSymbolRefExpr::VK_PPC_TLS:
    364         if (is64Bit())
    365           Type = ELF::R_PPC64_TLS;
    366         else
    367           Type = ELF::R_PPC_TLS;
    368         break;
    369       }
    370       break;
    371     case FK_Data_8:
    372       switch (Modifier) {
    373       default: llvm_unreachable("Unsupported Modifier");
    374       case MCSymbolRefExpr::VK_PPC_TOCBASE:
    375         Type = ELF::R_PPC64_TOC;
    376         break;
    377       case MCSymbolRefExpr::VK_None:
    378         Type = ELF::R_PPC64_ADDR64;
    379         break;
    380       case MCSymbolRefExpr::VK_PPC_DTPMOD:
    381         Type = ELF::R_PPC64_DTPMOD64;
    382         break;
    383       case MCSymbolRefExpr::VK_PPC_TPREL:
    384         Type = ELF::R_PPC64_TPREL64;
    385         break;
    386       case MCSymbolRefExpr::VK_PPC_DTPREL:
    387         Type = ELF::R_PPC64_DTPREL64;
    388         break;
    389       }
    390       break;
    391     case FK_Data_4:
    392       Type = ELF::R_PPC_ADDR32;
    393       break;
    394     case FK_Data_2:
    395       Type = ELF::R_PPC_ADDR16;
    396       break;
    397     }
    398   }
    399   return Type;
    400 }
    401 
    402 bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
    403                                                  unsigned Type) const {
    404   switch (Type) {
    405     default:
    406       return false;
    407 
    408     case ELF::R_PPC_REL24:
    409       // If the target symbol has a local entry point, we must keep the
    410       // target symbol to preserve that information for the linker.
    411       // The "other" values are stored in the last 6 bits of the second byte.
    412       // The traditional defines for STO values assume the full byte and thus
    413       // the shift to pack it.
    414       unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
    415       return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
    416   }
    417 }
    418 
    419 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_pwrite_stream &OS,
    420                                                bool Is64Bit,
    421                                                bool IsLittleEndian,
    422                                                uint8_t OSABI) {
    423   MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
    424   return createELFObjectWriter(MOTW, OS, IsLittleEndian);
    425 }
    426