1234285Sdim//===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim 10249423Sdim#include "MCTargetDesc/ARMMCTargetDesc.h" 11234285Sdim#include "MCTargetDesc/ARMFixupKinds.h" 12234285Sdim#include "llvm/ADT/Statistic.h" 13234285Sdim#include "llvm/ADT/StringSwitch.h" 14234285Sdim#include "llvm/MC/MCELFObjectWriter.h" 15234285Sdim#include "llvm/MC/MCExpr.h" 16234285Sdim#include "llvm/MC/MCSectionELF.h" 17234285Sdim#include "llvm/MC/MCValue.h" 18249423Sdim#include "llvm/Support/Debug.h" 19249423Sdim#include "llvm/Support/ErrorHandling.h" 20249423Sdim#include "llvm/Support/raw_ostream.h" 21234285Sdim 22234285Sdimusing namespace llvm; 23234285Sdim 24234285Sdimnamespace { 25234285Sdim class ARMELFObjectWriter : public MCELFObjectTargetWriter { 26234285Sdim enum { DefaultEABIVersion = 0x05000000U }; 27234285Sdim unsigned GetRelocTypeInner(const MCValue &Target, 28234285Sdim const MCFixup &Fixup, 29234285Sdim bool IsPCRel) const; 30234285Sdim 31234285Sdim 32234285Sdim public: 33234285Sdim ARMELFObjectWriter(uint8_t OSABI); 34234285Sdim 35288943Sdim ~ARMELFObjectWriter() override; 36234285Sdim 37276479Sdim unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 38276479Sdim bool IsPCRel) const override; 39276479Sdim 40288943Sdim bool needsRelocateWithSymbol(const MCSymbol &Sym, 41276479Sdim unsigned Type) const override; 42234285Sdim }; 43234285Sdim} 44234285Sdim 45234285SdimARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) 46234285Sdim : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, 47234285Sdim ELF::EM_ARM, 48234285Sdim /*HasRelocationAddend*/ false) {} 49234285Sdim 50234285SdimARMELFObjectWriter::~ARMELFObjectWriter() {} 51234285Sdim 52288943Sdimbool ARMELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, 53276479Sdim unsigned Type) const { 54280031Sdim // FIXME: This is extremely conservative. This really needs to use a 55276479Sdim // whitelist with a clear explanation for why each realocation needs to 56276479Sdim // point to the symbol, not to the section. 57276479Sdim switch (Type) { 58276479Sdim default: 59276479Sdim return true; 60234285Sdim 61276479Sdim case ELF::R_ARM_PREL31: 62276479Sdim case ELF::R_ARM_ABS32: 63276479Sdim return false; 64234285Sdim } 65234285Sdim} 66234285Sdim 67234285Sdim// Need to examine the Fixup when determining whether to 68234285Sdim// emit the relocation as an explicit symbol or as a section relative 69234285Sdim// offset 70234285Sdimunsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, 71234285Sdim const MCFixup &Fixup, 72276479Sdim bool IsPCRel) const { 73234285Sdim return GetRelocTypeInner(Target, Fixup, IsPCRel); 74234285Sdim} 75234285Sdim 76234285Sdimunsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, 77234285Sdim const MCFixup &Fixup, 78234285Sdim bool IsPCRel) const { 79276479Sdim MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 80234285Sdim 81234285Sdim unsigned Type = 0; 82234285Sdim if (IsPCRel) { 83234285Sdim switch ((unsigned)Fixup.getKind()) { 84288943Sdim default: 85288943Sdim report_fatal_error("unsupported relocation on symbol"); 86288943Sdim return ELF::R_ARM_NONE; 87234285Sdim case FK_Data_4: 88234285Sdim switch (Modifier) { 89234285Sdim default: llvm_unreachable("Unsupported Modifier"); 90234285Sdim case MCSymbolRefExpr::VK_None: 91234285Sdim Type = ELF::R_ARM_REL32; 92234285Sdim break; 93276479Sdim case MCSymbolRefExpr::VK_TLSGD: 94234285Sdim llvm_unreachable("unimplemented"); 95276479Sdim case MCSymbolRefExpr::VK_GOTTPOFF: 96234285Sdim Type = ELF::R_ARM_TLS_IE32; 97234285Sdim break; 98296417Sdim case MCSymbolRefExpr::VK_ARM_GOT_PREL: 99276479Sdim Type = ELF::R_ARM_GOT_PREL; 100276479Sdim break; 101234285Sdim } 102234285Sdim break; 103239462Sdim case ARM::fixup_arm_blx: 104234285Sdim case ARM::fixup_arm_uncondbl: 105234285Sdim switch (Modifier) { 106276479Sdim case MCSymbolRefExpr::VK_PLT: 107280031Sdim Type = ELF::R_ARM_CALL; 108234285Sdim break; 109276479Sdim case MCSymbolRefExpr::VK_ARM_TLSCALL: 110276479Sdim Type = ELF::R_ARM_TLS_CALL; 111276479Sdim break; 112234285Sdim default: 113234285Sdim Type = ELF::R_ARM_CALL; 114234285Sdim break; 115234285Sdim } 116234285Sdim break; 117234285Sdim case ARM::fixup_arm_condbl: 118234285Sdim case ARM::fixup_arm_condbranch: 119239462Sdim case ARM::fixup_arm_uncondbranch: 120234285Sdim Type = ELF::R_ARM_JUMP24; 121234285Sdim break; 122243830Sdim case ARM::fixup_t2_condbranch: 123243830Sdim case ARM::fixup_t2_uncondbranch: 124243830Sdim Type = ELF::R_ARM_THM_JUMP24; 125243830Sdim break; 126234285Sdim case ARM::fixup_arm_movt_hi16: 127234285Sdim Type = ELF::R_ARM_MOVT_PREL; 128234285Sdim break; 129234285Sdim case ARM::fixup_arm_movw_lo16: 130234285Sdim Type = ELF::R_ARM_MOVW_PREL_NC; 131234285Sdim break; 132234285Sdim case ARM::fixup_t2_movt_hi16: 133234285Sdim Type = ELF::R_ARM_THM_MOVT_PREL; 134234285Sdim break; 135234285Sdim case ARM::fixup_t2_movw_lo16: 136234285Sdim Type = ELF::R_ARM_THM_MOVW_PREL_NC; 137234285Sdim break; 138234285Sdim case ARM::fixup_arm_thumb_bl: 139234285Sdim case ARM::fixup_arm_thumb_blx: 140276479Sdim switch (Modifier) { 141276479Sdim case MCSymbolRefExpr::VK_ARM_TLSCALL: 142276479Sdim Type = ELF::R_ARM_THM_TLS_CALL; 143276479Sdim break; 144276479Sdim default: 145276479Sdim Type = ELF::R_ARM_THM_CALL; 146276479Sdim break; 147276479Sdim } 148234285Sdim break; 149234285Sdim } 150234285Sdim } else { 151234285Sdim switch ((unsigned)Fixup.getKind()) { 152288943Sdim default: 153288943Sdim report_fatal_error("unsupported relocation on symbol"); 154288943Sdim return ELF::R_ARM_NONE; 155280031Sdim case FK_Data_1: 156280031Sdim switch (Modifier) { 157280031Sdim default: llvm_unreachable("unsupported Modifier"); 158280031Sdim case MCSymbolRefExpr::VK_None: 159280031Sdim Type = ELF::R_ARM_ABS8; 160280031Sdim break; 161280031Sdim } 162280031Sdim break; 163280031Sdim case FK_Data_2: 164280031Sdim switch (Modifier) { 165280031Sdim default: llvm_unreachable("unsupported modifier"); 166280031Sdim case MCSymbolRefExpr::VK_None: 167280031Sdim Type = ELF::R_ARM_ABS16; 168280031Sdim break; 169280031Sdim } 170280031Sdim break; 171234285Sdim case FK_Data_4: 172234285Sdim switch (Modifier) { 173234285Sdim default: llvm_unreachable("Unsupported Modifier"); 174249423Sdim case MCSymbolRefExpr::VK_ARM_NONE: 175249423Sdim Type = ELF::R_ARM_NONE; 176249423Sdim break; 177276479Sdim case MCSymbolRefExpr::VK_GOT: 178234285Sdim Type = ELF::R_ARM_GOT_BREL; 179234285Sdim break; 180276479Sdim case MCSymbolRefExpr::VK_TLSGD: 181234285Sdim Type = ELF::R_ARM_TLS_GD32; 182234285Sdim break; 183276479Sdim case MCSymbolRefExpr::VK_TPOFF: 184234285Sdim Type = ELF::R_ARM_TLS_LE32; 185234285Sdim break; 186276479Sdim case MCSymbolRefExpr::VK_GOTTPOFF: 187234285Sdim Type = ELF::R_ARM_TLS_IE32; 188234285Sdim break; 189234285Sdim case MCSymbolRefExpr::VK_None: 190234285Sdim Type = ELF::R_ARM_ABS32; 191234285Sdim break; 192276479Sdim case MCSymbolRefExpr::VK_GOTOFF: 193234285Sdim Type = ELF::R_ARM_GOTOFF32; 194234285Sdim break; 195296417Sdim case MCSymbolRefExpr::VK_ARM_GOT_PREL: 196276479Sdim Type = ELF::R_ARM_GOT_PREL; 197276479Sdim break; 198234285Sdim case MCSymbolRefExpr::VK_ARM_TARGET1: 199234285Sdim Type = ELF::R_ARM_TARGET1; 200234285Sdim break; 201243830Sdim case MCSymbolRefExpr::VK_ARM_TARGET2: 202243830Sdim Type = ELF::R_ARM_TARGET2; 203243830Sdim break; 204249423Sdim case MCSymbolRefExpr::VK_ARM_PREL31: 205249423Sdim Type = ELF::R_ARM_PREL31; 206249423Sdim break; 207280031Sdim case MCSymbolRefExpr::VK_ARM_SBREL: 208280031Sdim Type = ELF::R_ARM_SBREL32; 209280031Sdim break; 210276479Sdim case MCSymbolRefExpr::VK_ARM_TLSLDO: 211276479Sdim Type = ELF::R_ARM_TLS_LDO32; 212276479Sdim break; 213276479Sdim case MCSymbolRefExpr::VK_ARM_TLSCALL: 214276479Sdim Type = ELF::R_ARM_TLS_CALL; 215276479Sdim break; 216276479Sdim case MCSymbolRefExpr::VK_ARM_TLSDESC: 217276479Sdim Type = ELF::R_ARM_TLS_GOTDESC; 218276479Sdim break; 219276479Sdim case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: 220276479Sdim Type = ELF::R_ARM_TLS_DESCSEQ; 221276479Sdim break; 222249423Sdim } 223234285Sdim break; 224234285Sdim case ARM::fixup_arm_ldst_pcrel_12: 225234285Sdim case ARM::fixup_arm_pcrel_10: 226234285Sdim case ARM::fixup_arm_adr_pcrel_12: 227234285Sdim case ARM::fixup_arm_thumb_bl: 228234285Sdim case ARM::fixup_arm_thumb_cb: 229234285Sdim case ARM::fixup_arm_thumb_cp: 230234285Sdim case ARM::fixup_arm_thumb_br: 231234285Sdim llvm_unreachable("Unimplemented"); 232239462Sdim case ARM::fixup_arm_condbranch: 233234285Sdim case ARM::fixup_arm_uncondbranch: 234234285Sdim Type = ELF::R_ARM_JUMP24; 235234285Sdim break; 236234285Sdim case ARM::fixup_arm_movt_hi16: 237234285Sdim Type = ELF::R_ARM_MOVT_ABS; 238234285Sdim break; 239234285Sdim case ARM::fixup_arm_movw_lo16: 240234285Sdim Type = ELF::R_ARM_MOVW_ABS_NC; 241234285Sdim break; 242234285Sdim case ARM::fixup_t2_movt_hi16: 243234285Sdim Type = ELF::R_ARM_THM_MOVT_ABS; 244234285Sdim break; 245234285Sdim case ARM::fixup_t2_movw_lo16: 246234285Sdim Type = ELF::R_ARM_THM_MOVW_ABS_NC; 247234285Sdim break; 248234285Sdim } 249234285Sdim } 250234285Sdim 251234285Sdim return Type; 252234285Sdim} 253234285Sdim 254288943SdimMCObjectWriter *llvm::createARMELFObjectWriter(raw_pwrite_stream &OS, 255276479Sdim uint8_t OSABI, 256276479Sdim bool IsLittleEndian) { 257234285Sdim MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); 258276479Sdim return createELFObjectWriter(MOTW, OS, IsLittleEndian); 259234285Sdim} 260