brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.7 KiB · 329ad6e Raw
521 lines · cpp
1//===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/PPCFixupKinds.h"10#include "MCTargetDesc/PPCMCAsmInfo.h"11#include "MCTargetDesc/PPCMCTargetDesc.h"12#include "llvm/MC/MCContext.h"13#include "llvm/MC/MCELFObjectWriter.h"14#include "llvm/MC/MCExpr.h"15#include "llvm/MC/MCObjectWriter.h"16#include "llvm/MC/MCSymbolELF.h"17#include "llvm/MC/MCValue.h"18#include "llvm/Support/ErrorHandling.h"19 20using namespace llvm;21 22namespace {23  class PPCELFObjectWriter : public MCELFObjectTargetWriter {24  public:25    PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);26 27  protected:28    unsigned getRelocType(const MCFixup &Fixup, const MCValue &Target,29                          bool IsPCRel) const override;30 31    bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;32  };33}34 35PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)36  : MCELFObjectTargetWriter(Is64Bit, OSABI,37                            Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,38                            /*HasRelocationAddend*/ true) {}39 40unsigned PPCELFObjectWriter::getRelocType(const MCFixup &Fixup,41                                          const MCValue &Target,42                                          bool IsPCRel) const {43  SMLoc Loc = Fixup.getValue()->getLoc();44  auto Spec = static_cast<PPCMCExpr::Specifier>(Target.getSpecifier());45  switch (Spec) {46  case PPC::S_DTPMOD:47  case PPC::S_DTPREL:48  case PPC::S_DTPREL_HA:49  case PPC::S_DTPREL_HI:50  case PPC::S_DTPREL_HIGH:51  case PPC::S_DTPREL_HIGHA:52  case PPC::S_DTPREL_HIGHER:53  case PPC::S_DTPREL_HIGHERA:54  case PPC::S_DTPREL_HIGHEST:55  case PPC::S_DTPREL_HIGHESTA:56  case PPC::S_DTPREL_LO:57  case PPC::S_GOT_DTPREL:58  case PPC::S_GOT_DTPREL_HA:59  case PPC::S_GOT_DTPREL_HI:60  case PPC::S_GOT_DTPREL_LO:61  case PPC::S_GOT_TLSGD:62  case PPC::S_GOT_TLSGD_HA:63  case PPC::S_GOT_TLSGD_HI:64  case PPC::S_GOT_TLSGD_LO:65  case PPC::S_GOT_TLSGD_PCREL:66  case PPC::S_GOT_TLSLD:67  case PPC::S_GOT_TLSLD_HA:68  case PPC::S_GOT_TLSLD_HI:69  case PPC::S_GOT_TLSLD_LO:70  case PPC::S_GOT_TPREL:71  case PPC::S_GOT_TPREL_HA:72  case PPC::S_GOT_TPREL_HI:73  case PPC::S_GOT_TPREL_LO:74  case PPC::S_GOT_TPREL_PCREL:75  case PPC::S_TLS:76  case PPC::S_TLSGD:77  case PPC::S_TLSLD:78  case PPC::S_TLS_PCREL:79  case PPC::S_TPREL:80  case PPC::S_TPREL_HA:81  case PPC::S_TPREL_HI:82  case PPC::S_TPREL_HIGH:83  case PPC::S_TPREL_HIGHA:84  case PPC::S_TPREL_HIGHER:85  case PPC::S_TPREL_HIGHERA:86  case PPC::S_TPREL_HIGHEST:87  case PPC::S_TPREL_HIGHESTA:88  case PPC::S_TPREL_LO:89    if (auto *SA = const_cast<MCSymbol *>(Target.getAddSym()))90      static_cast<MCSymbolELF *>(SA)->setType(ELF::STT_TLS);91    break;92  default:93    break;94  }95 96  // determine the type of the relocation97  unsigned Type = 0;98  if (IsPCRel) {99    switch (Fixup.getKind()) {100    default:101      llvm_unreachable("Unimplemented");102    case PPC::fixup_ppc_br24:103    case PPC::fixup_ppc_br24abs:104    case PPC::fixup_ppc_br24_notoc:105      switch (Spec) {106      default:107        reportError(Loc, "unsupported relocation type");108        break;109      case PPC::S_None:110        Type = ELF::R_PPC_REL24;111        break;112      case PPC::S_PLT:113        Type = ELF::R_PPC_PLTREL24;114        break;115      case PPC::S_LOCAL:116        Type = ELF::R_PPC_LOCAL24PC;117        break;118      case PPC::S_NOTOC:119        Type = ELF::R_PPC64_REL24_NOTOC;120        break;121      }122      break;123    case PPC::fixup_ppc_brcond14:124    case PPC::fixup_ppc_brcond14abs:125      Type = ELF::R_PPC_REL14;126      break;127    case PPC::fixup_ppc_half16:128      switch (Spec) {129      default:130        reportError(Loc, "unsupported relocation type");131        return ELF::R_PPC_NONE;132      case PPC::S_None:133        return ELF::R_PPC_REL16;134      case PPC::S_LO:135        return ELF::R_PPC_REL16_LO;136      case PPC::S_HI:137        return ELF::R_PPC_REL16_HI;138      case PPC::S_HA:139        return ELF::R_PPC_REL16_HA;140      }141      break;142    case PPC::fixup_ppc_half16ds:143    case PPC::fixup_ppc_half16dq:144      reportError(Loc, "unsupported relocation type");145      break;146    case PPC::fixup_ppc_pcrel34:147      switch (Spec) {148      default:149        reportError(Loc, "unsupported relocation type");150        break;151      case PPC::S_PCREL:152        Type = ELF::R_PPC64_PCREL34;153        break;154      case PPC::S_GOT_PCREL:155        Type = ELF::R_PPC64_GOT_PCREL34;156        break;157      case PPC::S_GOT_TLSGD_PCREL:158        Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;159        break;160      case PPC::S_GOT_TLSLD_PCREL:161        Type = ELF::R_PPC64_GOT_TLSLD_PCREL34;162        break;163      case PPC::S_GOT_TPREL_PCREL:164        Type = ELF::R_PPC64_GOT_TPREL_PCREL34;165        break;166      }167      break;168    case FK_Data_4:169      Type = ELF::R_PPC_REL32;170      break;171    case FK_Data_8:172      Type = ELF::R_PPC64_REL64;173      break;174    }175  } else {176    switch (Fixup.getKind()) {177    default:178      llvm_unreachable("invalid fixup kind!");179    case PPC::fixup_ppc_br24abs:180      Type = ELF::R_PPC_ADDR24;181      break;182    case PPC::fixup_ppc_brcond14abs:183      Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_184      break;185    case PPC::fixup_ppc_half16:186      switch (Spec) {187      default:188        reportError(Loc, "unsupported relocation type");189        break;190      case PPC::S_LO:191        return ELF::R_PPC_ADDR16_LO;192      case PPC::S_HI:193        return ELF::R_PPC_ADDR16_HI;194      case PPC::S_HA:195        return ELF::R_PPC_ADDR16_HA;196      case PPC::S_HIGH:197        return ELF::R_PPC64_ADDR16_HIGH;198      case PPC::S_HIGHA:199        return ELF::R_PPC64_ADDR16_HIGHA;200      case PPC::S_HIGHER:201        return ELF::R_PPC64_ADDR16_HIGHER;202      case PPC::S_HIGHERA:203        return ELF::R_PPC64_ADDR16_HIGHERA;204      case PPC::S_HIGHEST:205        return ELF::R_PPC64_ADDR16_HIGHEST;206      case PPC::S_HIGHESTA:207        return ELF::R_PPC64_ADDR16_HIGHESTA;208 209      case PPC::S_None:210        Type = ELF::R_PPC_ADDR16;211        break;212      case PPC::S_GOT:213        Type = ELF::R_PPC_GOT16;214        break;215      case PPC::S_GOT_LO:216        Type = ELF::R_PPC_GOT16_LO;217        break;218      case PPC::S_GOT_HI:219        Type = ELF::R_PPC_GOT16_HI;220        break;221      case PPC::S_GOT_HA:222        Type = ELF::R_PPC_GOT16_HA;223        break;224      case PPC::S_TOC:225        Type = ELF::R_PPC64_TOC16;226        break;227      case PPC::S_TOC_LO:228        Type = ELF::R_PPC64_TOC16_LO;229        break;230      case PPC::S_TOC_HI:231        Type = ELF::R_PPC64_TOC16_HI;232        break;233      case PPC::S_TOC_HA:234        Type = ELF::R_PPC64_TOC16_HA;235        break;236      case PPC::S_TPREL:237        Type = ELF::R_PPC_TPREL16;238        break;239      case PPC::S_TPREL_LO:240        Type = ELF::R_PPC_TPREL16_LO;241        break;242      case PPC::S_TPREL_HI:243        Type = ELF::R_PPC_TPREL16_HI;244        break;245      case PPC::S_TPREL_HA:246        Type = ELF::R_PPC_TPREL16_HA;247        break;248      case PPC::S_TPREL_HIGH:249        Type = ELF::R_PPC64_TPREL16_HIGH;250        break;251      case PPC::S_TPREL_HIGHA:252        Type = ELF::R_PPC64_TPREL16_HIGHA;253        break;254      case PPC::S_TPREL_HIGHER:255        Type = ELF::R_PPC64_TPREL16_HIGHER;256        break;257      case PPC::S_TPREL_HIGHERA:258        Type = ELF::R_PPC64_TPREL16_HIGHERA;259        break;260      case PPC::S_TPREL_HIGHEST:261        Type = ELF::R_PPC64_TPREL16_HIGHEST;262        break;263      case PPC::S_TPREL_HIGHESTA:264        Type = ELF::R_PPC64_TPREL16_HIGHESTA;265        break;266      case PPC::S_DTPREL:267        Type = ELF::R_PPC64_DTPREL16;268        break;269      case PPC::S_DTPREL_LO:270        Type = ELF::R_PPC64_DTPREL16_LO;271        break;272      case PPC::S_DTPREL_HI:273        Type = ELF::R_PPC64_DTPREL16_HI;274        break;275      case PPC::S_DTPREL_HA:276        Type = ELF::R_PPC64_DTPREL16_HA;277        break;278      case PPC::S_DTPREL_HIGH:279        Type = ELF::R_PPC64_DTPREL16_HIGH;280        break;281      case PPC::S_DTPREL_HIGHA:282        Type = ELF::R_PPC64_DTPREL16_HIGHA;283        break;284      case PPC::S_DTPREL_HIGHER:285        Type = ELF::R_PPC64_DTPREL16_HIGHER;286        break;287      case PPC::S_DTPREL_HIGHERA:288        Type = ELF::R_PPC64_DTPREL16_HIGHERA;289        break;290      case PPC::S_DTPREL_HIGHEST:291        Type = ELF::R_PPC64_DTPREL16_HIGHEST;292        break;293      case PPC::S_DTPREL_HIGHESTA:294        Type = ELF::R_PPC64_DTPREL16_HIGHESTA;295        break;296      case PPC::S_GOT_TLSGD:297        if (is64Bit())298          Type = ELF::R_PPC64_GOT_TLSGD16;299        else300          Type = ELF::R_PPC_GOT_TLSGD16;301        break;302      case PPC::S_GOT_TLSGD_LO:303        Type = ELF::R_PPC64_GOT_TLSGD16_LO;304        break;305      case PPC::S_GOT_TLSGD_HI:306        Type = ELF::R_PPC64_GOT_TLSGD16_HI;307        break;308      case PPC::S_GOT_TLSGD_HA:309        Type = ELF::R_PPC64_GOT_TLSGD16_HA;310        break;311      case PPC::S_GOT_TLSLD:312        if (is64Bit())313          Type = ELF::R_PPC64_GOT_TLSLD16;314        else315          Type = ELF::R_PPC_GOT_TLSLD16;316        break;317      case PPC::S_GOT_TLSLD_LO:318        Type = ELF::R_PPC64_GOT_TLSLD16_LO;319        break;320      case PPC::S_GOT_TLSLD_HI:321        Type = ELF::R_PPC64_GOT_TLSLD16_HI;322        break;323      case PPC::S_GOT_TLSLD_HA:324        Type = ELF::R_PPC64_GOT_TLSLD16_HA;325        break;326      case PPC::S_GOT_TPREL:327        /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets328           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */329        Type = ELF::R_PPC64_GOT_TPREL16_DS;330        break;331      case PPC::S_GOT_TPREL_LO:332        /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets333           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */334        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;335        break;336      case PPC::S_GOT_TPREL_HI:337        Type = ELF::R_PPC64_GOT_TPREL16_HI;338        break;339      case PPC::S_GOT_DTPREL:340        /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets341           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */342        Type = ELF::R_PPC64_GOT_DTPREL16_DS;343        break;344      case PPC::S_GOT_DTPREL_LO:345        /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets346           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */347        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;348        break;349      case PPC::S_GOT_TPREL_HA:350        Type = ELF::R_PPC64_GOT_TPREL16_HA;351        break;352      case PPC::S_GOT_DTPREL_HI:353        Type = ELF::R_PPC64_GOT_DTPREL16_HI;354        break;355      case PPC::S_GOT_DTPREL_HA:356        Type = ELF::R_PPC64_GOT_DTPREL16_HA;357        break;358      }359      break;360    case PPC::fixup_ppc_half16ds:361    case PPC::fixup_ppc_half16dq:362      switch (Spec) {363      default:364        reportError(Loc, "unsupported relocation type");365        break;366      case PPC::S_LO:367        return ELF::R_PPC64_ADDR16_LO_DS;368      case PPC::S_None:369        Type = ELF::R_PPC64_ADDR16_DS;370        break;371      case PPC::S_GOT:372        Type = ELF::R_PPC64_GOT16_DS;373        break;374      case PPC::S_GOT_LO:375        Type = ELF::R_PPC64_GOT16_LO_DS;376        break;377      case PPC::S_TOC:378        Type = ELF::R_PPC64_TOC16_DS;379        break;380      case PPC::S_TOC_LO:381        Type = ELF::R_PPC64_TOC16_LO_DS;382        break;383      case PPC::S_TPREL:384        Type = ELF::R_PPC64_TPREL16_DS;385        break;386      case PPC::S_TPREL_LO:387        Type = ELF::R_PPC64_TPREL16_LO_DS;388        break;389      case PPC::S_DTPREL:390        Type = ELF::R_PPC64_DTPREL16_DS;391        break;392      case PPC::S_DTPREL_LO:393        Type = ELF::R_PPC64_DTPREL16_LO_DS;394        break;395      case PPC::S_GOT_TPREL:396        Type = ELF::R_PPC64_GOT_TPREL16_DS;397        break;398      case PPC::S_GOT_TPREL_LO:399        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;400        break;401      case PPC::S_GOT_DTPREL:402        Type = ELF::R_PPC64_GOT_DTPREL16_DS;403        break;404      case PPC::S_GOT_DTPREL_LO:405        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;406        break;407      }408      break;409    case PPC::fixup_ppc_nofixup:410      switch (Spec) {411      default:412        reportError(Loc, "unsupported relocation type");413        break;414      case PPC::S_TLSGD:415        if (is64Bit())416          Type = ELF::R_PPC64_TLSGD;417        else418          Type = ELF::R_PPC_TLSGD;419        break;420      case PPC::S_TLSLD:421        if (is64Bit())422          Type = ELF::R_PPC64_TLSLD;423        else424          Type = ELF::R_PPC_TLSLD;425        break;426      case PPC::S_TLS:427        if (is64Bit())428          Type = ELF::R_PPC64_TLS;429        else430          Type = ELF::R_PPC_TLS;431        break;432      case PPC::S_TLS_PCREL:433        Type = ELF::R_PPC64_TLS;434        break;435      }436      break;437    case PPC::fixup_ppc_imm34:438      switch (Spec) {439      default:440        reportError(Loc, "unsupported relocation type");441        break;442      case PPC::S_DTPREL:443        Type = ELF::R_PPC64_DTPREL34;444        break;445      case PPC::S_TPREL:446        Type = ELF::R_PPC64_TPREL34;447        break;448      }449      break;450    case FK_Data_8:451      switch (Spec) {452      default:453        reportError(Loc, "unsupported relocation type");454        break;455      case PPC::S_TOCBASE:456        Type = ELF::R_PPC64_TOC;457        break;458      case PPC::S_None:459        Type = ELF::R_PPC64_ADDR64;460        break;461      case PPC::S_DTPMOD:462        Type = ELF::R_PPC64_DTPMOD64;463        break;464      case PPC::S_TPREL:465        Type = ELF::R_PPC64_TPREL64;466        break;467      case PPC::S_DTPREL:468        Type = ELF::R_PPC64_DTPREL64;469        break;470      }471      break;472    case FK_Data_4:473      switch (Spec) {474      case PPC::S_DTPREL:475        Type = ELF::R_PPC_DTPREL32;476        break;477      default:478        Type = ELF::R_PPC_ADDR32;479      }480      break;481    case FK_Data_2:482      Type = ELF::R_PPC_ADDR16;483      break;484    }485  }486  return Type;487}488 489bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,490                                                 unsigned Type) const {491  switch (Type) {492    default:493      return false;494 495    case ELF::R_PPC_REL24:496    case ELF::R_PPC64_REL24_NOTOC: {497      // If the target symbol has a local entry point, we must keep the498      // target symbol to preserve that information for the linker.499      // The "other" values are stored in the last 6 bits of the second byte.500      // The traditional defines for STO values assume the full byte and thus501      // the shift to pack it.502      unsigned Other =503          static_cast<const MCSymbolELF *>(V.getAddSym())->getOther() << 2;504      return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;505    }506 507    case ELF::R_PPC64_GOT16:508    case ELF::R_PPC64_GOT16_DS:509    case ELF::R_PPC64_GOT16_LO:510    case ELF::R_PPC64_GOT16_LO_DS:511    case ELF::R_PPC64_GOT16_HI:512    case ELF::R_PPC64_GOT16_HA:513      return true;514    }515}516 517std::unique_ptr<MCObjectTargetWriter>518llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {519  return std::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);520}521