Beispiel #1
0
TEST_F(SectionDataTest, Fragment_list_and_iterator) {
  LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
  SectionData* s = SectionData::Create(*test);
  EXPECT_TRUE(s->empty());

  new Fragment(Fragment::Alignment, s);
  new Fragment(Fragment::Alignment, s);
  new Fragment(Fragment::Region, s);
  new Fragment(Fragment::Fillment, s);
  new Fragment(Fragment::Target, s);
  EXPECT_TRUE(5 == s->size());

  // iterator
  llvm::iplist<Fragment>::iterator iter = s->begin();
  EXPECT_TRUE(Fragment::Alignment == iter->getKind());
  ++iter;
  EXPECT_TRUE(Fragment::Alignment == iter->getKind());
  ++iter;
  EXPECT_TRUE(Fragment::Region == iter->getKind());
  ++iter;
  EXPECT_TRUE(Fragment::Fillment == iter->getKind());
  ++iter;
  EXPECT_TRUE(Fragment::Target == iter->getKind());
  ++iter;
  EXPECT_TRUE(iter == s->end());

  LDSection::Destroy(test);
}
Beispiel #2
0
static RegionFragment* findRegionFragment(LDSection& pSection) {
  SectionData* sectData = pSection.getSectionData();
  for (SectionData::iterator it = sectData->begin(),
                             end = sectData->end(); it != end; ++it) {
    if (it->getKind() == Fragment::Region) {
      return static_cast<RegionFragment*>(&*it);
    }
  }
  return NULL;
}
void AArch64GNULDBackend::scanErrata(Module& pModule,
                                     IRBuilder& pBuilder,
                                     size_t& num_new_stubs,
                                     size_t& stubs_strlen) {
  // TODO: Implement AArch64 ErrataStubFactory to create the specific erratum
  //       stub and simplify the logics.
  for (Module::iterator sect = pModule.begin(), sectEnd = pModule.end();
       sect != sectEnd; ++sect) {
    if (((*sect)->kind() == LDFileFormat::TEXT) && (*sect)->hasSectionData()) {
      SectionData* sd = (*sect)->getSectionData();
      for (SectionData::iterator it = sd->begin(), ie = sd->end(); it != ie;
           ++it) {
        Fragment* frag = llvm::dyn_cast<RegionFragment>(it);
        if (frag != NULL) {
          FragmentRef* frag_ref = FragmentRef::Create(*frag, 0);
          for (unsigned offset = 0; offset < frag->size();
               offset += AArch64InsnHelpers::InsnSize) {
            Stub* stub = getStubFactory()->create(*frag_ref,
                                                  pBuilder,
                                                  *getBRIslandFactory());
            if (stub != NULL) {
              // A stub symbol should be local
              assert(stub->symInfo() != NULL && stub->symInfo()->isLocal());
              const AArch64CA53ErratumStub* erratum_stub =
                  reinterpret_cast<const AArch64CA53ErratumStub*>(stub);
              assert(erratum_stub != NULL);
              // Rewrite the erratum instruction as a branch to the stub.
              uint64_t offset = frag_ref->offset() +
                                erratum_stub->getErratumInsnOffset();
              Relocation* reloc =
                  Relocation::Create(llvm::ELF::R_AARCH64_JUMP26,
                                     *(FragmentRef::Create(*frag, offset)),
                                     /* pAddend */0);
              reloc->setSymInfo(stub->symInfo());
              reloc->target() = AArch64InsnHelpers::buildBranchInsn();
              addExtraRelocation(reloc);

              ++num_new_stubs;
              stubs_strlen += stub->symInfo()->nameSize() + 1;
            }

            frag_ref->assign(*frag, offset + AArch64InsnHelpers::InsnSize);
          }  // for each INSN
        }
      }  // for each FRAGMENT
    }
  }  // for each TEXT section
}
/// emitSectionData
void ELFObjectWriter::emitSectionData(const SectionData& pSD,
                                      MemoryRegion& pRegion) const
{
  SectionData::const_iterator fragIter, fragEnd = pSD.end();
  size_t cur_offset = 0;
  for (fragIter = pSD.begin(); fragIter != fragEnd; ++fragIter) {
    size_t size = fragIter->size();
    switch(fragIter->getKind()) {
      case Fragment::Region: {
        const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
        const uint8_t* from = region_frag.getRegion().start();
        memcpy(pRegion.getBuffer(cur_offset), from, size);
        break;
      }
      case Fragment::Alignment: {
        // TODO: emit values with different sizes (> 1 byte), and emit nops
        const AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
        uint64_t count = size / align_frag.getValueSize();
        switch (align_frag.getValueSize()) {
          case 1u:
            std::memset(pRegion.getBuffer(cur_offset),
                        align_frag.getValue(),
                        count);
            break;
          default:
            llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
            break;
        }
        break;
      }
      case Fragment::Fillment: {
        const FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
        if (0 == size ||
            0 == fill_frag.getValueSize() ||
            0 == fill_frag.size()) {
          // ignore virtual fillment
          break;
        }

        uint64_t num_tiles = fill_frag.size() / fill_frag.getValueSize();
        for (uint64_t i = 0; i != num_tiles; ++i) {
          std::memset(pRegion.getBuffer(cur_offset),
                      fill_frag.getValue(),
                      fill_frag.getValueSize());
        }
        break;
      }
      case Fragment::Stub: {
        const Stub& stub_frag = llvm::cast<Stub>(*fragIter);
        memcpy(pRegion.getBuffer(cur_offset), stub_frag.getContent(), size);
        break;
      }
      case Fragment::Null: {
        assert(0x0 == size);
        break;
      }
      case Fragment::Target:
        llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
        break;
      default:
        llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
        break;
    }
    cur_offset += size;
  }
}
Beispiel #5
0
void ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
  if (!m_pEXIDX->hasSectionData()) {
    // Return if this is empty section.
    return;
  }

  SectionData* sectData = m_pEXIDX->getSectionData();
  SectionData::FragmentListType& list = sectData->getFragmentList();

  // Move the first fragment (align fragment) and last fragment (null fragment)
  // to temporary list because we would only like to sort the region fragment.
  SectionData::FragmentListType tmp;
  {
    SectionData::iterator first = sectData->begin();
    SectionData::iterator last = sectData->end();
    --last;

    assert(first->getKind() == Fragment::Alignment);
    assert(last->getKind() == Fragment::Null);

    tmp.splice(tmp.end(), list, first);
    tmp.splice(tmp.end(), list, last);
  }

  // Sort the region fragments in the .ARM.exidx output section.
  sort(list, ExIdxFragmentComparator(m_ExData));

  // Fix the coverage of the .ARM.exidx table.
  llvm::StringRef cantUnwindRegion(g_CantUnwindEntry,
                                   sizeof(g_CantUnwindEntry));

  SectionData::FragmentListType::iterator it = list.begin();
  if (it != list.end()) {
    Fragment* prevTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment();
    uint64_t prevTextEnd = prevTextFrag->getParent()->getSection().addr() +
                           prevTextFrag->getOffset() +
                           prevTextFrag->size();
    ++it;
    while (it != list.end()) {
      Fragment* currTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment();
      uint64_t currTextBegin = currTextFrag->getParent()->getSection().addr() +
                               currTextFrag->getOffset();

      if (currTextBegin > prevTextEnd) {
        // Found a gap. Insert a can't unwind entry.
        RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
        frag->setParent(sectData);
        list.insert(it, frag);

        // Add PREL31 reference to the beginning of the uncovered region.
        Relocation* reloc =
            Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
                               *FragmentRef::Create(*frag, /* pOffset */0),
                               /* pAddend */0);
        reloc->setSymInfo(
            CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
        addExtraRelocation(reloc);
      }

      prevTextEnd = currTextBegin + currTextFrag->size();
      prevTextFrag = currTextFrag;
      ++it;
    }

    // Add a can't unwind entry to terminate .ARM.exidx section.
    RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
    frag->setParent(sectData);
    list.push_back(frag);

    // Add PREL31 reference to the end of the .text section.
    Relocation* reloc =
        Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
                           *FragmentRef::Create(*frag, /* pOffset */0),
                           /* pAddend */0);
    reloc->setSymInfo(CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
    addExtraRelocation(reloc);
  }

  // Add the first and the last fragment back.
  list.splice(list.begin(), tmp, tmp.begin());
  list.splice(list.end(), tmp, tmp.begin());

  // Update the fragment offsets.
  uint64_t offset = 0;
  for (SectionData::iterator it = sectData->begin(), end = sectData->end();
       it != end; ++it) {
    it->setOffset(offset);
    offset += it->size();
  }

  // Update the section size.
  m_pEXIDX->setSize(offset);

  // Rebuild the section header.
  setOutputSectionAddress(pModule);
}