bool MipsGNULDBackend::initTargetStubs() { if (getStubFactory() == NULL) return false; getStubFactory()->addPrototype(new MipsLA25Stub(*this)); return true; }
bool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel) { uint64_t sym_value = 0x0; LDSymbol* symbol = pRel.symInfo()->outSymbol(); if (symbol->hasFragRef()) { uint64_t value = symbol->fragRef()->getOutputOffset(); uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr(); sym_value = addr + value; } Stub* stub = getStubFactory()->create( pRel, sym_value, pBuilder, *getBRIslandFactory()); if (stub == NULL) return false; assert(stub->symInfo() != NULL); // increase the size of .symtab and .strtab LDSection& symtab = getOutputFormat()->getSymTab(); LDSection& strtab = getOutputFormat()->getStrTab(); symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym)); strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1); return true; }
// remotely accessible boost::int32_t SessionObjectFactoryService::CreateSessionObject( const std::string &objectName) { StubFactoryPtr stubFactoryPtr( getStubFactory( objectName)); if (stubFactoryPtr.get()) { RcfClientPtr rcfClientPtr( stubFactoryPtr->makeServerStub()); getTlsRcfSession().setDefaultStubEntryPtr( StubEntryPtr( new StubEntry(rcfClientPtr))); return RcfError_Ok; } return RcfError_ObjectFactoryNotFound; }
// remotely accessible boost::int32_t ObjectFactoryService::CreateObject( const std::string &objectName, Token &token) { RCF_LOG_3()(objectName); { Lock lock(mCleanupThresholdMutex); if (!mLazyStarted) { mTaskEntries[0].start(); mLazyStarted = true; } } // TODO: seems unnecessary to be triggering a sweep here std::size_t nAvail = mTokenFactory->getAvailableTokenCount(); std::size_t nTotal = mTokenFactory->getTokenSpace().size(); float used = float(nTotal - nAvail) / float(nTotal); if (used > mCleanupThreshold) { Lock lock(mCleanupThresholdMutex); mCleanupThresholdCondition.notify_all(lock); } boost::int32_t ret = RcfError_Ok; StubFactoryPtr stubFactoryPtr( getStubFactory( objectName)); if (stubFactoryPtr.get()) { RcfClientPtr rcfClientPtr( stubFactoryPtr->makeServerStub()); StubEntryPtr stubEntryPtr( new StubEntry(rcfClientPtr)); ret = addObject(TokenMappedPtr(stubEntryPtr), token); if (ret == RcfError_Ok) { getTlsRcfSession().setCachedStubEntryPtr(stubEntryPtr); RCF_LOG_3()(objectName)(token) << "Dynamically bound object created."; } } else { ret = RcfError_ObjectFactoryNotFound; } return ret; }
bool AArch64GNULDBackend::initTargetStubs() { StubFactory* factory = getStubFactory(); if (factory != NULL) { factory->addPrototype(new AArch64LongBranchStub(config().isCodeIndep())); if (config().targets().fixCA53Erratum835769()) { factory->addPrototype(new AArch64CA53Erratum835769Stub()); } if (config().targets().fixCA53Erratum843419()) { factory->addPrototype(new AArch64CA53Erratum843419Stub()); factory->addPrototype(new AArch64CA53Erratum843419Stub2()); } return true; } return false; }
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 }
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) }