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); }
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; }
bool HexagonLDBackend::SetSDataSection() { SectionData *pTo = (m_psdata->getSectionData()); if (pTo) { MoveCommonData(*m_pscommon_1->getSectionData(), *pTo); MoveCommonData(*m_pscommon_2->getSectionData(), *pTo); MoveCommonData(*m_pscommon_4->getSectionData(), *pTo); MoveCommonData(*m_pscommon_8->getSectionData(), *pTo); SectionData::FragmentListType& to_list = pTo->getFragmentList(); SectionData::FragmentListType::iterator fragTo, fragToEnd = to_list.end(); uint32_t offset = 0; for (fragTo = to_list.begin(); fragTo != fragToEnd; ++fragTo) { fragTo->setOffset(offset); offset += fragTo->size(); } // set up pTo's header pTo->getSection().setSize(offset); SectionData::FragmentListType& newlist = pTo->getFragmentList(); for (fragTo = newlist.begin(), fragToEnd = newlist.end(); fragTo != fragToEnd; ++fragTo) { fragTo->setParent(pTo); } } return true; }
/// addStub - add a stub into the island bool BranchIsland::addStub(const Stub* pPrototype, const Relocation& pReloc, Stub& pStub) { bool exist = false; Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend()); StubEntryType* entry = m_StubMap.insert(key, exist); if (!exist) { entry->setValue(&pStub); m_pRear = &pStub; SectionData* sd = m_Entry.getParent(); // insert alignment fragment // TODO: check if we can reduce this alignment fragment for some cases AlignFragment* align_frag = new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1); align_frag->setParent(sd); sd->getFragmentList().insert(end(), align_frag); align_frag->setOffset(align_frag->getPrevNode()->getOffset() + align_frag->getPrevNode()->size()); // insert stub fragment pStub.setParent(sd); sd->getFragmentList().insert(end(), &pStub); pStub.setOffset(pStub.getPrevNode()->getOffset() + pStub.getPrevNode()->size()); } return !exist; }
TEST_F(SectionDataTest, constructor_and_trivial_func) { LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0); SectionData* s = SectionData::Create(*test); EXPECT_TRUE(s->getSection().name() == "test" && s->getSection().kind() == LDFileFormat::Null); LDSection::Destroy(test); }
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 }
/** * 检查是否超限 * 如果有左值、右值小于超限值,则返回true * 如果当前值为-1不做比较 */ bool ClearanceData::checkLessThanStdSectionData(SectionData & basedata) { std::map<int,ClearanceItem>::iterator it = vals.begin(); std::map<int, item> & basemap = basedata.getMaps(); int tempkey; float tmpvalf; int tmpvali; while (it != vals.end()) { /* vs2012下不行,出错“初始化”: 无法从“std::pair<_Ty1,_Ty2>”转换为“std::pair<_Ty1,_Ty2>” std::pair<int,item&> pair = (*it); pair.second.left = -1; pair.second.right = -1; */ std::pair<int,ClearanceItem> pair = (*it); tempkey = pair.first; if (vals[tempkey].leftval > 0 && vals[tempkey].leftval < basemap[tempkey].left) return true; if (vals[tempkey].rightval > 0 && vals[tempkey].rightval < basemap[tempkey].right) return true; it++; } return false; }
pySectionData(int np, const bpn::array &z_np, const bpn::array &EA_np, const bpn::array &EIxx_np, const bpn::array &EIyy_np, const bpn::array &GJ_np, const bpn::array &rhoA_np, const bpn::array &rhoJ_np) { sec.nodes = np; sec.z.resize(sec.nodes); sec.EA.resize(sec.nodes); sec.EIxx.resize(sec.nodes); sec.EIyy.resize(sec.nodes); sec.GJ.resize(sec.nodes); sec.rhoA.resize(sec.nodes); sec.rhoJ.resize(sec.nodes); for (int i = 0 ; i < sec.nodes; i++) { sec.z(i) = bp::extract<double>(z_np[i]); sec.EA(i) = bp::extract<double>(EA_np[i]); sec.EIxx(i) = bp::extract<double>(EIxx_np[i]); sec.EIyy(i) = bp::extract<double>(EIyy_np[i]); sec.GJ(i) = bp::extract<double>(GJ_np[i]); sec.rhoA(i) = bp::extract<double>(rhoA_np[i]); sec.rhoJ(i) = bp::extract<double>(rhoJ_np[i]); } }
bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD) { Fragment* frag = NULL; uint32_t offset = pInput.fileOffset() + pSD.getSection().offset(); uint32_t size = pSD.getSection().size(); llvm::StringRef region = pInput.memArea()->request(offset, size); if (region.size() == 0) { // If the input section's size is zero, we got a NULL region. // use a virtual fill fragment frag = new FillFragment(0x0, 0, 0); } else { frag = new RegionFragment(region); } ObjectBuilder::AppendFragment(*frag, pSD); return true; }
ErrorStatus::FileError AFTSectionPipeFace::Save(SectionData &Data,SectionPipePerisistent& model) { Data.Search(model.Search()); Data.MaxSections(model.MaxSections()); Data.MinSections(model.MinSections()); Data.MaxError(model.MaxError()); Data.PctIncrement(model.PctIncrement()); Data.Sort(model.Sort()); Data.IdealSections(model.IdealSections()); Data.TimeStep(model.TimeStep()); return ErrorStatus::eFileOK; }
FragmentRef* FragmentRef::Create(LDSection& pSection, uint64_t pOffset) { SectionData* data = NULL; switch (pSection.kind()) { case LDFileFormat::Relocation: // No fragment reference refers to a relocation section break; case LDFileFormat::EhFrame: if (pSection.hasEhFrame()) data = pSection.getEhFrame()->getSectionData(); break; default: data = pSection.getSectionData(); break; } if (data == NULL || data->empty()) { return Null(); } return Create(data->front(), pOffset); }
bool HexagonLDBackend::MoveCommonData(SectionData &pFrom, SectionData &pTo) { SectionData::FragmentListType& to_list = pTo.getFragmentList(); SectionData::FragmentListType::iterator frag, fragEnd = to_list.end(); uint32_t pFromFlag = pFrom.getSection().align(); bool found = false; SectionData::FragmentListType::iterator fragInsert; for (frag = to_list.begin(); frag != fragEnd; ++frag) { if (frag->getKind() == mcld::Fragment::Alignment) { fragInsert = frag; continue; } if ((frag->getKind() != mcld::Fragment::Region) && (frag->getKind() != mcld::Fragment::Fillment)) { continue; } uint32_t flag = frag->getParent()->getSection().align(); if (pFromFlag < flag) { found = true; break; } } AlignFragment* align = NULL; if (pFrom.getSection().align() > 1) { // if the align constraint is larger than 1, append an alignment align = new AlignFragment(pFrom.getSection().align(), // alignment 0x0, // the filled value 1u, // the size of filled value pFrom.getSection().align() - 1 // max bytes to emit ); pFrom.getFragmentList().push_front(align); } if (found) to_list.splice(fragInsert, pFrom.getFragmentList()); else to_list.splice(frag, pFrom.getFragmentList()); return true; }
/// 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; } }
int LzExcelOutput::outputSingleSection(TunnelDataModel * inputbasicdata, QString collectdate, SectionData & inputdata, QString templatepath, QString outputfile, QString insertimgpath) { QString templatename = "SingleSectionTemplate.xls"; int ret = copy(templatepath, templatename, outputfile); qDebug() << templatepath << outputfile << insertimgpath; if (ret != 0) return ret; // 插入图片路径不存在 if (!QFile(insertimgpath).exists()) return 3; //操作已经存在的excel,生成限界尺寸表 ExcelEngine excel; excel.Open(outputfile, 1, false); // 限界表名称 excel.SetCellData(1,1,QObject::tr("%1隧道单幅尺寸表").arg(QObject::tr(inputbasicdata->getName().c_str()))); excel.SetCellData(52,1,QObject::tr("%1隧道断面示意图").arg(QObject::tr(inputbasicdata->getName().c_str()))); // 线路名称 excel.SetCellData(3,2,QObject::tr(inputbasicdata->getLinename().c_str())); excel.SetCellData(54,2,QObject::tr(inputbasicdata->getLinename().c_str())); // 区段///TODO excel.SetCellData(3,7,QObject::tr(inputbasicdata->getLinename().c_str())); // 面向站名 excel.SetCellData(3,10,QObject::tr(inputbasicdata->getLineEndStation().c_str())); excel.SetCellData(54,8,QObject::tr(inputbasicdata->getLineEndStation().c_str())); // 桥隧名称 excel.SetCellData(4,3,QObject::tr(inputbasicdata->getName().c_str())); excel.SetCellData(54,4,QObject::tr(inputbasicdata->getName().c_str())); // 时间 QByteArray ba = collectdate.toLocal8Bit(); excel.SetCellData(48,10,ba.constData()); excel.SetCellData(54,10,ba.constData()); // 计算隧道长度 _int64 tunnellength = inputbasicdata->getEndPoint() - inputbasicdata->getStartPoint(); if (tunnellength < 0) tunnellength = 0 - tunnellength; //excel.SetCellData(102,3,tunnellength); // 计算中心里程 隧道中心点的里程数 float centerlength = 1.0 * (inputbasicdata->getEndPoint() + inputbasicdata->getStartPoint()) / 2; excel.SetCellData(4,7,centerlength); excel.SetCellData(101,3,centerlength); SectionData & data = inputdata; int rowcount = data.getMaps().size(); // Excel模板从第9行开始为高度限界数据,前面几行为表头或空格 int startrownum = 9; int startcolumnnumdef = 1; // 临时变量 int startcolumnnum = startcolumnnumdef; float tmpval; __int64 tmppos; int tmpradius; { startcolumnnum = startcolumnnumdef; CurveType type = inputdata.getType(); long long pos = inputdata.getMile(); int radius = inputdata.getRadius(); float minHeight = inputdata.getCenterHeight(); switch(type) { case Curve_Straight: startcolumnnum += LzOutputTableColumn::Straight_Left_Val; break; case Curve_Left: startcolumnnum += 3; break; case Curve_Right: startcolumnnum += 7; break; default: break; } // map反向遍历,正向为高度从小到大,插入图表是需要高度从大到小 std::map<int, item>::reverse_iterator it = data.getMaps().rbegin(); int k = 0; // 相对行数 while (it != data.getMaps().rend()) { std::pair<int, item> pair = (*it); if (pair.first > minHeight) { it++; k++; continue; } // 此处写要插入的内容 if (pair.second.left >= 0) excel.SetCellData(k + startrownum, startcolumnnum, (int)pair.second.left); if (pair.second.right >= 0) excel.SetCellData(k + startrownum, startcolumnnum + 1, (int)pair.second.right); if (type != Curve_Straight) // 不是直线,折减后尺寸 { if (pair.second.left >= 0) excel.SetCellData(k + startrownum, startcolumnnum + 2, (long long)pair.second.left); if (pair.second.right >= 0) excel.SetCellData(k + startrownum, startcolumnnum + 3, (long long)pair.second.left); } it++; k++; } } // <150高度手动输入? ///TODO // 线路中心线上方最低净高mm///TODO excel.SetCellData(rowcount+startrownum+1,6,(int)inputdata.getCenterHeight()); // 半径 int radius = inputdata.getRadius(); if (radius <= 0) radius = 0; excel.SetCellData(4,10,radius); excel.SetCellData(54,6,radius); excel.SetCellData(102,3,radius); excel.setProperty("DisplayAlerts", 0); // 保存 excel.Save(); excel.Close(); // 生成限界图 initExcelEngine(); QAxObject *workBooks1 = excel1->querySubObject("Workbooks"); workBooks1->dynamicCall("Open(const QString&)", outputfile); QAxObject *workBook1 = excel1->querySubObject("ActiveWorkBook"); QAxObject *sheets1 = workBook1->querySubObject("WorkSheets"); QAxObject *sheet1 = sheets1->querySubObject("Item(int)", 1);//获得第一个工作表 // QAxObject *range=sheet1->querySubObject("Range(const QVariant&)",QVariant(QString("D52:AA92"))); // range->dynamicCall("Clear()");//指定清除某个区域 /////////////AddPicture函数详解//////////////// // AddPicture(FileName, LinkToFile, SaveWithDocument, Left, Top, Width, Height)中7个参数的意思。 // (1)FileName 必选 String 图片的路径和文件名。 // (2)LinkToFile 可选 Variant 如果该参数值为 True,则将图片链接到创建它的文件。如果该参数值为 False,则将图片作为该文件的独立副本。默认值为 False。 // (3)SaveWithDocument 可选 Variant 如果该参数值为 True,则将链接的图片与文档一起保存。默认值为 False。 // (4)Left 可选 Variant 新图片的左边缘相对于绘图画布的位置,以磅为单位。 // (5)Top 可选 Variant 新图片的上边缘相对于绘图画布的位置,以磅为单位。 // (6)Width 可选 Variant 图片的宽度,以磅为单位。 // (7)Height 可选 Variant 图片的高度,以磅为单位。 /////////////////////////////////////////////// // @author 熊雪、范翔。路径变成反斜杠,否则AddPicture,SaveAs函数出错 outputfile = toBackSlashStr(outputfile); insertimgpath = toBackSlashStr(insertimgpath); QAxObject *shapes1 = sheet1->querySubObject("Shapes"); shapes1->dynamicCall("AddPicture(QString&,bool,bool,double,double,double,double",QString("%1").arg(insertimgpath),true,true,8,770,510,595);//8,750,510,627 QString("%1image.jpg").arg(outputfile) excel1->setProperty("DisplayAlerts", 0); //excel1->dynamicCall("Save()"); workBook1->dynamicCall("SaveAs(const QString&)", outputfile); // QMessageBox::information(NULL, tr("OK"), tr("成功生成Excel文件!"),QMessageBox::Yes | QMessageBox::No); excel1->dynamicCall("Quit()"); return 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); }
/// MoveSectionData - move the fragments of pTO section data to pTo bool HexagonLDBackend::MoveSectionDataAndSort(SectionData& pFrom, SectionData& pTo) { assert(&pFrom != &pTo && "Cannot move section data to itself!"); SectionData::FragmentListType& to_list = pTo.getFragmentList(); SectionData::FragmentListType::iterator frag, fragEnd = to_list.end(); uint32_t pFromFlag = pFrom.getSection().align(); bool found = false; SectionData::FragmentListType::iterator fragInsert; for (frag = to_list.begin(); frag != fragEnd; ++frag) { if (frag->getKind() == mcld::Fragment::Alignment) { fragInsert = frag; continue; } if ((frag->getKind() != mcld::Fragment::Region) && (frag->getKind() != mcld::Fragment::Fillment)) { continue; } uint32_t flag = frag->getParent()->getSection().align(); if (pFromFlag < flag) { found = true; break; } } AlignFragment* align = NULL; if (pFrom.getSection().align() > 1) { // if the align constraint is larger than 1, append an alignment align = new AlignFragment(pFrom.getSection().align(), // alignment 0x0, // the filled value 1u, // the size of filled value pFrom.getSection().align() - 1 // max bytes to emit ); pFrom.getFragmentList().push_front(align); } if (found) to_list.splice(fragInsert, pFrom.getFragmentList()); else to_list.splice(frag, pFrom.getFragmentList()); uint32_t offset = 0; for (frag = to_list.begin(); frag != fragEnd; ++frag) { frag->setOffset(offset); offset += frag->size(); } // set up pTo's header pTo.getSection().setSize(offset); if (pFrom.getSection().align() > pTo.getSection().align()) pTo.getSection().setAlign(pFrom.getSection().align()); if (pFrom.getSection().flag() > pTo.getSection().flag()) pTo.getSection().setFlag(pFrom.getSection().flag()); return true; }
bool MipsGNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished) { assert(getStubFactory() != NULL && getBRIslandFactory() != NULL); bool isRelaxed = false; for (Module::obj_iterator input = pModule.obj_begin(); input != pModule.obj_end(); ++input) { LDContext* context = (*input)->context(); for (LDContext::sect_iterator rs = context->relocSectBegin(); rs != context->relocSectEnd(); ++rs) { LDSection* sec = *rs; if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData()) continue; for (RelocData::iterator reloc = sec->getRelocData()->begin(); reloc != sec->getRelocData()->end(); ++reloc) { if (llvm::ELF::R_MIPS_26 != reloc->type()) continue; if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc))) isRelaxed = true; } } } SectionData* textData = getOutputFormat()->getText().getSectionData(); // find the first fragment w/ invalid offset due to stub insertion Fragment* invalid = NULL; pFinished = true; for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(), ie = getBRIslandFactory()->end(); ii != ie; ++ii) { BranchIsland& island = *ii; if (island.end() == textData->end()) break; Fragment* exit = island.end(); if ((island.offset() + island.size()) > exit->getOffset()) { invalid = exit; pFinished = false; break; } } // reset the offset of invalid fragments while (invalid != NULL) { invalid->setOffset(invalid->getPrevNode()->getOffset() + invalid->getPrevNode()->size()); invalid = invalid->getNextNode(); } // reset the size of .text if (isRelaxed) getOutputFormat()->getText().setSize(textData->back().getOffset() + textData->back().size()); return isRelaxed; }
bool AArch64GNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished) { assert(getStubFactory() != NULL && getBRIslandFactory() != NULL); // Number of new stubs added size_t num_new_stubs = 0; // String lengh to hold new stub symbols size_t stubs_strlen = 0; if (config().targets().fixCA53Erratum835769() || config().targets().fixCA53Erratum843419()) { scanErrata(pModule, pBuilder, num_new_stubs, stubs_strlen); } ELFFileFormat* file_format = getOutputFormat(); // check branch relocs and create the related stubs if needed Module::obj_iterator input, inEnd = pModule.obj_end(); for (input = pModule.obj_begin(); input != inEnd; ++input) { LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) continue; RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end(); for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) { Relocation* relocation = llvm::cast<Relocation>(reloc); switch (relocation->type()) { case llvm::ELF::R_AARCH64_CALL26: case llvm::ELF::R_AARCH64_JUMP26: { // calculate the possible symbol value uint64_t sym_value = 0x0; LDSymbol* symbol = relocation->symInfo()->outSymbol(); if (symbol->hasFragRef()) { uint64_t value = symbol->fragRef()->getOutputOffset(); uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr(); sym_value = addr + value; } if ((relocation->symInfo()->reserved() & AArch64Relocator::ReservePLT) != 0x0) { // FIXME: we need to find out the address of the specific plt // entry assert(file_format->hasPLT()); sym_value = file_format->getPLT().addr(); } Stub* stub = getStubFactory()->create(*relocation, // relocation sym_value, // symbol value pBuilder, *getBRIslandFactory()); if (stub != NULL) { // a stub symbol should be local assert(stub->symInfo() != NULL && stub->symInfo()->isLocal()); // reset the branch target of the reloc to this stub instead relocation->setSymInfo(stub->symInfo()); ++num_new_stubs; stubs_strlen += stub->symInfo()->nameSize() + 1; } break; } default: { break; } } // end of switch } // for all relocations } // for all relocation section } // for all inputs // Find the first fragment w/ invalid offset due to stub insertion. std::vector<Fragment*> invalid_frags; pFinished = true; for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(), island_end = getBRIslandFactory()->end(); island != island_end; ++island) { if ((*island).size() > stubGroupSize()) { error(diag::err_no_space_to_place_stubs) << stubGroupSize(); return false; } if ((*island).numOfStubs() == 0) { continue; } Fragment* exit = &*(*island).end(); if (exit == (*island).begin()->getParent()->end()) { continue; } if (((*island).offset() + (*island).size()) > exit->getOffset()) { if (invalid_frags.empty() || (invalid_frags.back()->getParent() != (*island).getParent())) { invalid_frags.push_back(exit); pFinished = false; } continue; } } // Reset the offset of invalid fragments. for (auto it = invalid_frags.begin(), ie = invalid_frags.end(); it != ie; ++it) { Fragment* invalid = *it; while (invalid != NULL) { invalid->setOffset(invalid->getPrevNode()->getOffset() + invalid->getPrevNode()->size()); invalid = invalid->getNextNode(); } } // Fix up the size of .symtab, .strtab, and TEXT sections if (num_new_stubs == 0) { return false; } else { switch (config().options().getStripSymbolMode()) { case GeneralOptions::StripSymbolMode::StripAllSymbols: case GeneralOptions::StripSymbolMode::StripLocals: break; default: { LDSection& symtab = file_format->getSymTab(); LDSection& strtab = file_format->getStrTab(); symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym) * num_new_stubs); symtab.setInfo(symtab.getInfo() + num_new_stubs); strtab.setSize(strtab.size() + stubs_strlen); } } // switch (config().options().getStripSymbolMode()) SectionData* prev = NULL; for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(), island_end = getBRIslandFactory()->end(); island != island_end; ++island) { SectionData* sd = (*island).begin()->getParent(); if ((*island).numOfStubs() != 0) { if (sd != prev) { sd->getSection().setSize(sd->back().getOffset() + sd->back().size()); } } prev = sd; } return true; } // if (num_new_stubs == 0) }