コード例 #1
0
// If linker relaxation is enabled, or the relax option had previously been
// enabled, always emit relocations even if the fixup can be resolved. This is
// necessary for correctness as offsets may change during relaxation.
bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
                                            const MCFixup &Fixup,
                                            const MCValue &Target) {
  bool ShouldForce = false;

  switch ((unsigned)Fixup.getKind()) {
  default:
    break;
  case RISCV::fixup_riscv_pcrel_lo12_i:
  case RISCV::fixup_riscv_pcrel_lo12_s:
    // For pcrel_lo12, force a relocation if the target of the corresponding
    // pcrel_hi20 is not in the same fragment.
    const MCFixup *T = cast<RISCVMCExpr>(Fixup.getValue())->getPCRelHiFixup();
    if (!T) {
      Asm.getContext().reportError(Fixup.getLoc(),
                                   "could not find corresponding %pcrel_hi");
      return false;
    }

    switch ((unsigned)T->getKind()) {
    default:
      llvm_unreachable("Unexpected fixup kind for pcrel_lo12");
      break;
    case RISCV::fixup_riscv_pcrel_hi20:
      ShouldForce = T->getValue()->findAssociatedFragment() !=
                    Fixup.getValue()->findAssociatedFragment();
      break;
    }
    break;
  }

  return ShouldForce || STI.getFeatureBits()[RISCV::FeatureRelax] ||
         ForceRelocs;
}
コード例 #2
0
unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
                                          const MCFixup &Fixup,
                                          bool IsPCRel) const {
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
  X86_64RelType Type = getType64(Fixup.getKind(), Modifier, IsPCRel);
  if (getEMachine() == ELF::EM_X86_64)
    return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel,
                          Fixup.getKind());

  assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
         "Unsupported ELF machine type.");
  return getRelocType32(Modifier, getType32(Type), IsPCRel);
}
コード例 #3
0
ファイル: AMDGPUAsmBackend.cpp プロジェクト: anupam128/llvm
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
                                 MCContext *Ctx) {
  int64_t SignedValue = static_cast<int64_t>(Value);

  switch (Fixup.getKind()) {
  case AMDGPU::fixup_si_sopp_br: {
    int64_t BrImm = (SignedValue - 4) / 4;

    if (Ctx && !isInt<16>(BrImm))
      Ctx->reportError(Fixup.getLoc(), "branch size exceeds simm16");

    return BrImm;
  }
  case FK_Data_1:
  case FK_Data_2:
  case FK_Data_4:
  case FK_Data_8:
  case FK_PCRel_4:
  case FK_SecRel_4:
    return Value;
  default:
    llvm_unreachable("unhandled fixup kind");
  }
}
コード例 #4
0
ファイル: AArch64ELFObjectWriter.cpp プロジェクト: ralic/llvm
unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
                                              const MCValue &Target,
                                              const MCFixup &Fixup,
                                              bool IsPCRel) const {
  AArch64MCExpr::VariantKind RefKind =
      static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
  AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
  bool IsNC = AArch64MCExpr::isNotChecked(RefKind);

  assert((!Target.getSymA() ||
          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
         "Should only be expression-level modifiers here");

  assert((!Target.getSymB() ||
          Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
         "Should only be expression-level modifiers here");

  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    case FK_Data_1:
      Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
      return ELF::R_AARCH64_NONE;
    case FK_Data_2:
      return R_CLS(PREL16);
    case FK_Data_4:
      return R_CLS(PREL32);
    case FK_Data_8:
      if (IsILP32) {
        Ctx.reportError(Fixup.getLoc(), "ILP32 8 byte PC relative data "
                        "relocation not supported (LP64 eqv: PREL64)");
        return ELF::R_AARCH64_NONE;
      } else
        return ELF::R_AARCH64_PREL64;
    case AArch64::fixup_aarch64_pcrel_adr_imm21:
      assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
      return R_CLS(ADR_PREL_LO21);
    case AArch64::fixup_aarch64_pcrel_adrp_imm21:
      if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
        return R_CLS(ADR_PREL_PG_HI21);
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) {
        if (IsILP32) {
          Ctx.reportError(Fixup.getLoc(),
                          "invalid fixup for 32-bit pcrel ADRP instruction "
                          "VK_ABS VK_NC");
          return ELF::R_AARCH64_NONE;
        } else {
          return ELF::R_AARCH64_ADR_PREL_PG_HI21_NC;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
        return R_CLS(ADR_GOT_PAGE);
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
        return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21);
      if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
        return R_CLS(TLSDESC_ADR_PAGE21);
      Ctx.reportError(Fixup.getLoc(),
                      "invalid symbol kind for ADRP relocation");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_pcrel_branch26:
      return R_CLS(JUMP26);
    case AArch64::fixup_aarch64_pcrel_call26:
      return R_CLS(CALL26);
    case AArch64::fixup_aarch64_ldr_pcrel_imm19:
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL)
        return R_CLS(TLSIE_LD_GOTTPREL_PREL19);
      return R_CLS(LD_PREL_LO19);
    case AArch64::fixup_aarch64_pcrel_branch14:
      return R_CLS(TSTBR14);
    case AArch64::fixup_aarch64_pcrel_branch19:
      return R_CLS(CONDBR19);
    default:
      Ctx.reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind");
      return ELF::R_AARCH64_NONE;
    }
  } else {
    if (IsILP32 && isNonILP32reloc(Fixup, RefKind, Ctx))
        return ELF::R_AARCH64_NONE;
    switch ((unsigned)Fixup.getKind()) {
    case FK_Data_1:
      Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
      return ELF::R_AARCH64_NONE;
    case FK_Data_2:
      return R_CLS(ABS16);
    case FK_Data_4:
      return R_CLS(ABS32);
    case FK_Data_8:
      if (IsILP32) {
        Ctx.reportError(Fixup.getLoc(), "ILP32 8 byte absolute data "
			"relocation not supported (LP64 eqv: ABS64)");
        return ELF::R_AARCH64_NONE;
      } else
        return ELF::R_AARCH64_ABS64;
    case AArch64::fixup_aarch64_add_imm12:
      if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
        return R_CLS(TLSLD_ADD_DTPREL_HI12);
      if (RefKind == AArch64MCExpr::VK_TPREL_HI12)
        return R_CLS(TLSLE_ADD_TPREL_HI12);
      if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC)
        return R_CLS(TLSLD_ADD_DTPREL_LO12_NC);
      if (RefKind == AArch64MCExpr::VK_DTPREL_LO12)
        return R_CLS(TLSLD_ADD_DTPREL_LO12);
      if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC)
        return R_CLS(TLSLE_ADD_TPREL_LO12_NC);
      if (RefKind == AArch64MCExpr::VK_TPREL_LO12)
        return R_CLS(TLSLE_ADD_TPREL_LO12);
      if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
        return R_CLS(TLSDESC_ADD_LO12);
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(ADD_ABS_LO12_NC);

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for add (uimm12) instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale1:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST8_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST8_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST8_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST8_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST8_TPREL_LO12_NC);

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 8-bit load/store instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale2:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST16_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST16_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST16_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST16_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST16_TPREL_LO12_NC);

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 16-bit load/store instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale4:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST32_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST32_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST32_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST32_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST32_TPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) {
        if (IsILP32) {
          return ELF::R_AARCH64_P32_LD32_GOT_LO12_NC;
        } else {
          Ctx.reportError(Fixup.getLoc(),
                          "LP64 4 byte unchecked GOT load/store relocation "
			  "not supported (ILP32 eqv: LD32_GOT_LO12_NC");
          return ELF::R_AARCH64_NONE;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC) {
        if (IsILP32) {
          Ctx.reportError(Fixup.getLoc(),
                          "ILP32 4 byte checked GOT load/store relocation "
			  "not supported (unchecked eqv: LD32_GOT_LO12_NC)");
        } else {
          Ctx.reportError(Fixup.getLoc(),
                          "LP64 4 byte checked GOT load/store relocation "
			  "not supported (unchecked/ILP32 eqv: "
			  "LD32_GOT_LO12_NC)");
        }
        return ELF::R_AARCH64_NONE;
      }
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) {
        if (IsILP32) {
          return ELF::R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC;
        } else {
          Ctx.reportError(Fixup.getLoc(), "LP64 32-bit load/store "
                          "relocation not supported (ILP32 eqv: "
                          "TLSIE_LD32_GOTTPREL_LO12_NC)");
          return ELF::R_AARCH64_NONE;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) {
        if (IsILP32) {
          return ELF::R_AARCH64_P32_TLSDESC_LD32_LO12;
        } else {
          Ctx.reportError(Fixup.getLoc(),
                          "LP64 4 byte TLSDESC load/store relocation "
			  "not supported (ILP32 eqv: TLSDESC_LD64_LO12)");
          return ELF::R_AARCH64_NONE;
        }
      }

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 32-bit load/store instruction "
		      "fixup_aarch64_ldst_imm12_scale4");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale8:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST64_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) {
        if (!IsILP32) {
          return ELF::R_AARCH64_LD64_GOT_LO12_NC;
        } else {
          Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
                          "relocation not supported (LP64 eqv: "
                          "LD64_GOT_LO12_NC)");
          return ELF::R_AARCH64_NONE;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST64_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST64_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST64_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST64_TPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) {
        if (!IsILP32) {
          return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
        } else {
          Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
                          "relocation not supported (LP64 eqv: "
                          "TLSIE_LD64_GOTTPREL_LO12_NC)");
          return ELF::R_AARCH64_NONE;
        }
      }
      if (SymLoc == AArch64MCExpr::VK_TLSDESC) {
        if (!IsILP32) {
          return ELF::R_AARCH64_TLSDESC_LD64_LO12;
        } else {
          Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
                          "relocation not supported (LP64 eqv: "
                          "TLSDESC_LD64_LO12)");
          return ELF::R_AARCH64_NONE;
        }
      }
      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 64-bit load/store instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_ldst_imm12_scale16:
      if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
        return R_CLS(LDST128_ABS_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
        return R_CLS(TLSLD_LDST128_DTPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
        return R_CLS(TLSLD_LDST128_DTPREL_LO12_NC);
      if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
        return R_CLS(TLSLE_LDST128_TPREL_LO12);
      if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
        return R_CLS(TLSLE_LDST128_TPREL_LO12_NC);

      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for 128-bit load/store instruction");
      return ELF::R_AARCH64_NONE;
    // ILP32 case not reached here, tested with isNonILP32reloc
    case AArch64::fixup_aarch64_movw:
      if (RefKind == AArch64MCExpr::VK_ABS_G3)
        return ELF::R_AARCH64_MOVW_UABS_G3;
      if (RefKind == AArch64MCExpr::VK_ABS_G2)
        return ELF::R_AARCH64_MOVW_UABS_G2;
      if (RefKind == AArch64MCExpr::VK_ABS_G2_S)
        return ELF::R_AARCH64_MOVW_SABS_G2;
      if (RefKind == AArch64MCExpr::VK_ABS_G2_NC)
        return ELF::R_AARCH64_MOVW_UABS_G2_NC;
      if (RefKind == AArch64MCExpr::VK_ABS_G1)
        return R_CLS(MOVW_UABS_G1);
      if (RefKind == AArch64MCExpr::VK_ABS_G1_S)
        return ELF::R_AARCH64_MOVW_SABS_G1;
      if (RefKind == AArch64MCExpr::VK_ABS_G1_NC)
        return ELF::R_AARCH64_MOVW_UABS_G1_NC;
      if (RefKind == AArch64MCExpr::VK_ABS_G0)
        return R_CLS(MOVW_UABS_G0);
      if (RefKind == AArch64MCExpr::VK_ABS_G0_S)
        return R_CLS(MOVW_SABS_G0);
      if (RefKind == AArch64MCExpr::VK_ABS_G0_NC)
        return R_CLS(MOVW_UABS_G0_NC);
      if (RefKind == AArch64MCExpr::VK_DTPREL_G2)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G1)
        return R_CLS(TLSLD_MOVW_DTPREL_G1);
      if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC)
        return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
      if (RefKind == AArch64MCExpr::VK_DTPREL_G0)
        return R_CLS(TLSLD_MOVW_DTPREL_G0);
      if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC)
        return R_CLS(TLSLD_MOVW_DTPREL_G0_NC);
      if (RefKind == AArch64MCExpr::VK_TPREL_G2)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
      if (RefKind == AArch64MCExpr::VK_TPREL_G1)
        return R_CLS(TLSLE_MOVW_TPREL_G1);
      if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC)
        return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
      if (RefKind == AArch64MCExpr::VK_TPREL_G0)
        return R_CLS(TLSLE_MOVW_TPREL_G0);
      if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC)
        return R_CLS(TLSLE_MOVW_TPREL_G0_NC);
      if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1)
        return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
      if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC)
        return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
      Ctx.reportError(Fixup.getLoc(),
                      "invalid fixup for movz/movk instruction");
      return ELF::R_AARCH64_NONE;
    case AArch64::fixup_aarch64_tlsdesc_call:
      return R_CLS(TLSDESC_CALL);
    default:
      Ctx.reportError(Fixup.getLoc(), "Unknown ELF relocation type");
      return ELF::R_AARCH64_NONE;
    }
  }

  llvm_unreachable("Unimplemented fixup -> relocation");
}
コード例 #5
0
unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx,
                                              const MCValue &Target,
                                              const MCFixup &Fixup,
                                              bool IsCrossSection,
                                              const MCAsmBackend &MAB) const {
  unsigned FixupKind = Fixup.getKind();
  if (IsCrossSection) {
    if (FixupKind != FK_Data_4 && FixupKind != llvm::X86::reloc_signed_4byte) {
      Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression");
      return COFF::IMAGE_REL_AMD64_ADDR32;
    }
    FixupKind = FK_PCRel_4;
  }

  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
    MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();

  if (getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64) {
    switch (FixupKind) {
    case FK_PCRel_4:
    case X86::reloc_riprel_4byte:
    case X86::reloc_riprel_4byte_movq_load:
    case X86::reloc_riprel_4byte_relax:
    case X86::reloc_riprel_4byte_relax_rex:
    case X86::reloc_branch_4byte_pcrel:
      return COFF::IMAGE_REL_AMD64_REL32;
    case FK_Data_4:
    case X86::reloc_signed_4byte:
    case X86::reloc_signed_4byte_relax:
      if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
        return COFF::IMAGE_REL_AMD64_ADDR32NB;
      if (Modifier == MCSymbolRefExpr::VK_SECREL)
        return COFF::IMAGE_REL_AMD64_SECREL;
      return COFF::IMAGE_REL_AMD64_ADDR32;
    case FK_Data_8:
      return COFF::IMAGE_REL_AMD64_ADDR64;
    case FK_SecRel_2:
      return COFF::IMAGE_REL_AMD64_SECTION;
    case FK_SecRel_4:
      return COFF::IMAGE_REL_AMD64_SECREL;
    default:
      Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
      return COFF::IMAGE_REL_AMD64_ADDR32;
    }
  } else if (getMachine() == COFF::IMAGE_FILE_MACHINE_I386) {
    switch (FixupKind) {
    case FK_PCRel_4:
    case X86::reloc_riprel_4byte:
    case X86::reloc_riprel_4byte_movq_load:
      return COFF::IMAGE_REL_I386_REL32;
    case FK_Data_4:
    case X86::reloc_signed_4byte:
    case X86::reloc_signed_4byte_relax:
      if (Modifier == MCSymbolRefExpr::VK_COFF_IMGREL32)
        return COFF::IMAGE_REL_I386_DIR32NB;
      if (Modifier == MCSymbolRefExpr::VK_SECREL)
        return COFF::IMAGE_REL_AMD64_SECREL;
      return COFF::IMAGE_REL_I386_DIR32;
    case FK_SecRel_2:
      return COFF::IMAGE_REL_I386_SECTION;
    case FK_SecRel_4:
      return COFF::IMAGE_REL_I386_SECREL;
    default:
      Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
      return COFF::IMAGE_REL_I386_DIR32;
    }
  } else
    llvm_unreachable("Unsupported COFF machine type.");
}
コード例 #6
0
static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
                                 MCContext *Ctx = NULL) {
  unsigned Kind = Fixup.getKind();
  switch (Kind) {
  default:
    llvm_unreachable("Unknown fixup kind!");
  case FK_Data_1:
  case FK_Data_2:
  case FK_Data_4:
    return Value;
  case ARM::fixup_arm_movt_hi16:
    Value >>= 16;
    // Fallthrough
  case ARM::fixup_arm_movw_lo16:
  case ARM::fixup_arm_movt_hi16_pcrel:
  case ARM::fixup_arm_movw_lo16_pcrel: {
    unsigned Hi4 = (Value & 0xF000) >> 12;
    unsigned Lo12 = Value & 0x0FFF;
    // inst{19-16} = Hi4;
    // inst{11-0} = Lo12;
    Value = (Hi4 << 16) | (Lo12);
    return Value;
  }
  case ARM::fixup_t2_movt_hi16:
    Value >>= 16;
    // Fallthrough
  case ARM::fixup_t2_movw_lo16:
  case ARM::fixup_t2_movt_hi16_pcrel:  //FIXME: Shouldn't this be shifted like
                                       // the other hi16 fixup?
  case ARM::fixup_t2_movw_lo16_pcrel: {
    unsigned Hi4 = (Value & 0xF000) >> 12;
    unsigned i = (Value & 0x800) >> 11;
    unsigned Mid3 = (Value & 0x700) >> 8;
    unsigned Lo8 = Value & 0x0FF;
    // inst{19-16} = Hi4;
    // inst{26} = i;
    // inst{14-12} = Mid3;
    // inst{7-0} = Lo8;
    Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
    uint64_t swapped = (Value & 0xFFFF0000) >> 16;
    swapped |= (Value & 0x0000FFFF) << 16;
    return swapped;
  }
  case ARM::fixup_arm_ldst_pcrel_12:
    // ARM PC-relative values are offset by 8.
    Value -= 4;
    // FALLTHROUGH
  case ARM::fixup_t2_ldst_pcrel_12: {
    // Offset by 4, adjusted by two due to the half-word ordering of thumb.
    Value -= 4;
    bool isAdd = true;
    if ((int64_t)Value < 0) {
      Value = -Value;
      isAdd = false;
    }
    if (Ctx && Value >= 4096)
      Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value");
    Value |= isAdd << 23;

    // Same addressing mode as fixup_arm_pcrel_10,
    // but with 16-bit halfwords swapped.
    if (Kind == ARM::fixup_t2_ldst_pcrel_12) {
      uint64_t swapped = (Value & 0xFFFF0000) >> 16;
      swapped |= (Value & 0x0000FFFF) << 16;
      return swapped;
    }

    return Value;
  }
  case ARM::fixup_thumb_adr_pcrel_10:
    return ((Value - 4) >> 2) & 0xff;
  case ARM::fixup_arm_adr_pcrel_12: {
    // ARM PC-relative values are offset by 8.
    Value -= 8;
    unsigned opc = 4; // bits {24-21}. Default to add: 0b0100
    if ((int64_t)Value < 0) {
      Value = -Value;
      opc = 2; // 0b0010
    }
    if (Ctx && ARM_AM::getSOImmVal(Value) == -1)
      Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value");
    // Encode the immediate and shift the opcode into place.
    return ARM_AM::getSOImmVal(Value) | (opc << 21);
  }

  case ARM::fixup_t2_adr_pcrel_12: {
    Value -= 4;
    unsigned opc = 0;
    if ((int64_t)Value < 0) {
      Value = -Value;
      opc = 5;
    }

    uint32_t out = (opc << 21);
    out |= (Value & 0x800) << 15;
    out |= (Value & 0x700) << 4;
    out |= (Value & 0x0FF);

    uint64_t swapped = (out & 0xFFFF0000) >> 16;
    swapped |= (out & 0x0000FFFF) << 16;
    return swapped;
  }

  case ARM::fixup_arm_condbranch:
  case ARM::fixup_arm_uncondbranch:
  case ARM::fixup_arm_uncondbl:
  case ARM::fixup_arm_condbl:
  case ARM::fixup_arm_blx:
    // These values don't encode the low two bits since they're always zero.
    // Offset by 8 just as above.
    return 0xffffff & ((Value - 8) >> 2);
  case ARM::fixup_t2_uncondbranch: {
    Value = Value - 4;
    Value >>= 1; // Low bit is not encoded.

    uint32_t out = 0;
    bool I =  Value & 0x800000;
    bool J1 = Value & 0x400000;
    bool J2 = Value & 0x200000;
    J1 ^= I;
    J2 ^= I;

    out |= I  << 26; // S bit
    out |= !J1 << 13; // J1 bit
    out |= !J2 << 11; // J2 bit
    out |= (Value & 0x1FF800)  << 5; // imm6 field
    out |= (Value & 0x0007FF);        // imm11 field

    uint64_t swapped = (out & 0xFFFF0000) >> 16;
    swapped |= (out & 0x0000FFFF) << 16;
    return swapped;
  }
  case ARM::fixup_t2_condbranch: {
    Value = Value - 4;
    Value >>= 1; // Low bit is not encoded.

    uint64_t out = 0;
    out |= (Value & 0x80000) << 7; // S bit
    out |= (Value & 0x40000) >> 7; // J2 bit
    out |= (Value & 0x20000) >> 4; // J1 bit
    out |= (Value & 0x1F800) << 5; // imm6 field
    out |= (Value & 0x007FF);      // imm11 field

    uint32_t swapped = (out & 0xFFFF0000) >> 16;
    swapped |= (out & 0x0000FFFF) << 16;
    return swapped;
  }
  case ARM::fixup_arm_thumb_bl: {
     // The value doesn't encode the low bit (always zero) and is offset by
     // four. The 32-bit immediate value is encoded as
     //   imm32 = SignExtend(S:I1:I2:imm10:imm11:0)
     // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
     // The value is encoded into disjoint bit positions in the destination
     // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
     // J = either J1 or J2 bit
     //
     //   BL:  xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII
     //
     // Note that the halfwords are stored high first, low second; so we need
     // to transpose the fixup value here to map properly.
     uint32_t offset = (Value - 4) >> 1;
     uint32_t signBit = (offset & 0x800000) >> 23;
     uint32_t I1Bit = (offset & 0x400000) >> 22;
     uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
     uint32_t I2Bit = (offset & 0x200000) >> 21;
     uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
     uint32_t imm10Bits = (offset & 0x1FF800) >> 11;
     uint32_t imm11Bits = (offset & 0x000007FF);
 
     uint32_t Binary = 0;
     uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits);
     uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
                           (uint16_t)imm11Bits);
     Binary |= secondHalf << 16;
     Binary |= firstHalf;
     return Binary;

  }
  case ARM::fixup_arm_thumb_blx: {
     // The value doesn't encode the low two bits (always zero) and is offset by
     // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as
     //   imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00)
     // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
     // The value is encoded into disjoint bit positions in the destination 
     // opcode. x = unchanged, I = immediate value bit, S = sign extension bit, 
     // J = either J1 or J2 bit, 0 = zero.
     //
     //   BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0
     //
     // Note that the halfwords are stored high first, low second; so we need
     // to transpose the fixup value here to map properly.
     uint32_t offset = (Value - 2) >> 2;
     uint32_t signBit = (offset & 0x400000) >> 22;
     uint32_t I1Bit = (offset & 0x200000) >> 21;
     uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
     uint32_t I2Bit = (offset & 0x100000) >> 20;
     uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
     uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
     uint32_t imm10LBits = (offset & 0x3FF);
 
     uint32_t Binary = 0;
     uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits);
     uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | 
                           ((uint16_t)imm10LBits) << 1);
     Binary |= secondHalf << 16;
     Binary |= firstHalf;
     return Binary;
  }
  case ARM::fixup_arm_thumb_cp:
    // Offset by 4, and don't encode the low two bits. Two bytes of that
    // 'off by 4' is implicitly handled by the half-word ordering of the
    // Thumb encoding, so we only need to adjust by 2 here.
    return ((Value - 2) >> 2) & 0xff;
  case ARM::fixup_arm_thumb_cb: {
    // Offset by 4 and don't encode the lower bit, which is always 0.
    uint32_t Binary = (Value - 4) >> 1;
    return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
  }
  case ARM::fixup_arm_thumb_br:
    // Offset by 4 and don't encode the lower bit, which is always 0.
    return ((Value - 4) >> 1) & 0x7ff;
  case ARM::fixup_arm_thumb_bcc:
    // Offset by 4 and don't encode the lower bit, which is always 0.
    return ((Value - 4) >> 1) & 0xff;
  case ARM::fixup_arm_pcrel_10_unscaled: {
    Value = Value - 8; // ARM fixups offset by an additional word and don't
                       // need to adjust for the half-word ordering.
    bool isAdd = true;
    if ((int64_t)Value < 0) {
      Value = -Value;
      isAdd = false;
    }
    // The value has the low 4 bits encoded in [3:0] and the high 4 in [11:8].
    if (Ctx && Value >= 256)
      Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value");
    Value = (Value & 0xf) | ((Value & 0xf0) << 4);
    return Value | (isAdd << 23);
  }
  case ARM::fixup_arm_pcrel_10:
    Value = Value - 4; // ARM fixups offset by an additional word and don't
                       // need to adjust for the half-word ordering.
    // Fall through.
  case ARM::fixup_t2_pcrel_10: {
    // Offset by 4, adjusted by two due to the half-word ordering of thumb.
    Value = Value - 4;
    bool isAdd = true;
    if ((int64_t)Value < 0) {
      Value = -Value;
      isAdd = false;
    }
    // These values don't encode the low two bits since they're always zero.
    Value >>= 2;
    if (Ctx && Value >= 256)
      Ctx->FatalError(Fixup.getLoc(), "out of range pc-relative fixup value");
    Value |= isAdd << 23;

    // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords
    // swapped.
    if (Kind == ARM::fixup_t2_pcrel_10) {
      uint32_t swapped = (Value & 0xFFFF0000) >> 16;
      swapped |= (Value & 0x0000FFFF) << 16;
      return swapped;
    }

    return Value;
  }
コード例 #7
0
void ARMMachObjectWriter::
RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
                                 const MCAssembler &Asm,
                                 const MCAsmLayout &Layout,
                                 const MCFragment *Fragment,
                                 const MCFixup &Fixup,
                                 MCValue Target,
                                 uint64_t &FixedValue) {
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned Type = MachO::ARM_RELOC_HALF;

  // See <reloc.h>.
  const MCSymbol *A = &Target.getSymA()->getSymbol();
  const MCSymbolData *A_SD = &Asm.getSymbolData(*A);

  if (!A_SD->getFragment())
    Asm.getContext().FatalError(Fixup.getLoc(),
                       "symbol '" + A->getName() +
                       "' can not be undefined in a subtraction expression");

  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
  uint32_t Value2 = 0;
  uint64_t SecAddr =
    Writer->getSectionAddress(A_SD->getFragment()->getParent());
  FixedValue += SecAddr;

  if (const MCSymbolRefExpr *B = Target.getSymB()) {
    const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());

    if (!B_SD->getFragment())
      Asm.getContext().FatalError(Fixup.getLoc(),
                         "symbol '" + B->getSymbol().getName() +
                         "' can not be undefined in a subtraction expression");

    // Select the appropriate difference relocation type.
    Type = MachO::ARM_RELOC_HALF_SECTDIFF;
    Value2 = Writer->getSymbolAddress(B_SD, Layout);
    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
  }

  // Relocations are written out in reverse order, so the PAIR comes first.
  // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
  //
  // For these two r_type relocations they always have a pair following them and
  // the r_length bits are used differently.  The encoding of the r_length is as
  // follows:
  //   low bit of r_length:
  //      0 - :lower16: for movw instructions
  //      1 - :upper16: for movt instructions
  //   high bit of r_length:
  //      0 - arm instructions
  //      1 - thumb instructions
  // the other half of the relocated expression is in the following pair
  // relocation entry in the low 16 bits of r_address field.
  unsigned ThumbBit = 0;
  unsigned MovtBit = 0;
  switch ((unsigned)Fixup.getKind()) {
  default: break;
  case ARM::fixup_arm_movt_hi16:
    MovtBit = 1;
    // The thumb bit shouldn't be set in the 'other-half' bit of the
    // relocation, but it will be set in FixedValue if the base symbol
    // is a thumb function. Clear it out here.
    if (Asm.isThumbFunc(A))
      FixedValue &= 0xfffffffe;
    break;
  case ARM::fixup_t2_movt_hi16:
    if (Asm.isThumbFunc(A))
      FixedValue &= 0xfffffffe;
    MovtBit = 1;
    // Fallthrough
  case ARM::fixup_t2_movw_lo16:
    ThumbBit = 1;
    break;
  }

  if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
    uint32_t OtherHalf = MovtBit
      ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);

    MachO::any_relocation_info MRE;
    MRE.r_word0 = ((OtherHalf             <<  0) |
                   (MachO::ARM_RELOC_PAIR << 24) |
                   (MovtBit               << 28) |
                   (ThumbBit              << 29) |
                   (IsPCRel               << 30) |
                   MachO::R_SCATTERED);
    MRE.r_word1 = Value2;
    Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
  }
コード例 #8
0
void AArch64MachObjectWriter::RecordRelocation(
    MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout,
    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
    uint64_t &FixedValue) {
    unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());

    // See <reloc.h>.
    uint32_t FixupOffset = Layout.getFragmentOffset(Fragment);
    unsigned Log2Size = 0;
    int64_t Value = 0;
    unsigned Index = 0;
    unsigned Type = 0;
    unsigned Kind = Fixup.getKind();
    const MCSymbolData *RelSymbol = nullptr;

    FixupOffset += Fixup.getOffset();

    // AArch64 pcrel relocation addends do not include the section offset.
    if (IsPCRel)
        FixedValue += FixupOffset;

    // ADRP fixups use relocations for the whole symbol value and only
    // put the addend in the instruction itself. Clear out any value the
    // generic code figured out from the sybmol definition.
    if (Kind == AArch64::fixup_aarch64_pcrel_adrp_imm21)
        FixedValue = 0;

    // imm19 relocations are for conditional branches, which require
    // assembler local symbols. If we got here, that's not what we have,
    // so complain loudly.
    if (Kind == AArch64::fixup_aarch64_pcrel_branch19) {
        Asm.getContext().FatalError(Fixup.getLoc(),
                                    "conditional branch requires assembler-local"
                                    " label. '" +
                                    Target.getSymA()->getSymbol().getName() +
                                    "' is external.");
        return;
    }

    // 14-bit branch relocations should only target internal labels, and so
    // should never get here.
    if (Kind == AArch64::fixup_aarch64_pcrel_branch14) {
        Asm.getContext().FatalError(Fixup.getLoc(),
                                    "Invalid relocation on conditional branch!");
        return;
    }

    if (!getAArch64FixupKindMachOInfo(Fixup, Type, Target.getSymA(), Log2Size,
                                      Asm)) {
        Asm.getContext().FatalError(Fixup.getLoc(), "unknown AArch64 fixup kind!");
        return;
    }

    Value = Target.getConstant();

    if (Target.isAbsolute()) { // constant
        // FIXME: Should this always be extern?
        // SymbolNum of 0 indicates the absolute section.
        Type = MachO::ARM64_RELOC_UNSIGNED;

        if (IsPCRel) {
            Asm.getContext().FatalError(Fixup.getLoc(),
                                        "PC relative absolute relocation!");

            // FIXME: x86_64 sets the type to a branch reloc here. Should we do
            // something similar?
        }
    } else if (Target.getSymB()) { // A - B + constant
        const MCSymbol *A = &Target.getSymA()->getSymbol();
        const MCSymbolData &A_SD = Asm.getSymbolData(*A);
        const MCSymbolData *A_Base = Asm.getAtom(&A_SD);

        const MCSymbol *B = &Target.getSymB()->getSymbol();
        const MCSymbolData &B_SD = Asm.getSymbolData(*B);
        const MCSymbolData *B_Base = Asm.getAtom(&B_SD);

        // Check for "_foo@got - .", which comes through here as:
        // Ltmp0:
        //    ... _foo@got - Ltmp0
        if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOT &&
                Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None &&
                Layout.getSymbolOffset(&B_SD) ==
                Layout.getFragmentOffset(Fragment) + Fixup.getOffset()) {
            // SymB is the PC, so use a PC-rel pointer-to-GOT relocation.
            Type = MachO::ARM64_RELOC_POINTER_TO_GOT;
            IsPCRel = 1;
            MachO::any_relocation_info MRE;
            MRE.r_word0 = FixupOffset;
            MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
            Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
            return;
        } else if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
                   Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
            // Otherwise, neither symbol can be modified.
            Asm.getContext().FatalError(Fixup.getLoc(),
                                        "unsupported relocation of modified symbol");

        // We don't support PCrel relocations of differences.
        if (IsPCRel)
            Asm.getContext().FatalError(Fixup.getLoc(),
                                        "unsupported pc-relative relocation of "
                                        "difference");

        // AArch64 always uses external relocations. If there is no symbol to use as
        // a base address (a local symbol with no preceding non-local symbol),
        // error out.
        //
        // FIXME: We should probably just synthesize an external symbol and use
        // that.
        if (!A_Base)
            Asm.getContext().FatalError(
                Fixup.getLoc(),
                "unsupported relocation of local symbol '" + A->getName() +
                "'. Must have non-local symbol earlier in section.");
        if (!B_Base)
            Asm.getContext().FatalError(
                Fixup.getLoc(),
                "unsupported relocation of local symbol '" + B->getName() +
                "'. Must have non-local symbol earlier in section.");

        if (A_Base == B_Base && A_Base)
            Asm.getContext().FatalError(Fixup.getLoc(),
                                        "unsupported relocation with identical base");

        Value += (!A_SD.getFragment() ? 0
                  : Writer->getSymbolAddress(&A_SD, Layout)) -
                 (!A_Base || !A_Base->getFragment()
                  ? 0
                  : Writer->getSymbolAddress(A_Base, Layout));
        Value -= (!B_SD.getFragment() ? 0
                  : Writer->getSymbolAddress(&B_SD, Layout)) -
                 (!B_Base || !B_Base->getFragment()
                  ? 0
                  : Writer->getSymbolAddress(B_Base, Layout));

        Type = MachO::ARM64_RELOC_UNSIGNED;

        MachO::any_relocation_info MRE;
        MRE.r_word0 = FixupOffset;
        MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
        Writer->addRelocation(A_Base, Fragment->getParent(), MRE);

        RelSymbol = B_Base;
        Type = MachO::ARM64_RELOC_SUBTRACTOR;
    } else { // A + constant
        const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
        const MCSectionMachO &Section = static_cast<const MCSectionMachO &>(
                                            Fragment->getParent()->getSection());

        bool CanUseLocalRelocation =
            canUseLocalRelocation(Section, *Symbol, Log2Size);
        if (Symbol->isTemporary() && (Value || !CanUseLocalRelocation)) {
            const MCSection &Sec = Symbol->getSection();
            if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec))
                Asm.addLocalUsedInReloc(*Symbol);
        }

        const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
        const MCSymbolData *Base = Asm.getAtom(&SD);

        // If the symbol is a variable and we weren't able to get a Base for it
        // (i.e., it's not in the symbol table associated with a section) resolve
        // the relocation based its expansion instead.
        if (Symbol->isVariable() && !Base) {
            // If the evaluation is an absolute value, just use that directly
            // to keep things easy.
            int64_t Res;
            if (SD.getSymbol().getVariableValue()->EvaluateAsAbsolute(
                        Res, Layout, Writer->getSectionAddressMap())) {
                FixedValue = Res;
                return;
            }

            // FIXME: Will the Target we already have ever have any data in it
            // we need to preserve and merge with the new Target? How about
            // the FixedValue?
            if (!Symbol->getVariableValue()->EvaluateAsRelocatable(Target, &Layout,
                    &Fixup))
                Asm.getContext().FatalError(Fixup.getLoc(),
                                            "unable to resolve variable '" +
                                            Symbol->getName() + "'");
            return RecordRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
                                    FixedValue);
        }

        // Relocations inside debug sections always use local relocations when
        // possible. This seems to be done because the debugger doesn't fully
        // understand relocation entries and expects to find values that
        // have already been fixed up.
        if (Symbol->isInSection()) {
            if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
                Base = nullptr;
        }

        // AArch64 uses external relocations as much as possible. For debug
        // sections, and for pointer-sized relocations (.quad), we allow section
        // relocations.  It's code sections that run into trouble.
        if (Base) {
            RelSymbol = Base;

            // Add the local offset, if needed.
            if (Base != &SD)
                Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
        } else if (Symbol->isInSection()) {
            if (!CanUseLocalRelocation)
                Asm.getContext().FatalError(
                    Fixup.getLoc(),
                    "unsupported relocation of local symbol '" + Symbol->getName() +
                    "'. Must have non-local symbol earlier in section.");
            // Adjust the relocation to be section-relative.
            // The index is the section ordinal (1-based).
            const MCSectionData &SymSD =
                Asm.getSectionData(SD.getSymbol().getSection());
            Index = SymSD.getOrdinal() + 1;
            Value += Writer->getSymbolAddress(&SD, Layout);

            if (IsPCRel)
                Value -= Writer->getFragmentAddress(Fragment, Layout) +
                         Fixup.getOffset() + (1ULL << Log2Size);
        } else {
            // Resolve constant variables.
            if (SD.getSymbol().isVariable()) {
                int64_t Res;
                if (SD.getSymbol().getVariableValue()->EvaluateAsAbsolute(
                            Res, Layout, Writer->getSectionAddressMap())) {
                    FixedValue = Res;
                    return;
                }
            }
            Asm.getContext().FatalError(Fixup.getLoc(),
                                        "unsupported relocation of variable '" +
                                        Symbol->getName() + "'");
        }
    }

    // If the relocation kind is Branch26, Page21, or Pageoff12, any addend
    // is represented via an Addend relocation, not encoded directly into
    // the instruction.
    if ((Type == MachO::ARM64_RELOC_BRANCH26 ||
            Type == MachO::ARM64_RELOC_PAGE21 ||
            Type == MachO::ARM64_RELOC_PAGEOFF12) &&
            Value) {
        assert((Value & 0xff000000) == 0 && "Added relocation out of range!");

        MachO::any_relocation_info MRE;
        MRE.r_word0 = FixupOffset;
        MRE.r_word1 =
            (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
        Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);

        // Now set up the Addend relocation.
        Type = MachO::ARM64_RELOC_ADDEND;
        Index = Value;
        RelSymbol = nullptr;
        IsPCRel = 0;
        Log2Size = 2;

        // Put zero into the instruction itself. The addend is in the relocation.
        Value = 0;
    }

    // If there's any addend left to handle, encode it in the instruction.
    FixedValue = Value;

    // struct relocation_info (8 bytes)
    MachO::any_relocation_info MRE;
    MRE.r_word0 = FixupOffset;
    MRE.r_word1 =
        (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
    Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
コード例 #9
0
bool AArch64MachObjectWriter::getAArch64FixupKindMachOInfo(
    const MCFixup &Fixup, unsigned &RelocType, const MCSymbolRefExpr *Sym,
    unsigned &Log2Size, const MCAssembler &Asm) {
    RelocType = unsigned(MachO::ARM64_RELOC_UNSIGNED);
    Log2Size = ~0U;

    switch ((unsigned)Fixup.getKind()) {
    default:
        return false;

    case FK_Data_1:
        Log2Size = llvm::Log2_32(1);
        return true;
    case FK_Data_2:
        Log2Size = llvm::Log2_32(2);
        return true;
    case FK_Data_4:
        Log2Size = llvm::Log2_32(4);
        if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
            RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
        return true;
    case FK_Data_8:
        Log2Size = llvm::Log2_32(8);
        if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
            RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
        return true;
    case AArch64::fixup_aarch64_add_imm12:
    case AArch64::fixup_aarch64_ldst_imm12_scale1:
    case AArch64::fixup_aarch64_ldst_imm12_scale2:
    case AArch64::fixup_aarch64_ldst_imm12_scale4:
    case AArch64::fixup_aarch64_ldst_imm12_scale8:
    case AArch64::fixup_aarch64_ldst_imm12_scale16:
        Log2Size = llvm::Log2_32(4);
        switch (Sym->getKind()) {
        default:
            llvm_unreachable("Unexpected symbol reference variant kind!");
        case MCSymbolRefExpr::VK_PAGEOFF:
            RelocType = unsigned(MachO::ARM64_RELOC_PAGEOFF12);
            return true;
        case MCSymbolRefExpr::VK_GOTPAGEOFF:
            RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
            return true;
        case MCSymbolRefExpr::VK_TLVPPAGEOFF:
            RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
            return true;
        }
    case AArch64::fixup_aarch64_pcrel_adrp_imm21:
        Log2Size = llvm::Log2_32(4);
        // This encompasses the relocation for the whole 21-bit value.
        switch (Sym->getKind()) {
        default:
            Asm.getContext().FatalError(Fixup.getLoc(),
                                        "ADR/ADRP relocations must be GOT relative");
        case MCSymbolRefExpr::VK_PAGE:
            RelocType = unsigned(MachO::ARM64_RELOC_PAGE21);
            return true;
        case MCSymbolRefExpr::VK_GOTPAGE:
            RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
            return true;
        case MCSymbolRefExpr::VK_TLVPPAGE:
            RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
            return true;
        }
        return true;
    case AArch64::fixup_aarch64_pcrel_branch26:
    case AArch64::fixup_aarch64_pcrel_call26:
        Log2Size = llvm::Log2_32(4);
        RelocType = unsigned(MachO::ARM64_RELOC_BRANCH26);
        return true;
    }
}
コード例 #10
0
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
                                 MCContext &Ctx) {
  unsigned Kind = Fixup.getKind();
  switch (Kind) {
  default:
    llvm_unreachable("Unknown fixup kind!");
  case RISCV::fixup_riscv_got_hi20:
    llvm_unreachable("Relocation should be unconditionally forced\n");
  case FK_Data_1:
  case FK_Data_2:
  case FK_Data_4:
  case FK_Data_8:
    return Value;
  case RISCV::fixup_riscv_lo12_i:
  case RISCV::fixup_riscv_pcrel_lo12_i:
  case RISCV::fixup_riscv_tprel_lo12_i:
    return Value & 0xfff;
  case RISCV::fixup_riscv_lo12_s:
  case RISCV::fixup_riscv_pcrel_lo12_s:
  case RISCV::fixup_riscv_tprel_lo12_s:
    return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7);
  case RISCV::fixup_riscv_hi20:
  case RISCV::fixup_riscv_pcrel_hi20:
  case RISCV::fixup_riscv_tprel_hi20:
    // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
    return ((Value + 0x800) >> 12) & 0xfffff;
  case RISCV::fixup_riscv_jal: {
    if (!isInt<21>(Value))
      Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
    if (Value & 0x1)
      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
    // Need to produce imm[19|10:1|11|19:12] from the 21-bit Value.
    unsigned Sbit = (Value >> 20) & 0x1;
    unsigned Hi8 = (Value >> 12) & 0xff;
    unsigned Mid1 = (Value >> 11) & 0x1;
    unsigned Lo10 = (Value >> 1) & 0x3ff;
    // Inst{31} = Sbit;
    // Inst{30-21} = Lo10;
    // Inst{20} = Mid1;
    // Inst{19-12} = Hi8;
    Value = (Sbit << 19) | (Lo10 << 9) | (Mid1 << 8) | Hi8;
    return Value;
  }
  case RISCV::fixup_riscv_branch: {
    if (!isInt<13>(Value))
      Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
    if (Value & 0x1)
      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
    // Need to extract imm[12], imm[10:5], imm[4:1], imm[11] from the 13-bit
    // Value.
    unsigned Sbit = (Value >> 12) & 0x1;
    unsigned Hi1 = (Value >> 11) & 0x1;
    unsigned Mid6 = (Value >> 5) & 0x3f;
    unsigned Lo4 = (Value >> 1) & 0xf;
    // Inst{31} = Sbit;
    // Inst{30-25} = Mid6;
    // Inst{11-8} = Lo4;
    // Inst{7} = Hi1;
    Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7);
    return Value;
  }
  case RISCV::fixup_riscv_call:
  case RISCV::fixup_riscv_call_plt: {
    // Jalr will add UpperImm with the sign-extended 12-bit LowerImm,
    // we need to add 0x800ULL before extract upper bits to reflect the
    // effect of the sign extension.
    uint64_t UpperImm = (Value + 0x800ULL) & 0xfffff000ULL;
    uint64_t LowerImm = Value & 0xfffULL;
    return UpperImm | ((LowerImm << 20) << 32);
  }
  case RISCV::fixup_riscv_rvc_jump: {
    // Need to produce offset[11|4|9:8|10|6|7|3:1|5] from the 11-bit Value.
    unsigned Bit11  = (Value >> 11) & 0x1;
    unsigned Bit4   = (Value >> 4) & 0x1;
    unsigned Bit9_8 = (Value >> 8) & 0x3;
    unsigned Bit10  = (Value >> 10) & 0x1;
    unsigned Bit6   = (Value >> 6) & 0x1;
    unsigned Bit7   = (Value >> 7) & 0x1;
    unsigned Bit3_1 = (Value >> 1) & 0x7;
    unsigned Bit5   = (Value >> 5) & 0x1;
    Value = (Bit11 << 10) | (Bit4 << 9) | (Bit9_8 << 7) | (Bit10 << 6) |
            (Bit6 << 5) | (Bit7 << 4) | (Bit3_1 << 1) | Bit5;
    return Value;
  }
  case RISCV::fixup_riscv_rvc_branch: {
    // Need to produce offset[8|4:3], [reg 3 bit], offset[7:6|2:1|5]
    unsigned Bit8   = (Value >> 8) & 0x1;
    unsigned Bit7_6 = (Value >> 6) & 0x3;
    unsigned Bit5   = (Value >> 5) & 0x1;
    unsigned Bit4_3 = (Value >> 3) & 0x3;
    unsigned Bit2_1 = (Value >> 1) & 0x3;
    Value = (Bit8 << 12) | (Bit4_3 << 10) | (Bit7_6 << 5) | (Bit2_1 << 3) |
            (Bit5 << 2);
    return Value;
  }

  }
}
コード例 #11
0
void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
                                       const MCAsmLayout &Layout,
                                       const MCFragment *Fragment,
                                       const MCFixup &Fixup, MCValue Target,
                                       uint64_t &FixedValue) {
  MCAsmBackend &Backend = Asm.getBackend();
  bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
                 MCFixupKindInfo::FKF_IsPCRel;
  const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
  uint64_t C = Target.getConstant();
  uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  MCContext &Ctx = Asm.getContext();

  if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
    // Let A, B and C being the components of Target and R be the location of
    // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
    // If it is pcrel, we want to compute (A - B + C - R).

    // In general, ELF has no relocations for -B. It can only represent (A + C)
    // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
    // replace B to implement it: (A - R - K + C)
    if (IsPCRel) {
      Ctx.reportError(
          Fixup.getLoc(),
          "No relocation available to represent this relative expression");
      return;
    }

    const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());

    if (SymB.isUndefined()) {
      Ctx.reportError(Fixup.getLoc(),
                      Twine("symbol '") + SymB.getName() +
                          "' can not be undefined in a subtraction expression");
      return;
    }

    assert(!SymB.isAbsolute() && "Should have been folded");
    const MCSection &SecB = SymB.getSection();
    if (&SecB != &FixupSection) {
      Ctx.reportError(Fixup.getLoc(),
                      "Cannot represent a difference across sections");
      return;
    }

    uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
    uint64_t K = SymBOffset - FixupOffset;
    IsPCRel = true;
    C -= K;
  }

  // We either rejected the fixup or folded B into C at this point.
  const MCSymbolRefExpr *RefA = Target.getSymA();
  const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr;

  bool ViaWeakRef = false;
  if (SymA && SymA->isVariable()) {
    const MCExpr *Expr = SymA->getVariableValue();
    if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
      if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
        SymA = cast<MCSymbolELF>(&Inner->getSymbol());
        ViaWeakRef = true;
      }
    }
  }

  unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel);
  uint64_t OriginalC = C;
  bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type);
  if (!RelocateWithSymbol && SymA && !SymA->isUndefined())
    C += Layout.getSymbolOffset(*SymA);

  uint64_t Addend = 0;
  if (hasRelocationAddend()) {
    Addend = C;
    C = 0;
  }

  FixedValue = C;

  if (!RelocateWithSymbol) {
    const MCSection *SecA =
        (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
    auto *ELFSec = cast_or_null<MCSectionELF>(SecA);
    const auto *SectionSymbol =
        ELFSec ? cast<MCSymbolELF>(ELFSec->getBeginSymbol()) : nullptr;
    if (SectionSymbol)
      SectionSymbol->setUsedInReloc();
    ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA,
                           OriginalC);
    Relocations[&FixupSection].push_back(Rec);
    return;
  }

  const auto *RenamedSymA = SymA;
  if (SymA) {
    if (const MCSymbolELF *R = Renames.lookup(SymA))
      RenamedSymA = R;

    if (ViaWeakRef)
      RenamedSymA->setIsWeakrefUsedInReloc();
    else
      RenamedSymA->setUsedInReloc();
  }
  ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA,
                         OriginalC);
  Relocations[&FixupSection].push_back(Rec);
}
コード例 #12
0
bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
                                const MCFixup &Fixup, const MCFragment *DF,
                                MCValue &Target, uint64_t &Value) const {
  ++stats::evaluateFixup;

  // FIXME: This code has some duplication with recordRelocation. We should
  // probably merge the two into a single callback that tries to evaluate a
  // fixup and records a relocation if one is needed.
  const MCExpr *Expr = Fixup.getValue();
  if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup))
    getContext().reportFatalError(Fixup.getLoc(), "expected relocatable expression");

  bool IsPCRel = Backend.getFixupKindInfo(
    Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;

  bool IsResolved;
  if (IsPCRel) {
    if (Target.getSymB()) {
      IsResolved = false;
    } else if (!Target.getSymA()) {
      IsResolved = false;
    } else {
      const MCSymbolRefExpr *A = Target.getSymA();
      const MCSymbol &SA = A->getSymbol();
      if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) {
        IsResolved = false;
      } else {
        IsResolved = getWriter().isSymbolRefDifferenceFullyResolvedImpl(
            *this, SA, *DF, false, true);
      }
    }
  } else {
    IsResolved = Target.isAbsolute();
  }

  Value = Target.getConstant();

  if (const MCSymbolRefExpr *A = Target.getSymA()) {
    const MCSymbol &Sym = A->getSymbol();
    if (Sym.isDefined())
      Value += Layout.getSymbolOffset(Sym);
  }
  if (const MCSymbolRefExpr *B = Target.getSymB()) {
    const MCSymbol &Sym = B->getSymbol();
    if (Sym.isDefined())
      Value -= Layout.getSymbolOffset(Sym);
  }


  bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
                         MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;
  assert((ShouldAlignPC ? IsPCRel : true) &&
    "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!");

  if (IsPCRel) {
    uint32_t Offset = Layout.getFragmentOffset(DF) + Fixup.getOffset();

    // A number of ARM fixups in Thumb mode require that the effective PC
    // address be determined as the 32-bit aligned version of the actual offset.
    if (ShouldAlignPC) Offset &= ~0x3;
    Value -= Offset;
  }

  // Let the backend adjust the fixup value if necessary, including whether
  // we need a relocation.
  Backend.processFixupValue(*this, Layout, Fixup, DF, Target, Value,
                            IsResolved);

  return IsResolved;
}
コード例 #13
0
ファイル: X86MachObjectWriter.cpp プロジェクト: traiansf/llvm
bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
                                                    const MCAssembler &Asm,
                                                    const MCAsmLayout &Layout,
                                                    const MCFragment *Fragment,
                                                    const MCFixup &Fixup,
                                                    MCValue Target,
                                                    unsigned Log2Size,
                                                    uint64_t &FixedValue) {
  uint64_t OriginalFixedValue = FixedValue;
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned Type = MachO::GENERIC_RELOC_VANILLA;

  // See <reloc.h>.
  const MCSymbol *A = &Target.getSymA()->getSymbol();
  const MCSymbolData *A_SD = &Asm.getSymbolData(*A);

  if (!A_SD->getFragment())
    report_fatal_error("symbol '" + A->getName() +
                       "' can not be undefined in a subtraction expression",
                       false);

  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
  uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
  FixedValue += SecAddr;
  uint32_t Value2 = 0;

  if (const MCSymbolRefExpr *B = Target.getSymB()) {
    const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());

    if (!B_SD->getFragment())
      report_fatal_error("symbol '" + B->getSymbol().getName() +
                         "' can not be undefined in a subtraction expression",
                         false);

    // Select the appropriate difference relocation type.
    //
    // Note that there is no longer any semantic difference between these two
    // relocation types from the linkers point of view, this is done solely for
    // pedantic compatibility with 'as'.
    Type = A_SD->isExternal() ? (unsigned)MachO::GENERIC_RELOC_SECTDIFF :
      (unsigned)MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
    Value2 = Writer->getSymbolAddress(B_SD, Layout);
    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
  }

  // Relocations are written out in reverse order, so the PAIR comes first.
  if (Type == MachO::GENERIC_RELOC_SECTDIFF ||
      Type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
    // If the offset is too large to fit in a scattered relocation,
    // we're hosed. It's an unfortunate limitation of the MachO format.
    if (FixupOffset > 0xffffff) {
      char Buffer[32];
      format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
      Asm.getContext().FatalError(Fixup.getLoc(),
                         Twine("Section too large, can't encode "
                                "r_address (") + Buffer +
                         ") into 24 bits of scattered "
                         "relocation entry.");
      llvm_unreachable("fatal error returned?!");
    }

    MachO::any_relocation_info MRE;
    MRE.r_word0 = ((0                         <<  0) | // r_address
                   (MachO::GENERIC_RELOC_PAIR << 24) | // r_type
                   (Log2Size                  << 28) |
                   (IsPCRel                   << 30) |
                   MachO::R_SCATTERED);
    MRE.r_word1 = Value2;
    Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
  } else {
    // If the offset is more than 24-bits, it won't fit in a scattered
    // relocation offset field, so we fall back to using a non-scattered
    // relocation. This is a bit risky, as if the offset reaches out of
    // the block and the linker is doing scattered loading on this
    // symbol, things can go badly.
    //
    // Required for 'as' compatibility.
    if (FixupOffset > 0xffffff) {
      FixedValue = OriginalFixedValue;
      return false;
    }
  }

  MachO::any_relocation_info MRE;
  MRE.r_word0 = ((FixupOffset <<  0) |
                 (Type        << 24) |
                 (Log2Size    << 28) |
                 (IsPCRel     << 30) |
                 MachO::R_SCATTERED);
  MRE.r_word1 = Value;
  Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
  return true;
}
コード例 #14
0
ファイル: ARMELFObjectWriter.cpp プロジェクト: Lucretia/llvm
unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
                                               const MCFixup &Fixup,
                                               bool IsPCRel,
                                               MCContext &Ctx) const {
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();

  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    default:
      Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
      return ELF::R_ARM_NONE;
    case FK_Data_4:
      switch (Modifier) {
      default:
        llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        return ELF::R_ARM_REL32;
      case MCSymbolRefExpr::VK_GOTTPOFF:
        return ELF::R_ARM_TLS_IE32;
      case MCSymbolRefExpr::VK_ARM_GOT_PREL:
        return ELF::R_ARM_GOT_PREL;
      case MCSymbolRefExpr::VK_ARM_PREL31:
        return ELF::R_ARM_PREL31;
      }
    case ARM::fixup_arm_blx:
    case ARM::fixup_arm_uncondbl:
      switch (Modifier) {
      case MCSymbolRefExpr::VK_PLT:
        return ELF::R_ARM_CALL;
      case MCSymbolRefExpr::VK_TLSCALL:
        return ELF::R_ARM_TLS_CALL;
      default:
        return ELF::R_ARM_CALL;
      }
    case ARM::fixup_arm_condbl:
    case ARM::fixup_arm_condbranch:
    case ARM::fixup_arm_uncondbranch:
      return ELF::R_ARM_JUMP24;
    case ARM::fixup_t2_condbranch:
      return ELF::R_ARM_THM_JUMP19;
    case ARM::fixup_t2_uncondbranch:
      return ELF::R_ARM_THM_JUMP24;
    case ARM::fixup_arm_movt_hi16:
      return ELF::R_ARM_MOVT_PREL;
    case ARM::fixup_arm_movw_lo16:
      return ELF::R_ARM_MOVW_PREL_NC;
    case ARM::fixup_t2_movt_hi16:
      return ELF::R_ARM_THM_MOVT_PREL;
    case ARM::fixup_t2_movw_lo16:
      return ELF::R_ARM_THM_MOVW_PREL_NC;
    case ARM::fixup_arm_thumb_br:
      return ELF::R_ARM_THM_JUMP11;
    case ARM::fixup_arm_thumb_bcc:
      return ELF::R_ARM_THM_JUMP8;
    case ARM::fixup_arm_thumb_bl:
    case ARM::fixup_arm_thumb_blx:
      switch (Modifier) {
      case MCSymbolRefExpr::VK_TLSCALL:
        return ELF::R_ARM_THM_TLS_CALL;
      default:
        return ELF::R_ARM_THM_CALL;
      }
    }
  }
  switch ((unsigned)Fixup.getKind()) {
  default:
    Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol");
    return ELF::R_ARM_NONE;
  case FK_Data_1:
    switch (Modifier) {
    default:
      llvm_unreachable("unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_ABS8;
    }
  case FK_Data_2:
    switch (Modifier) {
    default:
      llvm_unreachable("unsupported modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_ABS16;
    }
  case FK_Data_4:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_ARM_NONE:
      return ELF::R_ARM_NONE;
    case MCSymbolRefExpr::VK_GOT:
      return ELF::R_ARM_GOT_BREL;
    case MCSymbolRefExpr::VK_TLSGD:
      return ELF::R_ARM_TLS_GD32;
    case MCSymbolRefExpr::VK_TPOFF:
      return ELF::R_ARM_TLS_LE32;
    case MCSymbolRefExpr::VK_GOTTPOFF:
      return ELF::R_ARM_TLS_IE32;
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_ABS32;
    case MCSymbolRefExpr::VK_GOTOFF:
      return ELF::R_ARM_GOTOFF32;
    case MCSymbolRefExpr::VK_ARM_GOT_PREL:
      return ELF::R_ARM_GOT_PREL;
    case MCSymbolRefExpr::VK_ARM_TARGET1:
      return ELF::R_ARM_TARGET1;
    case MCSymbolRefExpr::VK_ARM_TARGET2:
      return ELF::R_ARM_TARGET2;
    case MCSymbolRefExpr::VK_ARM_PREL31:
      return ELF::R_ARM_PREL31;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_SBREL32;
    case MCSymbolRefExpr::VK_ARM_TLSLDO:
      return ELF::R_ARM_TLS_LDO32;
    case MCSymbolRefExpr::VK_TLSCALL:
      return ELF::R_ARM_TLS_CALL;
    case MCSymbolRefExpr::VK_TLSDESC:
      return ELF::R_ARM_TLS_GOTDESC;
    case MCSymbolRefExpr::VK_TLSLDM:
      return ELF::R_ARM_TLS_LDM32;
    case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
      return ELF::R_ARM_TLS_DESCSEQ;
    }
  case ARM::fixup_arm_condbranch:
  case ARM::fixup_arm_uncondbranch:
    return ELF::R_ARM_JUMP24;
  case ARM::fixup_arm_movt_hi16:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_MOVT_ABS;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_MOVT_BREL;
    }
  case ARM::fixup_arm_movw_lo16:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_MOVW_ABS_NC;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_MOVW_BREL_NC;
    }
  case ARM::fixup_t2_movt_hi16:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_THM_MOVT_ABS;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_THM_MOVT_BREL;
    }
  case ARM::fixup_t2_movw_lo16:
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return ELF::R_ARM_THM_MOVW_ABS_NC;
    case MCSymbolRefExpr::VK_ARM_SBREL:
      return ELF::R_ARM_THM_MOVW_BREL_NC;
    }
  }
}
コード例 #15
0
ファイル: AArch64ELFObjectWriter.cpp プロジェクト: Zoxc/llvm
unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
        const MCValue &Target,
        const MCFixup &Fixup,
        bool IsPCRel) const {
    AArch64MCExpr::VariantKind RefKind =
        static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
    AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
    bool IsNC = AArch64MCExpr::isNotChecked(RefKind);

    assert((!Target.getSymA() ||
            Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
           "Should only be expression-level modifiers here");

    assert((!Target.getSymB() ||
            Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
           "Should only be expression-level modifiers here");

    if (IsPCRel) {
        switch ((unsigned)Fixup.getKind()) {
        case FK_Data_1:
            Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
            return ELF::R_AARCH64_NONE;
        case FK_Data_2:
            return ELF::R_AARCH64_PREL16;
        case FK_Data_4:
            return ELF::R_AARCH64_PREL32;
        case FK_Data_8:
            return ELF::R_AARCH64_PREL64;
        case AArch64::fixup_aarch64_pcrel_adr_imm21:
            assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
            return ELF::R_AARCH64_ADR_PREL_LO21;
        case AArch64::fixup_aarch64_pcrel_adrp_imm21:
            if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
                return ELF::R_AARCH64_ADR_PREL_PG_HI21;
            if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
                return ELF::R_AARCH64_ADR_GOT_PAGE;
            if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
                return ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
            if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
                return ELF::R_AARCH64_TLSDESC_ADR_PAGE21;
            Ctx.reportError(Fixup.getLoc(),
                            "invalid symbol kind for ADRP relocation");
            return ELF::R_AARCH64_NONE;
        case AArch64::fixup_aarch64_pcrel_branch26:
            return ELF::R_AARCH64_JUMP26;
        case AArch64::fixup_aarch64_pcrel_call26:
            return ELF::R_AARCH64_CALL26;
        case AArch64::fixup_aarch64_ldr_pcrel_imm19:
            if (SymLoc == AArch64MCExpr::VK_GOTTPREL)
                return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19;
            return ELF::R_AARCH64_LD_PREL_LO19;
        case AArch64::fixup_aarch64_pcrel_branch14:
            return ELF::R_AARCH64_TSTBR14;
        case AArch64::fixup_aarch64_pcrel_branch19:
            return ELF::R_AARCH64_CONDBR19;
        default:
            Ctx.reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind");
            return ELF::R_AARCH64_NONE;
        }
    } else {
        switch ((unsigned)Fixup.getKind()) {
        case FK_Data_1:
            Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
            return ELF::R_AARCH64_NONE;
        case FK_Data_2:
            return ELF::R_AARCH64_ABS16;
        case FK_Data_4:
            return ELF::R_AARCH64_ABS32;
        case FK_Data_8:
            return ELF::R_AARCH64_ABS64;
        case AArch64::fixup_aarch64_add_imm12:
            if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
                return ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12;
            if (RefKind == AArch64MCExpr::VK_TPREL_HI12)
                return ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12;
            if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC)
                return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC;
            if (RefKind == AArch64MCExpr::VK_DTPREL_LO12)
                return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12;
            if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC)
                return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC;
            if (RefKind == AArch64MCExpr::VK_TPREL_LO12)
                return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12;
            if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
                return ELF::R_AARCH64_TLSDESC_ADD_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
                return ELF::R_AARCH64_ADD_ABS_LO12_NC;

            Ctx.reportError(Fixup.getLoc(),
                            "invalid fixup for add (uimm12) instruction");
            return ELF::R_AARCH64_NONE;
        case AArch64::fixup_aarch64_ldst_imm12_scale1:
            if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
                return ELF::R_AARCH64_LDST8_ABS_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
                return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12;
            if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
                return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
                return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12;
            if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
                return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC;

            Ctx.reportError(Fixup.getLoc(),
                            "invalid fixup for 8-bit load/store instruction");
            return ELF::R_AARCH64_NONE;
        case AArch64::fixup_aarch64_ldst_imm12_scale2:
            if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
                return ELF::R_AARCH64_LDST16_ABS_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
                return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12;
            if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
                return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
                return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12;
            if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
                return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC;

            Ctx.reportError(Fixup.getLoc(),
                            "invalid fixup for 16-bit load/store instruction");
            return ELF::R_AARCH64_NONE;
        case AArch64::fixup_aarch64_ldst_imm12_scale4:
            if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
                return ELF::R_AARCH64_LDST32_ABS_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
                return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12;
            if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
                return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
                return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12;
            if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
                return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC;

            Ctx.reportError(Fixup.getLoc(),
                            "invalid fixup for 32-bit load/store instruction");
            return ELF::R_AARCH64_NONE;
        case AArch64::fixup_aarch64_ldst_imm12_scale8:
            if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
                return ELF::R_AARCH64_LDST64_ABS_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_GOT && IsNC)
                return ELF::R_AARCH64_LD64_GOT_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
                return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12;
            if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
                return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
                return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12;
            if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
                return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC)
                return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
            if (SymLoc == AArch64MCExpr::VK_TLSDESC && IsNC)
                return ELF::R_AARCH64_TLSDESC_LD64_LO12_NC;

            Ctx.reportError(Fixup.getLoc(),
                            "invalid fixup for 64-bit load/store instruction");
            return ELF::R_AARCH64_NONE;
        case AArch64::fixup_aarch64_ldst_imm12_scale16:
            if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
                return ELF::R_AARCH64_LDST128_ABS_LO12_NC;

            Ctx.reportError(Fixup.getLoc(),
                            "invalid fixup for 128-bit load/store instruction");
            return ELF::R_AARCH64_NONE;
        case AArch64::fixup_aarch64_movw:
            if (RefKind == AArch64MCExpr::VK_ABS_G3)
                return ELF::R_AARCH64_MOVW_UABS_G3;
            if (RefKind == AArch64MCExpr::VK_ABS_G2)
                return ELF::R_AARCH64_MOVW_UABS_G2;
            if (RefKind == AArch64MCExpr::VK_ABS_G2_S)
                return ELF::R_AARCH64_MOVW_SABS_G2;
            if (RefKind == AArch64MCExpr::VK_ABS_G2_NC)
                return ELF::R_AARCH64_MOVW_UABS_G2_NC;
            if (RefKind == AArch64MCExpr::VK_ABS_G1)
                return ELF::R_AARCH64_MOVW_UABS_G1;
            if (RefKind == AArch64MCExpr::VK_ABS_G1_S)
                return ELF::R_AARCH64_MOVW_SABS_G1;
            if (RefKind == AArch64MCExpr::VK_ABS_G1_NC)
                return ELF::R_AARCH64_MOVW_UABS_G1_NC;
            if (RefKind == AArch64MCExpr::VK_ABS_G0)
                return ELF::R_AARCH64_MOVW_UABS_G0;
            if (RefKind == AArch64MCExpr::VK_ABS_G0_S)
                return ELF::R_AARCH64_MOVW_SABS_G0;
            if (RefKind == AArch64MCExpr::VK_ABS_G0_NC)
                return ELF::R_AARCH64_MOVW_UABS_G0_NC;
            if (RefKind == AArch64MCExpr::VK_DTPREL_G2)
                return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
            if (RefKind == AArch64MCExpr::VK_DTPREL_G1)
                return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1;
            if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC)
                return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
            if (RefKind == AArch64MCExpr::VK_DTPREL_G0)
                return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0;
            if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC)
                return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC;
            if (RefKind == AArch64MCExpr::VK_TPREL_G2)
                return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
            if (RefKind == AArch64MCExpr::VK_TPREL_G1)
                return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1;
            if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC)
                return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
            if (RefKind == AArch64MCExpr::VK_TPREL_G0)
                return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0;
            if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC)
                return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC;
            if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1)
                return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
            if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC)
                return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
            Ctx.reportError(Fixup.getLoc(),
                            "invalid fixup for movz/movk instruction");
            return ELF::R_AARCH64_NONE;
        case AArch64::fixup_aarch64_tlsdesc_call:
            return ELF::R_AARCH64_TLSDESC_CALL;
        default:
            Ctx.reportError(Fixup.getLoc(), "Unknown ELF relocation type");
            return ELF::R_AARCH64_NONE;
        }
    }

    llvm_unreachable("Unimplemented fixup -> relocation");
}
コード例 #16
0
void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
                                           const MCAsmLayout &Layout,
                                           const MCFragment *Fragment,
                                           const MCFixup &Fixup,
                                           MCValue Target,
                                           uint64_t &FixedValue) {
  assert(Target.getSymA() != NULL && "Relocation must reference a symbol!");

  const MCSymbol &Symbol = Target.getSymA()->getSymbol();
  const MCSymbol &A = Symbol.AliasedSymbol();
  if (!Asm.hasSymbolData(A))
    Asm.getContext().FatalError(
        Fixup.getLoc(),
        Twine("symbol '") + A.getName() + "' can not be undefined");

  MCSymbolData &A_SD = Asm.getSymbolData(A);

  MCSectionData const *SectionData = Fragment->getParent();

  // Mark this symbol as requiring an entry in the symbol table.
  assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() &&
         "Section must already have been defined in ExecutePostLayoutBinding!");
  assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() &&
         "Symbol must already have been defined in ExecutePostLayoutBinding!");

  COFFSection *coff_section = SectionMap[&SectionData->getSection()];
  COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()];
  const MCSymbolRefExpr *SymB = Target.getSymB();
  bool CrossSection = false;

  if (SymB) {
    const MCSymbol *B = &SymB->getSymbol();
    MCSymbolData &B_SD = Asm.getSymbolData(*B);
    if (!B_SD.getFragment())
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          Twine("symbol '") + B->getName() +
              "' can not be undefined in a subtraction expression");

    if (!A_SD.getFragment())
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          Twine("symbol '") + Symbol.getName() +
              "' can not be undefined in a subtraction expression");

    CrossSection = &Symbol.getSection() != &B->getSection();

    // Offset of the symbol in the section
    int64_t a = Layout.getSymbolOffset(&B_SD);

    // Ofeset of the relocation in the section
    int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();

    FixedValue = b - a;
    // In the case where we have SymbA and SymB, we just need to store the delta
    // between the two symbols.  Update FixedValue to account for the delta, and
    // skip recording the relocation.
    if (!CrossSection)
      return;
  } else {
    FixedValue = Target.getConstant();
  }

  COFFRelocation Reloc;

  Reloc.Data.SymbolTableIndex = 0;
  Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);

  // Turn relocations for temporary symbols into section relocations.
  if (coff_symbol->MCData->getSymbol().isTemporary() || CrossSection) {
    Reloc.Symb = coff_symbol->Section->Symbol;
    FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment)
                + coff_symbol->MCData->getOffset();
  } else
    Reloc.Symb = coff_symbol;

  ++Reloc.Symb->Relocations;

  Reloc.Data.VirtualAddress += Fixup.getOffset();
  Reloc.Data.Type = TargetObjectWriter->getRelocType(Target, Fixup,
                                                     CrossSection);

  // FIXME: Can anyone explain what this does other than adjust for the size
  // of the offset?
  if (Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32 ||
      Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32)
    FixedValue += 4;

  coff_section->Relocations.push_back(Reloc);
}
コード例 #17
0
void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
                                           const MCAsmLayout &Layout,
                                           const MCFragment *Fragment,
                                           const MCFixup &Fixup,
                                           MCValue Target,
                                           bool &IsPCRel,
                                           uint64_t &FixedValue) {
  assert(Target.getSymA() && "Relocation must reference a symbol!");

  const MCSymbol &Symbol = Target.getSymA()->getSymbol();
  const MCSymbol &A = Symbol.AliasedSymbol();
  if (!Asm.hasSymbolData(A))
    Asm.getContext().FatalError(
        Fixup.getLoc(),
        Twine("symbol '") + A.getName() + "' can not be undefined");

  const MCSymbolData &A_SD = Asm.getSymbolData(A);

  MCSectionData const *SectionData = Fragment->getParent();

  // Mark this symbol as requiring an entry in the symbol table.
  assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() &&
         "Section must already have been defined in ExecutePostLayoutBinding!");
  assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() &&
         "Symbol must already have been defined in ExecutePostLayoutBinding!");

  COFFSection *coff_section = SectionMap[&SectionData->getSection()];
  COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()];
  const MCSymbolRefExpr *SymB = Target.getSymB();
  bool CrossSection = false;

  if (SymB) {
    const MCSymbol *B = &SymB->getSymbol();
    const MCSymbolData &B_SD = Asm.getSymbolData(*B);
    if (!B_SD.getFragment())
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          Twine("symbol '") + B->getName() +
              "' can not be undefined in a subtraction expression");

    if (!A_SD.getFragment())
      Asm.getContext().FatalError(
          Fixup.getLoc(),
          Twine("symbol '") + Symbol.getName() +
              "' can not be undefined in a subtraction expression");

    CrossSection = &Symbol.getSection() != &B->getSection();

    // Offset of the symbol in the section
    int64_t a = Layout.getSymbolOffset(&B_SD);

    // Ofeset of the relocation in the section
    int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();

    FixedValue = b - a;
    // In the case where we have SymbA and SymB, we just need to store the delta
    // between the two symbols.  Update FixedValue to account for the delta, and
    // skip recording the relocation.
    if (!CrossSection)
      return;
  } else {
    FixedValue = Target.getConstant();
  }

  COFFRelocation Reloc;

  Reloc.Data.SymbolTableIndex = 0;
  Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);

  // Turn relocations for temporary symbols into section relocations.
  if (coff_symbol->MCData->getSymbol().isTemporary() || CrossSection) {
    Reloc.Symb = coff_symbol->Section->Symbol;
    FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment)
                + coff_symbol->MCData->getOffset();
  } else
    Reloc.Symb = coff_symbol;

  ++Reloc.Symb->Relocations;

  Reloc.Data.VirtualAddress += Fixup.getOffset();
  Reloc.Data.Type = TargetObjectWriter->getRelocType(Target, Fixup,
                                                     CrossSection);

  // FIXME: Can anyone explain what this does other than adjust for the size
  // of the offset?
  if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 &&
       Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) ||
      (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 &&
       Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32))
    FixedValue += 4;

  if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) {
    switch (Reloc.Data.Type) {
    case COFF::IMAGE_REL_ARM_ABSOLUTE:
    case COFF::IMAGE_REL_ARM_ADDR32:
    case COFF::IMAGE_REL_ARM_ADDR32NB:
    case COFF::IMAGE_REL_ARM_TOKEN:
    case COFF::IMAGE_REL_ARM_SECTION:
    case COFF::IMAGE_REL_ARM_SECREL:
      break;
    case COFF::IMAGE_REL_ARM_BRANCH11:
    case COFF::IMAGE_REL_ARM_BLX11:
      // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for
      // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid
      // for Windows CE).
    case COFF::IMAGE_REL_ARM_BRANCH24:
    case COFF::IMAGE_REL_ARM_BLX24:
    case COFF::IMAGE_REL_ARM_MOV32A:
      // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are
      // only used for ARM mode code, which is documented as being unsupported
      // by Windows on ARM.  Emperical proof indicates that masm is able to
      // generate the relocations however the rest of the MSVC toolchain is
      // unable to handle it.
      llvm_unreachable("unsupported relocation");
      break;
    case COFF::IMAGE_REL_ARM_MOV32T:
      break;
    case COFF::IMAGE_REL_ARM_BRANCH20T:
    case COFF::IMAGE_REL_ARM_BRANCH24T:
    case COFF::IMAGE_REL_ARM_BLX23T:
      // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all
      // perform a 4 byte adjustment to the relocation.  Relative branches are
      // offset by 4 on ARM, however, because there is no RELA relocations, all
      // branches are offset by 4.
      FixedValue = FixedValue + 4;
      break;
    }
  }

  coff_section->Relocations.push_back(Reloc);
}
コード例 #18
0
ファイル: AArch64ELFObjectWriter.cpp プロジェクト: ralic/llvm
// assumes IsILP32 is true
static bool isNonILP32reloc(const MCFixup &Fixup,
                            AArch64MCExpr::VariantKind RefKind,
                            MCContext &Ctx) {
  if ((unsigned)Fixup.getKind() != AArch64::fixup_aarch64_movw)
    return false;
  switch(RefKind) {
    case AArch64MCExpr::VK_ABS_G3:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G3));
      return true;
    case AArch64MCExpr::VK_ABS_G2:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2));
      return true;
    case AArch64MCExpr::VK_ABS_G2_S:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G2));
      return true;
    case AArch64MCExpr::VK_ABS_G2_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2_NC));
      return true;
    case AArch64MCExpr::VK_ABS_G1_S:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G1));
      return true;
    case AArch64MCExpr::VK_ABS_G1_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G1_NC));
      return true;
    case AArch64MCExpr::VK_DTPREL_G2:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G2));
      return true;
    case AArch64MCExpr::VK_DTPREL_G1_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G1_NC));
      return true;
    case AArch64MCExpr::VK_TPREL_G2:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G2));
      return true;
    case AArch64MCExpr::VK_TPREL_G1_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G1_NC));
      return true;
    case AArch64MCExpr::VK_GOTTPREL_G1:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G1));
      return true;
    case AArch64MCExpr::VK_GOTTPREL_G0_NC:
      Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G0_NC));
      return true;
    default: return false;
  }
  return false;
}
コード例 #19
0
ファイル: X86MachObjectWriter.cpp プロジェクト: traiansf/llvm
void X86MachObjectWriter::RecordX86_64Relocation(
    MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout,
    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
    uint64_t &FixedValue) {
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());

  // See <reloc.h>.
  uint32_t FixupOffset =
    Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  uint32_t FixupAddress =
    Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
  int64_t Value = 0;
  unsigned Index = 0;
  unsigned IsExtern = 0;
  unsigned Type = 0;
  const MCSymbol *RelSymbol = nullptr;

  Value = Target.getConstant();

  if (IsPCRel) {
    // Compensate for the relocation offset, Darwin x86_64 relocations only have
    // the addend and appear to have attempted to define it to be the actual
    // expression addend without the PCrel bias. However, instructions with data
    // following the relocation are not accommodated for (see comment below
    // regarding SIGNED{1,2,4}), so it isn't exactly that either.
    Value += 1LL << Log2Size;
  }

  if (Target.isAbsolute()) { // constant
    // SymbolNum of 0 indicates the absolute section.
    Type = MachO::X86_64_RELOC_UNSIGNED;

    // FIXME: I believe this is broken, I don't think the linker can understand
    // it. I think it would require a local relocation, but I'm not sure if that
    // would work either. The official way to get an absolute PCrel relocation
    // is to use an absolute symbol (which we don't support yet).
    if (IsPCRel) {
      IsExtern = 1;
      Type = MachO::X86_64_RELOC_BRANCH;
    }
  } else if (Target.getSymB()) { // A - B + constant
    const MCSymbol *A = &Target.getSymA()->getSymbol();
    if (A->isTemporary())
      A = &Writer->findAliasedSymbol(*A);
    const MCSymbolData &A_SD = Asm.getSymbolData(*A);
    const MCSymbol *A_Base = Asm.getAtom(&A_SD);

    const MCSymbol *B = &Target.getSymB()->getSymbol();
    if (B->isTemporary())
      B = &Writer->findAliasedSymbol(*B);
    const MCSymbolData &B_SD = Asm.getSymbolData(*B);
    const MCSymbol *B_Base = Asm.getAtom(&B_SD);

    // Neither symbol can be modified.
    if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
        Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
      report_fatal_error("unsupported relocation of modified symbol", false);

    // We don't support PCrel relocations of differences. Darwin 'as' doesn't
    // implement most of these correctly.
    if (IsPCRel)
      report_fatal_error("unsupported pc-relative relocation of difference",
                         false);

    // The support for the situation where one or both of the symbols would
    // require a local relocation is handled just like if the symbols were
    // external.  This is certainly used in the case of debug sections where the
    // section has only temporary symbols and thus the symbols don't have base
    // symbols.  This is encoded using the section ordinal and non-extern
    // relocation entries.

    // Darwin 'as' doesn't emit correct relocations for this (it ends up with a
    // single SIGNED relocation); reject it for now.  Except the case where both
    // symbols don't have a base, equal but both NULL.
    if (A_Base == B_Base && A_Base)
      report_fatal_error("unsupported relocation with identical base", false);

    // A subtraction expression where either symbol is undefined is a
    // non-relocatable expression.
    if (A->isUndefined() || B->isUndefined()) {
      StringRef Name = A->isUndefined() ? A->getName() : B->getName();
      Asm.getContext().FatalError(Fixup.getLoc(),
        "unsupported relocation with subtraction expression, symbol '" +
        Name + "' can not be undefined in a subtraction expression");
    }

    Value +=
        Writer->getSymbolAddress(&A_SD, Layout) -
        (!A_Base ? 0 : Writer->getSymbolAddress(&A_Base->getData(), Layout));
    Value -=
        Writer->getSymbolAddress(&B_SD, Layout) -
        (!B_Base ? 0 : Writer->getSymbolAddress(&B_Base->getData(), Layout));

    if (!A_Base)
      Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
    Type = MachO::X86_64_RELOC_UNSIGNED;

    MachO::any_relocation_info MRE;
    MRE.r_word0 = FixupOffset;
    MRE.r_word1 =
        (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
    Writer->addRelocation(A_Base, Fragment->getParent(), MRE);

    if (B_Base)
      RelSymbol = B_Base;
    else
      Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
    Type = MachO::X86_64_RELOC_SUBTRACTOR;
  } else {
    const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
    if (Symbol->isTemporary() && Value) {
      const MCSection &Sec = Symbol->getSection();
      if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec))
        Asm.addLocalUsedInReloc(*Symbol);
    }
    const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
    RelSymbol = Asm.getAtom(&SD);

    // Relocations inside debug sections always use local relocations when
    // possible. This seems to be done because the debugger doesn't fully
    // understand x86_64 relocation entries, and expects to find values that
    // have already been fixed up.
    if (Symbol->isInSection()) {
      const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
        Fragment->getParent()->getSection());
      if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
        RelSymbol = nullptr;
    }

    // x86_64 almost always uses external relocations, except when there is no
    // symbol to use as a base address (a local symbol with no preceding
    // non-local symbol).
    if (RelSymbol) {
      // Add the local offset, if needed.
      if (&RelSymbol->getData() != &SD)
        Value += Layout.getSymbolOffset(&SD) -
                 Layout.getSymbolOffset(&RelSymbol->getData());
    } else if (Symbol->isInSection() && !Symbol->isVariable()) {
      // The index is the section ordinal (1-based).
      Index = SD.getFragment()->getParent()->getOrdinal() + 1;
      Value += Writer->getSymbolAddress(&SD, Layout);

      if (IsPCRel)
        Value -= FixupAddress + (1 << Log2Size);
    } else if (Symbol->isVariable()) {
      const MCExpr *Value = Symbol->getVariableValue();
      int64_t Res;
      bool isAbs = Value->EvaluateAsAbsolute(Res, Layout,
                                             Writer->getSectionAddressMap());
      if (isAbs) {
        FixedValue = Res;
        return;
      } else {
        report_fatal_error("unsupported relocation of variable '" +
                           Symbol->getName() + "'", false);
      }
    } else {
      report_fatal_error("unsupported relocation of undefined symbol '" +
                         Symbol->getName() + "'", false);
    }

    MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
    if (IsPCRel) {
      if (IsRIPRel) {
        if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
          // x86_64 distinguishes movq foo@GOTPCREL so that the linker can
          // rewrite the movq to an leaq at link time if the symbol ends up in
          // the same linkage unit.
          if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load)
            Type = MachO::X86_64_RELOC_GOT_LOAD;
          else
            Type = MachO::X86_64_RELOC_GOT;
        }  else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
          Type = MachO::X86_64_RELOC_TLV;
        }  else if (Modifier != MCSymbolRefExpr::VK_None) {
          report_fatal_error("unsupported symbol modifier in relocation",
                             false);
        } else {
          Type = MachO::X86_64_RELOC_SIGNED;

          // The Darwin x86_64 relocation format has a problem where it cannot
          // encode an address (L<foo> + <constant>) which is outside the atom
          // containing L<foo>. Generally, this shouldn't occur but it does
          // happen when we have a RIPrel instruction with data following the
          // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
          // adjustment Darwin x86_64 uses, the offset is still negative and the
          // linker has no way to recognize this.
          //
          // To work around this, Darwin uses several special relocation types
          // to indicate the offsets. However, the specification or
          // implementation of these seems to also be incomplete; they should
          // adjust the addend as well based on the actual encoded instruction
          // (the additional bias), but instead appear to just look at the final
          // offset.
          switch (-(Target.getConstant() + (1LL << Log2Size))) {
          case 1: Type = MachO::X86_64_RELOC_SIGNED_1; break;
          case 2: Type = MachO::X86_64_RELOC_SIGNED_2; break;
          case 4: Type = MachO::X86_64_RELOC_SIGNED_4; break;
          }
        }
      } else {
        if (Modifier != MCSymbolRefExpr::VK_None)
          report_fatal_error("unsupported symbol modifier in branch "
                             "relocation", false);

        Type = MachO::X86_64_RELOC_BRANCH;
      }
    } else {
      if (Modifier == MCSymbolRefExpr::VK_GOT) {
        Type = MachO::X86_64_RELOC_GOT;
      } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
        // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which
        // case all we do is set the PCrel bit in the relocation entry; this is
        // used with exception handling, for example. The source is required to
        // include any necessary offset directly.
        Type = MachO::X86_64_RELOC_GOT;
        IsPCRel = 1;
      } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
        report_fatal_error("TLVP symbol modifier should have been rip-rel",
                           false);
      } else if (Modifier != MCSymbolRefExpr::VK_None)
        report_fatal_error("unsupported symbol modifier in relocation", false);
      else {
        Type = MachO::X86_64_RELOC_UNSIGNED;
        unsigned Kind = Fixup.getKind();
        if (Kind == X86::reloc_signed_4byte)
          report_fatal_error("32-bit absolute addressing is not supported in "
                             "64-bit mode", false);
      }
    }
  }

  // x86_64 always writes custom values into the fixups.
  FixedValue = Value;

  // struct relocation_info (8 bytes)
  MachO::any_relocation_info MRE;
  MRE.r_word0 = FixupOffset;
  MRE.r_word1 = (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
                (IsExtern << 27) | (Type << 28);
  Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
}
コード例 #20
0
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
                                 MCContext *Ctx) {
  unsigned Kind = Fixup.getKind();
  int64_t SignedValue = static_cast<int64_t>(Value);
  switch (Kind) {
  default:
    llvm_unreachable("Unknown fixup kind!");
  case AArch64::fixup_aarch64_pcrel_adr_imm21:
    if (Ctx && (SignedValue > 2097151 || SignedValue < -2097152))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    return AdrImmBits(Value & 0x1fffffULL);
  case AArch64::fixup_aarch64_pcrel_adrp_imm21:
    return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
  case AArch64::fixup_aarch64_ldr_pcrel_imm19:
  case AArch64::fixup_aarch64_pcrel_branch19:
    // Signed 21-bit immediate
    if (SignedValue > 2097151 || SignedValue < -2097152)
      if (Ctx) Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0x3))
      Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
    // Low two bits are not encoded.
    return (Value >> 2) & 0x7ffff;
  case AArch64::fixup_aarch64_add_imm12:
  case AArch64::fixup_aarch64_ldst_imm12_scale1:
    // Unsigned 12-bit immediate
    if (Ctx && Value >= 0x1000)
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    return Value;
  case AArch64::fixup_aarch64_ldst_imm12_scale2:
    // Unsigned 12-bit immediate which gets multiplied by 2
    if (Ctx && (Value >= 0x2000))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0x1))
      Ctx->reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
    return Value >> 1;
  case AArch64::fixup_aarch64_ldst_imm12_scale4:
    // Unsigned 12-bit immediate which gets multiplied by 4
    if (Ctx && (Value >= 0x4000))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0x3))
      Ctx->reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
    return Value >> 2;
  case AArch64::fixup_aarch64_ldst_imm12_scale8:
    // Unsigned 12-bit immediate which gets multiplied by 8
    if (Ctx && (Value >= 0x8000))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0x7))
      Ctx->reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
    return Value >> 3;
  case AArch64::fixup_aarch64_ldst_imm12_scale16:
    // Unsigned 12-bit immediate which gets multiplied by 16
    if (Ctx && (Value >= 0x10000))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    if (Ctx && (Value & 0xf))
      Ctx->reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
    return Value >> 4;
  case AArch64::fixup_aarch64_movw:
    if (Ctx)
      Ctx->reportError(Fixup.getLoc(),
                       "no resolvable MOVZ/MOVK fixups supported yet");
    return Value;
  case AArch64::fixup_aarch64_pcrel_branch14:
    // Signed 16-bit immediate
    if (Ctx && (SignedValue > 32767 || SignedValue < -32768))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    // Low two bits are not encoded (4-byte alignment assumed).
    if (Ctx && (Value & 0x3))
      Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
    return (Value >> 2) & 0x3fff;
  case AArch64::fixup_aarch64_pcrel_branch26:
  case AArch64::fixup_aarch64_pcrel_call26:
    // Signed 28-bit immediate
    if (Ctx && (SignedValue > 134217727 || SignedValue < -134217728))
      Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
    // Low two bits are not encoded (4-byte alignment assumed).
    if (Ctx && (Value & 0x3))
      Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
    return (Value >> 2) & 0x3ffffff;
  case FK_Data_1:
  case FK_Data_2:
  case FK_Data_4:
  case FK_Data_8:
    return Value;
  }
}