mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-29 10:32:47 +00:00
[MCJIT] Add command-line argument to llvm-rtdyld to specify target addresses for
sections. This allows fine-grained control of the memory layout of hypothetical target processes for testing purposes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217122 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cd72c216cd
commit
5ade584a96
@ -67,6 +67,12 @@ public:
|
||||
MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
|
||||
~RuntimeDyldChecker();
|
||||
|
||||
// \brief Get the associated RTDyld instance.
|
||||
RuntimeDyld& getRTDyld();
|
||||
|
||||
// \brief Get the associated RTDyld instance.
|
||||
const RuntimeDyld& getRTDyld() const;
|
||||
|
||||
/// \brief Check a single expression against the attached RuntimeDyld
|
||||
/// instance.
|
||||
bool check(StringRef CheckExpr) const;
|
||||
@ -76,6 +82,16 @@ public:
|
||||
/// method to be evaluated as an expression.
|
||||
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
|
||||
|
||||
/// \brief Returns the address of the requested section (or an error message
|
||||
/// in the second element of the pair if the address cannot be found).
|
||||
///
|
||||
/// if 'LinkerAddress' is true, this returns the address of the section
|
||||
/// within the linker's memory. If 'LinkerAddress' is false it returns the
|
||||
/// address within the target process (i.e. the load address).
|
||||
std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName,
|
||||
StringRef SectionName,
|
||||
bool LinkerAddress);
|
||||
|
||||
private:
|
||||
std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
|
||||
};
|
||||
|
@ -695,6 +695,10 @@ void RuntimeDyldImpl::reassignSectionAddress(unsigned SectionID,
|
||||
// Addr is a uint64_t because we can't assume the pointer width
|
||||
// of the target is the same as that of the host. Just use a generic
|
||||
// "big enough" type.
|
||||
DEBUG(dbgs() << "Reassigning address for section "
|
||||
<< SectionID << " (" << Sections[SectionID].Name << "): "
|
||||
<< format("0x%016x", Sections[SectionID].LoadAddress) << " -> "
|
||||
<< format("0x%016x", Addr) << "\n");
|
||||
Sections[SectionID].LoadAddress = Addr;
|
||||
}
|
||||
|
||||
|
@ -905,6 +905,14 @@ RuntimeDyldChecker::RuntimeDyldChecker(RuntimeDyld &RTDyld,
|
||||
|
||||
RuntimeDyldChecker::~RuntimeDyldChecker() {}
|
||||
|
||||
RuntimeDyld& RuntimeDyldChecker::getRTDyld() {
|
||||
return Impl->RTDyld;
|
||||
}
|
||||
|
||||
const RuntimeDyld& RuntimeDyldChecker::getRTDyld() const {
|
||||
return Impl->RTDyld;
|
||||
}
|
||||
|
||||
bool RuntimeDyldChecker::check(StringRef CheckExpr) const {
|
||||
return Impl->check(CheckExpr);
|
||||
}
|
||||
@ -913,3 +921,9 @@ bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix,
|
||||
MemoryBuffer *MemBuf) const {
|
||||
return Impl->checkAllRulesInBuffer(RulePrefix, MemBuf);
|
||||
}
|
||||
|
||||
std::pair<uint64_t, std::string>
|
||||
RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName,
|
||||
bool LinkerAddress) {
|
||||
return Impl->getSectionAddr(FileName, SectionName, LinkerAddress);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
namespace llvm {
|
||||
|
||||
class RuntimeDyldCheckerImpl {
|
||||
friend class RuntimeDyldChecker;
|
||||
friend class RuntimeDyldImpl;
|
||||
friend class RuntimeDyldCheckerExprEval;
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <list>
|
||||
#include <system_error>
|
||||
|
||||
using namespace llvm;
|
||||
@ -98,6 +99,11 @@ TargetSectionSep("target-section-sep",
|
||||
cl::init(0),
|
||||
cl::Hidden);
|
||||
|
||||
static cl::list<std::string>
|
||||
SpecificSectionMappings("map-section",
|
||||
cl::desc("Map a section to a specific address."),
|
||||
cl::ZeroOrMore);
|
||||
|
||||
/* *** */
|
||||
|
||||
// A trivial memory manager that doesn't do anything fancy, just uses the
|
||||
@ -320,6 +326,53 @@ static int checkAllExpressions(RuntimeDyldChecker &Checker) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -333,7 +386,40 @@ static int checkAllExpressions(RuntimeDyldChecker &Checker) {
|
||||
//
|
||||
void remapSections(const llvm::Triple &TargetTriple,
|
||||
const TrivialMemoryManager &MemMgr,
|
||||
RuntimeDyld &RTDyld) {
|
||||
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.
|
||||
@ -346,19 +432,23 @@ void remapSections(const llvm::Triple &TargetTriple,
|
||||
// there's nothing to do in the 64-bit case.
|
||||
}
|
||||
|
||||
uint64_t NextSectionAddress = TargetAddrStart;
|
||||
// Process any elements remaining in the worklist.
|
||||
while (!Worklist.empty()) {
|
||||
std::pair<void*, uint64_t> CurEntry = Worklist.front();
|
||||
Worklist.pop_front();
|
||||
|
||||
// Remap code sections.
|
||||
for (const auto& CodeSection : MemMgr.FunctionMemory) {
|
||||
RTDyld.mapSectionAddress(CodeSection.base(), NextSectionAddress);
|
||||
NextSectionAddress += CodeSection.size() + TargetSectionSep;
|
||||
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);
|
||||
}
|
||||
|
||||
// Remap data sections.
|
||||
for (const auto& DataSection : MemMgr.DataMemory) {
|
||||
RTDyld.mapSectionAddress(DataSection.base(), NextSectionAddress);
|
||||
NextSectionAddress += DataSection.size() + TargetSectionSep;
|
||||
}
|
||||
}
|
||||
|
||||
// Load and link the objects specified on the command line, but do not execute
|
||||
@ -435,7 +525,7 @@ static int linkAndVerify() {
|
||||
}
|
||||
|
||||
// Re-map the section addresses into the phony target address space.
|
||||
remapSections(TheTriple, MemMgr, Dyld);
|
||||
remapSections(TheTriple, MemMgr, Checker);
|
||||
|
||||
// Resolve all the relocations we can.
|
||||
Dyld.resolveRelocations();
|
||||
|
Loading…
Reference in New Issue
Block a user