arch,base: Separate the idea of a memory image and object file.
authorGabe Black <gabeblack@google.com>
Wed, 2 Oct 2019 04:15:06 +0000 (21:15 -0700)
committerGabe Black <gabeblack@google.com>
Sat, 12 Oct 2019 04:10:59 +0000 (04:10 +0000)
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>

34 files changed:
src/arch/alpha/process.cc
src/arch/alpha/system.cc
src/arch/arm/freebsd/system.cc
src/arch/arm/linux/system.cc
src/arch/arm/process.cc
src/arch/arm/system.cc
src/arch/mips/process.cc
src/arch/power/process.cc
src/arch/riscv/bare_metal/system.cc
src/arch/riscv/process.cc
src/arch/sparc/process.cc
src/arch/sparc/process.hh
src/arch/sparc/system.cc
src/arch/x86/process.cc
src/base/SConscript
src/base/loader/aout_object.cc
src/base/loader/aout_object.hh
src/base/loader/dtb_object.cc
src/base/loader/dtb_object.hh
src/base/loader/ecoff_object.cc
src/base/loader/ecoff_object.hh
src/base/loader/elf_object.cc
src/base/loader/elf_object.hh
src/base/loader/memory_image.cc [new file with mode: 0644]
src/base/loader/memory_image.hh [new file with mode: 0644]
src/base/loader/object_file.cc
src/base/loader/object_file.hh
src/base/loader/raw_object.cc
src/base/loader/raw_object.hh
src/sim/process.cc
src/sim/process.hh
src/sim/syscall_emul.hh
src/sim/system.cc
src/sim/system.hh

index e266b92b2b70603325c256932ac6154ad44dff62..9311a6415806a87168ee3bf1cfbaf96a54a76428 100644 (file)
@@ -54,10 +54,10 @@ AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile)
       objFile)
 {
     fatal_if(params->useArchPT, "Arch page tables not implemented.");
-    Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes);
+    Addr brk_point = roundUp(image.maxAddr(), PageBytes);
 
     // Set up stack.  On Alpha, stack goes below the image.
-    Addr stack_base = objFile->minSegmentAddr() - (409600 + 4096);
+    Addr stack_base = image.minAddr() - (409600 + 4096);
 
     // Set up region for mmaps.
     Addr mmap_end = 0x10000;
@@ -74,13 +74,6 @@ AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile)
 void
 AlphaProcess::argsInit(int intSize, int pageSize)
 {
-    // Patch the ld_bias for dynamic executables.
-    updateBias();
-
-    objFile->loadSegments(initVirtMem);
-    if (objFile->getInterpreter())
-        objFile->getInterpreter()->loadSegments(initVirtMem);
-
     std::vector<AuxVector<uint64_t>>  auxv;
 
     ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
index 31e7aa062a4c42298cede3b08c58b5bb5acdf5bc..a7a47036a63d120a744a8f0496406a872b5b54b8 100644 (file)
@@ -57,13 +57,11 @@ AlphaSystem::AlphaSystem(Params *p)
      */
     // Load Console Code
     console = createObjectFile(params()->console);
-    console->setLoadMask(loadAddrMask);
     if (console == NULL)
         fatal("Could not load console file %s", params()->console);
 
     // Load pal file
     pal = createObjectFile(params()->pal);
-    pal->setLoadMask(loadAddrMask);
     if (pal == NULL)
         fatal("Could not load PALcode file %s", params()->pal);
 
@@ -111,8 +109,8 @@ AlphaSystem::initState()
     System::initState();
 
     // Load program sections into memory
-    pal->loadSegments(physProxy);
-    console->loadSegments(physProxy);
+    pal->buildImage().mask(loadAddrMask).write(physProxy);
+    console->buildImage().mask(loadAddrMask).write(physProxy);
 
     /**
      * Copy the osflags (kernel arguments) into the consoles
index 764f036b42076e083f5c4cd588bab65fd4f945c7..106c8e432ff55038033c775a2563ce3e4a9799f5 100644 (file)
@@ -132,8 +132,8 @@ FreebsdArmSystem::initState()
     if (ra)
         bootReleaseAddr = ra & ~ULL(0x7F);
 
-    dtb_file->setLoadOffset(params()->atags_addr + loadAddrOffset);
-    dtb_file->loadSegments(physProxy);
+    dtb_file->buildImage().
+        offset(params()->atags_addr + loadAddrOffset).write(physProxy);
     delete dtb_file;
 
     // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
index a0869b46a892479401608a3d5af11e0cfa827cee..740d2e0e6b1876716e91df942d131001469e8a7d 100644 (file)
@@ -151,8 +151,8 @@ LinuxArmSystem::initState()
                  "to DTB file: %s\n", params()->dtb_filename);
         }
 
-        dtb_file->setLoadOffset(params()->atags_addr + loadAddrOffset);
-        dtb_file->loadSegments(physProxy);
+        dtb_file->buildImage().
+            offset(params()->atags_addr + loadAddrOffset).write(physProxy);
         delete dtb_file;
     } else {
         // Using ATAGS
index ff3b92f4867e33f494e3efdad90131c3e41a9363..d9b714c4448468e03c561644095bec572657c18c 100644 (file)
@@ -75,7 +75,7 @@ ArmProcess32::ArmProcess32(ProcessParams *params, ObjectFile *objFile,
                            ObjectFile::Arch _arch)
     : ArmProcess(params, objFile, _arch)
 {
-    Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes);
+    Addr brk_point = roundUp(image.maxAddr(), PageBytes);
     Addr stack_base = 0xbf000000L;
     Addr max_stack_size = 8 * 1024 * 1024;
     Addr next_thread_stack_base = stack_base - max_stack_size;
@@ -89,7 +89,7 @@ ArmProcess64::ArmProcess64(ProcessParams *params, ObjectFile *objFile,
                            ObjectFile::Arch _arch)
     : ArmProcess(params, objFile, _arch)
 {
-    Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes);
+    Addr brk_point = roundUp(image.maxAddr(), PageBytes);
     Addr stack_base = 0x7fffff0000L;
     Addr max_stack_size = 8 * 1024 * 1024;
     Addr next_thread_stack_base = stack_base - max_stack_size;
@@ -266,14 +266,6 @@ ArmProcess::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->loadSegments(initVirtMem);
-    if (objFile->getInterpreter())
-        objFile->getInterpreter()->loadSegments(initVirtMem);
-
     //Setup the auxilliary vectors. These will already have endian conversion.
     //Auxilliary vectors are loaded only for elf formatted executables.
     ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
index efc347d9d4d84dd049a413fa3c239bbb53c32a46..bf2881026fe8a1fbdd9134e10d4a3a6a2a9f15b7 100644 (file)
@@ -143,7 +143,7 @@ ArmSystem::initState()
 
     if (bootldr) {
         bool isGICv3System = dynamic_cast<Gicv3 *>(getGIC()) != nullptr;
-        bootldr->loadSegments(physProxy);
+        bootldr->buildImage().write(physProxy);
 
         inform("Using bootloader at address %#x\n", bootldr->entryPoint());
 
index 4c4b0e414ce1b38da0ac1c30df8f575c79f7c865..8e1e22b6618ceb6bd92a44f0b1197637d97e1c2f 100644 (file)
@@ -65,7 +65,7 @@ MipsProcess::MipsProcess(ProcessParams *params, ObjectFile *objFile)
     Addr next_thread_stack_base = stack_base - max_stack_size;
 
     // Set up break point (Top of Heap)
-    Addr brk_point = objFile->maxSegmentAddr();
+    Addr brk_point = image.maxAddr();
     brk_point = roundUp(brk_point, PageBytes);
 
     // Set up region for mmaps.  Start it 1GB above the top of the heap.
@@ -89,14 +89,6 @@ MipsProcess::argsInit(int pageSize)
 {
     int intSize = sizeof(IntType);
 
-    // Patch the ld_bias for dynamic executables.
-    updateBias();
-
-    // load object file into target memory
-    objFile->loadSegments(initVirtMem);
-    if (objFile->getInterpreter())
-        objFile->getInterpreter()->loadSegments(initVirtMem);
-
     std::vector<AuxVector<IntType>> auxv;
 
     ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
index 89b94b21f4d82784d4d94ee6b25e5ad4a4cbd632..7b53d70389edbb21c98b4b7ae18345871d555912 100644 (file)
@@ -56,7 +56,7 @@ PowerProcess::PowerProcess(ProcessParams *params, ObjectFile *objFile)
 {
     fatal_if(params->useArchPT, "Arch page tables not implemented.");
     // Set up break point (Top of Heap)
-    Addr brk_point = objFile->maxSegmentAddr();
+    Addr brk_point = image.maxAddr();
     brk_point = roundUp(brk_point, PageBytes);
 
     Addr stack_base = 0xbf000000L;
@@ -95,13 +95,9 @@ PowerProcess::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->loadSegments(initVirtMem);
-    if (objFile->getInterpreter())
-        objFile->getInterpreter()->loadSegments(initVirtMem);
+    image.write(initVirtMem);
+    interpImage.write(initVirtMem);
 
     //Setup the auxilliary vectors. These will already have endian conversion.
     //Auxilliary vectors are loaded only for elf formatted executables.
index 3fb07a489e5c22314e00d05321c8c223bc4d698b..44e14e5ce83e673078237d02ae489dbedc7d14c7 100644 (file)
@@ -55,7 +55,7 @@ BareMetalRiscvSystem::initState()
     RiscvSystem::initState();
 
     // load program sections into memory
-    if (!bootloader->loadSegments(physProxy)) {
+    if (!bootloader->buildImage().write(physProxy)) {
         warn("could not load sections to memory");
     }
 }
index 35dde76004f8765f54611588a8cec2d3c06a5441..617efa0eed200c232be07115d06e3add71579715 100644 (file)
@@ -75,7 +75,7 @@ RiscvProcess64::RiscvProcess64(ProcessParams *params, ObjectFile *objFile) :
     const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
     const Addr max_stack_size = 8 * 1024 * 1024;
     const Addr next_thread_stack_base = stack_base - max_stack_size;
-    const Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes);
+    const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
     const Addr mmap_end = 0x4000000000000000L;
     memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
             next_thread_stack_base, mmap_end);
@@ -87,7 +87,7 @@ RiscvProcess32::RiscvProcess32(ProcessParams *params, ObjectFile *objFile) :
     const Addr stack_base = 0x7FFFFFFF;
     const Addr max_stack_size = 8 * 1024 * 1024;
     const Addr next_thread_stack_base = stack_base - max_stack_size;
-    const Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes);
+    const Addr brk_point = roundUp(image.maxAddr(), PageBytes);
     const Addr mmap_end = 0x40000000L;
     memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
                                      next_thread_stack_base, mmap_end);
@@ -123,10 +123,6 @@ RiscvProcess::argsInit(int pageSize)
     const int RandomBytes = 16;
     const int addrSize = sizeof(IntType);
 
-    updateBias();
-    objFile->loadSegments(initVirtMem);
-    if (objFile->getInterpreter())
-        objFile->getInterpreter()->loadSegments(initVirtMem);
     ElfObject* elfObject = dynamic_cast<ElfObject*>(objFile);
     memState->setStackMin(memState->getStackBase());
 
index 1c020c6b165f7aaa71781889b919a05e390ce938..048c7e957d4d5ac272c18cc1c747574e5cb4123f 100644 (file)
@@ -204,14 +204,6 @@ SparcProcess::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->loadSegments(initVirtMem);
-    if (objFile->getInterpreter())
-        objFile->getInterpreter()->loadSegments(initVirtMem);
-
     enum hardwareCaps
     {
         M5_HWCAP_SPARC_FLUSH = 1,
index f8f19f2905828bd82d0d2c6b8480f6557940922c..0ef34352b1d607da2ba5bfe993c165aabc90662a 100644 (file)
@@ -78,7 +78,7 @@ class Sparc32Process : public SparcProcess
     Sparc32Process(ProcessParams * params, ObjectFile *objFile)
         : SparcProcess(params, objFile, 0)
     {
-        Addr brk_point = objFile->maxSegmentAddr();
+        Addr brk_point = image.maxAddr();
         brk_point = roundUp(brk_point, SparcISA::PageBytes);
 
         // Reserve 8M for main stack.
@@ -122,7 +122,7 @@ class Sparc64Process : public SparcProcess
     Sparc64Process(ProcessParams * params, ObjectFile *objFile)
         : SparcProcess(params, objFile, 2047)
     {
-        Addr brk_point = objFile->maxSegmentAddr();
+        Addr brk_point = image.maxAddr();
         brk_point = roundUp(brk_point, SparcISA::PageBytes);
 
         Addr max_stack_size = 8 * 1024 * 1024;
index e9615b00c59e176791144f92fa5cd1cfd027b213..255cc145371f268398dca2fe53c0de31c68a2c9b 100644 (file)
@@ -136,25 +136,15 @@ SparcSystem::initState()
     // Call the initialisation of the super class
     System::initState();
 
-    // Load reset binary into memory
-    reset->setLoadOffset(params()->reset_addr);
-    reset->loadSegments(physProxy);
-    // Load the openboot binary
-    openboot->setLoadOffset(params()->openboot_addr);
-    openboot->loadSegments(physProxy);
-    // Load the hypervisor binary
-    hypervisor->setLoadOffset(params()->hypervisor_addr);
-    hypervisor->loadSegments(physProxy);
-    // Load the nvram image
-    nvram->setLoadOffset(params()->nvram_addr);
-    nvram->loadSegments(physProxy);
-    // Load the hypervisor description image
-    hypervisor_desc->setLoadOffset(params()->hypervisor_desc_addr);
-    hypervisor_desc->loadSegments(physProxy);
-    // Load the partition description image
-    partition_desc->setLoadOffset(params()->partition_desc_addr);
-    partition_desc->loadSegments(physProxy);
-
+    reset->buildImage().offset(params()->reset_addr).write(physProxy);
+    openboot->buildImage().offset(params()->openboot_addr).write(physProxy);
+    hypervisor->buildImage().
+        offset(params()->hypervisor_addr).write(physProxy);
+    nvram->buildImage().offset(params()->nvram_addr).write(physProxy);
+    hypervisor_desc->buildImage().
+        offset(params()->hypervisor_desc_addr).write(physProxy);
+    partition_desc->buildImage().
+        offset(params()->partition_desc_addr).write(physProxy);
 
     // @todo any fixup code over writing data in binaries on setting break
     // events on functions should happen here.
index 5464741388fe21e316ee7c41ca65d0400a90a951..11b46c8242274182b4cef0badd41d7df48e77baf 100644 (file)
@@ -136,7 +136,7 @@ X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile,
     vsyscallPage.vtimeOffset = 0x400;
     vsyscallPage.vgettimeofdayOffset = 0x0;
 
-    Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes);
+    Addr brk_point = roundUp(image.maxAddr(), PageBytes);
     Addr stack_base = 0x7FFFFFFFF000ULL;
     Addr max_stack_size = 8 * 1024 * 1024;
     Addr next_thread_stack_base = stack_base - max_stack_size;
@@ -175,7 +175,7 @@ I386Process::I386Process(ProcessParams *params, ObjectFile *objFile,
     vsyscallPage.vsyscallOffset = 0x400;
     vsyscallPage.vsysexitOffset = 0x410;
 
-    Addr brk_point = roundUp(objFile->maxSegmentAddr(), PageBytes);
+    Addr brk_point = roundUp(image.maxAddr(), PageBytes);
     Addr stack_base = _gdtStart;
     Addr max_stack_size = 8 * 1024 * 1024;
     Addr next_thread_stack_base = stack_base - max_stack_size;
@@ -770,14 +770,6 @@ X86Process::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->loadSegments(initVirtMem);
-    if (objFile->getInterpreter())
-        objFile->getInterpreter()->loadSegments(initVirtMem);
-
     enum X86CpuFeature {
         X86_OnboardFPU = 1 << 0,
         X86_VirtualModeExtensions = 1 << 1,
index 0c7558d09ae434f5ca8fddb4fb5d4f3b48cd49bd..efa7df7008a06ff982c6b35d691a0e38e969ea39 100644 (file)
@@ -76,6 +76,7 @@ Source('loader/aout_object.cc')
 Source('loader/dtb_object.cc')
 Source('loader/ecoff_object.cc')
 Source('loader/elf_object.cc')
+Source('loader/memory_image.cc')
 Source('loader/object_file.cc')
 Source('loader/raw_object.cc')
 Source('loader/symtab.cc')
index 97651586fedb66c77fbe27cea3a49fb280cd97cb..eb633c1ce752abe57134a036297930102d8e1618 100644 (file)
@@ -58,17 +58,23 @@ AoutObject::AoutObject(const string &_filename,
     : ObjectFile(_filename, _len, _data, _arch, _opSys)
 {
     execHdr = (aout_exechdr *)fileData;
-
     entry = execHdr->entry;
+}
 
-    addSegment("text", N_TXTADDR(*execHdr), fileData + N_TXTOFF(*execHdr),
-            execHdr->tsize);
-    addSegment("data", N_DATADDR(*execHdr), fileData + N_DATOFF(*execHdr),
-            execHdr->dsize);
-    addSegment("bss", N_BSSADDR(*execHdr), nullptr, execHdr->bsize);
+MemoryImage
+AoutObject::buildImage() const
+{
+    MemoryImage image({
+            { "text", N_TXTADDR(*execHdr),
+              fileData + N_TXTOFF(*execHdr), execHdr->tsize },
+            { "data", N_DATADDR(*execHdr),
+              fileData + N_DATOFF(*execHdr), execHdr->dsize },
+            { "bss", N_BSSADDR(*execHdr), nullptr, execHdr->bsize}
+    });
 
-    for (auto &seg: segments)
-        DPRINTFR(Loader, "%s\n", *seg);
+    for (auto &seg: image.segments())
+        DPRINTFR(Loader, "%s\n", seg);
+    return image;
 }
 
 
index 65ed7ca0fe2c2b7cef0d5af5d4534b306274988c..4f8c86fcd802539fba24fad6e97955c27c81e591 100644 (file)
@@ -48,13 +48,14 @@ class AoutObject : public ObjectFile
   public:
     virtual ~AoutObject() {}
 
-    virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0,
-                                Addr offset = 0, Addr addr_mask = maxAddr);
-    virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0,
-                                   Addr offset = 0,
-                                   Addr addr_mask = maxAddr);
-    virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0,
-                                  Addr offset = 0, Addr addr_mask = maxAddr);
+    MemoryImage buildImage() const override;
+
+    bool loadAllSymbols(SymbolTable *symtab, Addr base=0,
+                        Addr offset=0, Addr addr_mask = MaxAddr) override;
+    bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0,
+                           Addr offset=0, Addr addr_mask=MaxAddr) override;
+    bool loadLocalSymbols(SymbolTable *symtab, Addr base=0,
+                          Addr offset=0, Addr addr_mask=MaxAddr) override;
 
     static ObjectFile *tryFile(const std::string &fname,
                                size_t len, uint8_t *data);
index 275139a8c9a958c98aad9c4b4241fc84b0ea75d6..f5b206a743760b1bc0ae111418447ac51480b50d 100644 (file)
@@ -53,10 +53,8 @@ DtbObject::tryFile(const std::string &fname, size_t len, uint8_t *data)
 
 DtbObject::DtbObject(const std::string &_filename, size_t _len, uint8_t *_data,
                      Arch _arch, OpSys _opSys)
-    : ObjectFile(_filename, _len, _data, _arch, _opSys),
-    data(new Segment{ "data", 0, fileData, len })
+    : ObjectFile(_filename, _len, _data, _arch, _opSys)
 {
-    segments.emplace_back(data);
     fileDataMmapped = true;
 }
 
@@ -131,9 +129,6 @@ DtbObject::addBootCmdLine(const char* _args, size_t len)
         return false;
     }
 
-    data->size = newLen;
-    data->data = fdt_buf_w_space;
-
     // clean up old buffer and set to new fdt blob
     munmap(fileData, this->len);
     fileData = fdt_buf_w_space;
@@ -164,6 +159,12 @@ DtbObject::findReleaseAddr()
     return rel_addr;
 }
 
+MemoryImage
+DtbObject::buildImage() const
+{
+    return {{"data", 0, fileData, len}};
+}
+
 bool
 DtbObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
                           Addr addr_mask)
index 7cb842e434bfede9206bc56890dc13fa39ec78b5..1284025ff5c28234819e89f6225e19d8b742ec84 100644 (file)
  */
 class DtbObject : public ObjectFile
 {
-    protected:
-        DtbObject(const std::string &_filename, size_t _len, uint8_t *_data,
-                  Arch _arch, OpSys _opSys);
+  protected:
+    DtbObject(const std::string &_filename, size_t _len, uint8_t *_data,
+              Arch _arch, OpSys _opSys);
 
-        /** Bool marking if this dtb file has replaced the original
-         *  read in DTB file with a new modified buffer
-         */
-        bool fileDataMmapped;
+    /** Bool marking if this dtb file has replaced the original
+     *  read in DTB file with a new modified buffer
+     */
+    bool fileDataMmapped;
 
-        Segment *data;
+  public:
+    virtual ~DtbObject();
 
-    public:
-        virtual ~DtbObject();
+    /** Adds the passed in Command Line options for the kernel
+      * to the proper location in the device tree.
+      * @param _args command line to append
+      * @param len length of the command line string
+      * @return returns true on success, false otherwise
+      */
+    bool addBootCmdLine(const char* _args, size_t len);
 
-        /** Adds the passed in Command Line options for the kernel
-          * to the proper location in the device tree.
-          * @param _args command line to append
-          * @param len length of the command line string
-          * @return returns true on success, false otherwise
-          */
-        bool addBootCmdLine(const char* _args, size_t len);
+    /** Parse the DTB file enough to find the provided release
+     * address and return it.
+     * @return release address for SMP boot
+     */
+    Addr findReleaseAddr();
 
-        /** Parse the DTB file enough to find the provided release
-         * address and return it.
-         * @return release address for SMP boot
-         */
-        Addr findReleaseAddr();
+    MemoryImage buildImage() const override;
 
-        bool loadAllSymbols(SymbolTable *symtab, Addr base = 0,
-                            Addr offset = 0, Addr addrMask = maxAddr);
-        bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0,
-                               Addr offset = 0, Addr addrMask = maxAddr);
-        bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0,
-                              Addr offset = 0, Addr addrMask = maxAddr);
+    bool loadAllSymbols(SymbolTable *symtab, Addr base=0,
+                        Addr offset=0, Addr addrMask=MaxAddr) override;
+    bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0,
+                           Addr offset=0, Addr addrMask=MaxAddr) override;
+    bool loadLocalSymbols(SymbolTable *symtab, Addr base=0,
+                          Addr offset=0, Addr addrMask=MaxAddr) override;
 
-        /** Static function that tries to load file as a
-          * flattened device tree blob.
-          * @param fname path to file
-          * @param len length of file
-          * @param data mmap'ed data buffer containing file contents
-          * @return ObjectFile representing closest match of file type
-          */
-        static ObjectFile *tryFile(const std::string &fname,
-                                   size_t len, uint8_t *data);
+    /** Static function that tries to load file as a
+      * flattened device tree blob.
+      * @param fname path to file
+      * @param len length of file
+      * @param data mmap'ed data buffer containing file contents
+      * @return ObjectFile representing closest match of file type
+      */
+    static ObjectFile *tryFile(const std::string &fname,
+                               size_t len, uint8_t *data);
 };
 
 #endif //__DTB_OBJECT_HH__
index 56f9b35fc77d1066fe767fc2e7b61c05f12a97f3..cecc68dc12568d103d829c7e77c2bcfad87a97d0 100644 (file)
@@ -72,15 +72,23 @@ EcoffObject::EcoffObject(const string &_filename, size_t _len, uint8_t *_data,
     aoutHdr = &(execHdr->a);
 
     entry = aoutHdr->entry;
+}
 
-    addSegment("text", aoutHdr->text_start, fileData + ECOFF_TXTOFF(execHdr),
-            aoutHdr->tsize);
-    addSegment("data", aoutHdr->data_start, fileData + ECOFF_DATOFF(execHdr),
-            aoutHdr->dsize);
-    addSegment("bss", aoutHdr->bss_start, nullptr, aoutHdr->bsize);
-
-    for (auto &seg: segments)
-        DPRINTFR(Loader, "%s\n", *seg);
+MemoryImage
+EcoffObject::buildImage() const
+{
+    MemoryImage image({
+            { "text", aoutHdr->text_start,
+              fileData + ECOFF_TXTOFF(execHdr), aoutHdr->tsize },
+            { "data", aoutHdr->data_start,
+              fileData + ECOFF_DATOFF(execHdr), aoutHdr->dsize },
+            { "bss", aoutHdr->bss_start, nullptr, aoutHdr->bsize }
+    });
+
+    for (auto &seg: image.segments())
+        DPRINTFR(Loader, "%s\n", seg);
+
+    return image;
 }
 
 bool
index b1ae91107e1ff4d94f6e5c3439bff86fa999ca81..94811158eea3f17af39dfebbec8e6e4361b6c239 100644 (file)
@@ -51,12 +51,14 @@ class EcoffObject : public ObjectFile
   public:
     virtual ~EcoffObject() {}
 
-    virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0,
-                                Addr offset = 0, Addr addr_mask = maxAddr);
-    virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0,
-                                  Addr offset = 0, Addr addr_mask = maxAddr);
-    virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0,
-                                  Addr offset = 0, Addr addr_mask = maxAddr);
+    MemoryImage buildImage() const override;
+
+    bool loadAllSymbols(SymbolTable *symtab, Addr base=0,
+                        Addr offset=0, Addr addr_mask=MaxAddr) override;
+    bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0,
+                           Addr offset=0, Addr addr_mask=MaxAddr) override;
+    bool loadLocalSymbols(SymbolTable *symtab, Addr base=0,
+                          Addr offset=0, Addr addr_mask=MaxAddr) override;
 
     static ObjectFile *tryFile(const std::string &fname,
                                size_t len, uint8_t *data);
index 4cf20975d922fafdbac33e2c052bc769f682668d..7a83c0bd2151fa18865213dc75dfe8281e97af32 100644 (file)
@@ -339,26 +339,25 @@ ElfObject::ElfObject(const std::string &_filename, size_t _len,
             section = elf_getscn(elf, ++sec_idx);
         }
 
-        addSegment(name, phdr.p_paddr, fileData + phdr.p_offset,
-                phdr.p_filesz);
+        image.addSegment(name, phdr.p_paddr, fileData + phdr.p_offset,
+                         phdr.p_filesz);
         Addr uninitialized = phdr.p_memsz - phdr.p_filesz;
         if (uninitialized) {
             // There may be parts of a segment which aren't included in the
             // file. In those cases, we need to create a new segment with no
             // data to take up the extra space. This should be zeroed when
             // loaded into memory.
-            addSegment(name + "(uninitialized)", phdr.p_paddr + phdr.p_filesz,
-                    nullptr, uninitialized);
+            image.addSegment(name + "(uninitialized)",
+                    phdr.p_paddr + phdr.p_filesz, nullptr, uninitialized);
         }
     }
 
     // should have found at least one loadable segment
-    warn_if(segments.empty(),
-            "No loadable segments in '%s'. ELF file corrupted?\n",
-            filename);
+    warn_if(image.segments().empty(),
+            "No loadable segments in '%s'. ELF file corrupted?\n", filename);
 
-    for (auto &seg: segments)
-        DPRINTFR(Loader, "%s\n", *seg);
+    for (auto &seg: image.segments())
+        DPRINTFR(Loader, "%s\n", seg);
 
     elf_end(elf);
 
@@ -518,6 +517,5 @@ ElfObject::updateBias(Addr bias_addr)
     entry += bias_addr;
 
     // Patch segments with the bias_addr.
-    for (auto &segment : segments)
-        segment->base += bias_addr;
+    image.offset(bias_addr);
 }
index dbefadd194aea0d92950381b01ec80b3aca95c41..0b8c79b4731e6ceeea0ec7270f0964a68079f2fa 100644 (file)
@@ -86,34 +86,30 @@ class ElfObject : public ObjectFile
     void getSections();
     bool sectionExists(std::string sec);
 
+    MemoryImage image;
+
   public:
     virtual ~ElfObject() {}
 
-    virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0,
-                                Addr offset = 0, Addr addr_mask = maxAddr)
-                                override;
-
-    virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0,
-                                   Addr offset = 0, Addr addr_mask = maxAddr)
-                                   override;
-
-    virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0,
-                                  Addr offset = 0, Addr addr_mask = maxAddr)
-                                  override;
+    MemoryImage buildImage() const override { return image; }
 
-    virtual bool loadWeakSymbols(SymbolTable *symtab, Addr base = 0,
-                                 Addr offset = 0, Addr addr_mask = maxAddr)
-                                 override;
+    bool loadAllSymbols(SymbolTable *symtab, Addr base=0,
+                        Addr offset=0, Addr addr_mask=MaxAddr) override;
+    bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0,
+                           Addr offset=0, Addr addr_mask=MaxAddr) override;
+    bool loadLocalSymbols(SymbolTable *symtab, Addr base=0,
+                          Addr offset=0, Addr addr_mask=MaxAddr) override;
+    bool loadWeakSymbols(SymbolTable *symtab, Addr base=0,
+                         Addr offset=0, Addr addr_mask=MaxAddr) override;
 
 
-    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;
+    ObjectFile *getInterpreter() const override { return interpreter; }
+    Addr bias() const override { return ldBias; }
+    bool relocatable() const override { return relocate; }
+    Addr mapSize() const override { return ldMax - ldMin; }
+    void updateBias(Addr bias_addr) override;
 
-    virtual bool hasTLS() override { return sectionExists(".tbss"); }
+    bool hasTLS() override { return sectionExists(".tbss"); }
 
     static ObjectFile *tryFile(const std::string &fname,
                                size_t len, uint8_t *data,
diff --git a/src/base/loader/memory_image.cc b/src/base/loader/memory_image.cc
new file mode 100644 (file)
index 0000000..6fa70c9
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Steve Reinhardt
+ */
+
+#include "base/loader/memory_image.hh"
+#include "mem/port_proxy.hh"
+
+bool
+MemoryImage::writeSegment(const Segment &seg, const PortProxy &proxy) const
+{
+    if (seg.size != 0) {
+        if (seg.data) {
+            proxy.writeBlob(seg.base, seg.data, seg.size);
+        } else {
+            // no image: must be bss
+            proxy.memsetBlob(seg.base, 0, seg.size);
+        }
+    }
+    return true;
+}
+
+bool
+MemoryImage::write(const PortProxy &proxy) const
+{
+    for (auto &seg: _segments)
+        if (!writeSegment(seg, proxy))
+            return false;
+    return true;
+}
+
+MemoryImage &
+MemoryImage::move(std::function<Addr(Addr)> mapper)
+{
+    for (auto &seg: _segments)
+        seg.base = mapper(seg.base);
+    return *this;
+}
diff --git a/src/base/loader/memory_image.hh b/src/base/loader/memory_image.hh
new file mode 100644 (file)
index 0000000..866e956
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ *          Steve Reinhardt
+ */
+
+#ifndef __BASE_LOADER_MEMORY_IMAGE_HH__
+#define __BASE_LOADER_MEMORY_IMAGE_HH__
+
+#include <functional>
+#include <initializer_list>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/logging.hh"
+#include "base/types.hh"
+
+class PortProxy;
+class Process;
+class ProcessParams;
+class SymbolTable;
+
+class MemoryImage
+{
+  public:
+    struct Segment
+    {
+        std::string name;
+        Addr base;
+        uint8_t *data;
+        size_t size;
+    };
+
+    MemoryImage() {}
+
+    MemoryImage(std::initializer_list<Segment> new_segs)
+    {
+        for (auto &seg: new_segs)
+            addSegment(seg);
+    }
+
+  private:
+    std::vector<Segment> _segments;
+    bool writeSegment(const Segment &seg, const PortProxy &proxy) const;
+
+  public:
+    const std::vector<Segment> &
+    segments() const
+    {
+        return _segments;
+    }
+
+    void
+    addSegment(const Segment &seg)
+    {
+        _segments.emplace_back(seg);
+    }
+
+    void
+    addSegment(std::string name, Addr base, uint8_t *data, size_t size)
+    {
+        _segments.push_back(Segment({name, base, data, size}));
+    }
+
+    bool write(const PortProxy &proxy) const;
+    MemoryImage &move(std::function<Addr(Addr)> mapper);
+    MemoryImage &
+    offset(Addr by)
+    {
+        return move([by](Addr a){ return by + a; });
+    }
+    MemoryImage &
+    mask(Addr m) {
+        return move([m](Addr a) { return a & m; });
+    }
+
+    Addr
+    maxAddr() const
+    {
+        Addr max = 0;
+        for (auto &seg: _segments) {
+            Addr end = seg.base + seg.size;
+            if (end > max)
+                max = end;
+        }
+        return max;
+    }
+
+    Addr
+    minAddr() const
+    {
+        Addr min = MaxAddr;
+        for (auto &seg: _segments)
+            if (seg.base < min)
+                min = seg.base;
+        return min;
+    }
+
+    bool
+    contains(Addr addr) const
+    {
+        for (auto &seg: _segments) {
+            Addr start = seg.base;
+            Addr end = seg.base + seg.size;
+            if (addr >= start && addr < end)
+                return true;
+        }
+        return false;
+    }
+};
+
+static inline std::ostream &
+operator << (std::ostream &os, const MemoryImage::Segment &seg)
+{
+    ccprintf(os, "%s: %#x %d", seg.name, seg.base, seg.size);
+    return os;
+}
+
+
+#endif // __BASE_LOADER_MEMORY_IMAGE_HH__
index d63b2221be7ecb2f136b347387c4a7bd900c3b3b..afecd21e322c8d2f58967cb014ceb5b2ff3907b8 100644 (file)
@@ -70,31 +70,6 @@ ObjectFile::~ObjectFile()
 }
 
 
-bool
-ObjectFile::loadSegment(Segment *seg, const PortProxy &mem_proxy)
-{
-    if (seg->size != 0) {
-        Addr addr = (seg->base & loadMask) + loadOffset;
-        if (seg->data) {
-            mem_proxy.writeBlob(addr, seg->data, seg->size);
-        } else {
-            // no image: must be bss
-            mem_proxy.memsetBlob(addr, 0, seg->size);
-        }
-    }
-    return true;
-}
-
-
-bool
-ObjectFile::loadSegments(const PortProxy &proxy)
-{
-    for (auto &seg: segments)
-        if (!loadSegment(seg.get(), proxy))
-            return false;
-    return true;
-}
-
 namespace
 {
 
index e5053ad8211e3b392a2fdb39a19df1ac3d3af258..669afeb11643a747e6425ee9da2e45ce7f7da8df 100644 (file)
@@ -37,6 +37,7 @@
 #include <string>
 #include <vector>
 
+#include "base/loader/memory_image.hh"
 #include "base/logging.hh"
 #include "base/types.hh"
 
@@ -74,14 +75,10 @@ class ObjectFile
         FreeBSD
     };
 
-    static const Addr maxAddr = std::numeric_limits<Addr>::max();
-
   protected:
     const std::string filename;
     uint8_t *fileData;
     size_t len;
-    Addr loadOffset=0;
-    Addr loadMask=maxAddr;
 
     Arch arch;
     OpSys opSys;
@@ -92,16 +89,16 @@ class ObjectFile
   public:
     virtual ~ObjectFile();
 
-    virtual bool loadSegments(const PortProxy &mem_proxy);
+    virtual MemoryImage buildImage() const = 0;
 
     virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0,
-                                Addr offset=0, Addr mask=maxAddr) = 0;
+                                Addr offset=0, Addr mask=MaxAddr) = 0;
     virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0,
-                                   Addr offset=0, Addr mask=maxAddr) = 0;
+                                   Addr offset=0, Addr mask=MaxAddr) = 0;
     virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base=0,
-                                  Addr offset=0, Addr mask=maxAddr) = 0;
+                                  Addr offset=0, Addr mask=MaxAddr) = 0;
     virtual bool loadWeakSymbols(SymbolTable *symtab, Addr base=0,
-                                 Addr offset=0, Addr mask=maxAddr)
+                                 Addr offset=0, Addr mask=MaxAddr)
     { return false; }
 
     virtual ObjectFile *getInterpreter() const { return nullptr; }
@@ -117,77 +114,12 @@ class ObjectFile
     Arch  getArch()  const { return arch; }
     OpSys getOpSys() const { return opSys; }
 
-    struct Segment
-    {
-        std::string name;
-        Addr base;
-        uint8_t *data;
-        size_t size;
-    };
-
   protected:
     Addr entry;
 
-    std::vector<std::unique_ptr<Segment>> segments;
-
-    void
-    addSegment(std::string name, Addr base, uint8_t *data, size_t size)
-    {
-        Segment *seg = new Segment;
-        seg->name = name;
-        seg->base = base;
-        seg->data = data;
-        seg->size = size;
-        segments.emplace_back(seg);
-    }
-
-    bool loadSegment(Segment *seg, const PortProxy &mem_proxy);
-
   public:
     Addr entryPoint() const { return entry; }
 
-    Addr
-    maxSegmentAddr() const
-    {
-        Addr max = 0;
-        for (auto &seg: segments) {
-            Addr end = seg->base + seg->size;
-            if (end > max)
-                max = end;
-        }
-        return max;
-    }
-
-    Addr
-    minSegmentAddr() const
-    {
-        Addr min = maxAddr;
-        for (auto &seg: segments)
-            if (seg->base < min)
-                min = seg->base;
-        return min;
-    }
-
-    bool
-    contains(Addr addr) const
-    {
-        for (auto &seg: segments) {
-            Addr start = seg->base;
-            Addr end = seg->base + seg->size;
-            if (addr >= start && addr < end)
-                return true;
-        }
-        return false;
-    }
-
-    /* This function allows you to override the base address where
-     * a binary is going to be loaded or set it if the binary is just a
-     * blob that doesn't include an object header.
-     * @param a address to load the binary/text section at
-     */
-    void setLoadOffset(Addr val) { loadOffset = val; }
-    void setLoadMask(Addr val) { loadMask = val; }
-
     /**
      * Each instance of a Loader subclass will have a chance to try to load
      * an object file when tryLoaders is called. If they can't because they
@@ -221,13 +153,6 @@ class ObjectFile
     static Process *tryLoaders(ProcessParams *params, ObjectFile *obj_file);
 };
 
-static inline std::ostream &
-operator << (std::ostream &os, const ObjectFile::Segment &seg)
-{
-    ccprintf(os, "%s: %#x %d", seg.name, seg.base, seg.size);
-    return os;
-}
-
 ObjectFile *createObjectFile(const std::string &fname, bool raw = false);
 
 
index b0ece3ba2aa43399e5185675583717cf99bb1651..35ed485c4eb3aa6847179388fae44357985a8c4f 100644 (file)
@@ -43,10 +43,14 @@ RawObject::tryFile(const std::string &fname, size_t len, uint8_t *data)
 
 RawObject::RawObject(const std::string &_filename, size_t _len,
         uint8_t *_data, Arch _arch, OpSys _opSys)
-    : ObjectFile(_filename, _len, _data, _arch, _opSys),
-    data(new Segment{ "data", 0, fileData, len })
+    : ObjectFile(_filename, _len, _data, _arch, _opSys)
 {
-    segments.emplace_back(data);
+}
+
+MemoryImage
+RawObject::buildImage() const
+{
+    return {{ "data", 0, fileData, len }};
 }
 
 bool
index 9eb9291078a2733c756f26f91497f7235f8d1980..6dc54c7aa2d71b6bf97c6d5c2fb52a7d2b7f052f 100644 (file)
@@ -39,18 +39,17 @@ class RawObject: public ObjectFile
     RawObject(const std::string &_filename, size_t _len,
               uint8_t *_data, Arch _arch, OpSys _opSys);
 
-    Segment *data;
-
   public:
     virtual ~RawObject() {}
 
-    virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0,
-                                Addr offset = 0, Addr addr_mask = maxAddr);
-    virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0,
-                                   Addr offset = 0,
-                                   Addr addr_mask = maxAddr);
-    virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base = 0,
-                                  Addr offset = 0, Addr addr_mask = maxAddr);
+    MemoryImage buildImage() const override;
+
+    bool loadAllSymbols(SymbolTable *symtab, Addr base=0,
+                        Addr offset=0, Addr addr_mask=MaxAddr) override;
+    bool loadGlobalSymbols(SymbolTable *symtab, Addr base=0,
+                           Addr offset=0, Addr addr_mask=MaxAddr) override;
+    bool loadLocalSymbols(SymbolTable *symtab, Addr base=0,
+                          Addr offset=0, Addr addr_mask=MaxAddr) override;
 
     static ObjectFile *tryFile(const std::string &fname, size_t len,
             uint8_t *data);
index 224152a329dcbea61996d5b5451f02d981d3e7d2..a01cfea91ccf7ac072af825e9628de3df53d17f6 100644 (file)
@@ -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
index ae23de42052d2233a9551604006c39bdeb750a74..8e353071ce527c549700e64ff0afbcf6772de22a 100644 (file)
@@ -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;
index 6c3b172c245d47ac28d26fbe08ce0262aea754a3..91ddb2567c416eefc126471a656bf1984f2e8be0 100644 (file)
@@ -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 (lib) {
-                    lib->loadAllSymbols(debugSymbolTable,
-                                        lib->minSegmentAddr(), start);
-                }
+        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->buildImage().minAddr(), start);
             }
         }
 
index bf8b45239ba71e537105887f83c885d0b3745029..87a220311a9c6cb0d44a039a900f0cb1fe9e9cc3 100644 (file)
@@ -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);
index c618e394445aeaa95cc1b71bf2c850999722cf55..345d83c2a6bab88f3b6799d38b31545ed95b858e 100644 (file)
@@ -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;