arch,base: Separate the idea of a memory image and object file.
A memory image can be described by an object file, but an object file is more than a memory image. Also, it makes sense to manipulate a memory image to, for instance, change how it's loaded into memory. That takes on larger implications (relocations, the entry point, symbols, etc.) when talking about the whole object file, and also modifies aspects which may not need to change. For instance if an image needs to be loaded into memory at addresses different from what's in the object file, but other things like symbols need to stay unmodified. Change-Id: Ia360405ffb2c1c48e0cc201ac0a0764357996a54 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21466 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Brandon Potter <Brandon.Potter@amd.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -129,6 +129,8 @@ Process::Process(ProcessParams *params, EmulationPageTable *pTable,
|
||||
exitGroup = new bool();
|
||||
sigchld = new bool();
|
||||
|
||||
image = objFile->buildImage();
|
||||
|
||||
if (!debugSymbolTable) {
|
||||
debugSymbolTable = new SymbolTable();
|
||||
if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
|
||||
@@ -270,6 +272,16 @@ Process::revokeThreadContext(int context_id)
|
||||
warn("Unable to find thread context to revoke");
|
||||
}
|
||||
|
||||
void
|
||||
Process::init()
|
||||
{
|
||||
// Patch the ld_bias for dynamic executables.
|
||||
updateBias();
|
||||
|
||||
if (objFile->getInterpreter())
|
||||
interpImage = objFile->getInterpreter()->buildImage();
|
||||
}
|
||||
|
||||
void
|
||||
Process::initState()
|
||||
{
|
||||
@@ -283,6 +295,10 @@ Process::initState()
|
||||
tc->activate();
|
||||
|
||||
pTable->initState();
|
||||
|
||||
// load object file into target memory
|
||||
image.write(initVirtMem);
|
||||
interpImage.write(initVirtMem);
|
||||
}
|
||||
|
||||
DrainState
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "arch/registers.hh"
|
||||
#include "base/loader/memory_image.hh"
|
||||
#include "base/statistics.hh"
|
||||
#include "base/types.hh"
|
||||
#include "config/the_isa.hh"
|
||||
@@ -69,6 +70,7 @@ class Process : public SimObject
|
||||
void serialize(CheckpointOut &cp) const override;
|
||||
void unserialize(CheckpointIn &cp) override;
|
||||
|
||||
void init() override;
|
||||
void initState() override;
|
||||
DrainState drain() override;
|
||||
|
||||
@@ -182,6 +184,8 @@ class Process : public SimObject
|
||||
SETranslatingPortProxy initVirtMem; // memory proxy for initial image load
|
||||
|
||||
ObjectFile *objFile;
|
||||
MemoryImage image;
|
||||
MemoryImage interpImage;
|
||||
std::vector<std::string> argv;
|
||||
std::vector<std::string> envp;
|
||||
std::string executable;
|
||||
|
||||
@@ -1886,17 +1886,14 @@ mmapImpl(SyscallDesc *desc, int num, ThreadContext *tc, bool is_mmap2)
|
||||
// executing inside the loader by checking the program counter value.
|
||||
// XXX: with multiprogrammed workloads or multi-node configurations,
|
||||
// this will not work since there is a single global symbol table.
|
||||
ObjectFile *interpreter = p->getInterpreter();
|
||||
if (interpreter) {
|
||||
if (interpreter->contains(tc->pcState().instAddr())) {
|
||||
std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
|
||||
auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
|
||||
ObjectFile *lib = createObjectFile(ffdp->getFileName());
|
||||
if (p->interpImage.contains(tc->pcState().instAddr())) {
|
||||
std::shared_ptr<FDEntry> fdep = (*p->fds)[tgt_fd];
|
||||
auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
|
||||
ObjectFile *lib = createObjectFile(ffdp->getFileName());
|
||||
|
||||
if (lib) {
|
||||
lib->loadAllSymbols(debugSymbolTable,
|
||||
lib->minSegmentAddr(), start);
|
||||
}
|
||||
if (lib) {
|
||||
lib->loadAllSymbols(debugSymbolTable,
|
||||
lib->buildImage().minAddr(), start);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -152,16 +152,16 @@ System::System(Params *p)
|
||||
} else {
|
||||
// Get the kernel code
|
||||
kernel = createObjectFile(params()->kernel);
|
||||
kernel->setLoadOffset(loadAddrOffset);
|
||||
kernel->setLoadMask(loadAddrMask);
|
||||
inform("kernel located at: %s", params()->kernel);
|
||||
|
||||
if (kernel == NULL)
|
||||
fatal("Could not load kernel file %s", params()->kernel);
|
||||
|
||||
kernelImage = kernel->buildImage();
|
||||
|
||||
// setup entry points
|
||||
kernelStart = kernel->minSegmentAddr();
|
||||
kernelEnd = kernel->maxSegmentAddr();
|
||||
kernelStart = kernelImage.minAddr();
|
||||
kernelEnd = kernelImage.maxAddr();
|
||||
kernelEntry = kernel->entryPoint();
|
||||
|
||||
// If load_addr_mask is set to 0x0, then auto-calculate
|
||||
@@ -170,9 +170,12 @@ System::System(Params *p)
|
||||
if (loadAddrMask == 0) {
|
||||
Addr shift_amt = findMsbSet(kernelEnd - kernelStart) + 1;
|
||||
loadAddrMask = ((Addr)1 << shift_amt) - 1;
|
||||
kernel->setLoadMask(loadAddrMask);
|
||||
}
|
||||
|
||||
kernelImage.move([this](Addr a) {
|
||||
return (a & loadAddrMask) + loadAddrOffset;
|
||||
});
|
||||
|
||||
// load symbols
|
||||
if (!kernel->loadGlobalSymbols(kernelSymtab))
|
||||
fatal("could not load kernel symbols\n");
|
||||
@@ -195,8 +198,6 @@ System::System(Params *p)
|
||||
ObjectFile *obj = createObjectFile(obj_name);
|
||||
fatal_if(!obj, "Failed to additional kernel object '%s'.\n",
|
||||
obj_name);
|
||||
obj->setLoadOffset(loadAddrOffset);
|
||||
obj->setLoadMask(loadAddrMask);
|
||||
kernelExtras.push_back(obj);
|
||||
}
|
||||
}
|
||||
@@ -316,25 +317,24 @@ System::initState()
|
||||
/**
|
||||
* Load the kernel code into memory
|
||||
*/
|
||||
auto mapper = [this](Addr a) {
|
||||
return (a & loadAddrMask) + loadAddrOffset;
|
||||
};
|
||||
if (params()->kernel != "") {
|
||||
if (params()->kernel_addr_check) {
|
||||
// Validate kernel mapping before loading binary
|
||||
if (!(isMemAddr((kernelStart & loadAddrMask) +
|
||||
loadAddrOffset) &&
|
||||
isMemAddr((kernelEnd & loadAddrMask) +
|
||||
loadAddrOffset))) {
|
||||
if (!isMemAddr(mapper(kernelStart)) ||
|
||||
!isMemAddr(mapper(kernelEnd))) {
|
||||
fatal("Kernel is mapped to invalid location (not memory). "
|
||||
"kernelStart 0x(%x) - kernelEnd 0x(%x) %#x:%#x\n",
|
||||
kernelStart,
|
||||
kernelEnd, (kernelStart & loadAddrMask) +
|
||||
loadAddrOffset,
|
||||
(kernelEnd & loadAddrMask) + loadAddrOffset);
|
||||
kernelStart, kernelEnd,
|
||||
mapper(kernelStart), mapper(kernelEnd));
|
||||
}
|
||||
}
|
||||
// Load program sections into memory
|
||||
kernel->loadSegments(physProxy);
|
||||
kernelImage.write(physProxy);
|
||||
for (const auto &extra_kernel : kernelExtras)
|
||||
extra_kernel->loadSegments(physProxy);
|
||||
extra_kernel->buildImage().move(mapper).write(physProxy);
|
||||
|
||||
DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
|
||||
DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "arch/isa_traits.hh"
|
||||
#include "base/loader/memory_image.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "base/statistics.hh"
|
||||
#include "config/the_isa.hh"
|
||||
@@ -224,6 +225,7 @@ class System : public SimObject
|
||||
|
||||
/** Object pointer for the kernel code */
|
||||
ObjectFile *kernel;
|
||||
MemoryImage kernelImage;
|
||||
|
||||
/** Additional object files */
|
||||
std::vector<ObjectFile *> kernelExtras;
|
||||
|
||||
Reference in New Issue
Block a user