コード例 #1
0
unsigned Cpu0ELFObjectWriter::GetRelocType(const MCValue &Target,
                                           const MCFixup &Fixup,
                                           bool IsPCRel) const {
  // determine the type of the relocation
  unsigned Type = (unsigned)ELF::R_CPU0_NONE;
  unsigned Kind = (unsigned)Fixup.getKind();

  switch (Kind) {
  default:
    llvm_unreachable("invalid fixup kind!");
  case FK_Data_4:
    Type = ELF::R_CPU0_32;
    break;
  case FK_GPRel_4:
    Type = ELF::R_CPU0_GPREL32;
    break;
  case Cpu0::fixup_Cpu0_24:
    Type = ELF::R_CPU0_24;
    break;
  case Cpu0::fixup_Cpu0_32:
    Type = ELF::R_CPU0_32;
    break;
  case Cpu0::fixup_Cpu0_HI16:
    Type = ELF::R_CPU0_HI16;
    break;
  case Cpu0::fixup_Cpu0_LO16:
    Type = ELF::R_CPU0_LO16;
    break;
  case Cpu0::fixup_Cpu0_GPREL16:
    Type = ELF::R_CPU0_GPREL16;
    break;
  case Cpu0::fixup_Cpu0_GOT_Global:
  case Cpu0::fixup_Cpu0_GOT_Local:
    Type = ELF::R_CPU0_GOT16;
    break;
  case Cpu0::fixup_Cpu0_PC16:
    Type = ELF::R_CPU0_PC16;
    break;
  case Cpu0::fixup_Cpu0_PC24:
    Type = ELF::R_CPU0_PC24;
    break;
  case Cpu0::fixup_Cpu0_GOT_HI16:
    Type = ELF::R_CPU0_GOT_HI16;
    break;
  case Cpu0::fixup_Cpu0_GOT_LO16:
    Type = ELF::R_CPU0_GOT_LO16;
    break;
  }

  return Type;
}
コード例 #2
0
ファイル: AMDGPUAsmBackend.cpp プロジェクト: alex-t/llvm
void AMDGPUAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
                                  const MCValue &Target,
                                  MutableArrayRef<char> Data, uint64_t Value,
                                  bool IsResolved,
                                  const MCSubtargetInfo *STI) const {
  Value = adjustFixupValue(Fixup, Value, &Asm.getContext());
  if (!Value)
    return; // Doesn't change encoding.

  MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());

  // Shift the value into position.
  Value <<= Info.TargetOffset;

  unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
  uint32_t Offset = Fixup.getOffset();
  assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");

  // For each byte of the fragment that the fixup touches, mask in the bits from
  // the fixup value.
  for (unsigned i = 0; i != NumBytes; ++i)
    Data[Offset + i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
}
コード例 #3
0
void AArch64AsmBackend::processFixupValue(const MCAssembler &Asm,
                                          const MCAsmLayout &Layout,
                                          const MCFixup &Fixup,
                                          const MCFragment *DF,
                                          MCValue &Target, uint64_t &Value,
                                          bool &IsResolved) {
  // The ADRP instruction adds some multiple of 0x1000 to the current PC &
  // ~0xfff. This means that the required offset to reach a symbol can vary by
  // up to one step depending on where the ADRP is in memory. For example:
  //
  //     ADRP x0, there
  //  there:
  //
  // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and
  // we'll need that as an offset. At any other address "there" will be in the
  // same page as the ADRP and the instruction should encode 0x0. Assuming the
  // section isn't 0x1000-aligned, we therefore need to delegate this decision
  // to the linker -- a relocation!
  if ((uint32_t)Fixup.getKind() == AArch64::fixup_a64_adr_prel_page ||
      (uint32_t)Fixup.getKind() == AArch64::fixup_a64_adr_prel_got_page ||
      (uint32_t)Fixup.getKind() == AArch64::fixup_a64_adr_gottprel_page ||
      (uint32_t)Fixup.getKind() == AArch64::fixup_a64_tlsdesc_adr_page)
    IsResolved = false;
}
コード例 #4
0
ファイル: SystemZMCAsmBackend.cpp プロジェクト: rui314/llvm
void SystemZMCAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
                                     unsigned DataSize, uint64_t Value) const {
  MCFixupKind Kind = Fixup.getKind();
  unsigned Offset = Fixup.getOffset();
  unsigned Size = (getFixupKindInfo(Kind).TargetSize + 7) / 8;

  assert(Offset + Size <= DataSize && "Invalid fixup offset!");

  // Big-endian insertion of Size bytes.
  Value = extractBitsForFixup(Kind, Value);
  unsigned ShiftValue = (Size * 8) - 8;
  for (unsigned I = 0; I != Size; ++I) {
    Data[Offset + I] |= uint8_t(Value >> ShiftValue);
    ShiftValue -= 8;
  }
}
コード例 #5
0
ファイル: X86MachObjectWriter.cpp プロジェクト: Drup/llvm
void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer,
                                               const MCAssembler &Asm,
                                               const MCAsmLayout &Layout,
                                               const MCFragment *Fragment,
                                               const MCFixup &Fixup,
                                               MCValue Target,
                                               uint64_t &FixedValue) {
  assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&
         !is64Bit() &&
         "Should only be called with a 32-bit TLVP relocation!");

  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
  uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
  unsigned IsPCRel = 0;

  // Get the symbol data.
  const MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol());
  unsigned Index = SD_A->getIndex();

  // We're only going to have a second symbol in pic mode and it'll be a
  // subtraction from the picbase. For 32-bit pic the addend is the difference
  // between the picbase and the next address.  For 32-bit static the addend is
  // zero.
  if (Target.getSymB()) {
    // If this is a subtraction then we're pcrel.
    uint32_t FixupAddress =
      Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
    const MCSymbolData *SD_B =
        &Asm.getSymbolData(Target.getSymB()->getSymbol());
    IsPCRel = 1;
    FixedValue = (FixupAddress - Writer->getSymbolAddress(SD_B, Layout) +
                  Target.getConstant());
    FixedValue += 1ULL << Log2Size;
  } else {
    FixedValue = 0;
  }

  // struct relocation_info (8 bytes)
  MachO::any_relocation_info MRE;
  MRE.r_word0 = Value;
  MRE.r_word1 = ((Index                    <<  0) |
                 (IsPCRel                  << 24) |
                 (Log2Size                 << 25) |
                 (1                        << 27) | // r_extern
                 (MachO::GENERIC_RELOC_TLV << 28)); // r_type
  Writer->addRelocation(Fragment->getParent(), MRE);
}
コード例 #6
0
// assumes IsILP32 is true
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 ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_ABS_G2_NC:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2_NC));
        return ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_ABS_G1_S:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G1));
        return ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_ABS_G1_NC:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G1_NC));
        return ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_DTPREL_G2:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G2));
        return ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_DTPREL_G1_NC:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G1_NC));
        return ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_TPREL_G2:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G2));
        return ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_TPREL_G1_NC:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G1_NC));
        return ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_GOTTPREL_G1:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G1));
        return ELF::R_AARCH64_NONE;
    case AArch64MCExpr::VK_GOTTPREL_G0_NC:
        Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G0_NC));
        return ELF::R_AARCH64_NONE;
    default:
        return false;
    }
    return false;
}
コード例 #7
0
unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
                                          const MCFixup &Fixup,
                                          bool IsPCRel) const {
  // determine the type of the relocation
  switch ((unsigned)Fixup.getKind()) {
  default:
    llvm_unreachable("invalid fixup kind!");
  case FK_SecRel_8:
    return ELF::R_X86_64_64;
  case FK_SecRel_4:
    return ELF::R_X86_64_PC32;
  case FK_Data_8:
    return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64;
  case FK_Data_4:
    return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32;
  }
}
コード例 #8
0
std::pair<uint64_t, bool> MCAssembler::handleFixup(const MCAsmLayout &Layout,
                                                   MCFragment &F,
                                                   const MCFixup &Fixup) {
  // Evaluate the fixup.
  MCValue Target;
  uint64_t FixedValue;
  bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
                 MCFixupKindInfo::FKF_IsPCRel;
  if (!evaluateFixup(Layout, Fixup, &F, Target, FixedValue)) {
    // The fixup was unresolved, we need a relocation. Inform the object
    // writer of the relocation, and give it an opportunity to adjust the
    // fixup value if need be.
    getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, IsPCRel,
                                 FixedValue);
  }
  return std::make_pair(FixedValue, IsPCRel);
}
コード例 #9
0
unsigned SystemZObjectWriter::getRelocType(MCContext &Ctx,
                                           const MCValue &Target,
                                           const MCFixup &Fixup,
                                           bool IsPCRel) const {
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
  unsigned Kind = Fixup.getKind();
  switch (Modifier) {
  case MCSymbolRefExpr::VK_None:
    if (IsPCRel)
      return getPCRelReloc(Kind);
    return getAbsoluteReloc(Kind);

  case MCSymbolRefExpr::VK_NTPOFF:
    assert(!IsPCRel && "NTPOFF shouldn't be PC-relative");
    return getTLSLEReloc(Kind);

  case MCSymbolRefExpr::VK_INDNTPOFF:
    if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
      return ELF::R_390_TLS_IEENT;
    llvm_unreachable("Only PC-relative INDNTPOFF accesses are supported for now");

  case MCSymbolRefExpr::VK_DTPOFF:
    assert(!IsPCRel && "DTPOFF shouldn't be PC-relative");
    return getTLSLDOReloc(Kind);

  case MCSymbolRefExpr::VK_TLSLDM:
    assert(!IsPCRel && "TLSLDM shouldn't be PC-relative");
    return getTLSLDMReloc(Kind);

  case MCSymbolRefExpr::VK_TLSGD:
    assert(!IsPCRel && "TLSGD shouldn't be PC-relative");
    return getTLSGDReloc(Kind);

  case MCSymbolRefExpr::VK_GOT:
    if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL)
      return ELF::R_390_GOTENT;
    llvm_unreachable("Only PC-relative GOT accesses are supported for now");

  case MCSymbolRefExpr::VK_PLT:
    assert(IsPCRel && "@PLT shouldt be PC-relative");
    return getPLTReloc(Kind);

  default:
    llvm_unreachable("Modifier not supported");
  }
}
コード例 #10
0
unsigned AMDGPUELFObjectWriter::getRelocType(MCContext &Ctx,
                                             const MCValue &Target,
                                             const MCFixup &Fixup,
                                             bool IsPCRel) const {
  // SCRATCH_RSRC_DWORD[01] is a special global variable that represents
  // the scratch buffer.
  if (Target.getSymA()->getSymbol().getName() == "SCRATCH_RSRC_DWORD0")
    return ELF::R_AMDGPU_ABS32_LO;
  if (Target.getSymA()->getSymbol().getName() == "SCRATCH_RSRC_DWORD1")
    return ELF::R_AMDGPU_ABS32_HI;

  switch (Fixup.getKind()) {
  default: break;
  case FK_PCRel_4:
    return ELF::R_AMDGPU_REL32;
  }

  llvm_unreachable("unhandled relocation type");
}
コード例 #11
0
unsigned SampleELFObjectWriter::
GetRelocType(const MCValue &Target,
             const MCFixup &Fixup,
             bool IsPCRel,
             bool IsRelocWithSymbol,
             int64_t Addend) const {
  // determine the type of the relocation
  unsigned Type = (unsigned)ELF::R_MIPS_NONE;
  unsigned Kind = (unsigned)Fixup.getKind();

  switch (Kind) {
  default:
    llvm_unreachable("invalid fixup kind!");
  case Sample::fixup_Sample_24:
    Type = ELF::R_MIPS_26;
    break;
  }

  return Type;
}
コード例 #12
0
unsigned LEGELFObjectWriter::GetRelocType(const MCValue &Target,
                                          const MCFixup &Fixup,
                                          bool IsPCRel) const {
  if (!IsPCRel) {
    llvm_unreachable("Only dealying with PC-relative fixups for now");
  }

  unsigned Type = 0;
  switch ((unsigned)Fixup.getKind()) {
  default:
    llvm_unreachable("Unimplemented");
  case LEG::fixup_leg_mov_hi16_pcrel:
    Type = ELF::R_ARM_MOVT_PREL;
    break;
  case LEG::fixup_leg_mov_lo16_pcrel:
    Type = ELF::R_ARM_MOVW_PREL_NC;
    break;
  }
  return Type;
}
コード例 #13
0
bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
                                         uint64_t Value,
                                         const MCRelaxableFragment *DF,
                                         const MCAsmLayout &Layout) const {
  switch ((unsigned)Fixup.getKind()) {
  case ARM::fixup_arm_thumb_br: {
    // Relaxing tB to t2B. tB has a signed 12-bit displacement with the
    // low bit being an implied zero. There's an implied +4 offset for the
    // branch, so we adjust the other way here to determine what's
    // encodable.
    //
    // Relax if the value is too big for a (signed) i8.
    int64_t Offset = int64_t(Value) - 4;
    return Offset > 2046 || Offset < -2048;
  }
  case ARM::fixup_arm_thumb_bcc: {
    // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the
    // low bit being an implied zero. There's an implied +4 offset for the
    // branch, so we adjust the other way here to determine what's
    // encodable.
    //
    // Relax if the value is too big for a (signed) i8.
    int64_t Offset = int64_t(Value) - 4;
    return Offset > 254 || Offset < -256;
  }
  case ARM::fixup_thumb_adr_pcrel_10:
  case ARM::fixup_arm_thumb_cp: {
    // If the immediate is negative, greater than 1020, or not a multiple
    // of four, the wide version of the instruction must be used.
    int64_t Offset = int64_t(Value) - 4;
    return Offset > 1020 || Offset < 0 || Offset & 3;
  }
  case ARM::fixup_arm_thumb_cb:
    // If we have a Thumb CBZ or CBNZ instruction and its target is the next
    // instruction it is is actually out of range for the instruction.
    // It will be changed to a NOP.
    int64_t Offset = (Value & ~1);
    return Offset == 2;
  }
  llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!");
}
コード例 #14
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_got_hi20:
    return true;
  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_got_hi20:
      ShouldForce = true;
      break;
    case RISCV::fixup_riscv_pcrel_hi20:
      ShouldForce = T->getValue()->findAssociatedFragment() !=
                    Fixup.getValue()->findAssociatedFragment();
      break;
    }
    break;
  }

  return ShouldForce || STI.getFeatureBits()[RISCV::FeatureRelax] ||
         ForceRelocs;
}
コード例 #15
0
void SVMMemoryLayout::RecordRelocation(const MCAssembler &Asm,
    const MCAsmLayout &Layout, const MCFragment *Fragment,
    const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue)
{
    SVM::Fixups kind = (SVM::Fixups) Fixup.getKind();
    switch (kind) {

        case SVM::fixup_fnstack: {
            /*
             * Function stack adjustment annotation. The adjustment amount is
             * stored in the first argument of a binary op.
             * (See SVMMCCodeEmitter::EncodeInstruction)
             *
             * We store this offset for later, in our FNStackMap, indexed
             * by the address of the FNStack pseudo-op itself.
             */
            FNStackMap[std::make_pair(Fragment->getParent(),
                Layout.getFragmentOffset(Fragment))] = (int)Target.getConstant();
            break;
        }
    
        default: {
            /*
             * All other fixups are applied later, in ApplyLateFixups().
             * This is necessary because other fixup types can depend on
             * the FNStack values collected above.
             */
            SVMLateFixup LF((MCFragment *) Fragment, Fixup, Target);
            LateFixupList.push_back(LF);

            // This gets OR'ed with the fixup later. Zero it.
            FixedValue = 0;
            break;
        }
    }
}
コード例 #16
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");
  }
}
コード例 #17
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);
  }
コード例 #18
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;
  }
コード例 #19
0
unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
                                           const MCValue &Target,
                                           const MCFixup &Fixup,
                                           bool IsPCRel) const {
  // Determine the type of the relocation.
  unsigned Kind = (unsigned)Fixup.getKind();

  switch (Kind) {
  case Mips::fixup_Mips_NONE:
    return ELF::R_MIPS_NONE;
  case Mips::fixup_Mips_16:
  case FK_Data_2:
    return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16;
  case Mips::fixup_Mips_32:
  case FK_Data_4:
    return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32;
  }

  if (IsPCRel) {
    switch (Kind) {
    case Mips::fixup_Mips_Branch_PCRel:
    case Mips::fixup_Mips_PC16:
      return ELF::R_MIPS_PC16;
    case Mips::fixup_MICROMIPS_PC7_S1:
      return ELF::R_MICROMIPS_PC7_S1;
    case Mips::fixup_MICROMIPS_PC10_S1:
      return ELF::R_MICROMIPS_PC10_S1;
    case Mips::fixup_MICROMIPS_PC16_S1:
      return ELF::R_MICROMIPS_PC16_S1;
    case Mips::fixup_MIPS_PC19_S2:
      return ELF::R_MIPS_PC19_S2;
    case Mips::fixup_MIPS_PC18_S3:
      return ELF::R_MIPS_PC18_S3;
    case Mips::fixup_MIPS_PC21_S2:
      return ELF::R_MIPS_PC21_S2;
    case Mips::fixup_MIPS_PC26_S2:
      return ELF::R_MIPS_PC26_S2;
    case Mips::fixup_MIPS_PCHI16:
      return ELF::R_MIPS_PCHI16;
    case Mips::fixup_MIPS_PCLO16:
      return ELF::R_MIPS_PCLO16;
    }

    llvm_unreachable("invalid PC-relative fixup kind!");
  }

  switch (Kind) {
  case Mips::fixup_Mips_64:
  case FK_Data_8:
    return ELF::R_MIPS_64;
  case FK_GPRel_4:
    if (isN64()) {
      unsigned Type = (unsigned)ELF::R_MIPS_NONE;
      Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type);
      Type = setRType2((unsigned)ELF::R_MIPS_64, Type);
      Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type);
      return Type;
    }
    return ELF::R_MIPS_GPREL32;
  case Mips::fixup_Mips_GPREL16:
    return ELF::R_MIPS_GPREL16;
  case Mips::fixup_Mips_26:
    return ELF::R_MIPS_26;
  case Mips::fixup_Mips_CALL16:
    return ELF::R_MIPS_CALL16;
  case Mips::fixup_Mips_GOT_Global:
  case Mips::fixup_Mips_GOT_Local:
    return ELF::R_MIPS_GOT16;
  case Mips::fixup_Mips_HI16:
    return ELF::R_MIPS_HI16;
  case Mips::fixup_Mips_LO16:
    return ELF::R_MIPS_LO16;
  case Mips::fixup_Mips_TLSGD:
    return ELF::R_MIPS_TLS_GD;
  case Mips::fixup_Mips_GOTTPREL:
    return ELF::R_MIPS_TLS_GOTTPREL;
  case Mips::fixup_Mips_TPREL_HI:
    return ELF::R_MIPS_TLS_TPREL_HI16;
  case Mips::fixup_Mips_TPREL_LO:
    return ELF::R_MIPS_TLS_TPREL_LO16;
  case Mips::fixup_Mips_TLSLDM:
    return ELF::R_MIPS_TLS_LDM;
  case Mips::fixup_Mips_DTPREL_HI:
    return ELF::R_MIPS_TLS_DTPREL_HI16;
  case Mips::fixup_Mips_DTPREL_LO:
    return ELF::R_MIPS_TLS_DTPREL_LO16;
  case Mips::fixup_Mips_GOT_PAGE:
    return ELF::R_MIPS_GOT_PAGE;
  case Mips::fixup_Mips_GOT_OFST:
    return ELF::R_MIPS_GOT_OFST;
  case Mips::fixup_Mips_GOT_DISP:
    return ELF::R_MIPS_GOT_DISP;
  case Mips::fixup_Mips_GPOFF_HI: {
    unsigned Type = (unsigned)ELF::R_MIPS_NONE;
    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
    Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type);
    return Type;
  }
  case Mips::fixup_Mips_GPOFF_LO: {
    unsigned Type = (unsigned)ELF::R_MIPS_NONE;
    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
    Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type);
    return Type;
  }
  case Mips::fixup_Mips_HIGHER:
    return ELF::R_MIPS_HIGHER;
  case Mips::fixup_Mips_HIGHEST:
    return ELF::R_MIPS_HIGHEST;
  case Mips::fixup_Mips_GOT_HI16:
    return ELF::R_MIPS_GOT_HI16;
  case Mips::fixup_Mips_GOT_LO16:
    return ELF::R_MIPS_GOT_LO16;
  case Mips::fixup_Mips_CALL_HI16:
    return ELF::R_MIPS_CALL_HI16;
  case Mips::fixup_Mips_CALL_LO16:
    return ELF::R_MIPS_CALL_LO16;
  case Mips::fixup_MICROMIPS_26_S1:
    return ELF::R_MICROMIPS_26_S1;
  case Mips::fixup_MICROMIPS_HI16:
    return ELF::R_MICROMIPS_HI16;
  case Mips::fixup_MICROMIPS_LO16:
    return ELF::R_MICROMIPS_LO16;
  case Mips::fixup_MICROMIPS_GOT16:
    return ELF::R_MICROMIPS_GOT16;
  case Mips::fixup_MICROMIPS_CALL16:
    return ELF::R_MICROMIPS_CALL16;
  case Mips::fixup_MICROMIPS_GOT_DISP:
    return ELF::R_MICROMIPS_GOT_DISP;
  case Mips::fixup_MICROMIPS_GOT_PAGE:
    return ELF::R_MICROMIPS_GOT_PAGE;
  case Mips::fixup_MICROMIPS_GOT_OFST:
    return ELF::R_MICROMIPS_GOT_OFST;
  case Mips::fixup_MICROMIPS_TLS_GD:
    return ELF::R_MICROMIPS_TLS_GD;
  case Mips::fixup_MICROMIPS_TLS_LDM:
    return ELF::R_MICROMIPS_TLS_LDM;
  case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16:
    return ELF::R_MICROMIPS_TLS_DTPREL_HI16;
  case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
    return ELF::R_MICROMIPS_TLS_DTPREL_LO16;
  case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
    return ELF::R_MICROMIPS_TLS_TPREL_HI16;
  case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
    return ELF::R_MICROMIPS_TLS_TPREL_LO16;
  }

  llvm_unreachable("invalid fixup kind!");
}
コード例 #20
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;
    }
}
コード例 #21
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);
}
コード例 #22
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);
}
コード例 #23
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;
}
コード例 #24
0
unsigned OR1KELFObjectWriter::GetRelocType(const MCValue &Target,
                                           const MCFixup &Fixup,
                                           bool IsPCRel,
                                           bool IsRelocWithSymbol,
                                           int64_t Addend) const {
  unsigned Type;
  unsigned Kind = (unsigned)Fixup.getKind();
  switch (Kind) {
    default: llvm_unreachable("Invalid fixup kind!");
    case FK_Data_4:
      if(IsPCRel)
        Type = ELF::R_OR1K_32_PCREL;
      else
        Type = ELF::R_OR1K_32;
    break;
    case FK_Data_2:
      if(IsPCRel)
        Type = ELF::R_OR1K_16_PCREL;
      else
        Type = ELF::R_OR1K_16;
    break;
    case FK_Data_1:
      if(IsPCRel)
        Type = ELF::R_OR1K_8_PCREL;
      else
        Type = ELF::R_OR1K_8;
    break;
    case OR1K::fixup_OR1K_PCREL32:
    case FK_PCRel_4:
      Type = ELF::R_OR1K_32_PCREL;
      break;
    case OR1K::fixup_OR1K_PCREL16:
    case FK_PCRel_2:
      Type = ELF::R_OR1K_16_PCREL;
      break;
    case OR1K::fixup_OR1K_PCREL8:
    case FK_PCRel_1:
      Type = ELF::R_OR1K_8_PCREL;
      break;
    case OR1K::fixup_OR1K_32:
      Type = ELF::R_OR1K_32;
      break;
    case OR1K::fixup_OR1K_16:
      Type = ELF::R_OR1K_16;
      break;
    case OR1K::fixup_OR1K_8:
      Type = ELF::R_OR1K_8;
      break;
    case OR1K::fixup_OR1K_NONE:
      Type = ELF::R_OR1K_NONE;
      break;
    case OR1K::fixup_OR1K_LO16_INSN:
      Type = ELF::R_OR1K_LO_16_IN_INSN;
      break;
    case OR1K::fixup_OR1K_HI16_INSN:
      Type = ELF::R_OR1K_HI_16_IN_INSN;
      break;
    case OR1K::fixup_OR1K_REL26:
      Type = ELF::R_OR1K_INSN_REL_26;
      break;
    case OR1K::fixup_OR1K_GOTPC_HI16:
      Type = ELF::R_OR1K_GOTPC_HI16;
      break;
    case OR1K::fixup_OR1K_GOTPC_LO16:
      Type = ELF::R_OR1K_GOTPC_LO16;
      break;
    case OR1K::fixup_OR1K_GOT16:
      Type = ELF::R_OR1K_GOT16;
      break;
    case OR1K::fixup_OR1K_PLT26:
      Type = ELF::R_OR1K_PLT26;
      break;
    case OR1K::fixup_OR1K_GOTOFF_HI16:
      Type = ELF::R_OR1K_GOTOFF_HI16;
      break;
    case OR1K::fixup_OR1K_GOTOFF_LO16:
      Type = ELF::R_OR1K_GOTOFF_LO16;
      break;
    case OR1K::fixup_OR1K_COPY:
      Type = ELF::R_OR1K_COPY;
      break;
    case OR1K::fixup_OR1K_GLOB_DAT:
      Type = ELF::R_OR1K_GLOB_DAT;
      break;
    case OR1K::fixup_OR1K_JMP_SLOT:
      Type = ELF::R_OR1K_JMP_SLOT;
      break;
    case OR1K::fixup_OR1K_RELATIVE:
      Type = ELF::R_OR1K_RELATIVE;
      break;
  }
  return Type;
}
コード例 #25
0
ファイル: ARMELFObjectWriter.cpp プロジェクト: EdHurtig/llvm
unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
                                               const MCFixup &Fixup,
                                               bool IsPCRel) const  {
  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();

  unsigned Type = 0;
  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    default:
      report_fatal_error("unsupported relocation on symbol");
      return ELF::R_ARM_NONE;
    case FK_Data_4:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_ARM_REL32;
        break;
      case MCSymbolRefExpr::VK_TLSGD:
        llvm_unreachable("unimplemented");
      case MCSymbolRefExpr::VK_GOTTPOFF:
        Type = ELF::R_ARM_TLS_IE32;
        break;
      case MCSymbolRefExpr::VK_ARM_GOT_PREL:
        Type = ELF::R_ARM_GOT_PREL;
        break;
      case MCSymbolRefExpr::VK_ARM_PREL31:
        Type = ELF::R_ARM_PREL31;
        break;
      }
      break;
    case ARM::fixup_arm_blx:
    case ARM::fixup_arm_uncondbl:
      switch (Modifier) {
      case MCSymbolRefExpr::VK_PLT:
        Type = ELF::R_ARM_CALL;
        break;
      case MCSymbolRefExpr::VK_TLSCALL:
        Type = ELF::R_ARM_TLS_CALL;
        break;
      default:
        Type = ELF::R_ARM_CALL;
        break;
      }
      break;
    case ARM::fixup_arm_condbl:
    case ARM::fixup_arm_condbranch:
    case ARM::fixup_arm_uncondbranch:
      Type = ELF::R_ARM_JUMP24;
      break;
    case ARM::fixup_t2_condbranch:
      Type = ELF::R_ARM_THM_JUMP19;
      break;
    case ARM::fixup_t2_uncondbranch:
      Type = ELF::R_ARM_THM_JUMP24;
      break;
    case ARM::fixup_arm_movt_hi16:
      Type = ELF::R_ARM_MOVT_PREL;
      break;
    case ARM::fixup_arm_movw_lo16:
      Type = ELF::R_ARM_MOVW_PREL_NC;
      break;
    case ARM::fixup_t2_movt_hi16:
      Type = ELF::R_ARM_THM_MOVT_PREL;
      break;
    case ARM::fixup_t2_movw_lo16:
      Type = ELF::R_ARM_THM_MOVW_PREL_NC;
      break;
    case ARM::fixup_arm_thumb_bl:
    case ARM::fixup_arm_thumb_blx:
      switch (Modifier) {
      case MCSymbolRefExpr::VK_TLSCALL:
        Type = ELF::R_ARM_THM_TLS_CALL;
        break;
      default:
        Type = ELF::R_ARM_THM_CALL;
        break;
      }
      break;
    }
  } else {
    switch ((unsigned)Fixup.getKind()) {
    default:
      report_fatal_error("unsupported relocation on symbol");
      return ELF::R_ARM_NONE;
    case FK_Data_1:
      switch (Modifier) {
      default: llvm_unreachable("unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_ARM_ABS8;
        break;
      }
      break;
    case FK_Data_2:
      switch (Modifier) {
      default: llvm_unreachable("unsupported modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_ARM_ABS16;
        break;
      }
      break;
    case FK_Data_4:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_ARM_NONE:
        Type = ELF::R_ARM_NONE;
        break;
      case MCSymbolRefExpr::VK_GOT:
        Type = ELF::R_ARM_GOT_BREL;
        break;
      case MCSymbolRefExpr::VK_TLSGD:
        Type = ELF::R_ARM_TLS_GD32;
        break;
      case MCSymbolRefExpr::VK_TPOFF:
        Type = ELF::R_ARM_TLS_LE32;
        break;
      case MCSymbolRefExpr::VK_GOTTPOFF:
        Type = ELF::R_ARM_TLS_IE32;
        break;
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_ARM_ABS32;
        break;
      case MCSymbolRefExpr::VK_GOTOFF:
        Type = ELF::R_ARM_GOTOFF32;
        break;
      case MCSymbolRefExpr::VK_ARM_GOT_PREL:
        Type = ELF::R_ARM_GOT_PREL;
        break;
      case MCSymbolRefExpr::VK_ARM_TARGET1:
        Type = ELF::R_ARM_TARGET1;
        break;
      case MCSymbolRefExpr::VK_ARM_TARGET2:
        Type = ELF::R_ARM_TARGET2;
        break;
      case MCSymbolRefExpr::VK_ARM_PREL31:
        Type = ELF::R_ARM_PREL31;
        break;
      case MCSymbolRefExpr::VK_ARM_SBREL:
        Type = ELF::R_ARM_SBREL32;
        break;
      case MCSymbolRefExpr::VK_ARM_TLSLDO:
        Type = ELF::R_ARM_TLS_LDO32;
        break;
      case MCSymbolRefExpr::VK_TLSCALL:
        Type = ELF::R_ARM_TLS_CALL;
        break;
      case MCSymbolRefExpr::VK_TLSDESC:
        Type = ELF::R_ARM_TLS_GOTDESC;
        break;
      case MCSymbolRefExpr::VK_TLSLDM:
        Type = ELF::R_ARM_TLS_LDM32;
        break;
      case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
        Type = ELF::R_ARM_TLS_DESCSEQ;
        break;
      }
      break;
    case ARM::fixup_arm_ldst_pcrel_12:
    case ARM::fixup_arm_pcrel_10:
    case ARM::fixup_arm_adr_pcrel_12:
    case ARM::fixup_arm_thumb_bl:
    case ARM::fixup_arm_thumb_cb:
    case ARM::fixup_arm_thumb_cp:
    case ARM::fixup_arm_thumb_br:
      llvm_unreachable("Unimplemented");
    case ARM::fixup_arm_condbranch:
    case ARM::fixup_arm_uncondbranch:
      Type = ELF::R_ARM_JUMP24;
      break;
    case ARM::fixup_arm_movt_hi16:
      Type = ELF::R_ARM_MOVT_ABS;
      break;
    case ARM::fixup_arm_movw_lo16:
      Type = ELF::R_ARM_MOVW_ABS_NC;
      break;
    case ARM::fixup_t2_movt_hi16:
      Type = ELF::R_ARM_THM_MOVT_ABS;
      break;
    case ARM::fixup_t2_movw_lo16:
      Type = ELF::R_ARM_THM_MOVW_ABS_NC;
      break;
    }
  }

  return Type;
}
コード例 #26
0
unsigned HexagonELFObjectWriter::GetRelocType(MCValue const & /*Target*/,
                                              MCFixup const &Fixup,
                                              bool IsPCRel) const {
  switch ((unsigned)Fixup.getKind()) {
  default:
    DEBUG(dbgs() << "unrecognized relocation " << Fixup.getKind() << "\n");
    llvm_unreachable("Unimplemented Fixup kind!");
    return ELF::R_HEX_NONE;
  case FK_Data_4:
    return (IsPCRel) ? ELF::R_HEX_32_PCREL : ELF::R_HEX_32;
  case FK_PCRel_4:
    return ELF::R_HEX_32_PCREL;
  case FK_Data_2:
    return ELF::R_HEX_16;
  case FK_Data_1:
    return ELF::R_HEX_8;
  case fixup_Hexagon_B22_PCREL:
    return ELF::R_HEX_B22_PCREL;
  case fixup_Hexagon_B15_PCREL:
    return ELF::R_HEX_B15_PCREL;
  case fixup_Hexagon_B7_PCREL:
    return ELF::R_HEX_B7_PCREL;
  case fixup_Hexagon_LO16:
    return ELF::R_HEX_LO16;
  case fixup_Hexagon_HI16:
    return ELF::R_HEX_HI16;
  case fixup_Hexagon_32:
    return ELF::R_HEX_32;
  case fixup_Hexagon_16:
    return ELF::R_HEX_16;
  case fixup_Hexagon_8:
    return ELF::R_HEX_8;
  case fixup_Hexagon_GPREL16_0:
    return ELF::R_HEX_GPREL16_0;
  case fixup_Hexagon_GPREL16_1:
    return ELF::R_HEX_GPREL16_1;
  case fixup_Hexagon_GPREL16_2:
    return ELF::R_HEX_GPREL16_2;
  case fixup_Hexagon_GPREL16_3:
    return ELF::R_HEX_GPREL16_3;
  case fixup_Hexagon_HL16:
    return ELF::R_HEX_HL16;
  case fixup_Hexagon_B13_PCREL:
    return ELF::R_HEX_B13_PCREL;
  case fixup_Hexagon_B9_PCREL:
    return ELF::R_HEX_B9_PCREL;
  case fixup_Hexagon_B32_PCREL_X:
    return ELF::R_HEX_B32_PCREL_X;
  case fixup_Hexagon_32_6_X:
    return ELF::R_HEX_32_6_X;
  case fixup_Hexagon_B22_PCREL_X:
    return ELF::R_HEX_B22_PCREL_X;
  case fixup_Hexagon_B15_PCREL_X:
    return ELF::R_HEX_B15_PCREL_X;
  case fixup_Hexagon_B13_PCREL_X:
    return ELF::R_HEX_B13_PCREL_X;
  case fixup_Hexagon_B9_PCREL_X:
    return ELF::R_HEX_B9_PCREL_X;
  case fixup_Hexagon_B7_PCREL_X:
    return ELF::R_HEX_B7_PCREL_X;
  case fixup_Hexagon_16_X:
    return ELF::R_HEX_16_X;
  case fixup_Hexagon_12_X:
    return ELF::R_HEX_12_X;
  case fixup_Hexagon_11_X:
    return ELF::R_HEX_11_X;
  case fixup_Hexagon_10_X:
    return ELF::R_HEX_10_X;
  case fixup_Hexagon_9_X:
    return ELF::R_HEX_9_X;
  case fixup_Hexagon_8_X:
    return ELF::R_HEX_8_X;
  case fixup_Hexagon_7_X:
    return ELF::R_HEX_7_X;
  case fixup_Hexagon_6_X:
    return ELF::R_HEX_6_X;
  case fixup_Hexagon_32_PCREL:
    return ELF::R_HEX_32_PCREL;
  case fixup_Hexagon_COPY:
    return ELF::R_HEX_COPY;
  case fixup_Hexagon_GLOB_DAT:
    return ELF::R_HEX_GLOB_DAT;
  case fixup_Hexagon_JMP_SLOT:
    return ELF::R_HEX_JMP_SLOT;
  case fixup_Hexagon_RELATIVE:
    return ELF::R_HEX_RELATIVE;
  case fixup_Hexagon_PLT_B22_PCREL:
    return ELF::R_HEX_PLT_B22_PCREL;
  case fixup_Hexagon_GOTREL_LO16:
    return ELF::R_HEX_GOTREL_LO16;
  case fixup_Hexagon_GOTREL_HI16:
    return ELF::R_HEX_GOTREL_HI16;
  case fixup_Hexagon_GOTREL_32:
    return ELF::R_HEX_GOTREL_32;
  case fixup_Hexagon_GOT_LO16:
    return ELF::R_HEX_GOT_LO16;
  case fixup_Hexagon_GOT_HI16:
    return ELF::R_HEX_GOT_HI16;
  case fixup_Hexagon_GOT_32:
    return ELF::R_HEX_GOT_32;
  case fixup_Hexagon_GOT_16:
    return ELF::R_HEX_GOT_16;
  case fixup_Hexagon_DTPMOD_32:
    return ELF::R_HEX_DTPMOD_32;
  case fixup_Hexagon_DTPREL_LO16:
    return ELF::R_HEX_DTPREL_LO16;
  case fixup_Hexagon_DTPREL_HI16:
    return ELF::R_HEX_DTPREL_HI16;
  case fixup_Hexagon_DTPREL_32:
    return ELF::R_HEX_DTPREL_32;
  case fixup_Hexagon_DTPREL_16:
    return ELF::R_HEX_DTPREL_16;
  case fixup_Hexagon_GD_PLT_B22_PCREL:
    return ELF::R_HEX_GD_PLT_B22_PCREL;
  case fixup_Hexagon_LD_PLT_B22_PCREL:
    return ELF::R_HEX_LD_PLT_B22_PCREL;
  case fixup_Hexagon_GD_GOT_LO16:
    return ELF::R_HEX_GD_GOT_LO16;
  case fixup_Hexagon_GD_GOT_HI16:
    return ELF::R_HEX_GD_GOT_HI16;
  case fixup_Hexagon_GD_GOT_32:
    return ELF::R_HEX_GD_GOT_32;
  case fixup_Hexagon_GD_GOT_16:
    return ELF::R_HEX_GD_GOT_16;
  case fixup_Hexagon_LD_GOT_LO16:
    return ELF::R_HEX_LD_GOT_LO16;
  case fixup_Hexagon_LD_GOT_HI16:
    return ELF::R_HEX_LD_GOT_HI16;
  case fixup_Hexagon_LD_GOT_32:
    return ELF::R_HEX_LD_GOT_32;
  case fixup_Hexagon_LD_GOT_16:
    return ELF::R_HEX_LD_GOT_16;
  case fixup_Hexagon_IE_LO16:
    return ELF::R_HEX_IE_LO16;
  case fixup_Hexagon_IE_HI16:
    return ELF::R_HEX_IE_HI16;
  case fixup_Hexagon_IE_32:
    return ELF::R_HEX_IE_32;
  case fixup_Hexagon_IE_GOT_LO16:
    return ELF::R_HEX_IE_GOT_LO16;
  case fixup_Hexagon_IE_GOT_HI16:
    return ELF::R_HEX_IE_GOT_HI16;
  case fixup_Hexagon_IE_GOT_32:
    return ELF::R_HEX_IE_GOT_32;
  case fixup_Hexagon_IE_GOT_16:
    return ELF::R_HEX_IE_GOT_16;
  case fixup_Hexagon_TPREL_LO16:
    return ELF::R_HEX_TPREL_LO16;
  case fixup_Hexagon_TPREL_HI16:
    return ELF::R_HEX_TPREL_HI16;
  case fixup_Hexagon_TPREL_32:
    return ELF::R_HEX_TPREL_32;
  case fixup_Hexagon_TPREL_16:
    return ELF::R_HEX_TPREL_16;
  case fixup_Hexagon_6_PCREL_X:
    return ELF::R_HEX_6_PCREL_X;
  case fixup_Hexagon_GOTREL_32_6_X:
    return ELF::R_HEX_GOTREL_32_6_X;
  case fixup_Hexagon_GOTREL_16_X:
    return ELF::R_HEX_GOTREL_16_X;
  case fixup_Hexagon_GOTREL_11_X:
    return ELF::R_HEX_GOTREL_11_X;
  case fixup_Hexagon_GOT_32_6_X:
    return ELF::R_HEX_GOT_32_6_X;
  case fixup_Hexagon_GOT_16_X:
    return ELF::R_HEX_GOT_16_X;
  case fixup_Hexagon_GOT_11_X:
    return ELF::R_HEX_GOT_11_X;
  case fixup_Hexagon_DTPREL_32_6_X:
    return ELF::R_HEX_DTPREL_32_6_X;
  case fixup_Hexagon_DTPREL_16_X:
    return ELF::R_HEX_DTPREL_16_X;
  case fixup_Hexagon_DTPREL_11_X:
    return ELF::R_HEX_DTPREL_11_X;
  case fixup_Hexagon_GD_GOT_32_6_X:
    return ELF::R_HEX_GD_GOT_32_6_X;
  case fixup_Hexagon_GD_GOT_16_X:
    return ELF::R_HEX_GD_GOT_16_X;
  case fixup_Hexagon_GD_GOT_11_X:
    return ELF::R_HEX_GD_GOT_11_X;
  case fixup_Hexagon_LD_GOT_32_6_X:
    return ELF::R_HEX_LD_GOT_32_6_X;
  case fixup_Hexagon_LD_GOT_16_X:
    return ELF::R_HEX_LD_GOT_16_X;
  case fixup_Hexagon_LD_GOT_11_X:
    return ELF::R_HEX_LD_GOT_11_X;
  case fixup_Hexagon_IE_32_6_X:
    return ELF::R_HEX_IE_32_6_X;
  case fixup_Hexagon_IE_16_X:
    return ELF::R_HEX_IE_16_X;
  case fixup_Hexagon_IE_GOT_32_6_X:
    return ELF::R_HEX_IE_GOT_32_6_X;
  case fixup_Hexagon_IE_GOT_16_X:
    return ELF::R_HEX_IE_GOT_16_X;
  case fixup_Hexagon_IE_GOT_11_X:
    return ELF::R_HEX_IE_GOT_11_X;
  case fixup_Hexagon_TPREL_32_6_X:
    return ELF::R_HEX_TPREL_32_6_X;
  case fixup_Hexagon_TPREL_16_X:
    return ELF::R_HEX_TPREL_16_X;
  case fixup_Hexagon_TPREL_11_X:
    return ELF::R_HEX_TPREL_11_X;
  }
}
コード例 #27
0
ファイル: X86MachObjectWriter.cpp プロジェクト: traiansf/llvm
void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer,
                                              const MCAssembler &Asm,
                                              const MCAsmLayout &Layout,
                                              const MCFragment *Fragment,
                                              const MCFixup &Fixup,
                                              MCValue Target,
                                              uint64_t &FixedValue) {
  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
  unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());

  // If this is a 32-bit TLVP reloc it's handled a bit differently.
  if (Target.getSymA() &&
      Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
    RecordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
                         FixedValue);
    return;
  }

  // If this is a difference or a defined symbol plus an offset, then we need a
  // scattered relocation entry. Differences always require scattered
  // relocations.
  if (Target.getSymB()) {
    RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
                              Target, Log2Size, FixedValue);
    return;
  }

  // Get the symbol data, if any.
  const MCSymbolData *SD = nullptr;
  if (Target.getSymA())
    SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());

  // If this is an internal relocation with an offset, it also needs a scattered
  // relocation entry.
  uint32_t Offset = Target.getConstant();
  if (IsPCRel)
    Offset += 1 << Log2Size;
  // Try to record the scattered relocation if needed. Fall back to non
  // scattered if necessary (see comments in RecordScatteredRelocation()
  // for details).
  if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD) &&
      RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
                                Target, Log2Size, FixedValue))
    return;

  // See <reloc.h>.
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
  unsigned Index = 0;
  unsigned Type = 0;
  const MCSymbol *RelSymbol = nullptr;

  if (Target.isAbsolute()) { // constant
    // SymbolNum of 0 indicates the absolute section.
    //
    // FIXME: Currently, these are never generated (see code below). I cannot
    // find a case where they are actually emitted.
    Type = MachO::GENERIC_RELOC_VANILLA;
  } else {
    // Resolve constant variables.
    if (SD->getSymbol().isVariable()) {
      int64_t Res;
      if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
            Res, Layout, Writer->getSectionAddressMap())) {
        FixedValue = Res;
        return;
      }
    }

    // Check whether we need an external or internal relocation.
    if (Writer->doesSymbolRequireExternRelocation(SD)) {
      RelSymbol = &SD->getSymbol();
      // For external relocations, make sure to offset the fixup value to
      // compensate for the addend of the symbol address, if it was
      // undefined. This occurs with weak definitions, for example.
      if (!SD->getSymbol().isUndefined())
        FixedValue -= Layout.getSymbolOffset(SD);
    } else {
      // The index is the section ordinal (1-based).
      const MCSectionData &SymSD = Asm.getSectionData(
        SD->getSymbol().getSection());
      Index = SymSD.getOrdinal() + 1;
      FixedValue += Writer->getSectionAddress(&SymSD);
    }
    if (IsPCRel)
      FixedValue -= Writer->getSectionAddress(Fragment->getParent());

    Type = MachO::GENERIC_RELOC_VANILLA;
  }

  // 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);
}
コード例 #28
0
ファイル: PPCELFObjectWriter.cpp プロジェクト: jyknight/llvm
unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
                                          const MCFixup &Fixup,
                                          bool IsPCRel) const {
  MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);

  // determine the type of the relocation
  unsigned Type;
  if (IsPCRel) {
    switch ((unsigned)Fixup.getKind()) {
    default:
      llvm_unreachable("Unimplemented");
    case PPC::fixup_ppc_br24:
    case PPC::fixup_ppc_br24abs:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC_REL24;
        break;
      case MCSymbolRefExpr::VK_PLT:
        Type = ELF::R_PPC_PLTREL24;
        break;
      case MCSymbolRefExpr::VK_PPC_LOCAL:
        Type = ELF::R_PPC_LOCAL24PC;
        break;
      }
      break;
    case PPC::fixup_ppc_brcond14:
    case PPC::fixup_ppc_brcond14abs:
      Type = ELF::R_PPC_REL14;
      break;
    case PPC::fixup_ppc_half16:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC_REL16;
        break;
      case MCSymbolRefExpr::VK_PPC_LO:
        Type = ELF::R_PPC_REL16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_HI:
        Type = ELF::R_PPC_REL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_HA:
        Type = ELF::R_PPC_REL16_HA;
        break;
      }
      break;
    case FK_Data_4:
    case FK_PCRel_4:
      Type = ELF::R_PPC_REL32;
      break;
    case FK_Data_8:
    case FK_PCRel_8:
      Type = ELF::R_PPC64_REL64;
      break;
    }
  } else {
    switch ((unsigned)Fixup.getKind()) {
      default: llvm_unreachable("invalid fixup kind!");
    case PPC::fixup_ppc_br24abs:
      Type = ELF::R_PPC_ADDR24;
      break;
    case PPC::fixup_ppc_brcond14abs:
      Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
      break;
    case PPC::fixup_ppc_half16:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC_ADDR16;
        break;
      case MCSymbolRefExpr::VK_PPC_LO:
        Type = ELF::R_PPC_ADDR16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_HI:
        Type = ELF::R_PPC_ADDR16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_HA:
        Type = ELF::R_PPC_ADDR16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_HIGHER:
        Type = ELF::R_PPC64_ADDR16_HIGHER;
        break;
      case MCSymbolRefExpr::VK_PPC_HIGHERA:
        Type = ELF::R_PPC64_ADDR16_HIGHERA;
        break;
      case MCSymbolRefExpr::VK_PPC_HIGHEST:
        Type = ELF::R_PPC64_ADDR16_HIGHEST;
        break;
      case MCSymbolRefExpr::VK_PPC_HIGHESTA:
        Type = ELF::R_PPC64_ADDR16_HIGHESTA;
        break;
      case MCSymbolRefExpr::VK_GOT:
        Type = ELF::R_PPC_GOT16;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_LO:
        Type = ELF::R_PPC_GOT16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_HI:
        Type = ELF::R_PPC_GOT16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_HA:
        Type = ELF::R_PPC_GOT16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC:
        Type = ELF::R_PPC64_TOC16;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC_LO:
        Type = ELF::R_PPC64_TOC16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC_HI:
        Type = ELF::R_PPC64_TOC16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC_HA:
        Type = ELF::R_PPC64_TOC16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL:
        Type = ELF::R_PPC_TPREL16;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_LO:
        Type = ELF::R_PPC_TPREL16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HI:
        Type = ELF::R_PPC_TPREL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HA:
        Type = ELF::R_PPC_TPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
        Type = ELF::R_PPC64_TPREL16_HIGHER;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
        Type = ELF::R_PPC64_TPREL16_HIGHERA;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
        Type = ELF::R_PPC64_TPREL16_HIGHEST;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
        Type = ELF::R_PPC64_TPREL16_HIGHESTA;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL:
        Type = ELF::R_PPC64_DTPREL16;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
        Type = ELF::R_PPC64_DTPREL16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
        Type = ELF::R_PPC64_DTPREL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
        Type = ELF::R_PPC64_DTPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
        Type = ELF::R_PPC64_DTPREL16_HIGHER;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
        Type = ELF::R_PPC64_DTPREL16_HIGHERA;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
        Type = ELF::R_PPC64_DTPREL16_HIGHEST;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
        Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
        if (is64Bit())
          Type = ELF::R_PPC64_GOT_TLSGD16;
        else
          Type = ELF::R_PPC_GOT_TLSGD16;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
        Type = ELF::R_PPC64_GOT_TLSGD16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
        Type = ELF::R_PPC64_GOT_TLSGD16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
        Type = ELF::R_PPC64_GOT_TLSGD16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
        if (is64Bit())
          Type = ELF::R_PPC64_GOT_TLSLD16;
        else
          Type = ELF::R_PPC_GOT_TLSLD16;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
        Type = ELF::R_PPC64_GOT_TLSLD16_LO;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
        Type = ELF::R_PPC64_GOT_TLSLD16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
        Type = ELF::R_PPC64_GOT_TLSLD16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
        /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
        Type = ELF::R_PPC64_GOT_TPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
        /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
           are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
        Type = ELF::R_PPC64_GOT_TPREL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
        /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
        Type = ELF::R_PPC64_GOT_DTPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
        /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
           are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
        Type = ELF::R_PPC64_GOT_TPREL16_HA;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
        Type = ELF::R_PPC64_GOT_DTPREL16_HI;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
        Type = ELF::R_PPC64_GOT_DTPREL16_HA;
        break;
      }
      break;
    case PPC::fixup_ppc_half16ds:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC64_ADDR16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_LO:
        Type = ELF::R_PPC64_ADDR16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_GOT:
        Type = ELF::R_PPC64_GOT16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_LO:
        Type = ELF::R_PPC64_GOT16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC:
        Type = ELF::R_PPC64_TOC16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_TOC_LO:
        Type = ELF::R_PPC64_TOC16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL:
        Type = ELF::R_PPC64_TPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL_LO:
        Type = ELF::R_PPC64_TPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL:
        Type = ELF::R_PPC64_DTPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
        Type = ELF::R_PPC64_DTPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
        Type = ELF::R_PPC64_GOT_TPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
        Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
        Type = ELF::R_PPC64_GOT_DTPREL16_DS;
        break;
      case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
        Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
        break;
      }
      break;
    case PPC::fixup_ppc_nofixup:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_PPC_TLSGD:
        if (is64Bit())
          Type = ELF::R_PPC64_TLSGD;
        else
          Type = ELF::R_PPC_TLSGD;
        break;
      case MCSymbolRefExpr::VK_PPC_TLSLD:
        if (is64Bit())
          Type = ELF::R_PPC64_TLSLD;
        else
          Type = ELF::R_PPC_TLSLD;
        break;
      case MCSymbolRefExpr::VK_PPC_TLS:
        if (is64Bit())
          Type = ELF::R_PPC64_TLS;
        else
          Type = ELF::R_PPC_TLS;
        break;
      }
      break;
    case FK_Data_8:
      switch (Modifier) {
      default: llvm_unreachable("Unsupported Modifier");
      case MCSymbolRefExpr::VK_PPC_TOCBASE:
        Type = ELF::R_PPC64_TOC;
        break;
      case MCSymbolRefExpr::VK_None:
        Type = ELF::R_PPC64_ADDR64;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPMOD:
        Type = ELF::R_PPC64_DTPMOD64;
        break;
      case MCSymbolRefExpr::VK_PPC_TPREL:
        Type = ELF::R_PPC64_TPREL64;
        break;
      case MCSymbolRefExpr::VK_PPC_DTPREL:
        Type = ELF::R_PPC64_DTPREL64;
        break;
      }
      break;
    case FK_Data_4:
      Type = ELF::R_PPC_ADDR32;
      break;
    case FK_Data_2:
      Type = ELF::R_PPC_ADDR16;
      break;
    }
  }
  return Type;
}
コード例 #29
0
ファイル: Cpu0ELFObjectWriter.cpp プロジェクト: AmesianX/lbd
//@GetRelocType {
unsigned Cpu0ELFObjectWriter::GetRelocType(const MCValue &Target,
                                           const MCFixup &Fixup,
                                           bool IsPCRel) const {
  // determine the type of the relocation
  unsigned Type = (unsigned)ELF::R_CPU0_NONE;
  unsigned Kind = (unsigned)Fixup.getKind();

  switch (Kind) {
  default:
    llvm_unreachable("invalid fixup kind!");
  case FK_Data_4:
    Type = ELF::R_CPU0_32;
    break;
#if CH >= CH8_1 //1
  case FK_GPRel_4:
    Type = ELF::R_CPU0_GPREL32;
    break;
#endif
  case Cpu0::fixup_Cpu0_32:
    Type = ELF::R_CPU0_32;
    break;
  case Cpu0::fixup_Cpu0_GPREL16:
    Type = ELF::R_CPU0_GPREL16;
    break;
#if CH >= CH9_1
  case Cpu0::fixup_Cpu0_CALL16:
    Type = ELF::R_CPU0_CALL16;
    break;
#endif
  case Cpu0::fixup_Cpu0_GOT_Global:
  case Cpu0::fixup_Cpu0_GOT_Local:
    Type = ELF::R_CPU0_GOT16;
    break;
  case Cpu0::fixup_Cpu0_HI16:
    Type = ELF::R_CPU0_HI16;
    break;
  case Cpu0::fixup_Cpu0_LO16:
    Type = ELF::R_CPU0_LO16;
    break;
#if CH >= CH12_1
  case Cpu0::fixup_Cpu0_TLSGD:
    Type = ELF::R_CPU0_TLS_GD;
    break;
  case Cpu0::fixup_Cpu0_GOTTPREL:
    Type = ELF::R_CPU0_TLS_GOTTPREL;
    break;
#endif
#if CH >= CH8_1 //2
  case Cpu0::fixup_Cpu0_PC16:
    Type = ELF::R_CPU0_PC16;
    break;
  case Cpu0::fixup_Cpu0_PC24:
    Type = ELF::R_CPU0_PC24;
    break;
#endif
#if CH >= CH12_1
  case Cpu0::fixup_Cpu0_TP_HI:
    Type = ELF::R_CPU0_TLS_TP_HI16;
    break;
  case Cpu0::fixup_Cpu0_TP_LO:
    Type = ELF::R_CPU0_TLS_TP_LO16;
    break;
  case Cpu0::fixup_Cpu0_TLSLDM:
    Type = ELF::R_CPU0_TLS_LDM;
    break;
  case Cpu0::fixup_Cpu0_DTP_HI:
    Type = ELF::R_CPU0_TLS_DTP_HI16;
    break;
  case Cpu0::fixup_Cpu0_DTP_LO:
    Type = ELF::R_CPU0_TLS_DTP_LO16;
    break;
#endif
  case Cpu0::fixup_Cpu0_GOT_HI16:
    Type = ELF::R_CPU0_GOT_HI16;
    break;
  case Cpu0::fixup_Cpu0_GOT_LO16:
    Type = ELF::R_CPU0_GOT_LO16;
    break;
  }

  return Type;
}
コード例 #30
0
unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target,
                                            const MCFixup &Fixup,
                                            bool IsPCRel) const {

  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Fixup.getValue())) {
    if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32)
      return ELF::R_SPARC_DISP32;
  }

  if (IsPCRel) {
    switch((unsigned)Fixup.getKind()) {
    default:
      llvm_unreachable("Unimplemented fixup -> relocation");
    case FK_Data_1:                  return ELF::R_SPARC_DISP8;
    case FK_Data_2:                  return ELF::R_SPARC_DISP16;
    case FK_Data_4:                  return ELF::R_SPARC_DISP32;
    case FK_Data_8:                  return ELF::R_SPARC_DISP64;
    case Sparc::fixup_sparc_call30:  return ELF::R_SPARC_WDISP30;
    case Sparc::fixup_sparc_br22:    return ELF::R_SPARC_WDISP22;
    case Sparc::fixup_sparc_br19:    return ELF::R_SPARC_WDISP19;
    case Sparc::fixup_sparc_pc22:    return ELF::R_SPARC_PC22;
    case Sparc::fixup_sparc_pc10:    return ELF::R_SPARC_PC10;
    case Sparc::fixup_sparc_wplt30:  return ELF::R_SPARC_WPLT30;
    }
  }

  switch((unsigned)Fixup.getKind()) {
  default:
    llvm_unreachable("Unimplemented fixup -> relocation");
  case FK_Data_1:                return ELF::R_SPARC_8;
  case FK_Data_2:                return ((Fixup.getOffset() % 2)
                                         ? ELF::R_SPARC_UA16
                                         : ELF::R_SPARC_16);
  case FK_Data_4:                return ((Fixup.getOffset() % 4)
                                         ? ELF::R_SPARC_UA32
                                         : ELF::R_SPARC_32);
  case FK_Data_8:                return ((Fixup.getOffset() % 8)
                                         ? ELF::R_SPARC_UA64
                                         : ELF::R_SPARC_64);
  case Sparc::fixup_sparc_hi22:  return ELF::R_SPARC_HI22;
  case Sparc::fixup_sparc_lo10:  return ELF::R_SPARC_LO10;
  case Sparc::fixup_sparc_h44:   return ELF::R_SPARC_H44;
  case Sparc::fixup_sparc_m44:   return ELF::R_SPARC_M44;
  case Sparc::fixup_sparc_l44:   return ELF::R_SPARC_L44;
  case Sparc::fixup_sparc_hh:    return ELF::R_SPARC_HH22;
  case Sparc::fixup_sparc_hm:    return ELF::R_SPARC_HM10;
  case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22;
  case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10;
  case Sparc::fixup_sparc_tls_gd_hi22:   return ELF::R_SPARC_TLS_GD_HI22;
  case Sparc::fixup_sparc_tls_gd_lo10:   return ELF::R_SPARC_TLS_GD_LO10;
  case Sparc::fixup_sparc_tls_gd_add:    return ELF::R_SPARC_TLS_GD_ADD;
  case Sparc::fixup_sparc_tls_gd_call:   return ELF::R_SPARC_TLS_GD_CALL;
  case Sparc::fixup_sparc_tls_ldm_hi22:  return ELF::R_SPARC_TLS_LDM_HI22;
  case Sparc::fixup_sparc_tls_ldm_lo10:  return ELF::R_SPARC_TLS_LDM_LO10;
  case Sparc::fixup_sparc_tls_ldm_add:   return ELF::R_SPARC_TLS_LDM_ADD;
  case Sparc::fixup_sparc_tls_ldm_call:  return ELF::R_SPARC_TLS_LDM_CALL;
  case Sparc::fixup_sparc_tls_ldo_hix22: return ELF::R_SPARC_TLS_LDO_HIX22;
  case Sparc::fixup_sparc_tls_ldo_lox10: return ELF::R_SPARC_TLS_LDO_LOX10;
  case Sparc::fixup_sparc_tls_ldo_add:   return ELF::R_SPARC_TLS_LDO_ADD;
  case Sparc::fixup_sparc_tls_ie_hi22:   return ELF::R_SPARC_TLS_IE_HI22;
  case Sparc::fixup_sparc_tls_ie_lo10:   return ELF::R_SPARC_TLS_IE_LO10;
  case Sparc::fixup_sparc_tls_ie_ld:     return ELF::R_SPARC_TLS_IE_LD;
  case Sparc::fixup_sparc_tls_ie_ldx:    return ELF::R_SPARC_TLS_IE_LDX;
  case Sparc::fixup_sparc_tls_ie_add:    return ELF::R_SPARC_TLS_IE_ADD;
  case Sparc::fixup_sparc_tls_le_hix22:  return ELF::R_SPARC_TLS_LE_HIX22;
  case Sparc::fixup_sparc_tls_le_lox10:  return ELF::R_SPARC_TLS_LE_LOX10;
  }

  return ELF::R_SPARC_NONE;
}