// R_386_32: S + A
X86RelocationFactory::Result abs32(Relocation& pReloc,
                                   const MCLDInfo& pLDInfo,
                                   X86RelocationFactory& pParent)
{
  ResolveInfo* rsym = pReloc.symInfo();
  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
  RelocationFactory::DWord S = pReloc.symValue();

  if(rsym->isLocal() && (rsym->reserved() & X86GNULDBackend::ReserveRel)) {
    helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
    pReloc.target() = S + A;
    return X86RelocationFactory::OK;
  }
  else if(!rsym->isLocal()) {
    if(rsym->reserved() & X86GNULDBackend::ReservePLT) {
      S = helper_PLT(pReloc, pParent);
      pReloc.target() = S + A;
    }
    if(rsym->reserved() & X86GNULDBackend::ReserveRel) {
      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
      }
      else {
        helper_DynRel(pReloc, pReloc.type(), pParent);
        return X86RelocationFactory::OK;
      }
    }
  }

  // perform static relocation
  pReloc.target() = S + A;
  return X86RelocationFactory::OK;
}
// R_386_PC32: S + A - P
X86RelocationFactory::Result rel32(Relocation& pReloc,
                                   const MCLDInfo& pLDInfo,
                                   X86RelocationFactory& pParent)
{
  // perform static relocation
  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
  pReloc.target() = pReloc.symValue() + A
      - pReloc.place(pParent.getLayout());
  return X86RelocationFactory::OK;
}
// R_386_GOTPC: GOT_ORG + A - P
X86RelocationFactory::Result gotpc32(Relocation& pReloc,
                                     const MCLDInfo& pLDInfo,
                                     X86RelocationFactory& pParent)
{
  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
  // Apply relocation.
  pReloc.target() = GOT_ORG + A - pReloc.place(pParent.getLayout());
  return X86RelocationFactory::OK;
}
// R_386_GOTOFF: S + A - GOT_ORG
X86RelocationFactory::Result gotoff32(Relocation& pReloc,
                                      const MCLDInfo& pLDInfo,
                                      X86RelocationFactory& pParent)
{
  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
  X86RelocationFactory::Address S = pReloc.symValue();

  pReloc.target() = S + A - GOT_ORG;
  return X86RelocationFactory::OK;
}
// R_386_32: S + A
X86RelocationFactory::Result abs32(Relocation& pReloc,
                                   const MCLDInfo& pLDInfo,
                                   X86RelocationFactory& pParent)
{
  ResolveInfo* rsym = pReloc.symInfo();
  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
  RelocationFactory::DWord S = pReloc.symValue();
  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
                       *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT),
                       pLDInfo, pLDInfo.output(), true);

  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
                                                  *(pReloc.targetRef().frag()));
  assert(NULL != target_sect);
  // If the flag of target section is not ALLOC, we will not scan this relocation
  // but perform static relocation. (e.g., applying .debug section)
  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
    pReloc.target() = S + A;
    return X86RelocationFactory::OK;
  }

  // A local symbol may need REL Type dynamic relocation
  if (rsym->isLocal() && has_dyn_rel) {
    helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
    pReloc.target() = S + A;
    return X86RelocationFactory::OK;
  }

  // An external symbol may need PLT and dynamic relocation
  if (!rsym->isLocal()) {
    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
      S = helper_PLT(pReloc, pParent);
      pReloc.target() = S + A;
    }
    // If we generate a dynamic relocation (except R_386_RELATIVE)
    // for a place, we should not perform static relocation on it
    // in order to keep the addend store in the place correct.
    if (has_dyn_rel) {
      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
      }
      else {
        helper_DynRel(pReloc, pReloc.type(), pParent);
        return X86RelocationFactory::OK;
      }
    }
  }

  // perform static relocation
  pReloc.target() = S + A;
  return X86RelocationFactory::OK;
}
Relocator::Result lea(Relocation& pReloc, NyuziRelocator& pParent)
{
  Relocator::Address S = pReloc.symValue();
  Relocator::Address P = pReloc.place();
  int offset = S - (P + 4);

  if (helper_check_signed_overflow(offset, 13))
    return Relocator::Overflow;

  pReloc.target() = helper_replace_field(pReloc.target(), offset, 10, 13);

  return Relocator::OK;
}
// R_HEX_PLT_B22_PCREL: PLT(S) + A - P
Relocator::Result relocPLTB22PCREL(Relocation& pReloc,
                                   HexagonRelocator& pParent) {
  // PLT_S depends on if there is a PLT entry.
  Relocator::Address PLT_S;
  if ((pReloc.symInfo()->reserved() & HexagonRelocator::ReservePLT))
    PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
  else
    PLT_S = pReloc.symValue();
  Relocator::Address P = pReloc.place();
  uint32_t bitMask = FINDBITMASK(pReloc.target());
  uint32_t result = (PLT_S + pReloc.addend() - P) >> 2;
  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
  return Relocator::OK;
}
// R_HEX_GOTREL_LO16: and its class of relocs
// (S + A - GOT) : Signed Truncate
Relocator::Result relocGOTREL(Relocation& pReloc, HexagonRelocator& pParent) {
  Relocator::Address S = pReloc.symValue();
  Relocator::DWord A = pReloc.addend();
  Relocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();

  uint32_t bitMask = 0;
  uint32_t alignment = 1;
  uint32_t shift = 0;

  uint32_t result = (uint32_t)(S + A - GOT);

  switch (pReloc.type()) {
    case llvm::ELF::R_HEX_GOTREL_LO16:
      bitMask = 0x00c03fff;
      break;

    case llvm::ELF::R_HEX_GOTREL_HI16:
      bitMask = 0x00c03fff;
      shift = 16;
      alignment = 4;
      break;

    case llvm::ELF::R_HEX_GOTREL_32:
      bitMask = 0xffffffff;
      break;

    case llvm::ELF::R_HEX_GOTREL_32_6_X:
      bitMask = 0x0fff3fff;
      shift = 6;
      break;

    case llvm::ELF::R_HEX_GOTREL_16_X:
    case llvm::ELF::R_HEX_GOTREL_11_X:
      bitMask = FINDBITMASK(pReloc.target());
      break;

    default:
      // show proper error
      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
                                          << "*****@*****.**";
  }

  if (result % alignment != 0)
    return Relocator::BadReloc;

  result >>= shift;

  pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
  return Relocator::OK;
}
// R_386_PLT32: PLT(S) + A - P
X86RelocationFactory::Result plt32(Relocation& pReloc,
                                   const MCLDInfo& pLDInfo,
                                   X86RelocationFactory& pParent)
{
  // PLT_S depends on if there is a PLT entry.
  X86RelocationFactory::Address PLT_S;
  if((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
    PLT_S = helper_PLT(pReloc, pParent);
  else
    PLT_S = pReloc.symValue();
  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
  X86RelocationFactory::Address P = pReloc.place(pParent.getLayout());
  pReloc.target() = PLT_S + A - P;
  return X86RelocationFactory::OK;
}
// R_386_GOT32: GOT(S) + A - GOT_ORG
X86RelocationFactory::Result got32(Relocation& pReloc,
                                   const MCLDInfo& pLDInfo,
                                   X86RelocationFactory& pParent)
{
  if(!(pReloc.symInfo()->reserved()
       & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
    return X86RelocationFactory::BadReloc;
  }
  X86RelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
  // Apply relocation.
  pReloc.target() = GOT_S + A - GOT_ORG;
  return X86RelocationFactory::OK;
}
Esempio n. 11
0
// R_HEX_GPREL16_0 and its class : Unsigned Verify
Relocator::Result relocGPREL(Relocation& pReloc, HexagonRelocator& pParent) {
  Relocator::Address S = pReloc.symValue();
  Relocator::DWord A = pReloc.addend();
  Relocator::DWord GP = pParent.getTarget().getGP();

  uint32_t result = (uint32_t)(S + A - GP);
  uint32_t shift = 0;
  uint32_t alignment = 1;

  switch (pReloc.type()) {
    case llvm::ELF::R_HEX_GPREL16_0:
      break;

    case llvm::ELF::R_HEX_GPREL16_1:
      shift = 1;
      alignment = 2;
      break;

    case llvm::ELF::R_HEX_GPREL16_2:
      shift = 2;
      alignment = 4;
      break;

    case llvm::ELF::R_HEX_GPREL16_3:
      shift = 3;
      alignment = 8;
      break;

    default:
      // show proper error
      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
                                          << "*****@*****.**";
  }

  uint32_t range = 1 << 16;
  uint32_t bitMask = FINDBITMASK(pReloc.target());

  if ((shift != 0) && (result % alignment != 0))
    return Relocator::BadReloc;

  result >>= shift;

  if (result < range - 1) {
    pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
    return Relocator::OK;
  }
  return Relocator::Overflow;
}
Esempio n. 12
0
uint32_t NyuziRelocator::getDebugStringOffset(Relocation& pReloc) const {
  if (pReloc.type() != llvm::ELF::R_NYUZI_ABS32)
    error(diag::unsupport_reloc_for_debug_string) << getName(pReloc.type());

  return pReloc.symInfo()->outSymbol()->fragRef()->offset() +
         pReloc.target() + pReloc.addend();
}
Esempio n. 13
0
Relocator::Result abs(Relocation& pReloc, NyuziRelocator& pParent)
{
  Relocator::DWord A = pReloc.addend();
  Relocator::DWord S = pReloc.symValue();
  pReloc.target() = S + A;

  return Relocator::OK;
}
// R_386_PC32: S + A - P
X86RelocationFactory::Result rel32(Relocation& pReloc,
                                   const MCLDInfo& pLDInfo,
                                   X86RelocationFactory& pParent)
{
  ResolveInfo* rsym = pReloc.symInfo();
  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
  RelocationFactory::DWord S = pReloc.symValue();
  RelocationFactory::DWord P = pReloc.place(pParent.getLayout());

  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
                                                  *(pReloc.targetRef().frag()));
  assert(NULL != target_sect);
  // If the flag of target section is not ALLOC, we will not scan this relocation
  // but perform static relocation. (e.g., applying .debug section)
  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
    pReloc.target() = S + A - P;
    return X86RelocationFactory::OK;
  }

  // An external symbol may need PLT and dynamic relocation
  if (!rsym->isLocal()) {
    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
       pReloc.target() = S + A - P;
    }
    if (pParent.getTarget().symbolNeedsDynRel(
          *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo,
                  pLDInfo.output(), false)) {
      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
      }
      else {
        helper_DynRel(pReloc, pReloc.type(), pParent);
          return X86RelocationFactory::OK;
      }
    }
  }

   // perform static relocation
  pReloc.target() = S + A - P;
  return X86RelocationFactory::OK;
}
void AArch64GNULDBackend::scanErrata(Module& pModule,
                                     IRBuilder& pBuilder,
                                     size_t& num_new_stubs,
                                     size_t& stubs_strlen) {
  // TODO: Implement AArch64 ErrataStubFactory to create the specific erratum
  //       stub and simplify the logics.
  for (Module::iterator sect = pModule.begin(), sectEnd = pModule.end();
       sect != sectEnd; ++sect) {
    if (((*sect)->kind() == LDFileFormat::TEXT) && (*sect)->hasSectionData()) {
      SectionData* sd = (*sect)->getSectionData();
      for (SectionData::iterator it = sd->begin(), ie = sd->end(); it != ie;
           ++it) {
        Fragment* frag = llvm::dyn_cast<RegionFragment>(it);
        if (frag != NULL) {
          FragmentRef* frag_ref = FragmentRef::Create(*frag, 0);
          for (unsigned offset = 0; offset < frag->size();
               offset += AArch64InsnHelpers::InsnSize) {
            Stub* stub = getStubFactory()->create(*frag_ref,
                                                  pBuilder,
                                                  *getBRIslandFactory());
            if (stub != NULL) {
              // A stub symbol should be local
              assert(stub->symInfo() != NULL && stub->symInfo()->isLocal());
              const AArch64CA53ErratumStub* erratum_stub =
                  reinterpret_cast<const AArch64CA53ErratumStub*>(stub);
              assert(erratum_stub != NULL);
              // Rewrite the erratum instruction as a branch to the stub.
              uint64_t offset = frag_ref->offset() +
                                erratum_stub->getErratumInsnOffset();
              Relocation* reloc =
                  Relocation::Create(llvm::ELF::R_AARCH64_JUMP26,
                                     *(FragmentRef::Create(*frag, offset)),
                                     /* pAddend */0);
              reloc->setSymInfo(stub->symInfo());
              reloc->target() = AArch64InsnHelpers::buildBranchInsn();
              addExtraRelocation(reloc);

              ++num_new_stubs;
              stubs_strlen += stub->symInfo()->nameSize() + 1;
            }

            frag_ref->assign(*frag, offset + AArch64InsnHelpers::InsnSize);
          }  // for each INSN
        }
      }  // for each FRAGMENT
    }
  }  // for each TEXT section
}
void Relocator::partialScanRelocation(Relocation& pReloc,
                                      Module& pModule,
                                      const LDSection& pSection)
{
  // if we meet a section symbol
  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
    LDSymbol* input_sym = pReloc.symInfo()->outSymbol();

    // 1. update the relocation target offset
    assert(input_sym->hasFragRef());
    uint64_t offset = input_sym->fragRef()->getOutputOffset();
    pReloc.target() += offset;

    // 2. get output section symbol
    // get the output LDSection which the symbol defined in
    const LDSection& out_sect =
                        input_sym->fragRef()->frag()->getParent()->getSection();
    ResolveInfo* sym_info =
                     pModule.getSectionSymbolSet().get(out_sect)->resolveInfo();
    // set relocation target symbol to the output section symbol's resolveInfo
    pReloc.setSymInfo(sym_info);
  }
}
Esempio n. 17
0
void NyuziRelocator::applyDebugStringOffset(Relocation& pReloc,
                                            uint32_t pOffset) {
  pReloc.target() = pOffset;
}
Esempio n. 18
0
// R_HEX_32 and its class of relocations use only addend and symbol value
// S + A : result is unsigned truncate.
// Exception: R_HEX_32_6_X : unsigned verify
Relocator::Result applyAbs(Relocation& pReloc) {
  Relocator::Address S = pReloc.symValue();
  Relocator::DWord A = pReloc.addend();
  uint32_t result = (uint32_t)(S + A);
  uint32_t bitMask = 0;
  uint32_t effectiveBits = 0;
  uint32_t alignment = 1;
  uint32_t shift = 0;

  switch (pReloc.type()) {
    case llvm::ELF::R_HEX_LO16:
      bitMask = 0x00c03fff;
      break;

    case llvm::ELF::R_HEX_HI16:
      shift = 16;
      bitMask = 0x00c03fff;
      break;

    case llvm::ELF::R_HEX_32:
      bitMask = 0xffffffff;
      break;

    case llvm::ELF::R_HEX_16:
      bitMask = 0x0000ffff;
      alignment = 2;
      break;

    case llvm::ELF::R_HEX_8:
      bitMask = 0x000000ff;
      alignment = 1;
      break;

    case llvm::ELF::R_HEX_12_X:
      bitMask = 0x000007e0;
      break;

    case llvm::ELF::R_HEX_32_6_X:
      bitMask = 0xfff3fff;
      shift = 6;
      effectiveBits = 26;
      break;

    case llvm::ELF::R_HEX_16_X:
    case llvm::ELF::R_HEX_11_X:
    case llvm::ELF::R_HEX_10_X:
    case llvm::ELF::R_HEX_9_X:
    case llvm::ELF::R_HEX_8_X:
    case llvm::ELF::R_HEX_7_X:
    case llvm::ELF::R_HEX_6_X:
      bitMask = FINDBITMASK(pReloc.target());
      break;

    default:
      // show proper error
      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
                                          << "*****@*****.**";
  }

  if ((shift != 0) && (result % alignment != 0))
    return Relocator::BadReloc;

  result >>= shift;

  if (effectiveBits) {
    uint32_t range = 1 << effectiveBits;
    if (result > (range - 1))
      return Relocator::Overflow;
  }

  pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
  return Relocator::OK;
}
Esempio n. 19
0
// R_HEX_B22_PCREL and its class of relocations, use
// S + A - P : result is signed verify.
// Exception: R_HEX_B32_PCREL_X : signed truncate
// Another Exception: R_HEX_6_PCREL_X is unsigned truncate
Relocator::Result applyRel(Relocation& pReloc, int64_t pResult) {
  uint32_t bitMask = 0;
  uint32_t effectiveBits = 0;
  uint32_t alignment = 1;
  uint32_t result;
  uint32_t shift = 0;

  switch (pReloc.type()) {
    case llvm::ELF::R_HEX_B22_PCREL:
      bitMask = 0x01ff3ffe;
      effectiveBits = 22;
      alignment = 4;
      shift = 2;
      break;

    case llvm::ELF::R_HEX_B15_PCREL:
      bitMask = 0x00df20fe;
      effectiveBits = 15;
      alignment = 4;
      shift = 2;
      break;

    case llvm::ELF::R_HEX_B7_PCREL:
      bitMask = 0x00001f18;
      effectiveBits = 7;
      alignment = 4;
      shift = 2;
      break;

    case llvm::ELF::R_HEX_B13_PCREL:
      bitMask = 0x00202ffe;
      effectiveBits = 13;
      alignment = 4;
      shift = 2;
      break;

    case llvm::ELF::R_HEX_B9_PCREL:
      bitMask = 0x003000fe;
      effectiveBits = 9;
      alignment = 4;
      shift = 2;
      break;

    case llvm::ELF::R_HEX_B32_PCREL_X:
      bitMask = 0xfff3fff;
      shift = 6;
      break;

    case llvm::ELF::R_HEX_B22_PCREL_X:
      bitMask = 0x01ff3ffe;
      effectiveBits = 22;
      pResult &= 0x3f;
      break;

    case llvm::ELF::R_HEX_B15_PCREL_X:
      bitMask = 0x00df20fe;
      effectiveBits = 15;
      pResult &= 0x3f;
      break;

    case llvm::ELF::R_HEX_B13_PCREL_X:
      bitMask = 0x00202ffe;
      effectiveBits = 13;
      pResult &= 0x3f;
      break;

    case llvm::ELF::R_HEX_B9_PCREL_X:
      bitMask = 0x003000fe;
      effectiveBits = 9;
      pResult &= 0x3f;
      break;

    case llvm::ELF::R_HEX_B7_PCREL_X:
      bitMask = 0x00001f18;
      effectiveBits = 7;
      pResult &= 0x3f;
      break;

    case llvm::ELF::R_HEX_32_PCREL:
      bitMask = 0xffffffff;
      effectiveBits = 32;
      break;

    case llvm::ELF::R_HEX_6_PCREL_X:
      // This is unique since it has a unsigned operand and its truncated
      bitMask = FINDBITMASK(pReloc.target());
      result = pReloc.addend() + pReloc.symValue() - pReloc.place();
      pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
      return Relocator::OK;

    default:
      // show proper error
      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
                                          << "*****@*****.**";
  }

  if ((shift != 0) && (pResult % alignment != 0))
    return Relocator::BadReloc;

  pResult >>= shift;

  if (effectiveBits) {
    int64_t range = 1LL << (effectiveBits - 1);
    if ((pResult > (range - 1)) || (pResult < -range))
      return Relocator::Overflow;
  }

  pReloc.target() |= (uint32_t)ApplyMask<int32_t>(bitMask, pResult);
  return Relocator::OK;
}
void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc,
                                     const LDSymbol& pInputSym,
                                     MCLinker& pLinker,
                                     const MCLDInfo& pLDInfo,
                                     const Output& pOutput)
{
  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();

  updateAddend(pReloc, pInputSym, pLinker.getLayout());

  switch(pReloc.type()){

    // Set R_ARM_TARGET1 to R_ARM_ABS32
    // Ref: GNU gold 1.11 arm.cc, line 9892
    case llvm::ELF::R_ARM_TARGET1:
       pReloc.setType(llvm::ELF::R_ARM_ABS32);
    case llvm::ELF::R_ARM_ABS32:
    case llvm::ELF::R_ARM_ABS32_NOI: {
      // If buiding PIC object (shared library or PIC executable),
      // a dynamic relocations with RELATIVE type to this location is needed.
      // Reserve an entry in .rel.dyn
      if(isPIC(pLDInfo, pOutput)) {
        // create .rel.dyn section if not exist
        if(NULL == m_pRelDyn)
          createARMRelDyn(pLinker, pOutput);
        m_pRelDyn->reserveEntry(*m_pRelocFactory);
        // set Rel bit
        rsym->setReserved(rsym->reserved() | 0x1u);
        }
      return;
    }

    case llvm::ELF::R_ARM_ABS16:
    case llvm::ELF::R_ARM_ABS12:
    case llvm::ELF::R_ARM_THM_ABS5:
    case llvm::ELF::R_ARM_ABS8:
    case llvm::ELF::R_ARM_BASE_ABS:
    case llvm::ELF::R_ARM_MOVW_ABS_NC:
    case llvm::ELF::R_ARM_MOVT_ABS:
    case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
    case llvm::ELF::R_ARM_THM_MOVT_ABS: {
      // Update value keep in relocation place if we meet a section symbol
      if(rsym->type() == ResolveInfo::Section) {
        pReloc.target() = pLinker.getLayout().getOutputOffset(
                            *pInputSym.fragRef()) + pReloc.target();
      }

      // If building PIC object (shared library or PIC executable),
      // a dynamic relocation for this location is needed.
      // Reserve an entry in .rel.dyn
      if(isPIC(pLDInfo, pOutput)) {
        checkValidReloc(pReloc, pLDInfo, pOutput);
        // create .rel.dyn section if not exist
        if(NULL == m_pRelDyn)
          createARMRelDyn(pLinker, pOutput);
        m_pRelDyn->reserveEntry(*m_pRelocFactory);
        // set Rel bit
        rsym->setReserved(rsym->reserved() | 0x1u);
      }
      return;
    }
    case llvm::ELF::R_ARM_GOTOFF32:
    case llvm::ELF::R_ARM_GOTOFF12: {
      // A GOT section is needed
      if(NULL == m_pGOT)
        createARMGOT(pLinker, pOutput);
      return;
    }

    // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
    // Ref: GNU gold 1.11 arm.cc, line 9892
    case llvm::ELF::R_ARM_TARGET2:
      pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
    case llvm::ELF::R_ARM_GOT_BREL:
    case llvm::ELF::R_ARM_GOT_PREL: {
      // A GOT entry is needed for these relocation type.
      // return if we already create GOT for this symbol
      if(rsym->reserved() & 0x6u)
        return;
      if(NULL == m_pGOT)
        createARMGOT(pLinker, pOutput);
      m_pGOT->reserveEntry();
      // If building PIC object, a dynamic relocation with
      // type RELATIVE is needed to relocate this GOT entry.
      // Reserve an entry in .rel.dyn
      if(isPIC(pLDInfo, pOutput)) {
        // create .rel.dyn section if not exist
        if(NULL == m_pRelDyn)
          createARMRelDyn(pLinker, pOutput);
        m_pRelDyn->reserveEntry(*m_pRelocFactory);
        // set GOTRel bit
        rsym->setReserved(rsym->reserved() | 0x4u);
        return;
      }
      // set GOT bit
      rsym->setReserved(rsym->reserved() | 0x2u);
      return;
    }

    case llvm::ELF::R_ARM_BASE_PREL: {
      // FIXME: Currently we only support R_ARM_BASE_PREL against
      // symbol _GLOBAL_OFFSET_TABLE_
      if(rsym != m_pGOTSymbol->resolveInfo()) {
        llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
                                 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
                                 llvm::Twine(rsym->name()) +
                                 llvm::Twine(".'"));
      }
      return;
    }
    case llvm::ELF::R_ARM_COPY:
    case llvm::ELF::R_ARM_GLOB_DAT:
    case llvm::ELF::R_ARM_JUMP_SLOT:
    case llvm::ELF::R_ARM_RELATIVE: {
      // These are relocation type for dynamic linker, shold not
      // appear in object file.
      llvm::report_fatal_error(llvm::Twine("unexpected reloc ") +
                               llvm::Twine((int)pReloc.type()) +
                               llvm::Twine(" in object file"));
      break;
    }
    default: {
      break;
    }
  } // end switch
}
Esempio n. 21
0
// R_HEX_GOT_LO16 and its class : (G) Signed Truncate
// Exception: R_HEX_GOT_16(_X): signed verify
// Exception: R_HEX_GOT_11_X : unsigned truncate
Relocator::Result relocGOT(Relocation& pReloc, HexagonRelocator& pParent) {
  if (!(pReloc.symInfo()->reserved() & HexagonRelocator::ReserveGOT)) {
    return Relocator::BadReloc;
  }

  // set got entry value if needed
  HexagonGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
  assert(got_entry != NULL);
  if (HexagonRelocator::SymVal == got_entry->getValue())
    got_entry->setValue(pReloc.symValue());

  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
  Relocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
  int32_t result = (int32_t)(GOT_S - GOT);
  uint32_t effectiveBits = 0;
  uint32_t alignment = 1;
  uint32_t bitMask = 0;
  uint32_t result_u;
  uint32_t shift = 0;

  switch (pReloc.type()) {
    case llvm::ELF::R_HEX_GOT_LO16:
      bitMask = 0x00c03fff;
      break;

    case llvm::ELF::R_HEX_GOT_HI16:
      bitMask = 0x00c03fff;
      shift = 16;
      alignment = 4;
      break;

    case llvm::ELF::R_HEX_GOT_32:
      bitMask = 0xffffffff;
      break;

    case llvm::ELF::R_HEX_GOT_16:
      bitMask = FINDBITMASK(pReloc.target());
      effectiveBits = 16;
      break;

    case llvm::ELF::R_HEX_GOT_32_6_X:
      bitMask = 0xfff3fff;
      shift = 6;
      break;

    case llvm::ELF::R_HEX_GOT_16_X:
      bitMask = FINDBITMASK(pReloc.target());
      effectiveBits = 6;
      break;

    case llvm::ELF::R_HEX_GOT_11_X:
      bitMask = FINDBITMASK(pReloc.target());
      result_u = GOT_S - GOT;
      pReloc.target() |= ApplyMask<uint32_t>(bitMask, result_u);
      return Relocator::OK;

    default:
      // show proper error
      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
                                          << "*****@*****.**";
  }

  if ((shift != 0) && (result % alignment != 0))
    return Relocator::BadReloc;

  result >>= shift;

  if (effectiveBits) {
    int32_t range = 1 << (effectiveBits - 1);
    if ((result > range - 1) || (result < -range))
      return Relocator::Overflow;
  }
  pReloc.target() |= ApplyMask<int32_t>(bitMask, result);
  return Relocator::OK;
}