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
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev