bool SectionSymbolSet::finalize(LDSection& pOutSect,
                                SymbolTable& pSymTab, bool relocatable)
{
  if (!relocatable && pOutSect.size() == 0)
      return true;

  LDSymbol* sym = get(pOutSect);
  assert(NULL != sym);
  SectionData* data = NULL;
  switch (pOutSect.kind()) {
    case LDFileFormat::Relocation:
      // Relocation section should not have section symbol.
      return true;

    case LDFileFormat::EhFrame:
      if (EhFrame *ehframe = pOutSect.getEhFrame())
          data = ehframe->getSectionData();
      break;

    default:
      data = pOutSect.getSectionData();
      break;
  }
  FragmentRef* frag_ref;
  if (data && !data->empty())
    frag_ref = FragmentRef::Create(data->front(), 0x0);
  else
    frag_ref = FragmentRef::Null();
  sym->setFragmentRef(frag_ref);
  // push symbol into output symbol table
  pSymTab.add(*sym);

  return true;
}
Ejemplo n.º 2
0
//==========================
// DebugString
void DebugString::merge(LDSection& pSection) {
  // get the fragment contents
  llvm::StringRef strings;
  SectionData::iterator it, end = pSection.getSectionData()->end();
  for (it = pSection.getSectionData()->begin(); it != end; ++it) {
    if ((*it).getKind() == Fragment::Region) {
      RegionFragment* frag = llvm::cast<RegionFragment>(&(*it));
      strings = frag->getRegion().data();
    }
  }

  // get the debug strings and add them into merged string table
  const char* str = strings.data();
  const char* str_end = str + pSection.size();
  while (str < str_end) {
    size_t len = string_length(str);
    m_StringTable.insertString(llvm::StringRef(str, len));
    str = str + len + 1;
  }
}
Ejemplo n.º 3
0
/// merge Input Sections
bool HexagonLDBackend::mergeSection(Module& pModule,
                                    const Input& pInputFile,
                                    LDSection& pInputSection) {
  if ((pInputSection.flag() & llvm::ELF::SHF_HEX_GPREL) ||
      (pInputSection.kind() == LDFileFormat::LinkOnce) ||
      (pInputSection.kind() == LDFileFormat::Target)) {
    SectionData* sd = NULL;
    if (!m_psdata->hasSectionData()) {
      sd = IRBuilder::CreateSectionData(*m_psdata);
      m_psdata->setSectionData(sd);
    }
    sd = m_psdata->getSectionData();
    MoveSectionDataAndSort(*pInputSection.getSectionData(), *sd);
  } else {
    ObjectBuilder builder(pModule);
    builder.MergeSection(pInputFile, pInputSection);
  }
  return true;
}
Ejemplo n.º 4
0
/// emitSectionData
void
ELFObjectWriter::emitSectionData(const LDSection& pSection,
                                 MemoryRegion& pRegion) const
{
  const SectionData* sd = NULL;
  switch (pSection.kind()) {
    case LDFileFormat::Relocation:
      assert(pSection.hasRelocData());
      return;
    case LDFileFormat::EhFrame:
      assert(pSection.hasEhFrame());
      sd = pSection.getEhFrame()->getSectionData();
      break;
    default:
      assert(pSection.hasSectionData());
      sd = pSection.getSectionData();
      break;
  }
  emitSectionData(*sd, pRegion);
}
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.º 6
0
/// group - group fragments and create islands when needed
/// @param pSectionData - the SectionData holds fragments need to be grouped
void BranchIslandFactory::group(Module& pModule) {
  /* FIXME: Currently only support relaxing .text section! */
  LDSection* text = pModule.getSection(".text");
  if (text != NULL && text->hasSectionData()) {
    SectionData& sd = *text->getSectionData();
    uint64_t group_end = m_MaxFwdBranchRange;
    for (SectionData::iterator it = sd.begin(), ie = sd.end(); it != ie; ++it) {
      if ((*it).getOffset() + (*it).size() > group_end) {
        Fragment* frag = (*it).getPrevNode();
        while (frag != NULL && frag->getKind() == Fragment::Alignment) {
          frag = frag->getPrevNode();
        }
        if (frag != NULL) {
          produce(*frag);
          group_end = (*it).getOffset() + m_MaxFwdBranchRange;
        }
      }
    }
    if (getIslands(sd.back()).first == NULL)
      produce(sd.back());
  }
}
Ejemplo n.º 7
0
bool MipsAbiFlags::fillBySection(const Input& pInput, const LDSection& pSection,
                                 MipsAbiFlags& mipsAbi) {
  assert(pSection.type() == llvm::ELF::SHT_MIPS_ABIFLAGS &&
         "Unexpected section type");

  if (pSection.size() != size()) {
    error(diag::error_Mips_abiflags_invalid_size) << pInput.name();
    return false;
  }

  const SectionData* secData = pSection.getSectionData();
  if (secData->size() != 2 || !llvm::isa<RegionFragment>(secData->front())) {
    error(diag::error_Mips_abiflags_invalid_size) << pInput.name();
    return false;
  }

  const auto& frag = llvm::cast<RegionFragment>(secData->front());
  auto* data =
      reinterpret_cast<const ElfMipsAbiFlags*>(frag.getRegion().data());
  if (data->version != 0) {
    error(diag::error_Mips_abiflags_invalid_version) << int(data->version)
                                                     << pInput.name();
    return false;
  }

  mipsAbi.m_IsaLevel = data->isa_level;
  mipsAbi.m_IsaRev = data->isa_rev;
  mipsAbi.m_GprSize = data->gpr_size;
  mipsAbi.m_Cpr1Size = data->cpr1_size;
  mipsAbi.m_Cpr2Size = data->cpr2_size;
  mipsAbi.m_FpAbi = data->fp_abi;
  mipsAbi.m_IsaExt = data->isa_ext;
  mipsAbi.m_Ases = data->ases;
  mipsAbi.m_Flags1 = data->flags1;
  return true;
}
Ejemplo n.º 8
0
uint64_t HexagonLDBackend::emitSectionData(const LDSection& pSection,
                                           MemoryRegion& pRegion) const
{
  if (!pRegion.size())
    return 0;

  const ELFFileFormat* FileFormat = getOutputFormat();
  unsigned int EntrySize = 0;
  uint64_t RegionSize = 0;

  if ((LinkerConfig::Object != config().codeGenType()) &&
      (!config().isCodeStatic())) {
    if (FileFormat->hasPLT() && (&pSection == &(FileFormat->getPLT()))) {

      unsigned char* buffer = pRegion.begin();

      m_pPLT->applyPLT0();
      m_pPLT->applyPLT1();
      HexagonPLT::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;
      HexagonPLT::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;
      }
      return RegionSize;
    }
    else if (FileFormat->hasGOT() && (&pSection == &(FileFormat->getGOT()))) {
      RegionSize += emitGOTSectionData(pRegion);
      return RegionSize;
    }
    else if (FileFormat->hasGOTPLT() &&
             (&pSection == &(FileFormat->getGOTPLT()))) {
      RegionSize += emitGOTPLTSectionData(pRegion, FileFormat);
      return RegionSize;
    }
  }

  const SectionData* sect_data = pSection.getSectionData();
  SectionData::const_iterator frag_iter, frag_end = sect_data->end();
  uint8_t* out_offset = pRegion.begin();
  for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
    size_t size = frag_iter->size();
    switch(frag_iter->getKind()) {
      case Fragment::Fillment: {
        const FillFragment& fill_frag =
          llvm::cast<FillFragment>(*frag_iter);
        if (0 == fill_frag.getValueSize()) {
          // virtual fillment, ignore it.
          break;
        }
        memset(out_offset, fill_frag.getValue(), fill_frag.size());
        break;
      }
      case Fragment::Region: {
        const RegionFragment& region_frag =
          llvm::cast<RegionFragment>(*frag_iter);
        const char* start = region_frag.getRegion().begin();
        memcpy(out_offset, start, size);
        break;
      }
      case Fragment::Alignment: {
        const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
        uint64_t count = size / align_frag.getValueSize();
        switch (align_frag.getValueSize()) {
          case 1u:
            std::memset(out_offset, align_frag.getValue(), count);
            break;
          default:
            llvm::report_fatal_error(
              "unsupported value size for align fragment emission yet.\n");
            break;
        } // end switch
        break;
      }
      case Fragment::Null: {
        assert(0x0 == size);
        break;
      }
      default:
        llvm::report_fatal_error("unsupported fragment type.\n");
        break;
    } // end switch
    out_offset += size;
  } // end for

  return pRegion.size();
}
Ejemplo n.º 9
0
bool ELFAttribute::merge(const Input &pInput, LDSection &pInputAttrSectHdr)
{
  // Skip corrupt subsection
  if (pInputAttrSectHdr.size() < MinimalELFAttributeSectionSize)
    return true;

  // Obtain the region containing the attribute data. Expect exactly one
  // RegionFragment in the section data.
  const SectionData* sect_data = pInputAttrSectHdr.getSectionData();

  // FIXME: Why is 2?
  if ((sect_data->size() != 2) ||
      (!llvm::isa<RegionFragment>(sect_data->front()))) {
    return true;
  }

  const RegionFragment& region_frag =
      llvm::cast<RegionFragment>(sect_data->front());

  llvm::StringRef region = region_frag.getRegion();

  // Parse the ELF attribute section header. ARM [ABI-addenda], 2.2.3.
  //
  // <format-version: ‘A’>
  // [ <uint32: subsection-length> NTBS: vendor-name
  //   <bytes: vendor-data>
  // ]*
  const char *attribute_data = region.begin();

  // format-version
  if (attribute_data[0] != FormatVersion) {
    warning(diag::warn_unsupported_attribute_section_format)
        << pInput.name() << attribute_data[0];
    return true;
  }

  size_t subsection_offset = FormatVersionFieldSize;

  // Iterate all subsections containing in this attribute section.
  do {
    const char *subsection_data = region.begin() + subsection_offset;

    // subsection-length
    uint32_t subsection_length =
        *reinterpret_cast<const uint32_t*>(subsection_data);

    if(llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian())
      bswap32(subsection_length);

    // vendor-name
    const char* vendor_name = subsection_data + SubsectionLengthFieldSize;
    const size_t vendor_name_length = ::strlen(vendor_name) + 1 /* '\0' */;

    // Check the length.
    if ((vendor_name_length <= 1) ||
        (subsection_length <= (SubsectionLengthFieldSize + vendor_name_length)))
      return true;

    // Select the attribute subsection.
    Subsection *subsection = getSubsection(vendor_name);

    // Only process the subsections whose vendor can be recognized.
    if (subsection == NULL) {
      warning(diag::warn_unrecognized_vendor_subsection)
          << vendor_name << pInput.name();
    } else {
      // vendor-data
      size_t vendor_data_offset = subsection_offset +
                                  SubsectionLengthFieldSize +
                                  vendor_name_length;
      size_t vendor_data_size = subsection_length - SubsectionLengthFieldSize -
                                vendor_name_length;

      ConstAddress vendor_data =
          reinterpret_cast<ConstAddress>(region.begin()) + vendor_data_offset;

      // Merge the vendor data in the subsection.
      if (!subsection->merge(pInput, vendor_data, vendor_data_size))
        return false;
    }

    subsection_offset += subsection_length;
  } while ((subsection_offset + SubsectionLengthFieldSize) < pInputAttrSectHdr.size());

  return true;
}
Ejemplo n.º 10
0
uint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection,
                                          MemoryRegion& pRegion) const
{
  assert(pRegion.size() && "Size of MemoryRegion is zero!");

  const ELFFileFormat* file_format = getOutputFormat();

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

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

  if (&pSection == m_pAttributes) {
    return attribute().emit(pRegion);
  }

  // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
  // directly from the input file.
  const SectionData* sect_data = pSection.getSectionData();
  SectionData::const_iterator frag_iter, frag_end = sect_data->end();
  uint8_t* out_offset = pRegion.begin();
  for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
    size_t size = frag_iter->size();
    switch(frag_iter->getKind()) {
      case Fragment::Fillment: {
        const FillFragment& fill_frag =
          llvm::cast<FillFragment>(*frag_iter);
        if (0 == fill_frag.getValueSize()) {
          // virtual fillment, ignore it.
          break;
        }

        memset(out_offset, fill_frag.getValue(), fill_frag.size());
        break;
      }
      case Fragment::Region: {
        const RegionFragment& region_frag =
          llvm::cast<RegionFragment>(*frag_iter);
        const char* start = region_frag.getRegion().begin();
        memcpy(out_offset, start, size);
        break;
      }
      case Fragment::Alignment: {
        const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
        uint64_t count = size / align_frag.getValueSize();
        switch (align_frag.getValueSize()) {
          case 1u:
            std::memset(out_offset, align_frag.getValue(), count);
            break;
          default:
            llvm::report_fatal_error(
              "unsupported value size for align fragment emission yet.\n");
            break;
        } // end switch
        break;
      }
      case Fragment::Null: {
        assert(0x0 == size);
        break;
      }
      default:
        llvm::report_fatal_error("unsupported fragment type.\n");
        break;
    } // end switch
    out_offset += size;
  } // end for
  return pRegion.size();
}