예제 #1
0
void HexagonRelocator::scanLocalReloc(Relocation& pReloc,
                                      IRBuilder& pBuilder,
                                      Module& pModule,
                                      LDSection& pSection) {
  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();

  switch (pReloc.type()) {
    case llvm::ELF::R_HEX_LO16:
    case llvm::ELF::R_HEX_HI16:
    case llvm::ELF::R_HEX_16:
    case llvm::ELF::R_HEX_8:
    case llvm::ELF::R_HEX_32_6_X:
    case llvm::ELF::R_HEX_16_X:
    case llvm::ELF::R_HEX_12_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:
      assert(!(rsym->reserved() & ReserveRel) &&
             "Cannot apply this relocation for read only section");
      return;

    case llvm::ELF::R_HEX_32:
      // 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 (config().isCodeIndep()) {
        Relocation& reloc = helper_DynRel_init(rsym,
                                               *pReloc.targetRef().frag(),
                                               pReloc.targetRef().offset(),
                                               llvm::ELF::R_HEX_RELATIVE,
                                               *this);
        // we need to set up the relocation addend at apply relocation, record
        // the
        // relocation
        getRelRelMap().record(pReloc, reloc);

        // set Rel bit
        rsym->setReserved(rsym->reserved() | ReserveRel);
        getTarget().checkAndSetHasTextRel(*pSection.getLink());
      }
      return;

    default:
      return;
  }
}
예제 #2
0
Relocator::Result relocPCREL(Relocation& pReloc, HexagonRelocator& pParent) {
  ResolveInfo* rsym = pReloc.symInfo();
  int64_t result;

  Relocator::Address S = pReloc.symValue();
  Relocator::DWord A = pReloc.addend();
  Relocator::DWord P = pReloc.place();

  FragmentRef& target_fragref = pReloc.targetRef();
  Fragment* target_frag = target_fragref.frag();
  LDSection& target_sect = target_frag->getParent()->getSection();

  result = (int64_t)(S + A - P);

  // for relocs inside non ALLOC, just apply
  if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0) {
    return applyRel(pReloc, result);
  }

  if (!rsym->isLocal()) {
    if (rsym->reserved() & HexagonRelocator::ReservePLT) {
      S = helper_get_PLT_address(*rsym, pParent);
      result = (int64_t)(S + A - P);
      applyRel(pReloc, result);
      return Relocator::OK;
    }
  }

  return applyRel(pReloc, result);
}
// 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;
}
void Relocator::issueUndefRef(Relocation& pReloc,
                              LDSection& pSection,
                              Input& pInput)
{
  FragmentRef::Offset undef_sym_pos = pReloc.targetRef().offset();
  std::string sect_name(pSection.name());
  sect_name = sect_name.substr(sect_name.find('.', /*pos=*/1));  // Drop .rel(a) prefix

  std::string reloc_sym(pReloc.symInfo()->name());
  if (reloc_sym.substr(0, 2) == "_Z")
    reloc_sym = demangleSymbol(reloc_sym);

  std::stringstream ss;
  ss << "0x" << std::hex << undef_sym_pos;
  std::string undef_sym_pos_hex(ss.str());

  if (sect_name.substr(0, 5) != ".text") {
    // Function name is only valid for text section
    fatal(diag::undefined_reference) << reloc_sym
                                     << pInput.path()
                                     << sect_name
                                     << undef_sym_pos_hex;
    return;
  }

  std::string caller_file_name;
  std::string caller_func_name;
  for (LDContext::sym_iterator i = pInput.context()->symTabBegin(),
       e = pInput.context()->symTabEnd(); i != e; ++i) {
    LDSymbol& sym = **i;
    if (sym.resolveInfo()->type() == ResolveInfo::File)
      caller_file_name = sym.resolveInfo()->name();

    if (sym.resolveInfo()->type() == ResolveInfo::Function &&
        sym.value() <= undef_sym_pos &&
        sym.value() + sym.size() > undef_sym_pos) {
      caller_func_name = sym.name();
      break;
    }
  }

  if (caller_func_name.substr(0, 2) == "_Z")
    caller_func_name = demangleSymbol(caller_func_name);

  fatal(diag::undefined_reference_text) << reloc_sym
                                        << pInput.path()
                                        << caller_file_name
                                        << caller_func_name;
}
// 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;
}
// Get an relocation entry in .rel.dyn and set its type to pType,
// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo()
static
void helper_DynRel(Relocation& pReloc,
                   X86RelocationFactory::Type pType,
                   X86RelocationFactory& pParent)
{
  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();
  X86GNULDBackend& ld_backend = pParent.getTarget();
  bool exist;

  Relocation& rel_entry =
    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
  rel_entry.setType(pType);
  rel_entry.targetRef() = pReloc.targetRef();

  if(pType == llvm::ELF::R_386_RELATIVE)
    rel_entry.setSymInfo(0);
  else
    rel_entry.setSymInfo(rsym);
}
예제 #7
0
Relocator::Result relocAbs(Relocation& pReloc, HexagonRelocator& pParent) {
  ResolveInfo* rsym = pReloc.symInfo();
  Relocator::Address S = pReloc.symValue();
  Relocator::DWord A = pReloc.addend();

  Relocation* rel_entry = pParent.getRelRelMap().lookUp(pReloc);
  bool has_dyn_rel = (rel_entry != NULL);

  // if the flag of target section is not ALLOC, we eprform only static
  // relocation.
  if (0 == (llvm::ELF::SHF_ALLOC &
            pReloc.targetRef().frag()->getParent()->getSection().flag())) {
    return applyAbs(pReloc);
  }

  // a local symbol with .rela type relocation
  if (rsym->isLocal() && has_dyn_rel) {
    rel_entry->setAddend(S + A);
    return Relocator::OK;
  }

  if (!rsym->isLocal()) {
    if (rsym->reserved() & HexagonRelocator::ReservePLT) {
      S = helper_get_PLT_address(*rsym, pParent);
    }

    if (has_dyn_rel) {
      if (llvm::ELF::R_HEX_32 == pReloc.type() &&
          helper_use_relative_reloc(*rsym, pParent)) {
        rel_entry->setAddend(S + A);
      } else {
        rel_entry->setAddend(A);
        return Relocator::OK;
      }
    }
  }

  return applyAbs(pReloc);
}
예제 #8
0
void HexagonRelocator::scanGlobalReloc(Relocation& pReloc,
                                       IRBuilder& pBuilder,
                                       Module& pModule,
                                       LDSection& pSection) {
  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();
  HexagonLDBackend& ld_backend = getTarget();

  switch (pReloc.type()) {
    case llvm::ELF::R_HEX_LO16:
    case llvm::ELF::R_HEX_HI16:
    case llvm::ELF::R_HEX_16:
    case llvm::ELF::R_HEX_8:
    case llvm::ELF::R_HEX_32_6_X:
    case llvm::ELF::R_HEX_16_X:
    case llvm::ELF::R_HEX_12_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:
      assert(!(rsym->reserved() & ReserveRel) &&
             "Cannot apply this relocation for read only section");
      return;

    case llvm::ELF::R_HEX_32:
      if (ld_backend.symbolNeedsPLT(*rsym)) {
        // create PLT for this symbol if it does not have.
        if (!(rsym->reserved() & ReservePLT)) {
          helper_PLT_init(pReloc, *this);
          rsym->setReserved(rsym->reserved() | ReservePLT);
        }
      }

      if (ld_backend.symbolNeedsDynRel(
              *rsym, (rsym->reserved() & ReservePLT), true)) {
        if (ld_backend.symbolNeedsCopyReloc(pReloc, *rsym)) {
          LDSymbol& cpy_sym =
              defineSymbolforCopyReloc(pBuilder, *rsym, ld_backend);
          addCopyReloc(*cpy_sym.resolveInfo(), ld_backend);
        } else {
          Relocation& reloc = helper_DynRel_init(rsym,
                                                 *pReloc.targetRef().frag(),
                                                 pReloc.targetRef().offset(),
                                                 llvm::ELF::R_HEX_RELATIVE,
                                                 *this);
          // we need to set up the relocation addend at apply relocation, record
          // the
          // relocation
          getRelRelMap().record(pReloc, reloc);
          rsym->setReserved(rsym->reserved() | ReserveRel);
          ld_backend.checkAndSetHasTextRel(*pSection.getLink());
        }
      }
      return;

    case llvm::ELF::R_HEX_GOTREL_LO16:
    case llvm::ELF::R_HEX_GOTREL_HI16:
    case llvm::ELF::R_HEX_GOTREL_32:
    case llvm::ELF::R_HEX_GOTREL_32_6_X:
    case llvm::ELF::R_HEX_GOTREL_16_X:
    case llvm::ELF::R_HEX_GOTREL_11_X:
      // This assumes that GOT exists
      return;

    case llvm::ELF::R_HEX_GOT_LO16:
    case llvm::ELF::R_HEX_GOT_HI16:
    case llvm::ELF::R_HEX_GOT_32:
    case llvm::ELF::R_HEX_GOT_16:
    case llvm::ELF::R_HEX_GOT_32_6_X:
    case llvm::ELF::R_HEX_GOT_16_X:
    case llvm::ELF::R_HEX_GOT_11_X:
      // Symbol needs GOT entry, reserve entry in .got
      // return if we already create GOT for this symbol
      if (rsym->reserved() & ReserveGOT)
        return;
      // If the GOT is used in statically linked binaries,
      // the GOT entry is enough and no relocation is needed.
      if (config().isCodeStatic())
        helper_GOT_init(pReloc, false, *this);
      else
        helper_GOT_init(pReloc, true, *this);
      // set GOT bit
      rsym->setReserved(rsym->reserved() | ReserveGOT);
      return;

    case llvm::ELF::R_HEX_B22_PCREL:
    case llvm::ELF::R_HEX_B15_PCREL:
    case llvm::ELF::R_HEX_B7_PCREL:
    case llvm::ELF::R_HEX_B13_PCREL:
    case llvm::ELF::R_HEX_B9_PCREL:
    case llvm::ELF::R_HEX_B32_PCREL_X:
    case llvm::ELF::R_HEX_B22_PCREL_X:
    case llvm::ELF::R_HEX_B15_PCREL_X:
    case llvm::ELF::R_HEX_B13_PCREL_X:
    case llvm::ELF::R_HEX_B9_PCREL_X:
    case llvm::ELF::R_HEX_B7_PCREL_X:
    case llvm::ELF::R_HEX_32_PCREL:
    case llvm::ELF::R_HEX_6_PCREL_X:
    case llvm::ELF::R_HEX_PLT_B22_PCREL:
      if (rsym->reserved() & ReservePLT)
        return;
      if (ld_backend.symbolNeedsPLT(*rsym) ||
          pReloc.type() == llvm::ELF::R_HEX_PLT_B22_PCREL) {
        helper_PLT_init(pReloc, *this);
        rsym->setReserved(rsym->reserved() | ReservePLT);
      }
      return;

    default:
      break;
  }  // end of switch
}