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