changeset 1e55f16160cb in /z/repo/gem5 details: http://repo.gem5.org/gem5?cmd=changeset;node=1e55f16160cb description: base: support dynamic loading of Linux ELF objects in SE mode
diffstat: src/arch/alpha/process.cc | 9 +++- src/arch/arm/process.cc | 13 +++-- src/arch/mips/process.cc | 9 +++- src/arch/power/process.cc | 14 +++-- src/arch/sparc/process.cc | 13 +++-- src/arch/x86/process.cc | 24 ++++++---- src/base/loader/elf_object.cc | 85 +++++++++++++++++++++++++++++++++++++++-- src/base/loader/elf_object.hh | 39 +++++++++++++++--- src/base/loader/object_file.hh | 10 ++++- src/sim/process.cc | 47 ++++++++++++++++++++-- src/sim/process.hh | 8 +++ 11 files changed, 224 insertions(+), 47 deletions(-) diffs (truncated from 555 to 300 lines): diff -r bd4125134e77 -r 1e55f16160cb src/arch/alpha/process.cc --- a/src/arch/alpha/process.cc Thu Mar 17 10:30:58 2016 -0700 +++ b/src/arch/alpha/process.cc Thu Mar 17 10:31:03 2016 -0700 @@ -67,6 +67,9 @@ 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 @@ 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 @@ setSyscallArg(tc, 1, argv_array_base); tc->setIntReg(StackPointerReg, stack_min); - tc->pcState(objFile->entryPoint()); + tc->pcState(getStartPC()); } void diff -r bd4125134e77 -r 1e55f16160cb src/arch/arm/process.cc --- a/src/arch/arm/process.cc Thu Mar 17 10:30:58 2016 -0700 +++ b/src/arch/arm/process.cc Thu Mar 17 10:31:03 2016 -0700 @@ -156,6 +156,9 @@ //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 @@ 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 @@ 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. diff -r bd4125134e77 -r 1e55f16160cb src/arch/mips/process.cc --- a/src/arch/mips/process.cc Thu Mar 17 10:30:58 2016 -0700 +++ b/src/arch/mips/process.cc Thu Mar 17 10:31:03 2016 -0700 @@ -78,6 +78,9 @@ { 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 @@ 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 @@ setSyscallArg(tc, 1, argv_array_base); tc->setIntReg(StackPointerReg, stack_min); - tc->pcState(objFile->entryPoint()); + tc->pcState(getStartPC()); } diff -r bd4125134e77 -r 1e55f16160cb src/arch/power/process.cc --- a/src/arch/power/process.cc Thu Mar 17 10:30:58 2016 -0700 +++ b/src/arch/power/process.cc Thu Mar 17 10:31:03 2016 -0700 @@ -85,6 +85,9 @@ //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 @@ 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 @@ //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); diff -r bd4125134e77 -r 1e55f16160cb src/arch/sparc/process.cc --- a/src/arch/sparc/process.cc Thu Mar 17 10:30:58 2016 -0700 +++ b/src/arch/sparc/process.cc Thu Mar 17 10:31:03 2016 -0700 @@ -203,6 +203,9 @@ // 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 @@ 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 @@ // 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); diff -r bd4125134e77 -r 1e55f16160cb src/arch/x86/process.cc --- a/src/arch/x86/process.cc Thu Mar 17 10:30:58 2016 -0700 +++ b/src/arch/x86/process.cc Thu Mar 17 10:31:03 2016 -0700 @@ -756,6 +756,9 @@ //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 @@ 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 @@ //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 @@ // 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); diff -r bd4125134e77 -r 1e55f16160cb src/base/loader/elf_object.cc --- a/src/base/loader/elf_object.cc Thu Mar 17 10:30:58 2016 -0700 +++ b/src/base/loader/elf_object.cc Thu Mar 17 10:31:03 2016 -0700 @@ -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/bitfield.hh" #include "base/loader/symtab.hh" -#include "base/bitfield.hh" #include "base/misc.hh" #include "base/trace.hh" #include "debug/Loader.hh" +#include "gelf.h" #include "sim/byteswap.hh" -#include "gelf.h" 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 @@ 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); + _______________________________________________ gem5-dev mailing list gem5-dev@gem5.org http://m5sim.org/mailman/listinfo/gem5-dev