static
PLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
                                  X86RelocationFactory& pParent)
{
  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();
  X86GNULDBackend& ld_backend = pParent.getTarget();

  bool exist;
  PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
  if (!exist) {
    // If we first get this PLT entry, we should initialize it.
    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
      GOTEntry& gotplt_entry =
        *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
      // Initialize corresponding dynamic relocation.
      Relocation& rel_entry =
        *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
      assert(!exist && "PLT entry not exist, but DynRel entry exist!");
      rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
      rel_entry.targetRef().assign(gotplt_entry);
      rel_entry.setSymInfo(rsym);
    }
    else {
      llvm::report_fatal_error("No PLT entry reserved for PLT type relocation!");
    }
  }
  return plt_entry;
}
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);
}
void ARMGNULDBackend::scanRelocation(Relocation& pReloc,
                                     const LDSymbol& pInputSym,
                                     MCLinker& pLinker,
                                     const MCLDInfo& pLDInfo,
                                     const Output& pOutput)
{
  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();
  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");

  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
  // entries should be created.
  // FIXME: Below judgements concern only .so is generated as output
  // FIXME: Below judgements concern nothing about TLS related relocation

  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section
  // is needed
  if(NULL == m_pGOT && NULL != m_pGOTSymbol) {
    if(rsym == m_pGOTSymbol->resolveInfo()) {
      createARMGOT(pLinker, pOutput);
    }
  }

  // rsym is local
  if(rsym->isLocal())
    scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);

  // rsym is external
  else
    scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);

}
void GarbageCollection::setUpReachedSections()
{
  // traverse all the input relocations to setup the reached sections
  Module::obj_iterator input, inEnd = m_Module.obj_end();
  for (input = m_Module.obj_begin(); input != inEnd; ++input) {
    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
      // bypass the discarded relocation section
      // 1. its section kind is changed to Ignore. (The target section is a
      // discarded group section.)
      // 2. it has no reloc data. (All symbols in the input relocs are in the
      // discarded group sections)
      LDSection* reloc_sect = *rs;
      LDSection* apply_sect = reloc_sect->getLink();
      if ((LDFileFormat::Ignore == reloc_sect->kind()) ||
          (!reloc_sect->hasRelocData()))
        continue;

      // bypass the apply target sections which are not handled by gc (currently
      // we only handle the Regular and BSS sections)
      if (apply_sect->kind() != LDFileFormat::Regular &&
          apply_sect->kind() != LDFileFormat::BSS)
        continue;

      bool add_first = false;
      SectionListTy* reached_sects = NULL;
      RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end();
      for (reloc_it = reloc_sect->getRelocData()->begin(); reloc_it != rEnd;
                                                                   ++reloc_it) {
        Relocation* reloc = llvm::cast<Relocation>(reloc_it);
        ResolveInfo* sym = reloc->symInfo();
        // only the target symbols defined in the input fragments can make the
        // reference
        if (NULL == sym)
          continue;
        if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
          continue;

        // only the target symbols defined in the concerned sections can make
        // the reference
        const LDSection* target_sect =
                &sym->outSymbol()->fragRef()->frag()->getParent()->getSection();
        if (target_sect->kind() != LDFileFormat::Regular &&
            target_sect->kind() != LDFileFormat::BSS)
          continue;

        // setup the reached list, if we first add the element to reached list
        // of this section, create an entry in ReachedSections map
        if (!add_first) {
          assert(NULL == reached_sects);
          reached_sects = &m_ReachedSections[apply_sect];
          add_first = true;
        }
        reached_sects->insert(target_sect);
      }
      reached_sects = NULL;
      add_first = false;
    }
  }
}
/// helper_use_relative_reloc - Check if symbol can use relocation
/// R_HEX_RELATIVE
static bool helper_use_relative_reloc(const ResolveInfo& pSym,
                                      const HexagonRelocator& pFactory) {
  // if symbol is dynamic or undefine or preemptible
  if (pSym.isDyn() || pSym.isUndef() ||
      pFactory.getTarget().isSymbolPreemptible(pSym))
    return false;
  return true;
}
void HexagonRelocator::addCopyReloc(ResolveInfo& pSym,
                                    HexagonLDBackend& pTarget) {
  Relocation& rel_entry = *pTarget.getRelaDyn().create();
  rel_entry.setType(pTarget.getCopyRelType());
  assert(pSym.outSymbol()->hasFragRef());
  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
  rel_entry.setSymInfo(&pSym);
}
bool ARMGNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym,
                                       const MCLDInfo& pLDInfo,
                                       const Output& pOutput) const
{
  return (Output::DynObj == pOutput.type() &&
          ResolveInfo::Function == pSym.type() &&
          (pSym.isDyn() || pSym.isUndef() ||
            isSymbolPreemptible(pSym, pLDInfo, pOutput)));
}
static bool isSymCtorOrDtor(const ResolveInfo& pSym) {
  // We can always fold ctors and dtors since accessing function pointer in C++
  // is forbidden.
  llvm::StringRef name(pSym.name(), pSym.nameSize());
  if (!name.startswith("_ZZ") && !name.startswith("_ZN")) {
    return false;
  }
  return isCtorOrDtor(pSym.name(), pSym.nameSize());
}
// 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;
}
// Check if symbol can use relocation R_386_RELATIVE
static bool
helper_use_relative_reloc(const ResolveInfo& pSym,
                          const MCLDInfo& pLDInfo,
                          const X86RelocationFactory& pFactory)

{
  // if symbol is dynamic or undefine or preemptible
  if(pSym.isDyn() ||
     pSym.isUndef() ||
     pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output()))
    return false;
  return true;
}
//===----------------------------------------------------------------------===//
// Category
SymbolCategory::Category::Type
SymbolCategory::Category::categorize(const ResolveInfo& pInfo)
{
  if (ResolveInfo::File == pInfo.type())
    return Category::File;
  if (ResolveInfo::Local == pInfo.binding())
    return Category::Local;
  if (ResolveInfo::Common == pInfo.desc())
    return Category::Common;
  if (ResolveInfo::Default   == pInfo.visibility() ||
      ResolveInfo::Protected == pInfo.visibility())
    return Category::Dynamic;
  return Category::Regular;
}
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;
  }
}
bool ARMGNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym,
                                          const Output& pOutput,
                                          bool isAbsReloc) const
{
  if(pSym.isUndef() && (Output::Exec == pOutput.type()))
    return false;
  if(pSym.isAbsolute())
    return false;
  if(Output::DynObj == pOutput.type() && isAbsReloc)
    return true;
  if(pSym.isDyn() || pSym.isUndef())
    return true;

  return false;
}
Example #14
0
void DebugString::applyOffset(Relocation& pReloc, TargetLDBackend& pBackend) {
  // get the refered string
  ResolveInfo* info = pReloc.symInfo();
  // the symbol should point to the first region fragment in the debug
  // string section, get the input .debut_str region
  llvm::StringRef d_str;
  if (info->outSymbol()->fragRef()->frag()->getKind() == Fragment::Region) {
    RegionFragment* frag =
        llvm::cast<RegionFragment>(info->outSymbol()->fragRef()->frag());
    d_str = frag->getRegion();
  }
  uint32_t offset = pBackend.getRelocator()->getDebugStringOffset(pReloc);
  const char* str = d_str.data() + offset;

  // apply the relocation
  pBackend.getRelocator()->applyDebugStringOffset(pReloc,
      m_StringTable.getOutputOffset(llvm::StringRef(str, string_length(str))));
}
void NyuziRelocator::scanRelocation(Relocation& pReloc,
                                      IRBuilder& pBuilder,
                                      Module& pModule,
                                      LDSection& pSection,
                                      Input& pInput)
{
  ResolveInfo* rsym = pReloc.symInfo();
  assert(NULL != rsym &&
         "ResolveInfo of relocation not set while scanRelocation");

  assert(NULL != pSection.getLink());
  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
    return;

  // check if we shoule issue undefined reference for the relocation target
  // symbol
  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
    issueUndefRef(pReloc, pSection, pInput);
}
// 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;
}
static
GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
                                  const MCLDInfo& pLDInfo,
                                  X86RelocationFactory& pParent)
{
  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();
  X86GNULDBackend& ld_backend = pParent.getTarget();

  bool exist;
  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
  if (!exist) {
    // If we first get this GOT entry, we should initialize it.
    if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
      // No corresponding dynamic relocation, initialize to the symbol value.
      got_entry.setContent(pReloc.symValue());
    }
    else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
      // Initialize corresponding dynamic relocation.
      Relocation& rel_entry =
        *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
      assert(!exist && "GOT entry not exist, but DynRel entry exist!");
      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
        // Initialize got entry to target symbol address
        got_entry.setContent(pReloc.symValue());
        rel_entry.setType(llvm::ELF::R_386_RELATIVE);
        rel_entry.setSymInfo(0);
      }
      else {
        got_entry.setContent(0);
        rel_entry.setType(llvm::ELF::R_386_GLOB_DAT);
        rel_entry.setSymInfo(rsym);
      }
      rel_entry.targetRef().assign(got_entry);
    }
    else {
      llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
    }
  }
  return got_entry;
}
bool MipsGOT::reserveLocalEntry(ResolveInfo& pInfo)
{
  if (pInfo.type() != ResolveInfo::Section) {
    if (m_InputLocalSymbols.count(&pInfo))
      return false;

    if (m_MergedLocalSymbols.count(&pInfo)) {
      m_InputLocalSymbols.insert(&pInfo);
      return false;
    }
  }

  if (isGOTFull())
    split();

  if (pInfo.type() != ResolveInfo::Section)
    m_InputLocalSymbols.insert(&pInfo);

  ++m_MultipartList.back().m_LocalNum;
  return true;
}
// 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;
}
void HexagonRelocator::scanRelocation(Relocation& pReloc,
                                      IRBuilder& pLinker,
                                      Module& pModule,
                                      LDSection& pSection,
                                      Input& pInput) {
  if (LinkerConfig::Object == config().codeGenType())
    return;

  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();
  assert(rsym != NULL &&
         "ResolveInfo of relocation not set while scanRelocation");

  if (config().isCodeStatic())
    return;

  assert(pSection.getLink() != NULL);
  if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0)
    return;

  if (rsym->isLocal())  // rsym is local
    scanLocalReloc(pReloc, pLinker, pModule, pSection);
  else  // rsym is external
    scanGlobalReloc(pReloc, pLinker, pModule, pSection);

  // check if we should issue undefined reference for the relocation target
  // symbol
  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
    issueUndefRef(pReloc, pSection, pInput);
}
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);
}
Example #22
0
bool MipsGOT::reserveGlobalEntry(ResolveInfo& pInfo)
{
  if (m_InputGlobalSymbols.count(&pInfo))
    return false;

  if (m_MergedGlobalSymbols.count(&pInfo)) {
    m_InputGlobalSymbols[&pInfo] = false;
    return false;
  }

  if (isGOTFull())
    split();

  m_InputGlobalSymbols[&pInfo] = true;
  ++m_MultipartList.back().m_GlobalNum;

  if (!(pInfo.reserved() & MipsRelocator::ReserveGot)) {
    m_SymbolOrderMap[pInfo.outSymbol()] = m_SymbolOrderMap.size();
    pInfo.setReserved(pInfo.reserved() | MipsRelocator::ReserveGot);
  }

  return true;
}
bool ARMGNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
                                          const MCLDInfo& pLDInfo,
                                          const Output& pOutput) const
{
  if(pSym.other() != ResolveInfo::Default)
    return false;

  if(Output::DynObj != pOutput.type())
    return false;

  if(pLDInfo.options().Bsymbolic())
    return false;

  return true;
}
/// createSymbol - create a symbol
ResolveInfo* StrSymPool::createSymbol(const llvm::StringRef& pName,
                                      bool pIsDyn,
                                      ResolveInfo::Type pType,
                                      ResolveInfo::Desc pDesc,
                                      ResolveInfo::Binding pBinding,
                                      ResolveInfo::SizeType pSize,
                                      ResolveInfo::Visibility pVisibility)
{
  ResolveInfo* result = m_Table.getEntryFactory().produce(pName);
  result->setIsSymbol(true);
  result->setSource(pIsDyn);
  result->setType(pType);
  result->setDesc(pDesc);
  result->setBinding(pBinding);
  result->setVisibility(pVisibility);
  result->setSize(pSize);
  return result;
}
void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc,
                                      const LDSymbol& pInputSym,
                                      MCLinker& pLinker,
                                      const MCLDInfo& pLDInfo,
                                      const Output& pOutput)
{
  // rsym - The relocation target symbol
  ResolveInfo* rsym = pReloc.symInfo();

  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_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:
    case llvm::ELF::R_ARM_ABS32_NOI: {
      // Absolute relocation type, symbol may needs PLT entry or
      // dynamic relocation entry
      if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
        // create plt for this symbol if it does not have one
        if(!(rsym->reserved() & 0x8u)){
          // Create .got section if it doesn't exist
          if(NULL == m_pGOT)
            createARMGOT(pLinker, pOutput);
          // create .plt and .rel.plt if not exist
          if(NULL == m_pPLT)
            createARMPLTandRelPLT(pLinker, pOutput);
          // Symbol needs PLT entry, we need to reserve a PLT entry
          // and the corresponding GOT and dynamic relocation entry
          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
          // when calling ARMPLT->reserveEntry())
          m_pPLT->reserveEntry();
          m_pRelPLT->reserveEntry(*m_pRelocFactory);
          // set PLT bit
          rsym->setReserved(rsym->reserved() | 0x8u);
        }
      }

      if(isSymbolNeedsDynRel(*rsym, pOutput, true)) {
        checkValidReloc(pReloc, pLDInfo, pOutput);
        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
        // 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;
    }

    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(".'"));
      }
    case llvm::ELF::R_ARM_REL32:
    case llvm::ELF::R_ARM_LDR_PC_G0:
    case llvm::ELF::R_ARM_SBREL32:
    case llvm::ELF::R_ARM_THM_PC8:
    case llvm::ELF::R_ARM_MOVW_PREL_NC:
    case llvm::ELF::R_ARM_MOVT_PREL:
    case llvm::ELF::R_ARM_THM_MOVW_PREL_NC:
    case llvm::ELF::R_ARM_THM_MOVT_PREL:
    case llvm::ELF::R_ARM_THM_ALU_PREL_11_0:
    case llvm::ELF::R_ARM_THM_PC12:
    case llvm::ELF::R_ARM_REL32_NOI:
    case llvm::ELF::R_ARM_ALU_PC_G0_NC:
    case llvm::ELF::R_ARM_ALU_PC_G0:
    case llvm::ELF::R_ARM_ALU_PC_G1_NC:
    case llvm::ELF::R_ARM_ALU_PC_G1:
    case llvm::ELF::R_ARM_ALU_PC_G2:
    case llvm::ELF::R_ARM_LDR_PC_G1:
    case llvm::ELF::R_ARM_LDR_PC_G2:
    case llvm::ELF::R_ARM_LDRS_PC_G0:
    case llvm::ELF::R_ARM_LDRS_PC_G1:
    case llvm::ELF::R_ARM_LDRS_PC_G2:
    case llvm::ELF::R_ARM_LDC_PC_G0:
    case llvm::ELF::R_ARM_LDC_PC_G1:
    case llvm::ELF::R_ARM_LDC_PC_G2:
    case llvm::ELF::R_ARM_ALU_SB_G0_NC:
    case llvm::ELF::R_ARM_ALU_SB_G0:
    case llvm::ELF::R_ARM_ALU_SB_G1_NC:
    case llvm::ELF::R_ARM_ALU_SB_G1:
    case llvm::ELF::R_ARM_ALU_SB_G2:
    case llvm::ELF::R_ARM_LDR_SB_G0:
    case llvm::ELF::R_ARM_LDR_SB_G1:
    case llvm::ELF::R_ARM_LDR_SB_G2:
    case llvm::ELF::R_ARM_LDRS_SB_G0:
    case llvm::ELF::R_ARM_LDRS_SB_G1:
    case llvm::ELF::R_ARM_LDRS_SB_G2:
    case llvm::ELF::R_ARM_LDC_SB_G0:
    case llvm::ELF::R_ARM_LDC_SB_G1:
    case llvm::ELF::R_ARM_LDC_SB_G2:
    case llvm::ELF::R_ARM_MOVW_BREL_NC:
    case llvm::ELF::R_ARM_MOVT_BREL:
    case llvm::ELF::R_ARM_MOVW_BREL:
    case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
    case llvm::ELF::R_ARM_THM_MOVT_BREL:
    case llvm::ELF::R_ARM_THM_MOVW_BREL: {
      // Relative addressing relocation, may needs dynamic relocation
      if(isSymbolNeedsDynRel(*rsym, pOutput, false)) {
        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_THM_CALL:
    case llvm::ELF::R_ARM_PLT32:
    case llvm::ELF::R_ARM_CALL:
    case llvm::ELF::R_ARM_JUMP24:
    case llvm::ELF::R_ARM_THM_JUMP24:
    case llvm::ELF::R_ARM_SBREL31:
    case llvm::ELF::R_ARM_PREL31:
    case llvm::ELF::R_ARM_THM_JUMP19:
    case llvm::ELF::R_ARM_THM_JUMP6:
    case llvm::ELF::R_ARM_THM_JUMP11:
    case llvm::ELF::R_ARM_THM_JUMP8: {
      // These are branch relocation (except PREL31)
      // A PLT entry is needed when building shared library

      // return if we already create plt for this symbol
      if(rsym->reserved() & 0x8u)
        return;

      // if symbol is defined in the ouput file and it's not
      // preemptible, no need plt
      if(rsym->isDefine() && !rsym->isDyn() &&
         !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
        return;
      }

      // Create .got section if it doesn't exist
      if(NULL == m_pGOT)
        createARMGOT(pLinker, pOutput);

      // create .plt and .rel.plt if not exist
      if(NULL == m_pPLT)
         createARMPLTandRelPLT(pLinker, pOutput);
      // Symbol needs PLT entry, we need to reserve a PLT entry
      // and the corresponding GOT and dynamic relocation entry
      // in .got and .rel.plt. (GOT entry will be reserved simultaneously
      // when calling ARMPLT->reserveEntry())
      m_pPLT->reserveEntry();
      m_pRelPLT->reserveEntry(*m_pRelocFactory);
      // set PLT bit
      rsym->setReserved(rsym->reserved() | 0x8u);
      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_ABS:
    case llvm::ELF::R_ARM_GOT_PREL: {
      // Symbol needs GOT entry, reserve entry in .got
      // 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 shared object or the symbol is undefined, a dynamic
      // relocation is needed to relocate this GOT entry. Reserve an
      // entry in .rel.dyn
      if(Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
        // 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_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
}
TEST_F( StaticResolverTest, SetUpDesc)
{
  ResolveInfo* sym = ResolveInfo::Create("abc");
  
  sym->setIsSymbol(true);

//  ASSERT_FALSE( sym->isSymbol() );
  ASSERT_TRUE( sym->isSymbol() );
  ASSERT_TRUE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_TRUE( sym->isUndef() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( 0 == sym->desc() );
  ASSERT_TRUE( 0 == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );

  sym->setIsSymbol(false);
  ASSERT_FALSE( sym->isSymbol() );
//  ASSERT_TRUE( sym->isSymbol() );
  ASSERT_TRUE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_TRUE( sym->isUndef() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( 0 == sym->desc() );
  ASSERT_TRUE( 0 == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );

  sym->setDesc(ResolveInfo::Define);
  ASSERT_FALSE( sym->isSymbol() );
//  ASSERT_TRUE( sym->isSymbol() );
  ASSERT_TRUE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_TRUE( sym->isDefine() );
  ASSERT_FALSE( sym->isUndef() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( ResolveInfo::Define == sym->desc() );
  ASSERT_TRUE( 0 == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );

  sym->setDesc(ResolveInfo::Common);
  ASSERT_FALSE( sym->isSymbol() );
//  ASSERT_TRUE( sym->isSymbol() );
  ASSERT_TRUE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_FALSE( sym->isUndef() );
  ASSERT_TRUE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( ResolveInfo::Common == sym->desc() );
  ASSERT_TRUE( 0 == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );

  sym->setDesc(ResolveInfo::Indirect);
  ASSERT_FALSE( sym->isSymbol() );
  ASSERT_TRUE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_FALSE( sym->isUndef() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_TRUE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( ResolveInfo::Indirect == sym->desc() );
  ASSERT_TRUE( 0 == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );

  sym->setDesc(ResolveInfo::Undefined);
  ASSERT_FALSE( sym->isSymbol() );
  ASSERT_TRUE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_TRUE( sym->isUndef() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( 0 == sym->desc() );
  ASSERT_TRUE( 0 == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );
}
void Resolver::Resolve()
{
	for (int i = 1; i <= g_GlobalVars->maxClients; i++)
	{
		auto &record = arr_infos[i];
		if (!record.m_bActive)
			continue;

		C_BasePlayer *player = C_BasePlayer::GetPlayerByIndex(i);
		if (!player || !player->IsAlive() || player->IsDormant() || player == g_LocalPlayer)
			continue;

		if (record.m_flVelocity == 0.f && player->m_vecVelocity().Length2D() != 0.f)
		{
			Math::VectorAngles(player->m_vecVelocity(), record.m_angDirectionFirstMoving);
			record.m_nCorrectedFakewalkIdx = 0;
		}

		auto firedShots = g_LocalPlayer->m_iShotsFired();

		if (g_Options.debug_fliponkey)
		{
			float_t new_yaw = player->m_flLowerBodyYawTarget();
			if (g_InputSystem->IsButtonDown(g_Options.debug_flipkey))
				new_yaw += 180.f;
			new_yaw = Math::ClampYaw(new_yaw);
			player->m_angEyeAngles().yaw = new_yaw;
			return;
		}

		if (g_Options.hvh_resolver_override && g_InputSystem->IsButtonDown(g_Options.hvh_resolver_override_key))
		{
			Override(); //needs an improvement sometimes f****d up xD

			Global::resolverModes[player->EntIndex()] = "Overriding";

			return;
		}

		AnimationLayer curBalanceLayer, prevBalanceLayer;

		ResolveInfo curtickrecord;
		curtickrecord.SaveRecord(player);

		if ((player->m_fFlags() & FL_ONGROUND) && (IsFakewalking(player, curtickrecord) || (player->m_vecVelocity().Length2D() > 0.1f && player->m_vecVelocity().Length2D() < 45.f && !(player->m_fFlags() & FL_DUCKING)))) //Fakewalk, shiftwalk check // We have to rework the fakewalk resolving, it sucks :D
		{
			float_t new_yaw = ResolveFakewalk(player, curtickrecord);
			new_yaw = Math::ClampYaw(new_yaw);

			player->m_angEyeAngles().yaw = new_yaw;

			Global::resolverModes[player->EntIndex()] = "Fakewalking";

			continue;
		}
		if (IsEntityMoving(player))
		{
			float_t new_yaw = player->m_flLowerBodyYawTarget();
			new_yaw = Math::ClampYaw(new_yaw);

			player->m_angEyeAngles().yaw = new_yaw;

			record.m_flStandingTime = player->m_flSimulationTime();
			record.m_flMovingLBY = player->m_flLowerBodyYawTarget();
			record.m_bIsMoving = true;

			Global::resolverModes[player->EntIndex()] = "Moving";

			continue;
		}
		if (IsAdjustingBalance(player, curtickrecord, &curBalanceLayer))
		{
			if (fabsf(LBYDelta(curtickrecord)) > 35.f)
			{
				float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
				new_yaw = Math::ClampYaw(new_yaw);

				player->m_angEyeAngles().yaw = new_yaw;

				Global::resolverModes[player->EntIndex()] = "Fakehead (delta > 35)";
			}
			if (IsAdjustingBalance(player, record, &prevBalanceLayer))
			{
				if ((prevBalanceLayer.m_flCycle != curBalanceLayer.m_flCycle) || curBalanceLayer.m_flWeight == 1.f)
				{
					float
						flAnimTime = curBalanceLayer.m_flCycle,
						flSimTime = player->m_flSimulationTime();

					if (flAnimTime < 0.01f && prevBalanceLayer.m_flCycle > 0.01f && g_Options.rage_lagcompensation && CMBacktracking::Get().IsTickValid(TIME_TO_TICKS(flSimTime - flAnimTime)))
					{
						CMBacktracking::Get().SetOverwriteTick(player, QAngle(player->m_angEyeAngles().pitch, player->m_flLowerBodyYawTarget(), 0), (flSimTime - flAnimTime), 2);
					}

					float_t new_yaw = player->m_flLowerBodyYawTarget();
					new_yaw = Math::ClampYaw(new_yaw);

					player->m_angEyeAngles().yaw = new_yaw;

					Global::resolverModes[player->EntIndex()] = "Breaking LBY";

					continue;
				}
				else if (curBalanceLayer.m_flWeight == 0.f && (prevBalanceLayer.m_flCycle > 0.92f && curBalanceLayer.m_flCycle > 0.92f)) // breaking lby with delta < 120
				{
					if (player->m_flSimulationTime() >= record.m_flStandingTime + 0.22f && record.m_bIsMoving)
					{
						record.m_flLbyDelta = record.m_flLowerBodyYawTarget - player->m_flLowerBodyYawTarget();

						float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
						new_yaw = Math::ClampYaw(new_yaw);

						player->m_angEyeAngles().yaw = new_yaw;

						record.m_bIsMoving = false;

						Global::resolverModes[player->EntIndex()] = "Breaking LBY (delta < 120)";

						continue;
					}

					if (player->m_flSimulationTime() >= record.m_flStandingTime + 1.32f && std::fabsf(record.m_flLbyDelta) < 35.f)
					{
						record.m_flLbyDelta = record.m_flMovingLBY - player->m_flLowerBodyYawTarget();
						float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
						new_yaw = Math::ClampYaw(new_yaw);

						player->m_angEyeAngles().yaw = new_yaw;

						record.m_bIsMoving = false;

						Global::resolverModes[player->EntIndex()] = "LBY delta < 35";

						continue;
					}
				}
			}
			else
			{
				float_t new_yaw = player->m_flLowerBodyYawTarget();
				new_yaw = Math::ClampYaw(new_yaw);

				player->m_angEyeAngles().yaw = new_yaw;

				Global::resolverModes[player->EntIndex()] = "Other";

				continue;
			}
		}
		if (player->m_flSimulationTime() >= record.m_flStandingTime + 0.22f && record.m_bIsMoving)
		{
			record.m_flLbyDelta = record.m_flLowerBodyYawTarget - player->m_flLowerBodyYawTarget();

			float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
			new_yaw = Math::ClampYaw(new_yaw);

			player->m_angEyeAngles().yaw = new_yaw;

			record.m_bIsMoving = false;

			Global::resolverModes[player->EntIndex()] = "Breaking LBY (delta < 120)";

			continue;
		}
		if (player->m_flSimulationTime() >= record.m_flStandingTime + 1.32f && std::fabsf(record.m_flLbyDelta) < 35.f)
		{
			record.m_flLbyDelta = record.m_flMovingLBY - player->m_flLowerBodyYawTarget();
			float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
			new_yaw = Math::ClampYaw(new_yaw);

			player->m_angEyeAngles().yaw = new_yaw;

			record.m_bIsMoving = false;

			Global::resolverModes[player->EntIndex()] = "LBY delta < 35";

			continue;
		}

		float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta;
		new_yaw = Math::ClampYaw(new_yaw);

		player->m_angEyeAngles().yaw = new_yaw;
	}
}
TEST_F( StaticResolverTest, SetUpBinding)
{
  ResolveInfo* sym = ResolveInfo::Create("abc");
  
  sym->setIsSymbol(true);

//  ASSERT_FALSE( sym->isSymbol() );
  ASSERT_TRUE( sym->isSymbol() );
  ASSERT_TRUE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_TRUE( sym->isUndef() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( 0 == sym->desc() );
  ASSERT_TRUE( 0 == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );

  sym->setBinding(ResolveInfo::Global);
  ASSERT_TRUE( sym->isSymbol() );
  ASSERT_TRUE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_TRUE( sym->isUndef() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( 0 == sym->desc() );
  ASSERT_TRUE( ResolveInfo::Global == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );

  sym->setBinding(ResolveInfo::Weak);
  ASSERT_TRUE( sym->isSymbol() );
  ASSERT_FALSE( sym->isGlobal() );
  ASSERT_TRUE( sym->isWeak() );
  ASSERT_FALSE( sym->isLocal() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_TRUE( sym->isUndef() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( 0 == sym->desc() );
  ASSERT_TRUE( ResolveInfo::Weak == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );

  sym->setBinding(ResolveInfo::Local);
  ASSERT_TRUE( sym->isSymbol() );
  ASSERT_FALSE( sym->isGlobal() );
  ASSERT_FALSE( sym->isWeak() );
  ASSERT_TRUE( sym->isLocal() );
  ASSERT_FALSE( sym->isDyn() );
  ASSERT_FALSE( sym->isDefine() );
  ASSERT_TRUE( sym->isUndef() );
  ASSERT_FALSE( sym->isCommon() );
  ASSERT_FALSE( sym->isIndirect() );
  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
  ASSERT_TRUE( 0 == sym->desc() );
  ASSERT_TRUE( ResolveInfo::Local == sym->binding() );
  ASSERT_TRUE( 0 == sym->other() );
}
/// readSections - read all regular sections.
bool ELFObjectReader::readSections(Input& pInput)
{
  // handle sections
  LDContext::sect_iterator section, sectEnd = pInput.context()->sectEnd();
  for (section = pInput.context()->sectBegin(); section != sectEnd; ++section) {
    // ignore the section if the LDSection* in input context is NULL
    if (NULL == *section)
        continue;

    switch((*section)->kind()) {
      /** group sections **/
      case LDFileFormat::Group: {
        assert(NULL != (*section)->getLink());
        ResolveInfo* signature =
            m_pELFReader->readSignature(pInput,
                                        *(*section)->getLink(),
                                        (*section)->getInfo());

        bool exist = false;
        if (0 == signature->nameSize() &&
            ResolveInfo::Section == signature->type()) {
          // if the signature is a section symbol in input object, we use the
          // section name as group signature.
          signatures().insert((*section)->name(), exist);
        } else {
          signatures().insert(signature->name(), exist);
        }

        if (exist) {
          // if this is not the first time we see this group signature, then
          // ignore all the members in this group (set Ignore)
          llvm::StringRef region = pInput.memArea()->request(
               pInput.fileOffset() + (*section)->offset(), (*section)->size());
          const llvm::ELF::Elf32_Word* value =
              reinterpret_cast<const llvm::ELF::Elf32_Word*>(region.begin());

          size_t size = region.size() / sizeof(llvm::ELF::Elf32_Word);
          if (llvm::ELF::GRP_COMDAT == *value) {
            for (size_t index = 1; index < size; ++index) {
              pInput.context()->getSection(value[index])->setKind(LDFileFormat::Ignore);
            }
          }
        }
        ResolveInfo::Destroy(signature);
        break;
      }
      /** linkonce sections **/
      case LDFileFormat::LinkOnce: {
        bool exist = false;
        // .gnu.linkonce + "." + type + "." + name
        llvm::StringRef name(llvm::StringRef((*section)->name()).drop_front(14));
        signatures().insert(name.split(".").second, exist);
        if (!exist) {
          if (name.startswith("wi")) {
            (*section)->setKind(LDFileFormat::Debug);
            if (m_Config.options().stripDebug())
              (*section)->setKind(LDFileFormat::Ignore);
            else {
              SectionData* sd = IRBuilder::CreateSectionData(**section);
              if (!m_pELFReader->readRegularSection(pInput, *sd))
                fatal(diag::err_cannot_read_section) << (*section)->name();
            }
          } else {
            (*section)->setKind(LDFileFormat::Regular);
            SectionData* sd = IRBuilder::CreateSectionData(**section);
            if (!m_pELFReader->readRegularSection(pInput, *sd))
              fatal(diag::err_cannot_read_section) << (*section)->name();
          }
        } else {
          (*section)->setKind(LDFileFormat::Ignore);
        }
        break;
      }
      /** relocation sections **/
      case LDFileFormat::Relocation: {
        assert(NULL != (*section)->getLink());
        size_t link_index = (*section)->getLink()->index();
        LDSection* link_sect = pInput.context()->getSection(link_index);
        if (NULL == link_sect || LDFileFormat::Ignore == link_sect->kind()) {
          // Relocation sections of group members should also be part of the
          // group. Thus, if the associated member sections are ignored, the
          // related relocations should be also ignored.
          (*section)->setKind(LDFileFormat::Ignore);
        }
        break;
      }
      /** normal sections **/
      // FIXME: support Version Kind
      case LDFileFormat::Version:
      // FIXME: support GCCExceptTable Kind
      case LDFileFormat::GCCExceptTable:
      /** Fall through **/
      case LDFileFormat::Regular:
      case LDFileFormat::Note:
      case LDFileFormat::MetaData: {
        SectionData* sd = IRBuilder::CreateSectionData(**section);
        if (!m_pELFReader->readRegularSection(pInput, *sd))
          fatal(diag::err_cannot_read_section) << (*section)->name();
        break;
      }
      case LDFileFormat::Debug: {
        if (m_Config.options().stripDebug()) {
          (*section)->setKind(LDFileFormat::Ignore);
        }
        else {
          SectionData* sd = IRBuilder::CreateSectionData(**section);
          if (!m_pELFReader->readRegularSection(pInput, *sd)) {
            fatal(diag::err_cannot_read_section) << (*section)->name();
          }
        }
        break;
      }
      case LDFileFormat::EhFrame: {
        EhFrame* eh_frame = IRBuilder::CreateEhFrame(**section);

        if (m_ReadFlag & ParseEhFrame) {
          if (!m_pEhFrameReader->read<32, true>(pInput, *eh_frame)) {
            // if we failed to parse a .eh_frame, we should not parse the rest
            // .eh_frame.
            m_ReadFlag ^= ParseEhFrame;
          }
        }
        else {
          if (!m_pELFReader->readRegularSection(pInput,
                                                *eh_frame->getSectionData())) {
            fatal(diag::err_cannot_read_section) << (*section)->name();
          }
        }
        break;
      }
      /** target dependent sections **/
      case LDFileFormat::Target: {
        SectionData* sd = IRBuilder::CreateSectionData(**section);
        if (!m_Backend.readSection(pInput, *sd)) {
          fatal(diag::err_cannot_read_target_section) << (*section)->name();
        }
        break;
      }
      /** BSS sections **/
      case LDFileFormat::BSS: {
        IRBuilder::CreateBSS(**section);
        break;
      }
      // ignore
      case LDFileFormat::Null:
      case LDFileFormat::NamePool:
      case LDFileFormat::Ignore:
      case LDFileFormat::StackNote:
        continue;
      // warning
      case LDFileFormat::EhFrameHdr:
      default: {
        warning(diag::warn_illegal_input_section) << (*section)->name()
                                                  << pInput.name()
                                                  << pInput.path();
        break;
      }
    }
  } // end of for all sections

  return true;
}
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
}