static std::map<void *, uint64_t> applySpecificSectionMappings(RuntimeDyldChecker &Checker) { std::map<void*, uint64_t> SpecificMappings; for (StringRef Mapping : SpecificSectionMappings) { size_t EqualsIdx = Mapping.find_first_of("="); StringRef SectionIDStr = Mapping.substr(0, EqualsIdx); size_t ComaIdx = Mapping.find_first_of(","); if (ComaIdx == StringRef::npos) { errs() << "Invalid section specification '" << Mapping << "'. Should be '<file name>,<section name>=<addr>'\n"; exit(1); } StringRef FileName = SectionIDStr.substr(0, ComaIdx); StringRef SectionName = SectionIDStr.substr(ComaIdx + 1); uint64_t OldAddrInt; std::string ErrorMsg; std::tie(OldAddrInt, ErrorMsg) = Checker.getSectionAddr(FileName, SectionName, true); if (ErrorMsg != "") { errs() << ErrorMsg; exit(1); } void* OldAddr = reinterpret_cast<void*>(static_cast<uintptr_t>(OldAddrInt)); StringRef NewAddrStr = Mapping.substr(EqualsIdx + 1); uint64_t NewAddr; if (NewAddrStr.getAsInteger(0, NewAddr)) { errs() << "Invalid section address in mapping: " << Mapping << "\n"; exit(1); } Checker.getRTDyld().mapSectionAddress(OldAddr, NewAddr); SpecificMappings[OldAddr] = NewAddr; } return SpecificMappings; }
static int checkAllExpressions(RuntimeDyldChecker &Checker) { for (const auto& CheckerFileName : CheckFiles) { ErrorOr<std::unique_ptr<MemoryBuffer>> CheckerFileBuf = MemoryBuffer::getFileOrSTDIN(CheckerFileName); if (std::error_code EC = CheckerFileBuf.getError()) return Error("unable to read input '" + CheckerFileName + "': " + EC.message()); if (!Checker.checkAllRulesInBuffer("# rtdyld-check:", CheckerFileBuf.get().get())) return Error("some checks in '" + CheckerFileName + "' failed"); } return 0; }
// Scatter sections in all directions! // Remaps section addresses for -verify mode. The following command line options // can be used to customize the layout of the memory within the phony target's // address space: // -target-addr-start <s> -- Specify where the phony target addres range starts. // -target-addr-end <e> -- Specify where the phony target address range ends. // -target-section-sep <d> -- Specify how big a gap should be left between the // end of one section and the start of the next. // Defaults to zero. Set to something big // (e.g. 1 << 32) to stress-test stubs, GOTs, etc. // static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple, TrivialMemoryManager &MemMgr, RuntimeDyldChecker &Checker) { // Set up a work list (section addr/size pairs). typedef std::list<std::pair<void*, uint64_t>> WorklistT; WorklistT Worklist; for (const auto& CodeSection : MemMgr.FunctionMemory) Worklist.push_back(std::make_pair(CodeSection.base(), CodeSection.size())); for (const auto& DataSection : MemMgr.DataMemory) Worklist.push_back(std::make_pair(DataSection.base(), DataSection.size())); // Apply any section-specific mappings that were requested on the command // line. typedef std::map<void*, uint64_t> AppliedMappingsT; AppliedMappingsT AppliedMappings = applySpecificSectionMappings(Checker); // Keep an "already allocated" mapping of section target addresses to sizes. // Sections whose address mappings aren't specified on the command line will // allocated around the explicitly mapped sections while maintaining the // minimum separation. std::map<uint64_t, uint64_t> AlreadyAllocated; // Move the previously applied mappings into the already-allocated map. for (WorklistT::iterator I = Worklist.begin(), E = Worklist.end(); I != E;) { WorklistT::iterator Tmp = I; ++I; AppliedMappingsT::iterator AI = AppliedMappings.find(Tmp->first); if (AI != AppliedMappings.end()) { AlreadyAllocated[AI->second] = Tmp->second; Worklist.erase(Tmp); } } // If the -target-addr-end option wasn't explicitly passed, then set it to a // sensible default based on the target triple. if (TargetAddrEnd.getNumOccurrences() == 0) { if (TargetTriple.isArch16Bit()) TargetAddrEnd = (1ULL << 16) - 1; else if (TargetTriple.isArch32Bit()) TargetAddrEnd = (1ULL << 32) - 1; // TargetAddrEnd already has a sensible default for 64-bit systems, so // there's nothing to do in the 64-bit case. } // Process any elements remaining in the worklist. while (!Worklist.empty()) { std::pair<void*, uint64_t> CurEntry = Worklist.front(); Worklist.pop_front(); uint64_t NextSectionAddr = TargetAddrStart; for (const auto &Alloc : AlreadyAllocated) if (NextSectionAddr + CurEntry.second + TargetSectionSep <= Alloc.first) break; else NextSectionAddr = Alloc.first + Alloc.second + TargetSectionSep; AlreadyAllocated[NextSectionAddr] = CurEntry.second; Checker.getRTDyld().mapSectionAddress(CurEntry.first, NextSectionAddr); } // Add dummy symbols to the memory manager. for (const auto &Mapping : DummySymbolMappings) { size_t EqualsIdx = Mapping.find_first_of("="); if (EqualsIdx == StringRef::npos) report_fatal_error("Invalid dummy symbol specification '" + Mapping + "'. Should be '<symbol name>=<addr>'"); std::string Symbol = Mapping.substr(0, EqualsIdx); std::string AddrStr = Mapping.substr(EqualsIdx + 1); uint64_t Addr; if (StringRef(AddrStr).getAsInteger(0, Addr)) report_fatal_error("Invalid symbol mapping '" + Mapping + "'."); MemMgr.addDummySymbol(Symbol, Addr); } }