bool SectionSymbolSet::add(LDSection& pOutSect, NamePool& pNamePool)
{
  // create the resolveInfo for this section symbol
  llvm::StringRef sym_name = llvm::StringRef(pOutSect.name());
  ResolveInfo* sym_info = pNamePool.createSymbol(sym_name,
                                                 false,
                                                 ResolveInfo::Section,
                                                 ResolveInfo::Define,
                                                 ResolveInfo::Local,
                                                 0x0, // size
                                                 ResolveInfo::Default);

  // create the output section symbol and set its fragRef to the first fragment
  // of the section
  LDSymbol* sym = LDSymbol::Create(*sym_info);
  sym_info->setSymPtr(sym);

  // insert the symbol to the Section to Symbol hash map
  bool exist = false;
  SectHashTableType::entry_type* entry =
                            m_pSectionSymbolMap->insert(&pOutSect, exist);
  assert(!exist);
  entry->setValue(sym);

  return true;
}
bool ARMGNULDBackend::readSection(Input& pInput,
                                  MCLinker& pLinker,
                                  LDSection& pInputSectHdr)
{
  LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
                                                         pInputSectHdr.kind(),
                                                         pInputSectHdr.type(),
                                                         pInputSectHdr.flag());
  // FIXME: (Luba)
  // Handle ARM attributes in the right way.
  // In current milestone, MCLinker goes through the shortcut.
  // It reads input's ARM attributes and copies the first ARM attributes
  // into the output file. The correct way is merge these sections, not
  // just copy.
  if ((0 == out_sect.name().compare(".ARM.attributes")) &&
      (0 != out_sect.size()))
    return true;

  MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(),
                                                   pInputSectHdr.size());

  llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);

  new MCRegionFragment(*region, &sect_data);

  out_sect.setSize(out_sect.size() + pInputSectHdr.size());
  return true;
}
Ejemplo n.º 3
0
/// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe
/// function pointer access
bool
ARMGNULDBackend::mayHaveUnsafeFunctionPointerAccess(const LDSection& pSection)
    const
{
  llvm::StringRef name(pSection.name());
  return !name.startswith(".ARM.exidx") &&
         !name.startswith(".ARM.extab") &&
         GNULDBackend::mayHaveUnsafeFunctionPointerAccess(pSection);
}
uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
                                          MemoryRegion& pRegion) const
{
  assert(pRegion.size() && "Size of MemoryRegion is zero!");

  const ELFFileFormat* FileFormat = getOutputFormat();
  assert(FileFormat &&
         "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");

  unsigned int EntrySize = 0;
  uint64_t RegionSize = 0;

  if (&pSection == &(FileFormat->getPLT())) {
    assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!");

    unsigned char* buffer = pRegion.getBuffer();

    m_pPLT->applyPLT0();
    m_pPLT->applyPLT1();
    X86PLT::iterator it = m_pPLT->begin();
    unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size();

    memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size);
    RegionSize += plt0_size;
    ++it;

    PLTEntryBase* plt1 = 0;
    X86PLT::iterator ie = m_pPLT->end();
    while (it != ie) {
      plt1 = &(llvm::cast<PLTEntryBase>(*it));
      EntrySize = plt1->size();
      memcpy(buffer + RegionSize, plt1->getValue(), EntrySize);
      RegionSize += EntrySize;
      ++it;
    }
  }

  else if (&pSection == &(FileFormat->getGOT())) {
    RegionSize += emitGOTSectionData(pRegion);
  }

  else if (&pSection == &(FileFormat->getGOTPLT())) {
    RegionSize += emitGOTPLTSectionData(pRegion, FileFormat);
  }

  else {
    fatal(diag::unrecognized_output_sectoin)
            << pSection.name()
            << "*****@*****.**";
  }
  return RegionSize;
}
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;
}
void GarbageCollection::getEntrySections(SectionVecTy& pEntry)
{
  // all the KEEP sections defined in ldscript are entries, traverse all the
  // input sections and check the SectionMap to find the KEEP sections
  Module::obj_iterator obj, objEnd = m_Module.obj_end();
  SectionMap& sect_map = m_Module.getScript().sectionMap();
  for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
    const std::string input_name = (*obj)->name();
    LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
    for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
      LDSection* section = *sect;
      if (LDFileFormat::Regular != section->kind() &&
          LDFileFormat::BSS != section->kind())
        continue;

      SectionMap::Input* sm_input =
                              sect_map.find(input_name, section->name()).second;
      if ((sm_input != NULL) && (InputSectDesc::Keep == sm_input->policy()))
        pEntry.push_back(section);
    }
  }

  // get the sections those the entry symbols defined in
  Module::SymbolTable& sym_tab = m_Module.getSymbolTable();
  if (LinkerConfig::Exec == m_Config.codeGenType()) {
    assert(NULL != m_pEntry);
    pEntry.push_back(&m_pEntry->fragRef()->frag()->getParent()->getSection());
  }
  else {
    // when building shared objects, the global define symbols are entries
    SymbolCategory::iterator it, end = sym_tab.regularEnd();
    for (it = sym_tab.dynamicBegin(); it != end; ++it) {
      LDSymbol* sym = *it;
      if (!sym->resolveInfo()->isDefine() || !sym->hasFragRef())
        continue;

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

      pEntry.push_back(sect);
    }
  }
}
uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput,
                                          const LDSection& pSection,
                                          const MCLDInfo& pInfo,
                                          MemoryRegion& pRegion) const
{
  assert(pRegion.size() && "Size of MemoryRegion is zero!");

  ELFFileFormat* file_format = getOutputFormat(pOutput);

  if (&pSection == m_pAttributes) {
    // FIXME: Currently Emitting .ARM.attributes directly from the input file.
    const llvm::MCSectionData* sect_data = pSection.getSectionData();
    assert(sect_data &&
           "Emit .ARM.attribute failed, MCSectionData doesn't exist!");

    uint8_t* start =
              llvm::cast<MCRegionFragment>(
                     sect_data->getFragmentList().front()).getRegion().start();

    memcpy(pRegion.start(), start, pRegion.size());
    return pRegion.size();
  }

  if (&pSection == &(file_format->getPLT())) {
    assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
    uint64_t result = m_pPLT->emit(pRegion);
    return result;
  }

  if (&pSection == &(file_format->getGOT())) {
    assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
    uint64_t result = m_pGOT->emit(pRegion);
    return result;
  }

  llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
                           pSection.name() +
                           llvm::Twine("'.\n"));
  return 0x0;
}
Ejemplo n.º 8
0
uint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection,
                                           MemoryRegion& pRegion) const {
  assert(pRegion.size() && "Size of MemoryRegion is zero!");

  const ELFFileFormat* file_format = getOutputFormat();

  if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
    return m_pGOT->emit(pRegion);
  }

  if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
    return m_pPLT->emit(pRegion);
  }

  if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
    return m_pGOTPLT->emit(pRegion);
  }

  fatal(diag::unrecognized_output_sectoin) << pSection.name()
                                           << "*****@*****.**";
  return 0;
}
Ejemplo n.º 9
0
void IdenticalCodeFolding::foldIdenticalCode() {
  // 1. Find folding candidates.
  FoldingCandidates candidate_list;
  findCandidates(candidate_list);

  // 2. Initialize constant section content
  for (size_t i = 0; i < candidate_list.size(); ++i) {
    candidate_list[i].initConstantContent(m_Backend, m_KeptSections);
  }

  // 3. Find identical code until convergence
  bool converged = false;
  size_t iterations = 0;
  while (!converged && (iterations < m_Config.options().getICFIterations())) {
    converged = matchCandidates(candidate_list);
    ++iterations;
  }
  if (m_Config.options().printICFSections()) {
    debug(diag::debug_icf_iterations) << iterations;
  }

  // 4. Fold the identical code
  typedef std::set<Input*> FoldedObjects;
  FoldedObjects folded_objs;
  KeptSections::iterator kept, keptEnd = m_KeptSections.end();
  size_t index = 0;
  for (kept = m_KeptSections.begin(); kept != keptEnd; ++kept, ++index) {
    LDSection* sect = (*kept).first;
    Input* obj = (*kept).second.first;
    size_t kept_index = (*kept).second.second;
    if (index != kept_index) {
      sect->setKind(LDFileFormat::Folded);
      folded_objs.insert(obj);

      if (m_Config.options().printICFSections()) {
        KeptSections::iterator it = m_KeptSections.begin() + kept_index;
        LDSection* kept_sect = (*it).first;
        Input* kept_obj = (*it).second.first;
        debug(diag::debug_icf_folded_section) << sect->name() << obj->name()
                                              << kept_sect->name()
                                              << kept_obj->name();
      }
    }
  }

  // Adjust the fragment reference of the folded symbols.
  FoldedObjects::iterator fobj, fobjEnd = folded_objs.end();
  for (fobj = folded_objs.begin(); fobj != fobjEnd; ++fobj) {
    LDContext::sym_iterator sym, symEnd = (*fobj)->context()->symTabEnd();
    for (sym = (*fobj)->context()->symTabBegin(); sym != symEnd; ++sym) {
      if ((*sym)->hasFragRef() && ((*sym)->type() == ResolveInfo::Function)) {
        LDSymbol* out_sym = (*sym)->resolveInfo()->outSymbol();
        FragmentRef* frag_ref = out_sym->fragRef();
        LDSection* sect = &(frag_ref->frag()->getParent()->getSection());
        if (sect->kind() == LDFileFormat::Folded) {
          size_t kept_index = m_KeptSections[sect].second;
          LDSection* kept_sect = (*(m_KeptSections.begin() + kept_index)).first;
          frag_ref->assign(kept_sect->getSectionData()->front(),
                           frag_ref->offset());
        }
      }
    }  // for each symbol
  }    // for each folded object
}
Ejemplo n.º 10
0
void ARMGNULDBackend::scanInputExceptionSections(Module& pModule,
                                                 Input& pInput) {
  std::unique_ptr<ARMInputExMap> exMap(new ARMInputExMap());

  // Scan the input and collect all related sections.
  LDContext* ctx = pInput.context();
  for (LDContext::sect_iterator it = ctx->sectBegin(),
                                end = ctx->sectEnd(); it != end; ++it) {
    LDSection* sect = *it;
    llvm::StringRef name(sect->name());

    if (name.startswith(".ARM.exidx")) {
      ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name);
      exTuple->setExIdxSection(sect);
      exTuple->setTextSection(sect->getLink());
    } else if (name.startswith(".ARM.extab")) {
      ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name);
      exTuple->setExTabSection(sect);
    } else if (name.startswith(".rel.ARM.exidx")) {
      ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name);
      exTuple->setRelExIdxSection(sect);
    } else if (name.startswith(".rel.ARM.extab")) {
      ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name);
      exTuple->setRelExIdxSection(sect);
    }
  }

  // Remove the invalid exception tuples and convert LDSection to RegionFragment
  // or RelocData.
  ARMInputExMap::iterator it = exMap->begin();
  ARMInputExMap::iterator end = exMap->end();
  while (it != end) {
    ARMExSectionTuple* exTuple = it->second.get();
    LDSection* const text = exTuple->getTextSection();
    LDSection* const exIdx = exTuple->getExIdxSection();
    LDSection* const exTab = exTuple->getExTabSection();
    LDSection* const relExIdx = exTuple->getRelExIdxSection();
    LDSection* const relExTab = exTuple->getRelExTabSection();

    // Check the .ARM.exidx section.
    if (!exIdx) {
      if (exTab) {
        fatal(diag::eh_missing_exidx_section) << exTab->name() << pInput.name();
      } else if (relExIdx) {
        fatal(diag::eh_missing_exidx_section) << relExIdx->name()
                                              << pInput.name();
      } else if (relExTab) {
        fatal(diag::eh_missing_exidx_section) << relExTab->name()
                                              << pInput.name();
      } else {
        llvm_unreachable("unexpected bad exception tuple");
      }
    }

    // Check the text section.
    if (!text) {
      fatal(diag::eh_missing_text_section) << exIdx->name() << pInput.name();
    }

    // Ignore the exception section if the text section is ignored.
    if ((text->kind() == LDFileFormat::Ignore) ||
        (text->kind() == LDFileFormat::Folded)) {
      // Set the related exception sections as LDFileFormat::Ignore.
      exIdx->setKind(LDFileFormat::Ignore);
      if (exTab) {
        exTab->setKind(LDFileFormat::Ignore);
      }
      // Remove this tuple from the input exception map.
      exMap->erase(it++);
      continue;
    }

    // Get RegionFragment from ".text", ".ARM.exidx", and ".ARM.extab" sections.
    RegionFragment* textFrag = findRegionFragment(*text);
    RegionFragment* exIdxFrag = findRegionFragment(*exIdx);
    RegionFragment* exTabFrag = exTab ? findRegionFragment(*exTab) : NULL;

    exTuple->setTextFragment(textFrag);
    exTuple->setExIdxFragment(exIdxFrag);
    exTuple->setExTabFragment(exTabFrag);

    // Get the RelocData from ".rel.ARM.exidx" and ".rel.ARM.extab" sections.
    RelocData* exIdxRD = relExIdx ? relExIdx->getRelocData() : NULL;
    RelocData* exTabRD = relExTab ? relExTab->getRelocData() : NULL;

    exTuple->setExIdxRelocData(exIdxRD);
    exTuple->setExTabRelocData(exTabRD);

    // If there is no region fragment in the .ARM.extab section, then we can
    // skip this tuple.
    if (!exIdxFrag) {
      exMap->erase(it++);
      continue;
    }

    // TODO: Sort the RelocData w.r.t. the fixup offset.

    // Check next tuple
    ++it;
  }

  // Add input map
  m_ExData.addInputMap(&pInput, std::move(exMap));
}