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

Reply via email to