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/PPCMCTargetDesc.h"
12 #include "llvm/MC/MCELFObjectWriter.h"
13 #include "llvm/Support/ErrorHandling.h"
14
15 using namespace llvm;
16
17 namespace {
18 class PPCELFObjectWriter : public MCELFObjectTargetWriter {
19 public:
20 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
21
22 virtual ~PPCELFObjectWriter();
23 protected:
24 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
25 bool IsPCRel, bool IsRelocWithSymbol,
26 int64_t Addend) const;
27 virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset);
28 };
29 }
30
PPCELFObjectWriter(bool Is64Bit,uint8_t OSABI)31 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
32 : MCELFObjectTargetWriter(Is64Bit, OSABI,
33 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
34 /*HasRelocationAddend*/ true) {}
35
~PPCELFObjectWriter()36 PPCELFObjectWriter::~PPCELFObjectWriter() {
37 }
38
GetRelocType(const MCValue & Target,const MCFixup & Fixup,bool IsPCRel,bool IsRelocWithSymbol,int64_t Addend) const39 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
40 const MCFixup &Fixup,
41 bool IsPCRel,
42 bool IsRelocWithSymbol,
43 int64_t Addend) const {
44 // determine the type of the relocation
45 unsigned Type;
46 if (IsPCRel) {
47 switch ((unsigned)Fixup.getKind()) {
48 default:
49 llvm_unreachable("Unimplemented");
50 case PPC::fixup_ppc_br24:
51 Type = ELF::R_PPC_REL24;
52 break;
53 case FK_PCRel_4:
54 Type = ELF::R_PPC_REL32;
55 break;
56 }
57 } else {
58 switch ((unsigned)Fixup.getKind()) {
59 default: llvm_unreachable("invalid fixup kind!");
60 case PPC::fixup_ppc_br24:
61 Type = ELF::R_PPC_ADDR24;
62 break;
63 case PPC::fixup_ppc_brcond14:
64 Type = ELF::R_PPC_ADDR14_BRTAKEN; // XXX: or BRNTAKEN?_
65 break;
66 case PPC::fixup_ppc_ha16:
67 Type = ELF::R_PPC_ADDR16_HA;
68 break;
69 case PPC::fixup_ppc_lo16:
70 Type = ELF::R_PPC_ADDR16_LO;
71 break;
72 case PPC::fixup_ppc_lo14:
73 Type = ELF::R_PPC_ADDR14;
74 break;
75 case FK_Data_4:
76 Type = ELF::R_PPC_ADDR32;
77 break;
78 case FK_Data_2:
79 Type = ELF::R_PPC_ADDR16;
80 break;
81 }
82 }
83 return Type;
84 }
85
86 void PPCELFObjectWriter::
adjustFixupOffset(const MCFixup & Fixup,uint64_t & RelocOffset)87 adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) {
88 switch ((unsigned)Fixup.getKind()) {
89 case PPC::fixup_ppc_ha16:
90 case PPC::fixup_ppc_lo16:
91 RelocOffset += 2;
92 break;
93 default:
94 break;
95 }
96 }
97
createPPCELFObjectWriter(raw_ostream & OS,bool Is64Bit,uint8_t OSABI)98 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
99 bool Is64Bit,
100 uint8_t OSABI) {
101 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
102 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
103 }
104