//===----------------------------------------------------------------------===//
// X86GNULDBackend
//===----------------------------------------------------------------------===//
X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig,
				 GNUInfo* pInfo,
				 Relocation::Type pCopyRel)
  : GNULDBackend(pConfig, pInfo),
    m_pRelocator(NULL),
    m_pPLT(NULL),
    m_pRelDyn(NULL),
    m_pRelPLT(NULL),
    m_pDynamic(NULL),
    m_pGOTSymbol(NULL),
    m_CopyRel(pCopyRel)
{
  Triple::ArchType arch = pConfig.targets().triple().getArch();
  assert (arch == Triple::x86 || arch == Triple::x86_64);
  if (arch == Triple::x86 ||
      pConfig.targets().triple().getEnvironment() == Triple::GNUX32) {
    m_RelEntrySize = 8;
    m_RelaEntrySize = 12;
    if (arch == Triple::x86)
      m_PointerRel = llvm::ELF::R_386_32;
    else
      m_PointerRel = llvm::ELF::R_X86_64_32;
  }
  else {
    m_RelEntrySize = 16;
    m_RelaEntrySize = 24;
    m_PointerRel = llvm::ELF::R_X86_64_64;
  }
}
/// configure the output filename
bool OutputFormatOptions::parseOutput(Module& pModule, LinkerConfig& pConfig)
{
  if (true == m_Shared || true == m_PIE) {
    // -shared or -pie
    m_FileType = mcld::LinkerConfig::DynObj;
  }
  else if (true == m_Relocatable) {
    // partial linking
    m_FileType = mcld::LinkerConfig::Object;
  }
  else if (mcld::LinkerConfig::Binary == m_OFormat) {
    // binary output
    m_FileType = mcld::LinkerConfig::Binary;
  }

  pConfig.setCodeGenType(m_FileType);

  std::string output_filename(m_OutputFilename.native());

  if (m_OutputFilename.empty()) {

    if (llvm::Triple::Win32 == pConfig.targets().triple().getOS()) {
      output_filename.assign("_out");
      switch (m_FileType) {
        case mcld::LinkerConfig::Object: {
          output_filename += ".obj";
        break;
        }
        case mcld::LinkerConfig::DynObj: {
          output_filename += ".dll";
          break;
        }
        case mcld::LinkerConfig::Exec: {
          output_filename += ".exe";
          break;
        }
        case mcld::LinkerConfig::External:
          break;
        default: {
          return false;
          break;
        }
      } // switch
    }
    else {
      if (mcld::LinkerConfig::Object   == m_FileType ||
          mcld::LinkerConfig::DynObj   == m_FileType ||
          mcld::LinkerConfig::Exec     == m_FileType ||
          mcld::LinkerConfig::External == m_FileType) {
        output_filename.assign("a.out");
      }
      else {
        return false;
      }
    }
  } // end of if empty m_OutputFilename

  pModule.setName(output_filename);
  return true;
}
// FIXME: LinkerConfig& pConfig should be constant
bool MCLDEmulateELF(LinkerScript& pScript, LinkerConfig& pConfig) {
  // set up section map
  if (pConfig.options().getScriptList().empty() &&
      pConfig.codeGenType() != LinkerConfig::Object) {
    const unsigned int map_size = (sizeof(map) / sizeof(map[0]));
    for (unsigned int i = 0; i < map_size; ++i) {
      std::pair<SectionMap::mapping, bool> res =
          pScript.sectionMap().insert(map[i].from, map[i].to, map[i].policy);
      if (!res.second)
        return false;
    }
  } else {
    // FIXME: this is the hack to help assignment processing in current
    // implementation.
    pScript.sectionMap().insert("", "");
  }

  if (!pConfig.options().nostdlib()) {
    // TODO: check if user sets the default search path instead via -Y option
    // set up default search path
    switch (pConfig.targets().triple().getOS()) {
      case llvm::Triple::NetBSD:
        pScript.directories().insert("=/usr/lib");
        break;
      case llvm::Triple::Win32:
        pScript.directories().insert("=/mingw/lib");
        break;
      default:
        pScript.directories().insert("=/lib");
        pScript.directories().insert("=/usr/lib");
        break;
    }
  }
  return true;
}
static bool MCLDEmulateX86ELF(LinkerScript& pScript, LinkerConfig& pConfig)
{
  if (!MCLDEmulateELF(pScript, pConfig))
    return false;

  // set up bitclass and endian
  pConfig.targets().setEndian(TargetOptions::Little);
  unsigned int bitclass;
  Triple::ArchType arch = pConfig.targets().triple().getArch();
  assert (arch == Triple::x86 || arch == Triple::x86_64);
  if (arch == Triple::x86 ||
      pConfig.targets().triple().getEnvironment() == Triple::GNUX32) {
    bitclass = 32;
  }
  else {
    bitclass = 64;
  }
  pConfig.targets().setBitClass(bitclass);

  // set up target-dependent constraints of attributes
  pConfig.attribute().constraint().enableWholeArchive();
  pConfig.attribute().constraint().enableAsNeeded();
  pConfig.attribute().constraint().setSharedSystem();

  // set up the predefined attributes
  pConfig.attribute().predefined().unsetWholeArchive();
  pConfig.attribute().predefined().unsetAsNeeded();
  pConfig.attribute().predefined().setDynamic();
  return true;
}
static bool MCLDEmulateARMELF(LinkerScript& pScript, LinkerConfig& pConfig)
{
  if (!MCLDEmulateELF(pScript, pConfig))
    return false;

  // set up bitclass and endian
  pConfig.targets().setEndian(TargetOptions::Little);
  pConfig.targets().setBitClass(32);

  // set up target-dependent constraints of attributes
  pConfig.attribute().constraint().enableWholeArchive();
  pConfig.attribute().constraint().enableAsNeeded();
  pConfig.attribute().constraint().setSharedSystem();

  // set up the predefined attributes
  pConfig.attribute().predefined().unsetWholeArchive();
  pConfig.attribute().predefined().unsetAsNeeded();
  pConfig.attribute().predefined().setDynamic();

  // set up section map
  if (pConfig.options().getScriptList().empty() &&
      pConfig.codeGenType() != LinkerConfig::Object) {
    pScript.sectionMap().insert(".ARM.exidx*", ".ARM.exidx");
    pScript.sectionMap().insert(".ARM.extab*", ".ARM.extab");
    pScript.sectionMap().insert(".ARM.attributes*", ".ARM.attributes");
  }
  return true;
}
bool SearchPathOptions::parse(LinkerConfig& pConfig, LinkerScript& pScript)
{
  // set --sysroot
  if (!m_SysRoot.empty()) {
    if (exists(m_SysRoot) && is_directory(m_SysRoot))
      pScript.setSysroot(m_SysRoot);
  }

  // set -L[path]
  llvm::cl::list<std::string>::iterator sd;
  llvm::cl::list<std::string>::iterator sdEnd = m_SearchDirList.end();
  for (sd = m_SearchDirList.begin(); sd != sdEnd; ++sd) {
    if (!pScript.directories().insert(*sd)) {
      // FIXME: need a warning function
      errs() << "WARNING: can not open search directory `-L"
             << *sd
             << "'.\n";
    }
  }

  // set -no-stdlib
  pConfig.options().setNoStdlib(m_NoStdlib);

  // set --rpath [path]
  llvm::cl::list<std::string>::iterator rp;
  llvm::cl::list<std::string>::iterator rpEnd = m_RuntimePath.end();
  for (rp = m_RuntimePath.begin(); rp != rpEnd; ++rp) {
    pConfig.options().getRpathList().push_back(*rp);
  }

  return true;
}
Example #7
0
void ELFObjectWriter::writeELFHeader(const LinkerConfig& pConfig,
                                     const Module& pModule,
                                     MemoryArea& pOutput) const
{
  typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
  typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;
  typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;

  // ELF header must start from 0x0
  MemoryRegion *region = pOutput.request(0, sizeof(ElfXX_Ehdr));
  ElfXX_Ehdr* header = (ElfXX_Ehdr*)region->start();

  memcpy(header->e_ident, ElfMagic, EI_MAG3+1);

  header->e_ident[EI_CLASS]      = (SIZE == 32) ? ELFCLASS32 : ELFCLASS64;
  header->e_ident[EI_DATA]       = pConfig.targets().isLittleEndian()?
                                       ELFDATA2LSB : ELFDATA2MSB;
  header->e_ident[EI_VERSION]    = target().getInfo().ELFVersion();
  header->e_ident[EI_OSABI]      = target().getInfo().OSABI();
  header->e_ident[EI_ABIVERSION] = target().getInfo().ABIVersion();

  // FIXME: add processor-specific and core file types.
  switch(pConfig.codeGenType()) {
    case LinkerConfig::Object:
      header->e_type = ET_REL;
      break;
    case LinkerConfig::DynObj:
      header->e_type = ET_DYN;
      break;
    case LinkerConfig::Exec:
      header->e_type = ET_EXEC;
      break;
    default:
      llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
      header->e_type = ET_NONE;
  }
  header->e_machine   = target().getInfo().machine();
  header->e_version   = header->e_ident[EI_VERSION];
  header->e_entry     = getEntryPoint(pConfig, pModule);

  if (LinkerConfig::Object != pConfig.codeGenType())
    header->e_phoff   = sizeof(ElfXX_Ehdr);
  else
    header->e_phoff   = 0x0;

  header->e_shoff     = getLastStartOffset<SIZE>(pModule);
  header->e_flags     = target().getInfo().flags();
  header->e_ehsize    = sizeof(ElfXX_Ehdr);
  header->e_phentsize = sizeof(ElfXX_Phdr);
  header->e_phnum     = target().elfSegmentTable().size();
  header->e_shentsize = sizeof(ElfXX_Shdr);
  header->e_shnum     = pModule.size();
  header->e_shstrndx  = pModule.getSection(".shstrtab")->index();
}
Example #8
0
//===----------------------------------------------------------------------===//
// ELFDynObjReader
//===----------------------------------------------------------------------===//
ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend,
                                 IRBuilder& pBuilder,
                                 const LinkerConfig& pConfig)
  : DynObjReader(),
    m_pELFReader(0),
    m_Builder(pBuilder) {
  if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian())
    m_pELFReader = new ELFReader<32, true>(pBackend);
  else if (pConfig.targets().is64Bits() && pConfig.targets().isLittleEndian())
    m_pELFReader = new ELFReader<64, true>(pBackend);
}
//===----------------------------------------------------------------------===//
// emulateX86LD - the help function to emulate X86 ld
//===----------------------------------------------------------------------===//
bool emulateX86LD(LinkerScript& pScript, LinkerConfig& pConfig)
{
  if (pConfig.targets().triple().isOSDarwin()) {
    assert(0 && "MachO linker has not supported yet");
    return false;
  }
  if (pConfig.targets().triple().isOSWindows()) {
    assert(0 && "COFF linker has not supported yet");
    return false;
  }

  return MCLDEmulateX86ELF(pScript, pConfig);
}
bool TargetControlOptions::parse(LinkerConfig& pConfig)
{
  // set -G [size]
  pConfig.options().setGPSize(m_GPSize);

  // set --warn-shared-textrel
  pConfig.options().setWarnSharedTextrel(m_WarnSharedTextrel);

  // set --fix-cortex-a8
  if (m_FIXCA8)
    mcld::warning(mcld::diag::warn_unsupported_option) << m_FIXCA8.ArgStr;

  return true;
}
Example #11
0
/// emitRelocation
void ELFObjectWriter::emitRelocation(const LinkerConfig& pConfig,
                                     const LDSection& pSection,
                                     MemoryRegion& pRegion) const
{
  const RelocData* sect_data = pSection.getRelocData();
  assert(NULL != sect_data && "SectionData is NULL in emitRelocation!");

  if (pSection.type() == SHT_REL) {
    if (pConfig.targets().is32Bits())
      emitRel<32>(pConfig, *sect_data, pRegion);
    else if (pConfig.targets().is64Bits())
      emitRel<64>(pConfig, *sect_data, pRegion);
    else {
      fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str()
                                        << pConfig.targets().bitclass();
    }
  } else if (pSection.type() == SHT_RELA) {
    if (pConfig.targets().is32Bits())
      emitRela<32>(pConfig, *sect_data, pRegion);
    else if (pConfig.targets().is64Bits())
      emitRela<64>(pConfig, *sect_data, pRegion);
    else {
      fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str()
                                        << pConfig.targets().bitclass();
    }
  } else
    llvm::report_fatal_error("unsupported relocation section type!");
}
Example #12
0
enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
  mLDConfig = pConfig.getLDConfig();
  if (mLDConfig == NULL) {
    return kDelegateLDInfo;
  }
  return kSuccess;
}
bool DynamicSectionOptions::parse(LinkerConfig& pConfig,
                                  LinkerScript& pScript) {
  // set up entry point from -e
  pScript.setEntry(m_Entry);

  // --Bsymbolic
  pConfig.options().setBsymbolic(m_Bsymbolic);

  // --Bgroup
  pConfig.options().setBgroup(m_Bgroup);

  // set --soname [soname]
  pConfig.options().setSOName(m_SOName);

  // set -z options
  llvm::cl::list<ZOption>::iterator zOpt;
  llvm::cl::list<ZOption>::iterator zOptEnd = m_ZOptionList.end();
  for (zOpt = m_ZOptionList.begin(); zOpt != zOptEnd; ++zOpt) {
    pConfig.options().addZOption(*zOpt);
  }

  // set --no-undefined
  if (llvm::cl::BOU_UNSET != m_NoUndefined)
    pConfig.options().setNoUndefined(llvm::cl::BOU_TRUE == m_NoUndefined);

  // set --allow-multiple-definition
  if (llvm::cl::BOU_UNSET != m_AllowMulDefs)
    pConfig.options().setMulDefs(llvm::cl::BOU_TRUE == m_AllowMulDefs);

  // set --dynamic-linker [dyld]
  pConfig.options().setDyld(m_Dyld);

  // set --enable-new-dtags
  pConfig.options().setNewDTags(m_EnableNewDTags);

  // set --auxiliary, -f
  llvm::cl::list<std::string>::iterator aux;
  llvm::cl::list<std::string>::iterator auxEnd = m_Auxiliary.end();
  for (aux = m_Auxiliary.begin(); aux != auxEnd; ++aux)
    pConfig.options().getAuxiliaryList().push_back(*aux);

  // set --filter, -F
  pConfig.options().setFilter(m_Filter);

  return true;
}
//===----------------------------------------------------------------------===//
// Testcases
//===----------------------------------------------------------------------===//
TEST_F(ELFBinaryReaderTest, is_myformat) {
  LinkerScript script;
  Module module("test", script);
  LinkerConfig config;
  IRBuilder builder(module, config);
  ELFBinaryReader* reader = new ELFBinaryReader(builder, config);

  Input input("test.bin");

  bool doContinue = false;
  config.options().setBinaryInput();
  ASSERT_TRUE(reader->isMyFormat(input, doContinue));

  config.options().setBinaryInput(false);
  ASSERT_FALSE(reader->isMyFormat(input, doContinue));

  delete reader;
}
//===----------------------------------------------------------------------===//
// ELFObjectReader
//===----------------------------------------------------------------------===//
/// constructor
ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend,
                                 IRBuilder& pBuilder,
                                 const LinkerConfig& pConfig)
  : ObjectReader(),
    m_pELFReader(NULL),
    m_pEhFrameReader(NULL),
    m_Builder(pBuilder),
    m_ReadFlag(ParseEhFrame),
    m_Backend(pBackend),
    m_Config(pConfig) {
  if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian()) {
    m_pELFReader = new ELFReader<32, true>(pBackend);
  }
  else if (pConfig.targets().is64Bits() && pConfig.targets().isLittleEndian()) {
    m_pELFReader = new ELFReader<64, true>(pBackend);
  }

  m_pEhFrameReader = new EhFrameReader();
}
/// getEntryPoint
uint64_t ELFObjectWriter::getEntryPoint(const LinkerConfig& pConfig,
                                        const Module& pModule) const
{
  llvm::StringRef entry_name;
  if (pConfig.options().hasEntry())
    entry_name = pConfig.options().entry();
  else
    entry_name = target().getInfo().entry();

  uint64_t result = 0x0;

  bool issue_warning = (pConfig.options().hasEntry() &&
                        LinkerConfig::Object != pConfig.codeGenType() &&
                        LinkerConfig::DynObj != pConfig.codeGenType());

  const LDSymbol* entry_symbol = pModule.getNamePool().findSymbol(entry_name);

  // found the symbol
  if (NULL != entry_symbol) {
    if (entry_symbol->desc() != ResolveInfo::Define && issue_warning) {
      llvm::errs() << "WARNING: entry symbol '"
                   << entry_symbol->name()
                   << "' exists but is not defined.\n";
    }
    result = entry_symbol->value();
  }
  // not in the symbol pool
  else {
    // We should parse entry as a number.
    // @ref GNU ld manual, Options -e. e.g., -e 0x1000.
    char* endptr;
    result = strtoull(entry_name.data(), &endptr, 0);
    if (*endptr != '\0') {
      if (issue_warning) {
        llvm::errs() << "cannot find entry symbol '"
                     << entry_name.data()
                     << "'.\n";
      }
      result = 0x0;
    }
  }
  return result;
}
Example #17
0
void ELFObjectWriter::emitRela(const LinkerConfig& pConfig,
                               const RelocData& pRelocData,
                               MemoryRegion& pRegion) const
{
  typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela;
  typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
  typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;

  ElfXX_Rela* rel = reinterpret_cast<ElfXX_Rela*>(pRegion.start());

  const Relocation* relocation = 0;
  const FragmentRef* frag_ref = 0;

  for (RelocData::const_iterator it = pRelocData.begin(),
       ie = pRelocData.end(); it != ie; ++it, ++rel) {
    ElfXX_Addr r_offset = 0;
    ElfXX_Word r_sym = 0;

    relocation = &(llvm::cast<Relocation>(*it));
    frag_ref = &(relocation->targetRef());

    if(LinkerConfig::DynObj == pConfig.codeGenType() ||
       LinkerConfig::Exec == pConfig.codeGenType()) {
      r_offset = static_cast<ElfXX_Addr>(
                      frag_ref->frag()->getParent()->getSection().addr() +
                      frag_ref->getOutputOffset());
    }
    else {
      r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
    }

    if( relocation->symInfo() == NULL )
      r_sym = 0;
    else
      r_sym = static_cast<ElfXX_Word>(
              target().getSymbolIdx(relocation->symInfo()->outSymbol()));

    target().emitRelocation(*rel, relocation->type(),
                            r_sym, r_offset, relocation->addend());
  }
}
bool OptimizationOptions::parse(LinkerConfig& pConfig)
{
  // set --gc-sections
  if (m_GCSections)
    pConfig.options().setGCSections();

  // set --ld-generated-unwind-info (or not)
  pConfig.options().setGenUnwindInfo(m_GenUnwindInfo);

  // set --icf [mode]
  switch (m_ICF) {
    case ICF_None:
      break;
    case ICF_All:
    case ICF_Safe:
    default:
      warning(mcld::diag::warn_unsupported_option) << m_ICF.ArgStr;
      break;
  }

  return true;
}
Example #19
0
Linker::Linker(const LinkerConfig& pConfig)
  : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
    mOutputHandler(-1) {

  const std::string &triple = pConfig.getTriple();

  enum ErrorCode err = config(pConfig);
  if (kSuccess != err) {
    ALOGE("%s (%s)", GetErrorString(err), triple.c_str());
    return;
  }

  return;
}
static bool MCLDEmulateHexagonELF(LinkerConfig& pConfig)
{
  if (!MCLDEmulateELF(pConfig))
    return false;

  // set up bitclass and endian
  pConfig.targets().setEndian(TargetOptions::Little);
  pConfig.targets().setBitClass(32);

  // set up target-dependent constraints of attributes
  pConfig.attribute().constraint().enableWholeArchive();
  pConfig.attribute().constraint().enableAsNeeded();
  pConfig.attribute().constraint().setSharedSystem();

  // set up the predefined attributes
  pConfig.attribute().predefined().unsetWholeArchive();
  pConfig.attribute().predefined().unsetAsNeeded();
  pConfig.attribute().predefined().setDynamic();
  return true;
}
Example #21
0
/// getSectLink - compute ElfXX_Shdr::sh_link
uint64_t ELFObjectWriter::getSectLink(const LDSection& pSection,
                                      const LinkerConfig& pConfig) const
{
  if (llvm::ELF::SHT_SYMTAB == pSection.type())
    return target().getOutputFormat()->getStrTab().index();
  if (llvm::ELF::SHT_DYNSYM == pSection.type())
    return target().getOutputFormat()->getDynStrTab().index();
  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
    return target().getOutputFormat()->getDynStrTab().index();
  if (llvm::ELF::SHT_HASH     == pSection.type() ||
      llvm::ELF::SHT_GNU_HASH == pSection.type())
    return target().getOutputFormat()->getDynSymTab().index();
  if (llvm::ELF::SHT_REL == pSection.type() ||
      llvm::ELF::SHT_RELA == pSection.type()) {
    if (LinkerConfig::Object == pConfig.codeGenType())
      return target().getOutputFormat()->getSymTab().index();
    else
      return target().getOutputFormat()->getDynSymTab().index();
  }
  // FIXME: currently we link ARM_EXIDX section to output text section here
  if (llvm::ELF::SHT_ARM_EXIDX == pSection.type())
    return target().getOutputFormat()->getText().index();
  return llvm::ELF::SHN_UNDEF;
}
bool OutputFormatOptions::parse(mcld::Module& pModule, LinkerConfig& pConfig)
{
  if (!parseOutput(pModule, pConfig)) {
    mcld::unreachable(mcld::diag::unrecognized_output_file) << pModule.name();
    return false;
  }

  if (mcld::Input::Binary == m_Format)
    pConfig.options().setBinaryInput();

  pConfig.options().setStripDebug(m_StripDebug || m_StripAll);
  if (m_StripAll)
    pConfig.options().setStripSymbols(mcld::GeneralOptions::StripAllSymbols);
  else if (m_DiscardAll)
    pConfig.options().setStripSymbols(mcld::GeneralOptions::StripLocals);
  else if (m_DiscardLocals)
    pConfig.options().setStripSymbols(mcld::GeneralOptions::StripTemporaries);
  else
    pConfig.options().setStripSymbols(mcld::GeneralOptions::KeepAllSymbols);

  pConfig.options().setEhFrameHdr(m_EhFrameHdr);
  pConfig.options().setPIE(m_PIE);
  pConfig.options().setNMagic(m_NMagic);
  pConfig.options().setOMagic(m_OMagic);
  pConfig.options().setHashStyle(m_HashStyle);
  pConfig.options().setExportDynamic(m_ExportDynamic);
  if (m_NoWarnMismatch)
    pConfig.options().setWarnMismatch(false);
  else
    pConfig.options().setWarnMismatch(true);
  // build-id
  // exclude-libs

  return true;
}
Example #23
0
/// includeMember - include the object member in the given file offset, and
/// return the size of the object
/// @param pConfig - LinkerConfig
/// @param pArchiveRoot - the archive root
/// @param pFileOffset  - file offset of the member header in the archive
size_t GNUArchiveReader::includeMember(const LinkerConfig& pConfig,
                                       Archive& pArchive,
                                       uint32_t pFileOffset)
{
  Input* cur_archive = &(pArchive.getARFile());
  Input* member = NULL;
  uint32_t file_offset = pFileOffset;
  size_t size = 0;
  do {
    uint32_t nested_offset = 0;
    // use the file offset in current archive to find out the member we
    // want to include
    member = readMemberHeader(pArchive,
                              *cur_archive,
                              file_offset,
                              nested_offset,
                              size);
    assert(member != NULL);
    // bypass if we get an archive that is already in the map
    if (Input::Archive == member->type()) {
        cur_archive = member;
        file_offset = nested_offset;
        continue;
    }

    // insert a node into the subtree of current archive.
    Archive::ArchiveMember* parent =
      pArchive.getArchiveMember(cur_archive->name());

    assert(NULL != parent);
    pArchive.inputs().insert(parent->lastPos, *(parent->move), *member);

    // move the iterator to new created node, and also adjust the
    // direction to Afterward for next insertion in this subtree
    parent->move->move(parent->lastPos);
    parent->move = &InputTree::Afterward;
    bool doContinue = false;

    if (m_ELFObjectReader.isMyFormat(*member, doContinue)) {
      member->setType(Input::Object);
      pArchive.addObjectMember(pFileOffset, parent->lastPos);
      m_ELFObjectReader.readHeader(*member);
      m_ELFObjectReader.readSections(*member);
      m_ELFObjectReader.readSymbols(*member);
      m_Module.getObjectList().push_back(member);
    }
    else if (doContinue && isMyFormat(*member, doContinue)) {
      member->setType(Input::Archive);
      // when adding a new archive node, set the iterator to archive
      // itself, and set the direction to Downward
      pArchive.addArchiveMember(member->name(),
                                parent->lastPos,
                                &InputTree::Downward);
      cur_archive = member;
      file_offset = nested_offset;
    }
    else {
      warning(diag::warn_unrecognized_input_file) << member->path()
        << pConfig.targets().triple().str();
    }
  } while (Input::Object != member->type());
  return size;
}
Example #24
0
bool GroupReader::readGroup(Module::input_iterator pRoot,
                            InputBuilder& pBuilder,
                            const LinkerConfig& pConfig)
{
  // record the number of total objects included in this sub-tree
  size_t cur_obj_cnt = 0;
  size_t last_obj_cnt = 0;
  size_t non_ar_obj_cnt = 0;

  // record the archive files in this sub-tree
  typedef std::vector<ArchiveListEntry*> ArchiveListType;
  ArchiveListType ar_list;

  Module::input_iterator input = --pRoot;

  // Since the end of a sub-tree is the same node to the end of whole tree, we
  // take the end of the whole input tree for conventience.
  Module::input_iterator input_end = m_Module.input_end();

  // first time read the sub-tree
  while (input != input_end) {
    // already got type - for example, bitcode or external OIR (object
    // intermediate representation)
    if ((*input)->type() == Input::Script ||
        (*input)->type() == Input::Object ||
        (*input)->type() == Input::DynObj  ||
        (*input)->type() == Input::Archive ||
        (*input)->type() == Input::External) {
      ++input;
      continue;
    }

    // is an archive
    if (m_ArchiveReader.isMyFormat(**input)) {
      (*input)->setType(Input::Archive);
      // record the Archive used by each archive node
      Archive* ar = new Archive(**input, pBuilder);
      ArchiveListEntry* entry = new ArchiveListEntry(*ar, input);
      ar_list.push_back(entry);
      // read archive
      m_ArchiveReader.readArchive(*ar);
      cur_obj_cnt += ar->numOfObjectMember();
    }
    // is a relocatable object file
    else if (m_ObjectReader.isMyFormat(**input)) {
      (*input)->setType(Input::Object);
      m_ObjectReader.readHeader(**input);
      m_ObjectReader.readSections(**input);
      m_ObjectReader.readSymbols(**input);
      m_Module.getObjectList().push_back(*input);
      ++cur_obj_cnt;
      ++non_ar_obj_cnt;
    }
    // is a shared object file
    else if (m_DynObjReader.isMyFormat(**input)) {
      (*input)->setType(Input::DynObj);
      m_DynObjReader.readHeader(**input);
      m_DynObjReader.readSymbols(**input);
      m_Module.getLibraryList().push_back(*input);
    }
    else {
      fatal(diag::err_unrecognized_input_file) << (*input)->path()
                                               << pConfig.targets().triple().str();
    }
    ++input;
  }

  // after read in all the archives, traverse the archive list in a loop until
  // there is no unresolved symbols added
  ArchiveListType::iterator it = ar_list.begin();
  ArchiveListType::iterator end = ar_list.end();
  while (cur_obj_cnt != last_obj_cnt) {
    last_obj_cnt = cur_obj_cnt;
    cur_obj_cnt = non_ar_obj_cnt;
    for (it = ar_list.begin(); it != end; ++it) {
      Archive& ar = (*it)->archive;
      // if --whole-archive is given to this archive, no need to read it again
      if ( ar.getARFile().attribute()->isWholeArchive())
        continue;
      m_ArchiveReader.readArchive(ar);
      cur_obj_cnt += ar.numOfObjectMember();
    }
  }

  // after all needed member included, merge the archive sub-tree to main
  // InputTree
  for (it = ar_list.begin(); it != end; ++it) {
    Archive& ar = (*it)->archive;
    if (ar.numOfObjectMember() > 0) {
      m_Module.getInputTree().merge<InputTree::Inclusive>((*it)->input,
                                                          ar.inputs());
    }
  }

  // cleanup ar_list
  for (it = ar_list.begin(); it != end; ++it) {
    delete &((*it)->archive);
    delete (*it);
  }
  ar_list.clear();

  return true;
}