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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "MCTargetDesc/ARMFixupKinds.h" 10 #include "MCTargetDesc/ARMMCTargetDesc.h" 11 #include "llvm/BinaryFormat/ELF.h" 12 #include "llvm/MC/MCContext.h" 13 #include "llvm/MC/MCELFObjectWriter.h" 14 #include "llvm/MC/MCExpr.h" 15 #include "llvm/MC/MCFixup.h" 16 #include "llvm/MC/MCObjectFileInfo.h" 17 #include "llvm/MC/MCObjectWriter.h" 18 #include "llvm/MC/MCValue.h" 19 #include "llvm/Object/ELF.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include <cstdint> 23 24 using namespace llvm; 25 26 namespace { 27 28 class ARMELFObjectWriter : public MCELFObjectTargetWriter { 29 enum { DefaultEABIVersion = 0x05000000U }; 30 31 unsigned GetRelocTypeInner(const MCValue &Target, const MCFixup &Fixup, 32 bool IsPCRel, MCContext &Ctx) const; 33 34 public: 35 ARMELFObjectWriter(uint8_t OSABI); 36 37 ~ARMELFObjectWriter() override = default; 38 39 unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 40 const MCFixup &Fixup, bool IsPCRel) const override; 41 42 bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym, 43 unsigned Type) const override; 44 45 void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec) override; 46 }; 47 48 } // end anonymous namespace 49 50 ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI) 51 : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, 52 ELF::EM_ARM, 53 /*HasRelocationAddend*/ false) {} 54 55 bool ARMELFObjectWriter::needsRelocateWithSymbol(const MCValue &, 56 const MCSymbol &, 57 unsigned Type) const { 58 // FIXME: This is extremely conservative. This really needs to use an 59 // explicit list with a clear explanation for why each realocation needs to 60 // point to the symbol, not to the section. 61 switch (Type) { 62 default: 63 return true; 64 65 case ELF::R_ARM_PREL31: 66 case ELF::R_ARM_ABS32: 67 return false; 68 } 69 } 70 71 // Need to examine the Fixup when determining whether to 72 // emit the relocation as an explicit symbol or as a section relative 73 // offset 74 unsigned ARMELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, 75 const MCFixup &Fixup, 76 bool IsPCRel) const { 77 return GetRelocTypeInner(Target, Fixup, IsPCRel, Ctx); 78 } 79 80 unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, 81 const MCFixup &Fixup, 82 bool IsPCRel, 83 MCContext &Ctx) const { 84 unsigned Kind = Fixup.getTargetKind(); 85 if (Kind >= FirstLiteralRelocationKind) 86 return Kind - FirstLiteralRelocationKind; 87 MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 88 auto CheckFDPIC = [&](uint32_t Type) { 89 if (getOSABI() != ELF::ELFOSABI_ARM_FDPIC) 90 Ctx.reportError(Fixup.getLoc(), 91 "relocation " + 92 object::getELFRelocationTypeName(ELF::EM_ARM, Type) + 93 " only supported in FDPIC mode"); 94 return Type; 95 }; 96 97 if (IsPCRel) { 98 switch (Fixup.getTargetKind()) { 99 default: 100 Ctx.reportError(Fixup.getLoc(), "unsupported relocation type"); 101 return ELF::R_ARM_NONE; 102 case FK_Data_4: 103 switch (Modifier) { 104 default: 105 Ctx.reportError(Fixup.getLoc(), 106 "invalid fixup for 4-byte pc-relative data relocation"); 107 return ELF::R_ARM_NONE; 108 case MCSymbolRefExpr::VK_None: { 109 if (const MCSymbolRefExpr *SymRef = Target.getSymA()) { 110 // For GNU AS compatibility expressions such as 111 // _GLOBAL_OFFSET_TABLE_ - label emit a R_ARM_BASE_PREL relocation. 112 if (SymRef->getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_") 113 return ELF::R_ARM_BASE_PREL; 114 } 115 return ELF::R_ARM_REL32; 116 } 117 case MCSymbolRefExpr::VK_GOTTPOFF: 118 return ELF::R_ARM_TLS_IE32; 119 case MCSymbolRefExpr::VK_ARM_GOT_PREL: 120 return ELF::R_ARM_GOT_PREL; 121 case MCSymbolRefExpr::VK_ARM_PREL31: 122 return ELF::R_ARM_PREL31; 123 } 124 case ARM::fixup_arm_blx: 125 case ARM::fixup_arm_uncondbl: 126 switch (Modifier) { 127 case MCSymbolRefExpr::VK_PLT: 128 return ELF::R_ARM_CALL; 129 case MCSymbolRefExpr::VK_TLSCALL: 130 return ELF::R_ARM_TLS_CALL; 131 default: 132 return ELF::R_ARM_CALL; 133 } 134 case ARM::fixup_arm_condbl: 135 case ARM::fixup_arm_condbranch: 136 case ARM::fixup_arm_uncondbranch: 137 return ELF::R_ARM_JUMP24; 138 case ARM::fixup_t2_condbranch: 139 return ELF::R_ARM_THM_JUMP19; 140 case ARM::fixup_t2_uncondbranch: 141 return ELF::R_ARM_THM_JUMP24; 142 case ARM::fixup_arm_movt_hi16: 143 return ELF::R_ARM_MOVT_PREL; 144 case ARM::fixup_arm_movw_lo16: 145 return ELF::R_ARM_MOVW_PREL_NC; 146 case ARM::fixup_t2_movt_hi16: 147 return ELF::R_ARM_THM_MOVT_PREL; 148 case ARM::fixup_t2_movw_lo16: 149 return ELF::R_ARM_THM_MOVW_PREL_NC; 150 case ARM::fixup_arm_thumb_upper_8_15: 151 return ELF::R_ARM_THM_ALU_ABS_G3; 152 case ARM::fixup_arm_thumb_upper_0_7: 153 return ELF::R_ARM_THM_ALU_ABS_G2_NC; 154 case ARM::fixup_arm_thumb_lower_8_15: 155 return ELF::R_ARM_THM_ALU_ABS_G1_NC; 156 case ARM::fixup_arm_thumb_lower_0_7: 157 return ELF::R_ARM_THM_ALU_ABS_G0_NC; 158 case ARM::fixup_arm_thumb_br: 159 return ELF::R_ARM_THM_JUMP11; 160 case ARM::fixup_arm_thumb_bcc: 161 return ELF::R_ARM_THM_JUMP8; 162 case ARM::fixup_arm_thumb_bl: 163 case ARM::fixup_arm_thumb_blx: 164 switch (Modifier) { 165 case MCSymbolRefExpr::VK_TLSCALL: 166 return ELF::R_ARM_THM_TLS_CALL; 167 default: 168 return ELF::R_ARM_THM_CALL; 169 } 170 case ARM::fixup_arm_ldst_pcrel_12: 171 return ELF::R_ARM_LDR_PC_G0; 172 case ARM::fixup_arm_pcrel_10_unscaled: 173 return ELF::R_ARM_LDRS_PC_G0; 174 case ARM::fixup_t2_ldst_pcrel_12: 175 return ELF::R_ARM_THM_PC12; 176 case ARM::fixup_arm_adr_pcrel_12: 177 return ELF::R_ARM_ALU_PC_G0; 178 case ARM::fixup_thumb_adr_pcrel_10: 179 return ELF::R_ARM_THM_PC8; 180 case ARM::fixup_t2_adr_pcrel_12: 181 return ELF::R_ARM_THM_ALU_PREL_11_0; 182 case ARM::fixup_bf_target: 183 return ELF::R_ARM_THM_BF16; 184 case ARM::fixup_bfc_target: 185 return ELF::R_ARM_THM_BF12; 186 case ARM::fixup_bfl_target: 187 return ELF::R_ARM_THM_BF18; 188 } 189 } 190 switch (Kind) { 191 default: 192 Ctx.reportError(Fixup.getLoc(), "unsupported relocation type"); 193 return ELF::R_ARM_NONE; 194 case FK_Data_1: 195 switch (Modifier) { 196 default: 197 Ctx.reportError(Fixup.getLoc(), 198 "invalid fixup for 1-byte data relocation"); 199 return ELF::R_ARM_NONE; 200 case MCSymbolRefExpr::VK_None: 201 return ELF::R_ARM_ABS8; 202 } 203 case FK_Data_2: 204 switch (Modifier) { 205 default: 206 Ctx.reportError(Fixup.getLoc(), 207 "invalid fixup for 2-byte data relocation"); 208 return ELF::R_ARM_NONE; 209 case MCSymbolRefExpr::VK_None: 210 return ELF::R_ARM_ABS16; 211 } 212 case FK_Data_4: 213 switch (Modifier) { 214 default: 215 Ctx.reportError(Fixup.getLoc(), 216 "invalid fixup for 4-byte data relocation"); 217 return ELF::R_ARM_NONE; 218 case MCSymbolRefExpr::VK_ARM_NONE: 219 return ELF::R_ARM_NONE; 220 case MCSymbolRefExpr::VK_GOT: 221 return ELF::R_ARM_GOT_BREL; 222 case MCSymbolRefExpr::VK_TLSGD: 223 return ELF::R_ARM_TLS_GD32; 224 case MCSymbolRefExpr::VK_TPOFF: 225 return ELF::R_ARM_TLS_LE32; 226 case MCSymbolRefExpr::VK_GOTTPOFF: 227 return ELF::R_ARM_TLS_IE32; 228 case MCSymbolRefExpr::VK_None: 229 return ELF::R_ARM_ABS32; 230 case MCSymbolRefExpr::VK_GOTOFF: 231 return ELF::R_ARM_GOTOFF32; 232 case MCSymbolRefExpr::VK_ARM_GOT_PREL: 233 return ELF::R_ARM_GOT_PREL; 234 case MCSymbolRefExpr::VK_ARM_TARGET1: 235 return ELF::R_ARM_TARGET1; 236 case MCSymbolRefExpr::VK_ARM_TARGET2: 237 return ELF::R_ARM_TARGET2; 238 case MCSymbolRefExpr::VK_ARM_PREL31: 239 return ELF::R_ARM_PREL31; 240 case MCSymbolRefExpr::VK_ARM_SBREL: 241 return ELF::R_ARM_SBREL32; 242 case MCSymbolRefExpr::VK_ARM_TLSLDO: 243 return ELF::R_ARM_TLS_LDO32; 244 case MCSymbolRefExpr::VK_TLSCALL: 245 return ELF::R_ARM_TLS_CALL; 246 case MCSymbolRefExpr::VK_TLSDESC: 247 return ELF::R_ARM_TLS_GOTDESC; 248 case MCSymbolRefExpr::VK_TLSLDM: 249 return ELF::R_ARM_TLS_LDM32; 250 case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ: 251 return ELF::R_ARM_TLS_DESCSEQ; 252 case MCSymbolRefExpr::VK_FUNCDESC: 253 return CheckFDPIC(ELF::R_ARM_FUNCDESC); 254 case MCSymbolRefExpr::VK_GOTFUNCDESC: 255 return CheckFDPIC(ELF::R_ARM_GOTFUNCDESC); 256 case MCSymbolRefExpr::VK_GOTOFFFUNCDESC: 257 return CheckFDPIC(ELF::R_ARM_GOTOFFFUNCDESC); 258 case MCSymbolRefExpr::VK_TLSGD_FDPIC: 259 return CheckFDPIC(ELF::R_ARM_TLS_GD32_FDPIC); 260 case MCSymbolRefExpr::VK_TLSLDM_FDPIC: 261 return CheckFDPIC(ELF::R_ARM_TLS_LDM32_FDPIC); 262 case MCSymbolRefExpr::VK_GOTTPOFF_FDPIC: 263 return CheckFDPIC(ELF::R_ARM_TLS_IE32_FDPIC); 264 } 265 case ARM::fixup_arm_condbranch: 266 case ARM::fixup_arm_uncondbranch: 267 return ELF::R_ARM_JUMP24; 268 case ARM::fixup_arm_movt_hi16: 269 switch (Modifier) { 270 default: 271 Ctx.reportError(Fixup.getLoc(), "invalid fixup for ARM MOVT instruction"); 272 return ELF::R_ARM_NONE; 273 case MCSymbolRefExpr::VK_None: 274 return ELF::R_ARM_MOVT_ABS; 275 case MCSymbolRefExpr::VK_ARM_SBREL: 276 return ELF::R_ARM_MOVT_BREL; 277 } 278 case ARM::fixup_arm_movw_lo16: 279 switch (Modifier) { 280 default: 281 Ctx.reportError(Fixup.getLoc(), "invalid fixup for ARM MOVW instruction"); 282 return ELF::R_ARM_NONE; 283 case MCSymbolRefExpr::VK_None: 284 return ELF::R_ARM_MOVW_ABS_NC; 285 case MCSymbolRefExpr::VK_ARM_SBREL: 286 return ELF::R_ARM_MOVW_BREL_NC; 287 } 288 case ARM::fixup_t2_movt_hi16: 289 switch (Modifier) { 290 default: 291 Ctx.reportError(Fixup.getLoc(), 292 "invalid fixup for Thumb MOVT instruction"); 293 return ELF::R_ARM_NONE; 294 case MCSymbolRefExpr::VK_None: 295 return ELF::R_ARM_THM_MOVT_ABS; 296 case MCSymbolRefExpr::VK_ARM_SBREL: 297 return ELF::R_ARM_THM_MOVT_BREL; 298 } 299 case ARM::fixup_t2_movw_lo16: 300 switch (Modifier) { 301 default: 302 Ctx.reportError(Fixup.getLoc(), 303 "invalid fixup for Thumb MOVW instruction"); 304 return ELF::R_ARM_NONE; 305 case MCSymbolRefExpr::VK_None: 306 return ELF::R_ARM_THM_MOVW_ABS_NC; 307 case MCSymbolRefExpr::VK_ARM_SBREL: 308 return ELF::R_ARM_THM_MOVW_BREL_NC; 309 } 310 311 case ARM::fixup_arm_thumb_upper_8_15: 312 return ELF::R_ARM_THM_ALU_ABS_G3; 313 case ARM::fixup_arm_thumb_upper_0_7: 314 return ELF::R_ARM_THM_ALU_ABS_G2_NC; 315 case ARM::fixup_arm_thumb_lower_8_15: 316 return ELF::R_ARM_THM_ALU_ABS_G1_NC; 317 case ARM::fixup_arm_thumb_lower_0_7: 318 return ELF::R_ARM_THM_ALU_ABS_G0_NC; 319 } 320 } 321 322 void ARMELFObjectWriter::addTargetSectionFlags(MCContext &Ctx, 323 MCSectionELF &Sec) { 324 // The mix of execute-only and non-execute-only at link time is 325 // non-execute-only. To avoid the empty implicitly created .text 326 // section from making the whole .text section non-execute-only, we 327 // mark it execute-only if it is empty and there is at least one 328 // execute-only section in the object. 329 MCSectionELF *TextSection = 330 static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection()); 331 bool IsExecOnly = Sec.getFlags() & ELF::SHF_ARM_PURECODE; 332 if (IsExecOnly && !TextSection->hasInstructions()) { 333 for (auto &F : *TextSection) 334 if (auto *DF = dyn_cast<MCDataFragment>(&F)) 335 if (!DF->getContents().empty()) 336 return; 337 TextSection->setFlags(TextSection->getFlags() | ELF::SHF_ARM_PURECODE); 338 } 339 } 340 341 std::unique_ptr<MCObjectTargetWriter> 342 llvm::createARMELFObjectWriter(uint8_t OSABI) { 343 return std::make_unique<ARMELFObjectWriter>(OSABI); 344 } 345