brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.4 KiB · d914f6e Raw
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