LLVM API Documentation

PPCELFObjectWriter.cpp
Go to the documentation of this file.
00001 //===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "MCTargetDesc/PPCMCTargetDesc.h"
00011 #include "MCTargetDesc/PPCFixupKinds.h"
00012 #include "MCTargetDesc/PPCMCExpr.h"
00013 #include "llvm/ADT/STLExtras.h"
00014 #include "llvm/MC/MCELF.h"
00015 #include "llvm/MC/MCELFObjectWriter.h"
00016 #include "llvm/MC/MCExpr.h"
00017 #include "llvm/MC/MCValue.h"
00018 #include "llvm/Support/ErrorHandling.h"
00019 
00020 using namespace llvm;
00021 
00022 namespace {
00023   class PPCELFObjectWriter : public MCELFObjectTargetWriter {
00024   public:
00025     PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
00026 
00027   protected:
00028     unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
00029                           bool IsPCRel) const override;
00030 
00031     bool needsRelocateWithSymbol(const MCSymbolData &SD,
00032                                  unsigned Type) const override;
00033   };
00034 }
00035 
00036 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
00037   : MCELFObjectTargetWriter(Is64Bit, OSABI,
00038                             Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,
00039                             /*HasRelocationAddend*/ true) {}
00040 
00041 static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
00042                                                      const MCFixup &Fixup) {
00043   const MCExpr *Expr = Fixup.getValue();
00044 
00045   if (Expr->getKind() != MCExpr::Target)
00046     return Target.getAccessVariant();
00047 
00048   switch (cast<PPCMCExpr>(Expr)->getKind()) {
00049   case PPCMCExpr::VK_PPC_None:
00050     return MCSymbolRefExpr::VK_None;
00051   case PPCMCExpr::VK_PPC_LO:
00052     return MCSymbolRefExpr::VK_PPC_LO;
00053   case PPCMCExpr::VK_PPC_HI:
00054     return MCSymbolRefExpr::VK_PPC_HI;
00055   case PPCMCExpr::VK_PPC_HA:
00056     return MCSymbolRefExpr::VK_PPC_HA;
00057   case PPCMCExpr::VK_PPC_HIGHERA:
00058     return MCSymbolRefExpr::VK_PPC_HIGHERA;
00059   case PPCMCExpr::VK_PPC_HIGHER:
00060     return MCSymbolRefExpr::VK_PPC_HIGHER;
00061   case PPCMCExpr::VK_PPC_HIGHEST:
00062     return MCSymbolRefExpr::VK_PPC_HIGHEST;
00063   case PPCMCExpr::VK_PPC_HIGHESTA:
00064     return MCSymbolRefExpr::VK_PPC_HIGHESTA;
00065   }
00066   llvm_unreachable("unknown PPCMCExpr kind");
00067 }
00068 
00069 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
00070                                           const MCFixup &Fixup,
00071                                           bool IsPCRel) const {
00072   MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
00073 
00074   // determine the type of the relocation
00075   unsigned Type;
00076   if (IsPCRel) {
00077     switch ((unsigned)Fixup.getKind()) {
00078     default:
00079       llvm_unreachable("Unimplemented");
00080     case PPC::fixup_ppc_br24:
00081     case PPC::fixup_ppc_br24abs:
00082       switch (Modifier) {
00083       default: llvm_unreachable("Unsupported Modifier");
00084       case MCSymbolRefExpr::VK_None:
00085         Type = ELF::R_PPC_REL24;
00086         break;
00087       case MCSymbolRefExpr::VK_PLT:
00088         Type = ELF::R_PPC_PLTREL24;
00089         break;
00090       }
00091       break;
00092     case PPC::fixup_ppc_brcond14:
00093     case PPC::fixup_ppc_brcond14abs:
00094       Type = ELF::R_PPC_REL14;
00095       break;
00096     case PPC::fixup_ppc_half16:
00097       switch (Modifier) {
00098       default: llvm_unreachable("Unsupported Modifier");
00099       case MCSymbolRefExpr::VK_None:
00100         Type = ELF::R_PPC_REL16;
00101         break;
00102       case MCSymbolRefExpr::VK_PPC_LO:
00103         Type = ELF::R_PPC_REL16_LO;
00104         break;
00105       case MCSymbolRefExpr::VK_PPC_HI:
00106         Type = ELF::R_PPC_REL16_HI;
00107         break;
00108       case MCSymbolRefExpr::VK_PPC_HA:
00109         Type = ELF::R_PPC_REL16_HA;
00110         break;
00111       }
00112       break;
00113     case FK_Data_4:
00114     case FK_PCRel_4:
00115       Type = ELF::R_PPC_REL32;
00116       break;
00117     case FK_Data_8:
00118     case FK_PCRel_8:
00119       Type = ELF::R_PPC64_REL64;
00120       break;
00121     }
00122   } else {
00123     switch ((unsigned)Fixup.getKind()) {
00124       default: llvm_unreachable("invalid fixup kind!");
00125     case PPC::fixup_ppc_br24abs:
00126       Type = ELF::R_PPC_ADDR24;
00127       break;
00128     case PPC::fixup_ppc_brcond14abs:
00129       Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
00130       break;
00131     case PPC::fixup_ppc_half16:
00132       switch (Modifier) {
00133       default: llvm_unreachable("Unsupported Modifier");
00134       case MCSymbolRefExpr::VK_None:
00135         Type = ELF::R_PPC_ADDR16;
00136         break;
00137       case MCSymbolRefExpr::VK_PPC_LO:
00138         Type = ELF::R_PPC_ADDR16_LO;
00139         break;
00140       case MCSymbolRefExpr::VK_PPC_HI:
00141         Type = ELF::R_PPC_ADDR16_HI;
00142         break;
00143       case MCSymbolRefExpr::VK_PPC_HA:
00144         Type = ELF::R_PPC_ADDR16_HA;
00145         break;
00146       case MCSymbolRefExpr::VK_PPC_HIGHER:
00147         Type = ELF::R_PPC64_ADDR16_HIGHER;
00148         break;
00149       case MCSymbolRefExpr::VK_PPC_HIGHERA:
00150         Type = ELF::R_PPC64_ADDR16_HIGHERA;
00151         break;
00152       case MCSymbolRefExpr::VK_PPC_HIGHEST:
00153         Type = ELF::R_PPC64_ADDR16_HIGHEST;
00154         break;
00155       case MCSymbolRefExpr::VK_PPC_HIGHESTA:
00156         Type = ELF::R_PPC64_ADDR16_HIGHESTA;
00157         break;
00158       case MCSymbolRefExpr::VK_GOT:
00159         Type = ELF::R_PPC_GOT16;
00160         break;
00161       case MCSymbolRefExpr::VK_PPC_GOT_LO:
00162         Type = ELF::R_PPC_GOT16_LO;
00163         break;
00164       case MCSymbolRefExpr::VK_PPC_GOT_HI:
00165         Type = ELF::R_PPC_GOT16_HI;
00166         break;
00167       case MCSymbolRefExpr::VK_PPC_GOT_HA:
00168         Type = ELF::R_PPC_GOT16_HA;
00169         break;
00170       case MCSymbolRefExpr::VK_PPC_TOC:
00171         Type = ELF::R_PPC64_TOC16;
00172         break;
00173       case MCSymbolRefExpr::VK_PPC_TOC_LO:
00174         Type = ELF::R_PPC64_TOC16_LO;
00175         break;
00176       case MCSymbolRefExpr::VK_PPC_TOC_HI:
00177         Type = ELF::R_PPC64_TOC16_HI;
00178         break;
00179       case MCSymbolRefExpr::VK_PPC_TOC_HA:
00180         Type = ELF::R_PPC64_TOC16_HA;
00181         break;
00182       case MCSymbolRefExpr::VK_PPC_TPREL:
00183         Type = ELF::R_PPC_TPREL16;
00184         break;
00185       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
00186         Type = ELF::R_PPC_TPREL16_LO;
00187         break;
00188       case MCSymbolRefExpr::VK_PPC_TPREL_HI:
00189         Type = ELF::R_PPC_TPREL16_HI;
00190         break;
00191       case MCSymbolRefExpr::VK_PPC_TPREL_HA:
00192         Type = ELF::R_PPC_TPREL16_HA;
00193         break;
00194       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
00195         Type = ELF::R_PPC64_TPREL16_HIGHER;
00196         break;
00197       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
00198         Type = ELF::R_PPC64_TPREL16_HIGHERA;
00199         break;
00200       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
00201         Type = ELF::R_PPC64_TPREL16_HIGHEST;
00202         break;
00203       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
00204         Type = ELF::R_PPC64_TPREL16_HIGHESTA;
00205         break;
00206       case MCSymbolRefExpr::VK_PPC_DTPREL:
00207         Type = ELF::R_PPC64_DTPREL16;
00208         break;
00209       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
00210         Type = ELF::R_PPC64_DTPREL16_LO;
00211         break;
00212       case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
00213         Type = ELF::R_PPC64_DTPREL16_HI;
00214         break;
00215       case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
00216         Type = ELF::R_PPC64_DTPREL16_HA;
00217         break;
00218       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
00219         Type = ELF::R_PPC64_DTPREL16_HIGHER;
00220         break;
00221       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
00222         Type = ELF::R_PPC64_DTPREL16_HIGHERA;
00223         break;
00224       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
00225         Type = ELF::R_PPC64_DTPREL16_HIGHEST;
00226         break;
00227       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
00228         Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
00229         break;
00230       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
00231         if (is64Bit())
00232           Type = ELF::R_PPC64_GOT_TLSGD16;
00233         else
00234           Type = ELF::R_PPC_GOT_TLSGD16;
00235         break;
00236       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
00237         Type = ELF::R_PPC64_GOT_TLSGD16_LO;
00238         break;
00239       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
00240         Type = ELF::R_PPC64_GOT_TLSGD16_HI;
00241         break;
00242       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
00243         Type = ELF::R_PPC64_GOT_TLSGD16_HA;
00244         break;
00245       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
00246         if (is64Bit())
00247           Type = ELF::R_PPC64_GOT_TLSLD16;
00248         else
00249           Type = ELF::R_PPC_GOT_TLSLD16;
00250         break;
00251       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
00252         Type = ELF::R_PPC64_GOT_TLSLD16_LO;
00253         break;
00254       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
00255         Type = ELF::R_PPC64_GOT_TLSLD16_HI;
00256         break;
00257       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
00258         Type = ELF::R_PPC64_GOT_TLSLD16_HA;
00259         break;
00260       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
00261         /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
00262            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
00263         Type = ELF::R_PPC64_GOT_TPREL16_DS;
00264         break;
00265       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
00266         /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
00267            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
00268         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
00269         break;
00270       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
00271         Type = ELF::R_PPC64_GOT_TPREL16_HI;
00272         break;
00273       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
00274         /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
00275            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
00276         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
00277         break;
00278       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
00279         /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
00280            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
00281         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
00282         break;
00283       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
00284         Type = ELF::R_PPC64_GOT_TPREL16_HA;
00285         break;
00286       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
00287         Type = ELF::R_PPC64_GOT_DTPREL16_HI;
00288         break;
00289       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
00290         Type = ELF::R_PPC64_GOT_DTPREL16_HA;
00291         break;
00292       }
00293       break;
00294     case PPC::fixup_ppc_half16ds:
00295       switch (Modifier) {
00296       default: llvm_unreachable("Unsupported Modifier");
00297       case MCSymbolRefExpr::VK_None:
00298         Type = ELF::R_PPC64_ADDR16_DS;
00299         break;
00300       case MCSymbolRefExpr::VK_PPC_LO:
00301         Type = ELF::R_PPC64_ADDR16_LO_DS;
00302         break;
00303       case MCSymbolRefExpr::VK_GOT:
00304         Type = ELF::R_PPC64_GOT16_DS;
00305   break;
00306       case MCSymbolRefExpr::VK_PPC_GOT_LO:
00307         Type = ELF::R_PPC64_GOT16_LO_DS;
00308         break;
00309       case MCSymbolRefExpr::VK_PPC_TOC:
00310         Type = ELF::R_PPC64_TOC16_DS;
00311   break;
00312       case MCSymbolRefExpr::VK_PPC_TOC_LO:
00313         Type = ELF::R_PPC64_TOC16_LO_DS;
00314         break;
00315       case MCSymbolRefExpr::VK_PPC_TPREL:
00316         Type = ELF::R_PPC64_TPREL16_DS;
00317         break;
00318       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
00319         Type = ELF::R_PPC64_TPREL16_LO_DS;
00320         break;
00321       case MCSymbolRefExpr::VK_PPC_DTPREL:
00322         Type = ELF::R_PPC64_DTPREL16_DS;
00323         break;
00324       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
00325         Type = ELF::R_PPC64_DTPREL16_LO_DS;
00326         break;
00327       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
00328         Type = ELF::R_PPC64_GOT_TPREL16_DS;
00329         break;
00330       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
00331         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
00332         break;
00333       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
00334         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
00335         break;
00336       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
00337         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
00338         break;
00339       }
00340       break;
00341     case PPC::fixup_ppc_nofixup:
00342       switch (Modifier) {
00343       default: llvm_unreachable("Unsupported Modifier");
00344       case MCSymbolRefExpr::VK_PPC_TLSGD:
00345         if (is64Bit())
00346           Type = ELF::R_PPC64_TLSGD;
00347         else
00348           Type = ELF::R_PPC_TLSGD;
00349         break;
00350       case MCSymbolRefExpr::VK_PPC_TLSLD:
00351         if (is64Bit())
00352           Type = ELF::R_PPC64_TLSLD;
00353         else
00354           Type = ELF::R_PPC_TLSLD;
00355         break;
00356       case MCSymbolRefExpr::VK_PPC_TLS:
00357         if (is64Bit())
00358           Type = ELF::R_PPC64_TLS;
00359         else
00360           Type = ELF::R_PPC_TLS;
00361         break;
00362       }
00363       break;
00364     case FK_Data_8:
00365       switch (Modifier) {
00366       default: llvm_unreachable("Unsupported Modifier");
00367       case MCSymbolRefExpr::VK_PPC_TOCBASE:
00368         Type = ELF::R_PPC64_TOC;
00369         break;
00370       case MCSymbolRefExpr::VK_None:
00371         Type = ELF::R_PPC64_ADDR64;
00372   break;
00373       case MCSymbolRefExpr::VK_PPC_DTPMOD:
00374         Type = ELF::R_PPC64_DTPMOD64;
00375   break;
00376       case MCSymbolRefExpr::VK_PPC_TPREL:
00377         Type = ELF::R_PPC64_TPREL64;
00378   break;
00379       case MCSymbolRefExpr::VK_PPC_DTPREL:
00380         Type = ELF::R_PPC64_DTPREL64;
00381   break;
00382       }
00383       break;
00384     case FK_Data_4:
00385       Type = ELF::R_PPC_ADDR32;
00386       break;
00387     case FK_Data_2:
00388       Type = ELF::R_PPC_ADDR16;
00389       break;
00390     }
00391   }
00392   return Type;
00393 }
00394 
00395 bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD,
00396                                                  unsigned Type) const {
00397   switch (Type) {
00398     default:
00399       return false;
00400 
00401     case ELF::R_PPC_REL24:
00402       // If the target symbol has a local entry point, we must keep the
00403       // target symbol to preserve that information for the linker.
00404       // The "other" values are stored in the last 6 bits of the second byte.
00405       // The traditional defines for STO values assume the full byte and thus
00406       // the shift to pack it.
00407       unsigned Other = MCELF::getOther(SD) << 2;
00408       return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
00409   }
00410 }
00411 
00412 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
00413                                                bool Is64Bit,
00414                                                bool IsLittleEndian,
00415                                                uint8_t OSABI) {
00416   MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
00417   return createELFObjectWriter(MOTW, OS, IsLittleEndian);
00418 }