base: support dynamic loading of Linux ELF objects in SE mode
This commit is contained in:
parent
4fc69db8f8
commit
9b4249410e
11 changed files with 224 additions and 47 deletions
|
@ -67,6 +67,9 @@ AlphaLiveProcess::AlphaLiveProcess(LiveProcessParams *params,
|
|||
void
|
||||
AlphaLiveProcess::argsInit(int intSize, int pageSize)
|
||||
{
|
||||
// Patch the ld_bias for dynamic executables.
|
||||
updateBias();
|
||||
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
typedef AuxVector<uint64_t> auxv_t;
|
||||
|
@ -88,6 +91,10 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize)
|
|||
auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
|
||||
DPRINTF(Loader, "auxv at PHDR %08p\n", elfObject->programHeaderTable());
|
||||
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
|
||||
// This is the base address of the ELF interpreter; it should be
|
||||
// zero for static executables or contain the base address for
|
||||
// dynamic executables.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, getBias()));
|
||||
auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
|
||||
auxv.push_back(auxv_t(M5_AT_UID, uid()));
|
||||
auxv.push_back(auxv_t(M5_AT_EUID, euid()));
|
||||
|
@ -163,7 +170,7 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize)
|
|||
setSyscallArg(tc, 1, argv_array_base);
|
||||
tc->setIntReg(StackPointerReg, stack_min);
|
||||
|
||||
tc->pcState(objFile->entryPoint());
|
||||
tc->pcState(getStartPC());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -156,6 +156,9 @@ ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex)
|
|||
//We want 16 byte alignment
|
||||
uint64_t align = 16;
|
||||
|
||||
// Patch the ld_bias for dynamic executables.
|
||||
updateBias();
|
||||
|
||||
// load object file into target memory
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
|
@ -225,10 +228,10 @@ ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex)
|
|||
auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
|
||||
// This is the number of program headers from the original elf file.
|
||||
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
|
||||
//This is the address of the elf "interpreter", It should be set
|
||||
//to 0 for regular executables. It should be something else
|
||||
//(not sure what) for dynamic libraries.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, 0));
|
||||
// This is the base address of the ELF interpreter; it should be
|
||||
// zero for static executables or contain the base address for
|
||||
// dynamic executables.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, getBias()));
|
||||
//XXX Figure out what this should be.
|
||||
auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
|
||||
//The entry point to the program
|
||||
|
@ -392,7 +395,7 @@ ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex)
|
|||
pc.nextThumb(pc.thumb());
|
||||
pc.aarch64(arch == ObjectFile::Arm64);
|
||||
pc.nextAArch64(pc.aarch64());
|
||||
pc.set(objFile->entryPoint() & ~mask(1));
|
||||
pc.set(getStartPC() & ~mask(1));
|
||||
tc->pcState(pc);
|
||||
|
||||
//Align the "stack_min" to a page boundary.
|
||||
|
|
|
@ -78,6 +78,9 @@ MipsLiveProcess::argsInit(int pageSize)
|
|||
{
|
||||
int intSize = sizeof(IntType);
|
||||
|
||||
// Patch the ld_bias for dynamic executables.
|
||||
updateBias();
|
||||
|
||||
// load object file into target memory
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
|
@ -100,6 +103,10 @@ MipsLiveProcess::argsInit(int pageSize)
|
|||
auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
|
||||
// This is the number of program headers from the original elf file.
|
||||
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
|
||||
// This is the base address of the ELF interpreter; it should be
|
||||
// zero for static executables or contain the base address for
|
||||
// dynamic executables.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, getBias()));
|
||||
//The entry point to the program
|
||||
auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
|
||||
//Different user and group IDs
|
||||
|
@ -177,7 +184,7 @@ MipsLiveProcess::argsInit(int pageSize)
|
|||
setSyscallArg(tc, 1, argv_array_base);
|
||||
tc->setIntReg(StackPointerReg, stack_min);
|
||||
|
||||
tc->pcState(objFile->entryPoint());
|
||||
tc->pcState(getStartPC());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -85,6 +85,9 @@ PowerLiveProcess::argsInit(int intSize, int pageSize)
|
|||
//We want 16 byte alignment
|
||||
uint64_t align = 16;
|
||||
|
||||
// Patch the ld_bias for dynamic executables.
|
||||
updateBias();
|
||||
|
||||
// load object file into target memory
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
|
@ -108,11 +111,10 @@ PowerLiveProcess::argsInit(int intSize, int pageSize)
|
|||
auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
|
||||
// This is the number of program headers from the original elf file.
|
||||
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
|
||||
//This is the address of the elf "interpreter", It should be set
|
||||
//to 0 for regular executables. It should be something else
|
||||
//(not sure what) for dynamic libraries.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, 0));
|
||||
|
||||
// This is the base address of the ELF interpreter; it should be
|
||||
// zero for static executables or contain the base address for
|
||||
// dynamic executables.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, getBias()));
|
||||
//XXX Figure out what this should be.
|
||||
auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
|
||||
//The entry point to the program
|
||||
|
@ -255,7 +257,7 @@ PowerLiveProcess::argsInit(int intSize, int pageSize)
|
|||
//Set the stack pointer register
|
||||
tc->setIntReg(StackPointerReg, stack_min);
|
||||
|
||||
tc->pcState(objFile->entryPoint());
|
||||
tc->pcState(getStartPC());
|
||||
|
||||
//Align the "stack_min" to a page boundary.
|
||||
stack_min = roundDown(stack_min, pageSize);
|
||||
|
|
|
@ -203,6 +203,9 @@ SparcLiveProcess::argsInit(int pageSize)
|
|||
// maintain double word alignment of the stack pointer.
|
||||
uint64_t align = 16;
|
||||
|
||||
// Patch the ld_bias for dynamic executables.
|
||||
updateBias();
|
||||
|
||||
// load object file into target memory
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
|
@ -245,10 +248,10 @@ SparcLiveProcess::argsInit(int pageSize)
|
|||
auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
|
||||
// This is the number of program headers from the original elf file.
|
||||
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
|
||||
// This is the address of the elf "interpreter", It should be set
|
||||
// to 0 for regular executables. It should be something else
|
||||
// (not sure what) for dynamic libraries.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, 0));
|
||||
// This is the base address of the ELF interpreter; it should be
|
||||
// zero for static executables or contain the base address for
|
||||
// dynamic executables.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, getBias()));
|
||||
// This is hardwired to 0 in the elf loading code in the kernel
|
||||
auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
|
||||
// The entry point to the program
|
||||
|
@ -402,7 +405,7 @@ SparcLiveProcess::argsInit(int pageSize)
|
|||
// don't have anything like that, it should be set to 0.
|
||||
tc->setIntReg(1, 0);
|
||||
|
||||
tc->pcState(objFile->entryPoint());
|
||||
tc->pcState(getStartPC());
|
||||
|
||||
// Align the "stack_min" to a page boundary.
|
||||
stack_min = roundDown(stack_min, pageSize);
|
||||
|
|
|
@ -756,6 +756,9 @@ X86LiveProcess::argsInit(int pageSize,
|
|||
//We want 16 byte alignment
|
||||
uint64_t align = 16;
|
||||
|
||||
// Patch the ld_bias for dynamic executables.
|
||||
updateBias();
|
||||
|
||||
// load object file into target memory
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
|
@ -798,8 +801,10 @@ X86LiveProcess::argsInit(int pageSize,
|
|||
X86_IA64Processor = 1 << 30
|
||||
};
|
||||
|
||||
// Setup the auxilliary vectors. These will already have endian conversion.
|
||||
// Auxilliary vectors are loaded only for elf formatted executables.
|
||||
// Setup the auxiliary vectors. These will already have endian
|
||||
// conversion. Auxiliary vectors are loaded only for elf formatted
|
||||
// executables; the auxv is responsible for passing information from
|
||||
// the OS to the interpreter.
|
||||
ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
|
||||
if (elfObject) {
|
||||
uint64_t features =
|
||||
|
@ -842,18 +847,17 @@ X86LiveProcess::argsInit(int pageSize,
|
|||
//Frequency at which times() increments
|
||||
//Defined to be 100 in the kernel source.
|
||||
auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
|
||||
// For statically linked executables, this is the virtual address of the
|
||||
// program header tables if they appear in the executable image
|
||||
// This is the virtual address of the program header tables if they
|
||||
// appear in the executable image.
|
||||
auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
|
||||
// This is the size of a program header entry from the elf file.
|
||||
auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
|
||||
// This is the number of program headers from the original elf file.
|
||||
auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
|
||||
//This is the address of the elf "interpreter", It should be set
|
||||
//to 0 for regular executables. It should be something else
|
||||
//(not sure what) for dynamic libraries.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, 0));
|
||||
|
||||
// This is the base address of the ELF interpreter; it should be
|
||||
// zero for static executables or contain the base address for
|
||||
// dynamic executables.
|
||||
auxv.push_back(auxv_t(M5_AT_BASE, getBias()));
|
||||
//XXX Figure out what this should be.
|
||||
auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
|
||||
//The entry point to the program
|
||||
|
@ -1014,7 +1018,7 @@ X86LiveProcess::argsInit(int pageSize,
|
|||
|
||||
// There doesn't need to be any segment base added in since we're dealing
|
||||
// with the flat segmentation model.
|
||||
tc->pcState(objFile->entryPoint());
|
||||
tc->pcState(getStartPC());
|
||||
|
||||
//Align the "stack_min" to a page boundary.
|
||||
stack_min = roundDown(stack_min, pageSize);
|
||||
|
|
|
@ -41,22 +41,30 @@
|
|||
* Ali Saidi
|
||||
*/
|
||||
|
||||
#include "base/loader/elf_object.hh"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "base/loader/elf_object.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/Loader.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
#include "gelf.h"
|
||||
#include "sim/byteswap.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ObjectFile *
|
||||
ElfObject::tryFile(const string &fname, size_t len, uint8_t *data)
|
||||
ElfObject::tryFile(const string &fname, size_t len, uint8_t *data,
|
||||
bool skip_interp_check)
|
||||
{
|
||||
Elf *elf;
|
||||
GElf_Ehdr ehdr;
|
||||
|
@ -243,6 +251,41 @@ ElfObject::tryFile(const string &fname, size_t len, uint8_t *data)
|
|||
result->_programHeaderTable = 0;
|
||||
|
||||
|
||||
if (!skip_interp_check) {
|
||||
for (int i = 0; i < ehdr.e_phnum; i++) {
|
||||
GElf_Phdr phdr;
|
||||
M5_VAR_USED void *check_p = gelf_getphdr(elf, i, &phdr);
|
||||
assert(check_p != nullptr);
|
||||
|
||||
if (phdr.p_type != PT_INTERP)
|
||||
continue;
|
||||
|
||||
char *interp_path = (char*)data + phdr.p_offset;
|
||||
int fd = open(interp_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fatal("Unable to open dynamic executable's "
|
||||
"interpreter.\n");
|
||||
}
|
||||
|
||||
struct stat sb;
|
||||
M5_VAR_USED int check_i = fstat(fd, &sb);
|
||||
assert(check_i == 0);
|
||||
|
||||
void *mm = mmap(nullptr, sb.st_size, PROT_READ,
|
||||
MAP_PRIVATE, fd, 0);
|
||||
assert(mm != MAP_FAILED);
|
||||
::close(fd);
|
||||
|
||||
uint8_t *interp_image = (uint8_t*)mm;
|
||||
ObjectFile *obj = tryFile(interp_path, sb.st_size,
|
||||
interp_image, true);
|
||||
assert(obj != nullptr);
|
||||
result->interpreter = dynamic_cast<ElfObject*>(obj);
|
||||
assert(result->interpreter != nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
elf_end(elf);
|
||||
return result;
|
||||
}
|
||||
|
@ -252,8 +295,10 @@ ElfObject::tryFile(const string &fname, size_t len, uint8_t *data)
|
|||
ElfObject::ElfObject(const string &_filename, size_t _len, uint8_t *_data,
|
||||
Arch _arch, OpSys _opSys)
|
||||
: ObjectFile(_filename, _len, _data, _arch, _opSys),
|
||||
_programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0)
|
||||
|
||||
_programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0),
|
||||
interpreter(nullptr), ldBias(0), relocate(true),
|
||||
ldMin(std::numeric_limits<Addr>::max()),
|
||||
ldMax(std::numeric_limits<Addr>::min())
|
||||
{
|
||||
Elf *elf;
|
||||
GElf_Ehdr ehdr;
|
||||
|
@ -326,6 +371,9 @@ ElfObject::ElfObject(const string &_filename, size_t _len, uint8_t *_data,
|
|||
if (!(phdr.p_type & PT_LOAD))
|
||||
continue;
|
||||
|
||||
ldMin = std::min(ldMin, phdr.p_vaddr);
|
||||
ldMax = std::max(ldMax, phdr.p_vaddr + phdr.p_memsz);
|
||||
|
||||
// Check to see if this segment contains the bss section.
|
||||
if (phdr.p_paddr <= bssSecStart &&
|
||||
phdr.p_paddr + phdr.p_memsz > bssSecStart &&
|
||||
|
@ -338,6 +386,11 @@ ElfObject::ElfObject(const string &_filename, size_t _len, uint8_t *_data,
|
|||
// Check to see if this is the text or data segment
|
||||
if (phdr.p_vaddr <= textSecStart &&
|
||||
phdr.p_vaddr + phdr.p_filesz > textSecStart) {
|
||||
|
||||
// If this value is nonzero, we need to flip the relocate flag.
|
||||
if (phdr.p_vaddr != 0)
|
||||
relocate = false;
|
||||
|
||||
text.baseAddr = phdr.p_paddr;
|
||||
text.size = phdr.p_filesz;
|
||||
text.fileImage = fileData + phdr.p_offset;
|
||||
|
@ -462,6 +515,10 @@ ElfObject::loadSections(PortProxy& memProxy, Addr addrMask, Addr offset)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (interpreter)
|
||||
interpreter->loadSections(memProxy, addrMask, offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -510,3 +567,19 @@ ElfObject::sectionExists(string sec)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
ElfObject::updateBias(Addr bias_addr)
|
||||
{
|
||||
// Record the bias.
|
||||
ldBias = bias_addr;
|
||||
|
||||
// Patch the entry point with bias_addr.
|
||||
entry += bias_addr;
|
||||
|
||||
// Patch segments with the bias_addr.
|
||||
text.baseAddr += bias_addr;
|
||||
data.baseAddr += bias_addr;
|
||||
bss.baseAddr += bias_addr;
|
||||
for (auto &segment : extraSegments)
|
||||
segment.baseAddr += bias_addr;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,24 @@ class ElfObject : public ObjectFile
|
|||
uint16_t _programHeaderCount;
|
||||
std::set<std::string> sectionNames;
|
||||
|
||||
ElfObject *interpreter;
|
||||
|
||||
// An interpreter load bias is the location in the process address space
|
||||
// where the interpreter is chosen to reside. Typically, this is carved
|
||||
// out of the top of the mmap reserve section.
|
||||
Addr ldBias;
|
||||
|
||||
// The interpreter is typically a relocatable shared library and will
|
||||
// have a default value of zero which means that it does not care where
|
||||
// it is placed. However, the loader can be compiled and linked so that
|
||||
// it does care and needs a specific entry point.
|
||||
bool relocate;
|
||||
|
||||
// The ldMin and ldMax fields are required to know how large of an
|
||||
// area is required to map the interpreter.
|
||||
Addr ldMin;
|
||||
Addr ldMax;
|
||||
|
||||
/// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
|
||||
bool loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask);
|
||||
|
||||
|
@ -78,19 +96,26 @@ class ElfObject : public ObjectFile
|
|||
|
||||
bool loadSections(PortProxy& memProxy,
|
||||
Addr addrMask = std::numeric_limits<Addr>::max(),
|
||||
Addr offset = 0);
|
||||
Addr offset = 0) override;
|
||||
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
|
||||
std::numeric_limits<Addr>::max());
|
||||
std::numeric_limits<Addr>::max()) override;
|
||||
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
|
||||
std::numeric_limits<Addr>::max());
|
||||
std::numeric_limits<Addr>::max()) override;
|
||||
virtual bool loadWeakSymbols(SymbolTable *symtab, Addr addrMask =
|
||||
std::numeric_limits<Addr>::max());
|
||||
std::numeric_limits<Addr>::max()) override;
|
||||
|
||||
virtual bool isDynamic() { return sectionExists(".interp"); }
|
||||
virtual bool hasTLS() { return sectionExists(".tbss"); }
|
||||
virtual ObjectFile *getInterpreter() const override
|
||||
{ return interpreter; }
|
||||
virtual Addr bias() const override { return ldBias; }
|
||||
virtual bool relocatable() const override { return relocate; }
|
||||
virtual Addr mapSize() const override { return ldMax - ldMin; }
|
||||
virtual void updateBias(Addr bias_addr) override;
|
||||
|
||||
virtual bool hasTLS() override { return sectionExists(".tbss"); }
|
||||
|
||||
static ObjectFile *tryFile(const std::string &fname,
|
||||
size_t len, uint8_t *data);
|
||||
size_t len, uint8_t *data,
|
||||
bool skip_interp_check = false);
|
||||
Addr programHeaderTable() {return _programHeaderTable;}
|
||||
uint16_t programHeaderSize() {return _programHeaderSize;}
|
||||
uint16_t programHeaderCount() {return _programHeaderCount;}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "base/types.hh"
|
||||
|
||||
class PortProxy;
|
||||
|
@ -94,7 +95,14 @@ class ObjectFile
|
|||
std::numeric_limits<Addr>::max())
|
||||
{ return false; }
|
||||
|
||||
virtual bool isDynamic() { return false; }
|
||||
virtual ObjectFile *getInterpreter() const { return nullptr; }
|
||||
virtual bool relocatable() const { return false; }
|
||||
virtual Addr mapSize() const
|
||||
{ panic("mapSize() should only be called on relocatable objects\n"); }
|
||||
virtual void updateBias(Addr bias_addr)
|
||||
{ panic("updateBias() should only be called on relocatable objects\n"); }
|
||||
virtual Addr bias() const { return 0; }
|
||||
|
||||
virtual bool hasTLS() { return false; }
|
||||
|
||||
Arch getArch() const { return arch; }
|
||||
|
|
|
@ -518,6 +518,48 @@ LiveProcess::findDriver(std::string filename)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
LiveProcess::updateBias()
|
||||
{
|
||||
ObjectFile *interp = objFile->getInterpreter();
|
||||
|
||||
if (!interp || !interp->relocatable())
|
||||
return;
|
||||
|
||||
// Determine how large the interpreters footprint will be in the process
|
||||
// address space.
|
||||
Addr interp_mapsize = roundUp(interp->mapSize(), TheISA::PageBytes);
|
||||
|
||||
// We are allocating the memory area; set the bias to the lowest address
|
||||
// in the allocated memory region.
|
||||
Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end;
|
||||
|
||||
// Adjust the process mmap area to give the interpreter room; the real
|
||||
// execve system call would just invoke the kernel's internal mmap
|
||||
// functions to make these adjustments.
|
||||
mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize;
|
||||
|
||||
interp->updateBias(ld_bias);
|
||||
}
|
||||
|
||||
|
||||
Addr
|
||||
LiveProcess::getBias()
|
||||
{
|
||||
ObjectFile *interp = objFile->getInterpreter();
|
||||
|
||||
return interp ? interp->bias() : objFile->bias();
|
||||
}
|
||||
|
||||
|
||||
Addr
|
||||
LiveProcess::getStartPC()
|
||||
{
|
||||
ObjectFile *interp = objFile->getInterpreter();
|
||||
|
||||
return interp ? interp->entryPoint() : objFile->entryPoint();
|
||||
}
|
||||
|
||||
|
||||
LiveProcess *
|
||||
LiveProcess::create(LiveProcessParams * params)
|
||||
|
@ -535,11 +577,6 @@ LiveProcess::create(LiveProcessParams * params)
|
|||
fatal("Can't load object file %s", params->executable);
|
||||
}
|
||||
|
||||
if (objFile->isDynamic())
|
||||
fatal("Object file is a dynamic executable however only static "
|
||||
"executables are supported!\n Please recompile your "
|
||||
"executable as a static binary and try again.\n");
|
||||
|
||||
#if THE_ISA == ALPHA_ISA
|
||||
if (objFile->getArch() != ObjectFile::Alpha)
|
||||
fatal("Object file architecture does not match compiled ISA (Alpha).");
|
||||
|
|
|
@ -336,6 +336,14 @@ class LiveProcess : public Process
|
|||
*/
|
||||
EmulatedDriver *findDriver(std::string filename);
|
||||
|
||||
// This function acts as a callback to update the bias value in
|
||||
// the object file because the parameters needed to calculate the
|
||||
// bias are not available when the object file is created.
|
||||
void updateBias();
|
||||
|
||||
Addr getBias();
|
||||
Addr getStartPC();
|
||||
|
||||
// this function is used to create the LiveProcess object, since
|
||||
// we can't tell which subclass of LiveProcess to use until we
|
||||
// open and look at the object file.
|
||||
|
|
Loading…
Reference in a new issue