331 lines · cpp
1//===-- ARMELFObjectWriter.cpp - ARM 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/ARMFixupKinds.h"10#include "MCTargetDesc/ARMMCAsmInfo.h"11#include "MCTargetDesc/ARMMCTargetDesc.h"12#include "llvm/BinaryFormat/ELF.h"13#include "llvm/MC/MCAssembler.h"14#include "llvm/MC/MCContext.h"15#include "llvm/MC/MCELFObjectWriter.h"16#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCFixup.h"18#include "llvm/MC/MCObjectWriter.h"19#include "llvm/MC/MCValue.h"20#include "llvm/Object/ELF.h"21#include "llvm/Support/ErrorHandling.h"22#include <cstdint>23 24using namespace llvm;25 26namespace {27 28class ARMELFObjectWriter : public MCELFObjectTargetWriter {29 enum { DefaultEABIVersion = 0x05000000U };30 31public:32 ARMELFObjectWriter(uint8_t OSABI);33 34 ~ARMELFObjectWriter() override = default;35 36 unsigned getRelocType(const MCFixup &, const MCValue &,37 bool IsPCRel) const override;38 39 bool needsRelocateWithSymbol(const MCValue &Val,40 unsigned Type) const override;41};42 43} // end anonymous namespace44 45ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)46 : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,47 ELF::EM_ARM,48 /*HasRelocationAddend*/ false) {}49 50bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,51 unsigned Type) const {52 // If the symbol is a thumb function the final relocation must set the lowest53 // bit. With a symbol that is done by just having the symbol have that bit54 // set, so we would lose the bit if we relocated with the section.55 // We could use the section but add the bit to the relocation value.56 if (Asm->isThumbFunc(V.getAddSym()))57 return true;58 59 // FIXME: This is extremely conservative. This really needs to use an60 // explicit list with a clear explanation for why each realocation needs to61 // point to the symbol, not to the section.62 switch (Type) {63 default:64 return true;65 66 case ELF::R_ARM_PREL31:67 case ELF::R_ARM_ABS32:68 return false;69 }70}71 72// Need to examine the Fixup when determining whether to73// emit the relocation as an explicit symbol or as a section relative74// offset75unsigned ARMELFObjectWriter::getRelocType(const MCFixup &Fixup,76 const MCValue &Target,77 bool IsPCRel) const {78 auto Kind = Fixup.getKind();79 uint8_t Specifier = Target.getSpecifier();80 auto CheckFDPIC = [&](uint32_t Type) {81 if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC)82 reportError(Fixup.getLoc(),83 "relocation " +84 object::getELFRelocationTypeName(ELF::EM_ARM, Type) +85 " only supported in FDPIC mode");86 return Type;87 };88 89 switch (Specifier) {90 case ARM::S_GOTTPOFF:91 case ARM::S_GOTTPOFF_FDPIC:92 case ARM::S_TLSCALL:93 case ARM::S_TLSDESC:94 case ARM::S_TLSGD:95 case ARM::S_TLSGD_FDPIC:96 case ARM::S_TLSLDM:97 case ARM::S_TLSLDM_FDPIC:98 case ARM::S_TLSLDO:99 case ARM::S_TPOFF:100 if (auto *SA = const_cast<MCSymbol *>(Target.getAddSym()))101 static_cast<MCSymbolELF *>(SA)->setType(ELF::STT_TLS);102 break;103 default:104 break;105 }106 107 if (IsPCRel) {108 switch (Fixup.getKind()) {109 default:110 reportError(Fixup.getLoc(), "unsupported relocation type");111 return ELF::R_ARM_NONE;112 case FK_Data_4:113 switch (Specifier) {114 default:115 reportError(Fixup.getLoc(),116 "invalid fixup for 4-byte pc-relative data relocation");117 return ELF::R_ARM_NONE;118 case ARM::S_None: {119 if (const auto *SA = Target.getAddSym()) {120 // For GNU AS compatibility expressions such as121 // _GLOBAL_OFFSET_TABLE_ - label emit a R_ARM_BASE_PREL relocation.122 if (SA->getName() == "_GLOBAL_OFFSET_TABLE_")123 return ELF::R_ARM_BASE_PREL;124 }125 return ELF::R_ARM_REL32;126 }127 case ARM::S_GOTTPOFF:128 return ELF::R_ARM_TLS_IE32;129 case ARM::S_GOT_PREL:130 return ELF::R_ARM_GOT_PREL;131 case ARM::S_PREL31:132 return ELF::R_ARM_PREL31;133 }134 case ARM::fixup_arm_blx:135 case ARM::fixup_arm_uncondbl:136 switch (Specifier) {137 case ARM::S_PLT:138 return ELF::R_ARM_CALL;139 case ARM::S_TLSCALL:140 return ELF::R_ARM_TLS_CALL;141 default:142 return ELF::R_ARM_CALL;143 }144 case ARM::fixup_arm_condbl:145 case ARM::fixup_arm_condbranch:146 case ARM::fixup_arm_uncondbranch:147 return ELF::R_ARM_JUMP24;148 case ARM::fixup_t2_condbranch:149 return ELF::R_ARM_THM_JUMP19;150 case ARM::fixup_t2_uncondbranch:151 return ELF::R_ARM_THM_JUMP24;152 case ARM::fixup_arm_movt_hi16:153 return ELF::R_ARM_MOVT_PREL;154 case ARM::fixup_arm_movw_lo16:155 return ELF::R_ARM_MOVW_PREL_NC;156 case ARM::fixup_t2_movt_hi16:157 return ELF::R_ARM_THM_MOVT_PREL;158 case ARM::fixup_t2_movw_lo16:159 return ELF::R_ARM_THM_MOVW_PREL_NC;160 case ARM::fixup_arm_thumb_upper_8_15:161 return ELF::R_ARM_THM_ALU_ABS_G3;162 case ARM::fixup_arm_thumb_upper_0_7:163 return ELF::R_ARM_THM_ALU_ABS_G2_NC;164 case ARM::fixup_arm_thumb_lower_8_15:165 return ELF::R_ARM_THM_ALU_ABS_G1_NC;166 case ARM::fixup_arm_thumb_lower_0_7:167 return ELF::R_ARM_THM_ALU_ABS_G0_NC;168 case ARM::fixup_arm_thumb_br:169 return ELF::R_ARM_THM_JUMP11;170 case ARM::fixup_arm_thumb_bcc:171 return ELF::R_ARM_THM_JUMP8;172 case ARM::fixup_arm_thumb_bl:173 case ARM::fixup_arm_thumb_blx:174 switch (Specifier) {175 case ARM::S_TLSCALL:176 return ELF::R_ARM_THM_TLS_CALL;177 default:178 return ELF::R_ARM_THM_CALL;179 }180 case ARM::fixup_arm_ldst_pcrel_12:181 return ELF::R_ARM_LDR_PC_G0;182 case ARM::fixup_arm_pcrel_10_unscaled:183 return ELF::R_ARM_LDRS_PC_G0;184 case ARM::fixup_t2_ldst_pcrel_12:185 return ELF::R_ARM_THM_PC12;186 case ARM::fixup_arm_adr_pcrel_12:187 return ELF::R_ARM_ALU_PC_G0;188 case ARM::fixup_thumb_adr_pcrel_10:189 return ELF::R_ARM_THM_PC8;190 case ARM::fixup_t2_adr_pcrel_12:191 return ELF::R_ARM_THM_ALU_PREL_11_0;192 case ARM::fixup_bf_target:193 return ELF::R_ARM_THM_BF16;194 case ARM::fixup_bfc_target:195 return ELF::R_ARM_THM_BF12;196 case ARM::fixup_bfl_target:197 return ELF::R_ARM_THM_BF18;198 }199 }200 switch (Kind) {201 default:202 reportError(Fixup.getLoc(), "unsupported relocation type");203 return ELF::R_ARM_NONE;204 case FK_Data_1:205 switch (Specifier) {206 default:207 reportError(Fixup.getLoc(), "invalid fixup for 1-byte data relocation");208 return ELF::R_ARM_NONE;209 case ARM::S_None:210 return ELF::R_ARM_ABS8;211 }212 case FK_Data_2:213 switch (Specifier) {214 default:215 reportError(Fixup.getLoc(), "invalid fixup for 2-byte data relocation");216 return ELF::R_ARM_NONE;217 case ARM::S_None:218 return ELF::R_ARM_ABS16;219 }220 case FK_Data_4:221 switch (Specifier) {222 default:223 reportError(Fixup.getLoc(), "invalid fixup for 4-byte data relocation");224 return ELF::R_ARM_NONE;225 case ARM::S_ARM_NONE:226 return ELF::R_ARM_NONE;227 case ARM::S_GOT:228 return ELF::R_ARM_GOT_BREL;229 case ARM::S_TLSGD:230 return ELF::R_ARM_TLS_GD32;231 case ARM::S_TPOFF:232 return ELF::R_ARM_TLS_LE32;233 case ARM::S_GOTTPOFF:234 return ELF::R_ARM_TLS_IE32;235 case ARM::S_None:236 return ELF::R_ARM_ABS32;237 case ARM::S_GOTOFF:238 return ELF::R_ARM_GOTOFF32;239 case ARM::S_GOT_PREL:240 return ELF::R_ARM_GOT_PREL;241 case ARM::S_TARGET1:242 return ELF::R_ARM_TARGET1;243 case ARM::S_TARGET2:244 return ELF::R_ARM_TARGET2;245 case ARM::S_PREL31:246 return ELF::R_ARM_PREL31;247 case ARM::S_SBREL:248 return ELF::R_ARM_SBREL32;249 case ARM::S_TLSLDO:250 return ELF::R_ARM_TLS_LDO32;251 case ARM::S_TLSCALL:252 return ELF::R_ARM_TLS_CALL;253 case ARM::S_TLSDESC:254 return ELF::R_ARM_TLS_GOTDESC;255 case ARM::S_TLSLDM:256 return ELF::R_ARM_TLS_LDM32;257 case ARM::S_TLSDESCSEQ:258 return ELF::R_ARM_TLS_DESCSEQ;259 case ARM::S_FUNCDESC:260 return CheckFDPIC(ELF::R_ARM_FUNCDESC);261 case ARM::S_GOTFUNCDESC:262 return CheckFDPIC(ELF::R_ARM_GOTFUNCDESC);263 case ARM::S_GOTOFFFUNCDESC:264 return CheckFDPIC(ELF::R_ARM_GOTOFFFUNCDESC);265 case ARM::S_TLSGD_FDPIC:266 return CheckFDPIC(ELF::R_ARM_TLS_GD32_FDPIC);267 case ARM::S_TLSLDM_FDPIC:268 return CheckFDPIC(ELF::R_ARM_TLS_LDM32_FDPIC);269 case ARM::S_GOTTPOFF_FDPIC:270 return CheckFDPIC(ELF::R_ARM_TLS_IE32_FDPIC);271 }272 case ARM::fixup_arm_condbranch:273 case ARM::fixup_arm_uncondbranch:274 return ELF::R_ARM_JUMP24;275 case ARM::fixup_arm_movt_hi16:276 switch (Specifier) {277 default:278 reportError(Fixup.getLoc(), "invalid fixup for ARM MOVT instruction");279 return ELF::R_ARM_NONE;280 case ARM::S_None:281 return ELF::R_ARM_MOVT_ABS;282 case ARM::S_SBREL:283 return ELF::R_ARM_MOVT_BREL;284 }285 case ARM::fixup_arm_movw_lo16:286 switch (Specifier) {287 default:288 reportError(Fixup.getLoc(), "invalid fixup for ARM MOVW instruction");289 return ELF::R_ARM_NONE;290 case ARM::S_None:291 return ELF::R_ARM_MOVW_ABS_NC;292 case ARM::S_SBREL:293 return ELF::R_ARM_MOVW_BREL_NC;294 }295 case ARM::fixup_t2_movt_hi16:296 switch (Specifier) {297 default:298 reportError(Fixup.getLoc(), "invalid fixup for Thumb MOVT instruction");299 return ELF::R_ARM_NONE;300 case ARM::S_None:301 return ELF::R_ARM_THM_MOVT_ABS;302 case ARM::S_SBREL:303 return ELF::R_ARM_THM_MOVT_BREL;304 }305 case ARM::fixup_t2_movw_lo16:306 switch (Specifier) {307 default:308 reportError(Fixup.getLoc(), "invalid fixup for Thumb MOVW instruction");309 return ELF::R_ARM_NONE;310 case ARM::S_None:311 return ELF::R_ARM_THM_MOVW_ABS_NC;312 case ARM::S_SBREL:313 return ELF::R_ARM_THM_MOVW_BREL_NC;314 }315 316 case ARM::fixup_arm_thumb_upper_8_15:317 return ELF::R_ARM_THM_ALU_ABS_G3;318 case ARM::fixup_arm_thumb_upper_0_7:319 return ELF::R_ARM_THM_ALU_ABS_G2_NC;320 case ARM::fixup_arm_thumb_lower_8_15:321 return ELF::R_ARM_THM_ALU_ABS_G1_NC;322 case ARM::fixup_arm_thumb_lower_0_7:323 return ELF::R_ARM_THM_ALU_ABS_G0_NC;324 }325}326 327std::unique_ptr<MCObjectTargetWriter>328llvm::createARMELFObjectWriter(uint8_t OSABI) {329 return std::make_unique<ARMELFObjectWriter>(OSABI);330}331