arch,base: Restructure the object file loaders.
authorGabe Black <gabeblack@google.com>
Fri, 4 Oct 2019 06:42:18 +0000 (23:42 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 15 Oct 2019 22:03:31 +0000 (22:03 +0000)
This change creates a distinction between object files which hold
executable code, and flat files which don't. The first type of files
have entry points, symbols, etc., while the others are just blobs which
can be shoved into memory. Rather than have those aspects but stub
them out, this change creates a new base class which simply doesn't
have them.

This change also restructures the ELF loader since it's main function
was quite long and doing multiple jobs.

It stops passing the architecture and operating system to the
ObjectFile constructor, since those might not be known at the very top
of the constructor. Instead, those default to Uknown*, and then are
filled in in the constructor body if appropriate. This removes a lot
of plumbing that was hard to actually use in practice.

It also introduces a mechanism to collect generic object file formats
so that they can be tried one by one by the general createObjectFile
function, rather than listing them all there one by one. It's unlikely
that new types of object files will need to be added in a modular way
without being able to modify the core loader code, but it's cleaner to
have that abstraction and modularization like is already there for
process loaders.

Finally, to make it possible to share the code which handles zipped
files for both true object files and also files which will be loaded
into memory but are just blobs, that mechanism is pulled out into a
new class called ImageFileData. It holds a collection of segments
which are set up by the object file and may refer to regions of the
original file, buffers maintained elsewhere, or even nothing to support
bss-es. shared_ptr is used to make it easier to keep track of that
information without having to do so explicitly or worry about deleting
a buffer before everyone was done using it.

Change-Id: I92890266f2ba0a703803cccad675a3ab41f2c4af
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21467
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Brandon Potter <Brandon.Potter@amd.com>
Maintainer: Gabe Black <gabeblack@google.com>

22 files changed:
src/arch/arm/freebsd/system.cc
src/arch/arm/linux/system.cc
src/base/SConscript
src/base/loader/aout_object.cc
src/base/loader/aout_object.hh
src/base/loader/dtb_file.cc [new file with mode: 0644]
src/base/loader/dtb_file.hh [new file with mode: 0644]
src/base/loader/dtb_object.cc [deleted file]
src/base/loader/dtb_object.hh [deleted file]
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/image_file.hh [new file with mode: 0644]
src/base/loader/image_file_data.cc [new file with mode: 0644]
src/base/loader/image_file_data.hh [new file with mode: 0644]
src/base/loader/memory_image.hh
src/base/loader/object_file.cc
src/base/loader/object_file.hh
src/base/loader/raw_image.hh [new file with mode: 0644]
src/base/loader/raw_object.cc [deleted file]
src/base/loader/raw_object.hh [deleted file]

index 106c8e432ff55038033c775a2563ce3e4a9799f5..3f38f2e0d029fca1fddb567d2826f7573b089d37 100644 (file)
@@ -35,7 +35,7 @@
 #include "arch/arm/isa_traits.hh"
 #include "arch/arm/utility.hh"
 #include "arch/generic/freebsd/threadinfo.hh"
-#include "base/loader/dtb_object.hh"
+#include "base/loader/dtb_file.hh"
 #include "base/loader/object_file.hh"
 #include "base/loader/symtab.hh"
 #include "cpu/base.hh"
@@ -110,25 +110,15 @@ FreebsdArmSystem::initState()
     inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename,
             params()->atags_addr + loadAddrOffset);
 
-    ObjectFile *dtb_file = createObjectFile(params()->dtb_filename, true);
-    if (!dtb_file) {
-        fatal("couldn't load DTB file: %s\n", params()->dtb_filename);
-    }
-
-    DtbObject *_dtb_file = dynamic_cast<DtbObject*>(dtb_file);
+    DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
 
-    if (_dtb_file) {
-        if (!_dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
-                                       params()->boot_osflags.size())) {
-            warn("couldn't append bootargs to DTB file: %s\n",
-                 params()->dtb_filename);
-        }
-    } else {
-        warn("dtb_file cast failed; couldn't append bootargs "
-             "to DTB file: %s\n", params()->dtb_filename);
+    if (!dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
+                                  params()->boot_osflags.size())) {
+        warn("couldn't append bootargs to DTB file: %s\n",
+             params()->dtb_filename);
     }
 
-    Addr ra = _dtb_file->findReleaseAddr();
+    Addr ra = dtb_file->findReleaseAddr();
     if (ra)
         bootReleaseAddr = ra & ~ULL(0x7F);
 
index 740d2e0e6b1876716e91df942d131001469e8a7d..acca58af30d36f02f082bc7b3bb8f45558ea33e3 100644 (file)
@@ -46,7 +46,7 @@
 #include "arch/arm/linux/atag.hh"
 #include "arch/arm/utility.hh"
 #include "arch/generic/linux/threadinfo.hh"
-#include "base/loader/dtb_object.hh"
+#include "base/loader/dtb_file.hh"
 #include "base/loader/object_file.hh"
 #include "base/loader/symtab.hh"
 #include "cpu/base.hh"
@@ -133,22 +133,12 @@ LinuxArmSystem::initState()
         inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename,
                 params()->atags_addr + loadAddrOffset);
 
-        ObjectFile *dtb_file = createObjectFile(params()->dtb_filename, true);
-        if (!dtb_file) {
-            fatal("couldn't load DTB file: %s\n", params()->dtb_filename);
-        }
-
-        DtbObject *_dtb_file = dynamic_cast<DtbObject*>(dtb_file);
+        DtbFile *dtb_file = new DtbFile(params()->dtb_filename);
 
-        if (_dtb_file) {
-            if (!_dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
-                                           params()->boot_osflags.size())) {
-                warn("couldn't append bootargs to DTB file: %s\n",
-                     params()->dtb_filename);
-            }
-        } else {
-            warn("dtb_file cast failed; couldn't append bootargs "
-                 "to DTB file: %s\n", params()->dtb_filename);
+        if (!dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
+                                      params()->boot_osflags.size())) {
+            warn("couldn't append bootargs to DTB file: %s\n",
+                 params()->dtb_filename);
         }
 
         dtb_file->buildImage().
index 8d170793b3d7f23cc0f2fdabeb33536544a58791..b4b381bf19c325db39d309b027ffa24e18ed963d 100644 (file)
@@ -74,12 +74,12 @@ GTest('trie.test', 'trie.test.cc')
 Source('types.cc')
 
 Source('loader/aout_object.cc')
-Source('loader/dtb_object.cc')
+Source('loader/dtb_file.cc')
 Source('loader/ecoff_object.cc')
 Source('loader/elf_object.cc')
+Source('loader/image_file_data.cc')
 Source('loader/memory_image.cc')
 Source('loader/object_file.cc')
-Source('loader/raw_object.cc')
 Source('loader/symtab.cc')
 
 Source('stats/group.cc')
index eb633c1ce752abe57134a036297930102d8e1618..47f3021b7cedf9419415ef190088eb12dd83f6ba 100644 (file)
 using namespace std;
 
 ObjectFile *
-AoutObject::tryFile(const string &fname, size_t len, uint8_t *data)
+AoutObjectFileFormat::load(ImageFileDataPtr ifd)
 {
-    if (!N_BADMAG(*(aout_exechdr *)data)) {
-        // right now this is only used for Alpha PAL code
-        return new AoutObject(fname, len, data,
-                              ObjectFile::Alpha, ObjectFile::UnknownOpSys);
-    } else {
+    if (!N_BADMAG(*(const aout_exechdr *)ifd->data()))
+        return new AoutObject(ifd);
+    else
         return nullptr;
-    }
 }
 
+namespace
+{
+
+AoutObjectFileFormat aoutObjectFileFormat;
+
+} // anonymous namespace
+
 
-AoutObject::AoutObject(const string &_filename,
-                       size_t _len, uint8_t *_data,
-                       Arch _arch, OpSys _opSys)
-    : ObjectFile(_filename, _len, _data, _arch, _opSys)
+AoutObject::AoutObject(ImageFileDataPtr ifd) : ObjectFile(ifd)
 {
-    execHdr = (aout_exechdr *)fileData;
+    execHdr = (const aout_exechdr *)imageData->data();
     entry = execHdr->entry;
+
+    // Right now this is only used for Alpha PAL code.
+    arch = Alpha;
 }
 
 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}
+            MemoryImage::Segment{ "text", N_TXTADDR(*execHdr), imageData,
+              N_TXTOFF(*execHdr), execHdr->tsize },
+            MemoryImage::Segment{ "data", N_DATADDR(*execHdr), imageData,
+              N_DATOFF(*execHdr), execHdr->dsize },
+            MemoryImage::Segment{ "bss", N_BSSADDR(*execHdr), execHdr->bsize}
     });
 
     for (auto &seg: image.segments())
         DPRINTFR(Loader, "%s\n", seg);
-    return image;
-}
-
 
-bool
-AoutObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                           Addr addr_mask)
-{
-    return false;
-}
-
-bool
-AoutObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                              Addr addr_mask)
-{
-    // a.out symbols not supported yet
-    return false;
-}
-
-bool
-AoutObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                             Addr addr_mask)
-{
-    // a.out symbols not supported yet
-    return false;
+    return image;
 }
index 4f8c86fcd802539fba24fad6e97955c27c81e591..480a30c92fb99f5897b12cf2596503befe55c5a8 100644 (file)
@@ -39,26 +39,18 @@ struct aout_exechdr;
 class AoutObject : public ObjectFile
 {
   protected:
-    aout_exechdr *execHdr;
-
-    AoutObject(const std::string &_filename,
-               size_t _len, uint8_t *_data,
-               Arch _arch, OpSys _opSys);
+    const aout_exechdr *execHdr;
 
   public:
-    virtual ~AoutObject() {}
+    AoutObject(ImageFileDataPtr ifd);
 
     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);
+class AoutObjectFileFormat : public ObjectFileFormat
+{
+  public:
+    ObjectFile *load(ImageFileDataPtr data) override;
 };
 
 #endif // __AOUT_OBJECT_HH__
diff --git a/src/base/loader/dtb_file.cc b/src/base/loader/dtb_file.cc
new file mode 100644 (file)
index 0000000..aaae0a2
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2013 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: Anthony Gutierrez
+ */
+
+#include "base/loader/dtb_file.hh"
+
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <cassert>
+
+#include "fdt.h"
+#include "libfdt.h"
+#include "sim/byteswap.hh"
+
+DtbFile::DtbFile(const std::string &filename) :
+    ImageFile(ImageFileDataPtr(new ImageFileData(filename)))
+{
+    panic_if(fdt_magic((const void *)imageData->data()) != FDT_MAGIC,
+            "File %s doesn't seem to be a DTB.\n", filename);
+    fileDataMmapped = true;
+    fileData = const_cast<uint8_t *>(imageData->data());
+    length = imageData->len();
+}
+
+DtbFile::~DtbFile()
+{
+    // Make sure to clean up memory properly depending
+    // on how buffer was allocated.
+    if (!fileDataMmapped)
+        delete [] fileData;
+}
+
+bool
+DtbFile::addBootCmdLine(const char *_args, size_t len)
+{
+    const char *root_path = "/";
+    const char *node_name = "chosen";
+    const char *full_path_node_name = "/chosen";
+    const char *property_name = "bootargs";
+
+    // Make a new buffer that has extra space to add nodes/properties
+    int newLen = 2 * length;
+    uint8_t *fdt_buf_w_space = new uint8_t[newLen];
+    // Copy and unpack flattened device tree into new buffer
+    int ret = fdt_open_into((void *)fileData, (void *)fdt_buf_w_space, newLen);
+    if (ret < 0) {
+        warn("Error resizing buffer of flattened device tree, "
+             "errno: %d\n", ret);
+        delete [] fdt_buf_w_space;
+        return false;
+    }
+
+    // First try finding the /chosen node in the dtb
+    int offset = fdt_path_offset((void *)fdt_buf_w_space, full_path_node_name);
+    if (offset < 0) {
+        // try adding the node by walking dtb tree to proper insertion point
+        offset = fdt_path_offset((void *)fdt_buf_w_space, root_path);
+        offset = fdt_add_subnode((void *)fdt_buf_w_space, offset, node_name);
+        // if we successfully add the subnode, get the offset
+        if (offset >= 0)
+          offset = fdt_path_offset((void *)fdt_buf_w_space,
+                                   full_path_node_name);
+
+        if (offset < 0) {
+            warn("Error finding or adding \"chosen\" subnode to flattened "
+                 "device tree, errno: %d\n", offset);
+            delete [] fdt_buf_w_space;
+            return false;
+        }
+    }
+
+    // Set the bootargs property in the /chosen node
+    ret = fdt_setprop((void *)fdt_buf_w_space, offset, property_name,
+                      (const void *)_args, len+1);
+    if (ret < 0) {
+        warn("Error setting \"bootargs\" property to flattened device tree, "
+             "errno: %d\n", ret);
+        delete [] fdt_buf_w_space;
+        return false;
+    }
+
+    // Repack the dtb for kernel use
+    ret = fdt_pack((void *)fdt_buf_w_space);
+    if (ret < 0) {
+        warn("Error re-packing flattened device tree structure, "
+             "errno: %d\n", ret);
+        delete [] fdt_buf_w_space;
+        return false;
+    }
+
+    // clean up old buffer and set to new fdt blob
+    if (!fileDataMmapped)
+        delete [] fileData;
+    fileData = fdt_buf_w_space;
+    fileDataMmapped = false;
+    length = newLen;
+
+    return true;
+}
+
+Addr
+DtbFile::findReleaseAddr()
+{
+    void *fd = (void *)fileData;
+
+    int offset = fdt_path_offset(fd, "/cpus/cpu@0");
+    int len;
+
+    const void *temp = fdt_getprop(fd, offset, "cpu-release-addr", &len);
+    Addr rel_addr = 0;
+
+    if (len > 3)
+        rel_addr = betoh(*static_cast<const uint32_t *>(temp));
+    if (len == 8) {
+        rel_addr = (rel_addr << 32) |
+            betoh(*(static_cast<const uint32_t *>(temp) + 1));
+    }
+
+    return rel_addr;
+}
+
+MemoryImage
+DtbFile::buildImage() const
+{
+    if (fileDataMmapped)
+        return {{ "data", imageData }};
+    else
+        return {{ "data", 0, fileData, length }};
+}
diff --git a/src/base/loader/dtb_file.hh b/src/base/loader/dtb_file.hh
new file mode 100644 (file)
index 0000000..53bc13e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 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: Anthony Gutierrez
+ */
+
+#ifndef __BASE_LOADER_DTB_FILE_HH__
+#define __BASE_LOADER_DTB_FILE_HH__
+
+#include "base/loader/image_file.hh"
+
+/** @file
+ * This implements an image file format to support loading
+ * and modifying flattened device tree blobs for use with
+ * current and future ARM Linux kernels.
+ */
+class DtbFile : public ImageFile
+{
+  protected:
+    /** Bool marking if this dtb file has replaced the original
+     *  read in DTB file with a new modified buffer
+     */
+    bool fileDataMmapped;
+    uint8_t *fileData = nullptr;
+    size_t length = 0;
+
+  public:
+    DtbFile(const std::string &name);
+    ~DtbFile();
+
+    /** 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();
+
+    MemoryImage buildImage() const override;
+};
+
+#endif //__BASE_LOADER_DTB_FILE_HH__
diff --git a/src/base/loader/dtb_object.cc b/src/base/loader/dtb_object.cc
deleted file mode 100644 (file)
index f5b206a..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2013 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: Anthony Gutierrez
- */
-
-#include "base/loader/dtb_object.hh"
-
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <cassert>
-
-#include "fdt.h"
-#include "libfdt.h"
-#include "sim/byteswap.hh"
-
-ObjectFile *
-DtbObject::tryFile(const std::string &fname, size_t len, uint8_t *data)
-{
-    // Check if this is a FDT file by looking for magic number
-    if (fdt_magic((void*)data) == FDT_MAGIC) {
-        return new DtbObject(fname, len, data,
-                             ObjectFile::UnknownArch, ObjectFile::UnknownOpSys);
-    } else {
-        return NULL;
-    }
-}
-
-DtbObject::DtbObject(const std::string &_filename, size_t _len, uint8_t *_data,
-                     Arch _arch, OpSys _opSys)
-    : ObjectFile(_filename, _len, _data, _arch, _opSys)
-{
-    fileDataMmapped = true;
-}
-
-DtbObject::~DtbObject()
-{
-    // Make sure to clean up memory properly depending
-    // on how buffer was allocated.
-    if (fileData && !fileDataMmapped) {
-        delete [] fileData;
-        fileData = NULL;
-    } else if (fileData) {
-        munmap(fileData, len);
-        fileData = NULL;
-    }
-}
-
-bool
-DtbObject::addBootCmdLine(const char* _args, size_t len)
-{
-    const char* root_path = "/";
-    const char* node_name = "chosen";
-    const char* full_path_node_name = "/chosen";
-    const char* property_name = "bootargs";
-
-    // Make a new buffer that has extra space to add nodes/properties
-    int newLen = 2 * this->len;
-    uint8_t *fdt_buf_w_space = new uint8_t[newLen];
-    // Copy and unpack flattened device tree into new buffer
-    int ret = fdt_open_into((void *)fileData, (void *)fdt_buf_w_space, newLen);
-    if (ret < 0) {
-        warn("Error resizing buffer of flattened device tree, "
-             "errno: %d\n", ret);
-        delete [] fdt_buf_w_space;
-        return false;
-    }
-
-    // First try finding the /chosen node in the dtb
-    int offset = fdt_path_offset((void *)fdt_buf_w_space, full_path_node_name);
-    if (offset < 0) {
-        // try adding the node by walking dtb tree to proper insertion point
-        offset = fdt_path_offset((void *)fdt_buf_w_space, root_path);
-        offset = fdt_add_subnode((void *)fdt_buf_w_space, offset, node_name);
-        // if we successfully add the subnode, get the offset
-        if (offset >= 0)
-          offset = fdt_path_offset((void *)fdt_buf_w_space,
-                                   full_path_node_name);
-
-        if (offset < 0) {
-            warn("Error finding or adding \"chosen\" subnode to flattened "
-                 "device tree, errno: %d\n", offset);
-            delete [] fdt_buf_w_space;
-            return false;
-        }
-    }
-
-    // Set the bootargs property in the /chosen node
-    ret = fdt_setprop((void *)fdt_buf_w_space, offset, property_name,
-                      (const void *)_args, len+1);
-    if (ret < 0) {
-        warn("Error setting \"bootargs\" property to flattened device tree, "
-             "errno: %d\n", ret);
-        delete [] fdt_buf_w_space;
-        return false;
-    }
-
-    // Repack the dtb for kernel use
-    ret = fdt_pack((void *)fdt_buf_w_space);
-    if (ret < 0) {
-        warn("Error re-packing flattened device tree structure, "
-             "errno: %d\n", ret);
-        delete [] fdt_buf_w_space;
-        return false;
-    }
-
-    // clean up old buffer and set to new fdt blob
-    munmap(fileData, this->len);
-    fileData = fdt_buf_w_space;
-    fileDataMmapped = false;
-    this->len = newLen;
-
-    return true;
-}
-
-Addr
-DtbObject::findReleaseAddr()
-{
-    void *fd = (void *)fileData;
-
-    int offset = fdt_path_offset(fd, "/cpus/cpu@0");
-    int len;
-
-    const void* temp = fdt_getprop(fd, offset, "cpu-release-addr", &len);
-    Addr rel_addr = 0;
-
-    if (len > 3)
-        rel_addr = betoh(*static_cast<const uint32_t *>(temp));
-    if (len == 8) {
-        rel_addr = (rel_addr << 32) |
-            betoh(*(static_cast<const uint32_t *>(temp) + 1));
-    }
-
-    return rel_addr;
-}
-
-MemoryImage
-DtbObject::buildImage() const
-{
-    return {{"data", 0, fileData, len}};
-}
-
-bool
-DtbObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                          Addr addr_mask)
-{
-    return false;
-}
-
-bool
-DtbObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                             Addr addr_mask)
-{
-    // nothing to do here
-    return false;
-}
-
-bool
-DtbObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                            Addr addr_mask)
-{
-    // nothing to do here
-    return false;
-}
diff --git a/src/base/loader/dtb_object.hh b/src/base/loader/dtb_object.hh
deleted file mode 100644 (file)
index 1284025..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2013 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: Anthony Gutierrez
- */
-
-#ifndef __DTB_OBJECT_HH__
-#define __DTB_OBJECT_HH__
-
-#include "base/loader/object_file.hh"
-
-/** @file
- * This implements an object file format to support loading
- * and modifying flattened device tree blobs for use with
- * current and future ARM Linux kernels.
- */
-class DtbObject : public ObjectFile
-{
-  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;
-
-  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);
-
-    /** 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) 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);
-};
-
-#endif //__DTB_OBJECT_HH__
index cecc68dc12568d103d829c7e77c2bcfad87a97d0..2f534311a4364456cd56a4d566b20a9b36edd734 100644 (file)
 using namespace std;
 
 ObjectFile *
-EcoffObject::tryFile(const string &fname, size_t len, uint8_t *data)
+EcoffObjectFormat::load(ImageFileDataPtr ifd)
 {
-    if (((ecoff_filehdr *)data)->f_magic == ECOFF_MAGIC_ALPHA) {
-        // it's Alpha ECOFF
-        return new EcoffObject(fname, len, data,
-                               ObjectFile::Alpha, ObjectFile::Tru64);
-    }
-    else {
-        return NULL;
-    }
+    if (((const ecoff_filehdr *)ifd->data())->f_magic == ECOFF_MAGIC_ALPHA)
+        return new EcoffObject(ifd);
+    else
+        return nullptr;
 }
 
+namespace
+{
+
+EcoffObjectFormat ecoffObjectFormat;
+
+} // anonymous namespace
+
 
-EcoffObject::EcoffObject(const string &_filename, size_t _len, uint8_t *_data,
-                         Arch _arch, OpSys _opSys)
-    : ObjectFile(_filename, _len, _data, _arch, _opSys)
+EcoffObject::EcoffObject(ImageFileDataPtr ifd) : ObjectFile(ifd)
 {
-    execHdr = (ecoff_exechdr *)fileData;
+    execHdr = (const ecoff_exechdr *)imageData->data();
     fileHdr = &(execHdr->f);
     aoutHdr = &(execHdr->a);
 
     entry = aoutHdr->entry;
+    // it's Alpha ECOFF
+    arch = Alpha;
+    opSys = Tru64;
 }
 
 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 }
+            { "text", aoutHdr->text_start, imageData,
+              ECOFF_TXTOFF(execHdr), aoutHdr->tsize },
+            { "data", aoutHdr->data_start, imageData,
+              ECOFF_DATOFF(execHdr), aoutHdr->dsize },
+            { "bss", aoutHdr->bss_start, aoutHdr->bsize }
     });
 
     for (auto &seg: image.segments())
@@ -108,21 +112,24 @@ EcoffObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset,
         return false;
 
     if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
-        warn("loadGlobalSymbols: wrong magic on %s\n", filename);
+        warn("loadGlobalSymbols: wrong magic on %s\n", imageData->filename());
         return false;
     }
 
-    ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
+    auto *syms = (const ecoff_symhdr *)(imageData->data() + fileHdr->f_symptr);
     if (syms->magic != magicSym2) {
-        warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
+        warn("loadGlobalSymbols: bad symbol header magic on %s\n",
+                imageData->filename());
         return false;
     }
 
-    ecoff_extsym *ext_syms = (ecoff_extsym *)(fileData + syms->cbExtOffset);
+    auto *ext_syms = (const ecoff_extsym *)(
+            imageData->data() + syms->cbExtOffset);
 
-    char *ext_strings = (char *)(fileData + syms->cbSsExtOffset);
+    auto *ext_strings =
+        (const char *)(imageData->data() + syms->cbSsExtOffset);
     for (int i = 0; i < syms->iextMax; i++) {
-        ecoff_sym *entry = &(ext_syms[i].asym);
+        const ecoff_sym *entry = &(ext_syms[i].asym);
         if (entry->iss != -1)
             symtab->insert(entry->value, ext_strings + entry->iss);
     }
@@ -138,23 +145,25 @@ EcoffObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
         return false;
 
     if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
-        warn("loadGlobalSymbols: wrong magic on %s\n", filename);
+        warn("loadGlobalSymbols: wrong magic on %s\n", imageData->filename());
         return false;
     }
 
-    ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
+    auto *syms = (const ecoff_symhdr *)(imageData->data() + fileHdr->f_symptr);
     if (syms->magic != magicSym2) {
-        warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
+        warn("loadGlobalSymbols: bad symbol header magic on %s\n",
+                imageData->filename());
         return false;
     }
 
-    ecoff_sym *local_syms = (ecoff_sym *)(fileData + syms->cbSymOffset);
-    char *local_strings = (char *)(fileData + syms->cbSsOffset);
-    ecoff_fdr *fdesc = (ecoff_fdr *)(fileData + syms->cbFdOffset);
+    auto *local_syms =
+        (const ecoff_sym *)(imageData->data() + syms->cbSymOffset);
+    auto *local_strings = (const char *)(imageData->data() + syms->cbSsOffset);
+    auto *fdesc = (const ecoff_fdr *)(imageData->data() + syms->cbFdOffset);
 
     for (int i = 0; i < syms->ifdMax; i++) {
-        ecoff_sym *entry = (ecoff_sym *)(local_syms + fdesc[i].isymBase);
-        char *strings = (char *)(local_strings + fdesc[i].issBase);
+        auto *entry = (const ecoff_sym *)(local_syms + fdesc[i].isymBase);
+        auto *strings = (const char *)(local_strings + fdesc[i].issBase);
         for (int j = 0; j < fdesc[i].csym; j++) {
             if (entry[j].st == stGlobal || entry[j].st == stProc)
                 if (entry[j].iss != -1)
@@ -163,7 +172,7 @@ EcoffObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
     }
 
     for (int i = 0; i < syms->isymMax; i++) {
-        ecoff_sym *entry = &(local_syms[i]);
+        const ecoff_sym *entry = &(local_syms[i]);
         if (entry->st == stProc)
             symtab->insert(entry->value, local_strings + entry->iss);
     }
index 94811158eea3f17af39dfebbec8e6e4361b6c239..9e6c53373905f6af735a66ed11c93a29d0a49268 100644 (file)
@@ -28,8 +28,8 @@
  * Authors: Steve Reinhardt
  */
 
-#ifndef __ECOFF_OBJECT_HH__
-#define __ECOFF_OBJECT_HH__
+#ifndef __BASE_LOADER_ECOFF_OBJECT_HH__
+#define __BASE_LOADER_ECOFF_OBJECT_HH__
 
 #include "base/loader/object_file.hh"
 
@@ -38,18 +38,21 @@ struct ecoff_exechdr;
 struct ecoff_filehdr;
 struct ecoff_aouthdr;
 
+class EcoffObjectFormat : public ObjectFileFormat
+{
+  public:
+    ObjectFile *load(ImageFileDataPtr data) override;
+};
+
 class EcoffObject : public ObjectFile
 {
   protected:
-    ecoff_exechdr *execHdr;
-    ecoff_filehdr *fileHdr;
-    ecoff_aouthdr *aoutHdr;
-
-    EcoffObject(const std::string &_filename, size_t _len, uint8_t *_data,
-                Arch _arch, OpSys _opSys);
+    const ecoff_exechdr *execHdr;
+    const ecoff_filehdr *fileHdr;
+    const ecoff_aouthdr *aoutHdr;
 
   public:
-    virtual ~EcoffObject() {}
+    EcoffObject(ImageFileDataPtr ifd);
 
     MemoryImage buildImage() const override;
 
@@ -59,9 +62,6 @@ class EcoffObject : public ObjectFile
                            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);
 };
 
-#endif // __ECOFF_OBJECT_HH__
+#endif // __BASE_LOADER_ECOFF_OBJECT_HH__
index 7a83c0bd2151fa18865213dc75dfe8281e97af32..e35c28bd0ccab3be1786ef2773a89ce076faf2be 100644 (file)
 #include "sim/byteswap.hh"
 
 ObjectFile *
-ElfObject::tryFile(const std::string &fname, size_t len, uint8_t *data,
-                   bool skip_interp_check)
+ElfObjectFormat::load(ImageFileDataPtr ifd)
 {
     // check that header matches library version
     if (elf_version(EV_CURRENT) == EV_NONE)
         panic("wrong elf version number!");
 
+    ObjectFile *object = nullptr;
+
     // get a pointer to elf structure
     // Check that we actually have a elf file
-    Elf *elf = elf_memory((char*)data, len);
+    Elf *elf =
+        elf_memory((char *)const_cast<uint8_t *>(ifd->data()), ifd->len());
     assert(elf);
 
     GElf_Ehdr ehdr;
-    if (gelf_getehdr(elf, &ehdr) == 0) {
+    if (gelf_getehdr(elf, &ehdr) == 0)
         DPRINTFR(Loader, "Not ELF\n");
-        elf_end(elf);
-        return NULL;
+    else
+        object = new ElfObject(ifd);
+
+    elf_end(elf);
+
+    return object;
+}
+
+namespace
+{
+
+ElfObjectFormat elfObjectFormat;
+
+} // anonymous namespace
+
+ElfObject::ElfObject(ImageFileDataPtr ifd) : ObjectFile(ifd)
+{
+    // get a pointer to elf structure
+    elf = elf_memory((char *)const_cast<uint8_t *>(imageData->data()),
+                     imageData->len());
+    assert(elf);
+    gelf_getehdr(elf, &ehdr);
+
+    determineArch();
+    determineOpSys();
+
+    entry = ehdr.e_entry;
+    _programHeaderCount = ehdr.e_phnum;
+    _programHeaderSize = ehdr.e_phentsize;
+
+    // Go through all the segments in the program and record them.
+    for (int i = 0; i < ehdr.e_phnum; ++i) {
+        GElf_Phdr phdr;
+        if (gelf_getphdr(elf, i, &phdr) == 0) {
+            panic("gelf_getphdr failed for segment %d.", i);
+        }
+
+        if (phdr.p_type == PT_LOAD)
+            handleLoadableSegment(phdr);
+        if (phdr.p_type == PT_INTERP) {
+            // Make sure the interpreter is an valid ELF file.
+            char *interp_path = (char *)imageData->data() + phdr.p_offset;
+            ObjectFile *obj = createObjectFile(interp_path);
+            interpreter = dynamic_cast<ElfObject *>(obj);
+            assert(interpreter != nullptr);
+        }
     }
 
+    // should have found at least one loadable segment
+    warn_if(image.segments().empty(),
+            "No loadable segments in '%s'. ELF file corrupted?\n",
+            imageData->filename());
+
+    for (auto &seg: image.segments())
+        DPRINTFR(Loader, "%s\n", seg);
+
+    // We will actually read the sections when we need to load them
+}
+
+void
+ElfObject::determineArch()
+{
+    auto &emach = ehdr.e_machine;
+    auto &eclass = ehdr.e_ident[EI_CLASS];
+    auto &edata = ehdr.e_ident[EI_DATA];
+
     // Detect the architecture
-    Arch arch = UnknownArch;
-    if (ehdr.e_machine == EM_SPARC64 ||
-        (ehdr.e_machine == EM_SPARC &&
-         ehdr.e_ident[EI_CLASS] == ELFCLASS64) ||
-        ehdr.e_machine == EM_SPARCV9) {
+    if (emach == EM_SPARC64 || (emach == EM_SPARC && eclass == ELFCLASS64) ||
+        emach == EM_SPARCV9) {
         arch = SPARC64;
-    } else if (ehdr.e_machine == EM_SPARC32PLUS ||
-               (ehdr.e_machine == EM_SPARC &&
-                ehdr.e_ident[EI_CLASS] == ELFCLASS32)) {
+    } else if (emach == EM_SPARC32PLUS ||
+               (emach == EM_SPARC && eclass == ELFCLASS32)) {
         arch = SPARC32;
-    } else if (ehdr.e_machine == EM_MIPS &&
-               ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+    } else if (emach == EM_MIPS && eclass == ELFCLASS32) {
         arch = Mips;
-        if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
+        if (edata != ELFDATA2LSB) {
             fatal("The binary you're trying to load is compiled for big "
                   "endian MIPS. gem5\nonly supports little endian MIPS. "
                   "Please recompile your binary.\n");
         }
-    } else if (ehdr.e_machine == EM_X86_64 &&
-               ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+    } else if (emach == EM_X86_64 && eclass == ELFCLASS64) {
         arch = X86_64;
-    } else if (ehdr.e_machine == EM_386 &&
-               ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+    } else if (emach == EM_386 && eclass == ELFCLASS32) {
         arch = I386;
-    } else if (ehdr.e_machine == EM_ARM &&
-               ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+    } else if (emach == EM_ARM && eclass == ELFCLASS32) {
         arch = bits(ehdr.e_entry, 0) ? Thumb : Arm;
-    } else if (ehdr.e_machine == EM_AARCH64 &&
-               ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+    } else if (emach == EM_AARCH64 && eclass == ELFCLASS64) {
         arch = Arm64;
-    } else if (ehdr.e_machine == EM_RISCV) {
-        arch = (ehdr.e_ident[EI_CLASS] == ELFCLASS64) ? Riscv64 : Riscv32;
-    } else if (ehdr.e_machine == EM_PPC &&
-               ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+    } else if (emach == EM_RISCV) {
+        arch = (eclass == ELFCLASS64) ? Riscv64 : Riscv32;
+    } else if (emach == EM_PPC && eclass == ELFCLASS32) {
         arch = Power;
-        if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB) {
+        if (edata != ELFDATA2MSB) {
             fatal("The binary you're trying to load is compiled for "
                   "little endian Power.\ngem5 only supports big "
                   "endian Power. Please recompile your binary.\n");
         }
-    } else if (ehdr.e_machine == EM_PPC64) {
+    } else if (emach == EM_PPC64) {
         fatal("The binary you're trying to load is compiled for 64-bit "
               "Power. M5\n only supports 32-bit Power. Please "
               "recompile your binary.\n");
-    } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+    } else if (eclass == ELFCLASS64) {
         // Since we don't know how to check for alpha right now, we'll
         // just assume if it wasn't something else and it's 64 bit, that's
         // what it must be.
         arch = Alpha;
     } else {
-        warn("Unknown architecture: %d\n", ehdr.e_machine);
-        arch = UnknownArch;
+        warn("Unknown architecture: %d\n", emach);
     }
+}
 
+void
+ElfObject::determineOpSys()
+{
     // Detect the operating system
-    OpSys op_sys;
     switch (ehdr.e_ident[EI_OSABI]) {
       case ELFOSABI_LINUX:
-        op_sys = Linux;
-        break;
+        opSys = Linux;
+        return;
       case ELFOSABI_SOLARIS:
-        op_sys = Solaris;
-        break;
+        opSys = Solaris;
+        return;
       case ELFOSABI_TRU64:
-        op_sys = Tru64;
-        break;
+        opSys = Tru64;
+        return;
       case ELFOSABI_ARM:
-        op_sys = LinuxArmOABI;
-        break;
+        opSys = LinuxArmOABI;
+        return;
       case ELFOSABI_FREEBSD:
-        op_sys = FreeBSD;
-        break;
+        opSys = FreeBSD;
+        return;
       default:
-        op_sys = UnknownOpSys;
+        opSys = UnknownOpSys;
     }
 
-    // Take a look at the .note.ABI section.
-    // It can let us know what's what.
-    if (op_sys == UnknownOpSys) {
-        int sec_idx = 1;
-
-        // Get the first section
-        Elf_Scn *section = elf_getscn(elf, sec_idx);
-
-        // While there are no more sections
-        while (section && op_sys == UnknownOpSys) {
-            GElf_Shdr shdr;
-            gelf_getshdr(section, &shdr);
-
-            char *e_str = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
-            if (shdr.sh_type == SHT_NOTE &&
-                !strcmp(".note.ABI-tag", e_str)) {
-                // we have found a ABI note section
-                // Check the 5th 32bit word for OS  0 == linux, 1 == hurd,
-                // 2 == solaris, 3 == freebsd
-                Elf_Data *raw_data = elf_rawdata(section, NULL);
-                assert(raw_data && raw_data->d_buf);
-
-                uint32_t raw_abi = ((uint32_t*)raw_data->d_buf)[4];
-                bool is_le = ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
-                uint32_t os_abi = is_le ? htole(raw_abi) : htobe(raw_abi);
-
-                switch (os_abi) {
-                  case 0:
-                    op_sys = Linux;
-                    break;
-                  case 1:
-                    fatal("gem5 does not support the HURD ABI.\n");
-                  case 2:
-                    op_sys = Solaris;
-                    break;
-                  case 3:
-                    op_sys = FreeBSD;
-                    break;
-                }
-            } // if section found
-
-            if (!strcmp(".SUNW_version", e_str) ||
-                !strcmp(".stab.index", e_str))
-                op_sys = Solaris;
-
-            section = elf_getscn(elf, ++sec_idx);
-        } // while sections
-    }
+    Elf_Scn *section = elf_getscn(elf, 1);
+    for (int sec_idx = 1; section; section = elf_getscn(elf, ++sec_idx)) {
+        GElf_Shdr shdr;
+        gelf_getshdr(section, &shdr);
 
-    ElfObject * result = new ElfObject(fname, len, data, arch, op_sys);
-
-    // The number of headers in the file
-    result->_programHeaderCount = ehdr.e_phnum;
-    // Record the size of each entry
-    result->_programHeaderSize = ehdr.e_phentsize;
-    result->_programHeaderTable = 0;
-    if (result->_programHeaderCount) { // If there is a program header table
-        // Figure out the virtual address of the header table in the
-        // final memory image. We use the program headers themselves
-        // to translate from a file offset to the address in the image.
-        GElf_Phdr phdr;
-        uint64_t e_phoff = ehdr.e_phoff;
-
-        for (int i = 0; i < result->_programHeaderCount; i++) {
-            gelf_getphdr(elf, i, &phdr);
-            // Check if we've found the segment with the headers in it
-            if (phdr.p_offset <= e_phoff &&
-                phdr.p_offset + phdr.p_filesz > e_phoff) {
-                result->_programHeaderTable =
-                    phdr.p_paddr + (e_phoff - phdr.p_offset);
-                break;
+        char *e_str = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
+        if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", e_str)) {
+            // we have found a ABI note section
+            // Check the 5th 32bit word for OS  0 == linux, 1 == hurd,
+            // 2 == solaris, 3 == freebsd
+            Elf_Data *raw_data = elf_rawdata(section, nullptr);
+            assert(raw_data && raw_data->d_buf);
+
+            uint32_t raw_abi = ((uint32_t *)raw_data->d_buf)[4];
+            bool is_le = ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
+            uint32_t os_abi = is_le ? htole(raw_abi) : htobe(raw_abi);
+
+            switch (os_abi) {
+              case 0:
+                opSys = Linux;
+                return;
+              case 1:
+                fatal("gem5 does not support the HURD ABI.\n");
+              case 2:
+                opSys = Solaris;
+                return;
+              case 3:
+                opSys = FreeBSD;
+                return;
             }
         }
-    }
 
-    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;
+        if (!strcmp(".SUNW_version", e_str) || !strcmp(".stab.index", e_str)) {
+            opSys = Solaris;
+            return;
         }
     }
-
-    elf_end(elf);
-    return result;
 }
 
-ElfObject::ElfObject(const std::string &_filename, size_t _len,
-                     uint8_t *_data, Arch _arch, OpSys _op_sys)
-    : ObjectFile(_filename, _len, _data, _arch, _op_sys),
-      _programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0),
-      interpreter(nullptr), ldBias(0), relocate(true),
-      ldMin(std::numeric_limits<Addr>::max()),
-      ldMax(std::numeric_limits<Addr>::min())
+void
+ElfObject::handleLoadableSegment(GElf_Phdr phdr)
 {
-    // check that header matches library version
-    if (elf_version(EV_CURRENT) == EV_NONE)
-        panic("wrong elf version number!");
+    Addr mem_start = phdr.p_vaddr;
+    Addr mem_end = mem_start + phdr.p_memsz;
+    Addr file_start = phdr.p_offset;
+    Addr file_end = file_start + phdr.p_filesz;
 
-    // get a pointer to elf structure
-    Elf *elf = elf_memory((char*)fileData,len);
-    assert(elf);
+    std::string name;
 
-    // Check that we actually have a elf file
-    GElf_Ehdr ehdr;
-    if (gelf_getehdr(elf, &ehdr) ==0) {
-        panic("Not ELF, shouldn't be here");
-    }
-
-    entry = ehdr.e_entry;
-
-    int sec_idx = 1;
-
-    // Go through all the segments in the program, record them, and scrape
-    // out information about the text, data, and bss areas needed by other
-    // code.
-    for (int i = 0; i < ehdr.e_phnum; ++i) {
-        GElf_Phdr phdr;
-        if (gelf_getphdr(elf, i, &phdr) == 0) {
-            panic("gelf_getphdr failed for segment %d.", i);
-        }
-
-        // for now we don't care about non-loadable segments
-        if (phdr.p_type != PT_LOAD)
-            continue;
-
-        ldMin = std::min(ldMin, phdr.p_vaddr);
-        ldMax = std::max(ldMax, phdr.p_vaddr + phdr.p_memsz);
-
-        std::string name;
-
-        // Get the first section
-        Elf_Scn *section = elf_getscn(elf, sec_idx);
-
-        // Name segments after the sections they contain.
-        while (section) {
-            GElf_Shdr shdr;
-            gelf_getshdr(section, &shdr);
-            char *sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
-
-            if (!sec_name) {
-                Elf_Error errorNum = (Elf_Error)elf_errno();
-                if (errorNum != ELF_E_NONE) {
-                    const char *errorMessage = elf_errmsg(errorNum);
-                    fatal("Error from libelf: %s.\n", errorMessage);
-                }
-            }
+    // Name segments after the sections they contain.
+    Elf_Scn *section = elf_getscn(elf, 1);
+    for (int sec_idx = 1; section; section = elf_getscn(elf, ++sec_idx)) {
+        GElf_Shdr shdr;
+        gelf_getshdr(section, &shdr);
+        char *sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
 
-            if (shdr.sh_addr >= ldMin && shdr.sh_addr < ldMax) {
-                if (name != "")
-                    name += ",";
-                name += sec_name;
+        if (!sec_name) {
+            Elf_Error errorNum = (Elf_Error)elf_errno();
+            if (errorNum != ELF_E_NONE) {
+                const char *errorMessage = elf_errmsg(errorNum);
+                fatal("Error from libelf: %s.\n", errorMessage);
             }
-
-            section = elf_getscn(elf, ++sec_idx);
         }
 
-        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.
-            image.addSegment(name + "(uninitialized)",
-                    phdr.p_paddr + phdr.p_filesz, nullptr, uninitialized);
+        if (shdr.sh_addr >= mem_start && shdr.sh_addr < mem_end) {
+            if (name != "")
+                name += ",";
+            name += sec_name;
         }
     }
 
-    // should have found at least one loadable segment
-    warn_if(image.segments().empty(),
-            "No loadable segments in '%s'. ELF file corrupted?\n", filename);
+    image.addSegment({ name, phdr.p_paddr, imageData,
+                       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.
+        image.addSegment({ name + "(uninitialized)",
+                           phdr.p_paddr + phdr.p_filesz, uninitialized });
+    }
 
-    for (auto &seg: image.segments())
-        DPRINTFR(Loader, "%s\n", seg);
+    // If there is a program header table, figure out the virtual
+    // address of the header table in the final memory image. We use
+    // the program headers themselves to translate from a file offset
+    // to the address in the image.
+    if (file_start <= ehdr.e_phoff && file_end > ehdr.e_phoff)
+        _programHeaderTable = mem_start + (ehdr.e_phoff - file_start);
+}
 
+ElfObject::~ElfObject()
+{
     elf_end(elf);
-
-    // We will actually read the sections when we need to load them
 }
 
-
 bool
 ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask,
                            Addr base, Addr offset)
@@ -377,7 +321,8 @@ ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask,
         panic("wrong elf version number!");
 
     // get a pointer to elf structure
-    Elf *elf = elf_memory((char*)fileData,len);
+    Elf *elf = elf_memory((char *)const_cast<uint8_t *>(
+                imageData->data()), imageData->len());
     assert(elf != NULL);
 
     // Get the first section
@@ -401,7 +346,8 @@ ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask,
                 GElf_Sym sym;
                 gelf_getsym(data, i, &sym);
                 if (GELF_ST_BIND(sym.st_info) == binding) {
-                    char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
+                    char *sym_name =
+                        elf_strptr(elf, shdr.sh_link, sym.st_name);
                     if (sym_name && sym_name[0] != '$') {
                         Addr value = sym.st_value - base + offset;
                         if (symtab->insert(value & mask, sym_name)) {
@@ -473,7 +419,9 @@ ElfObject::getSections()
         panic("wrong elf version number!");
 
     // get a pointer to elf structure
-    Elf *elf = elf_memory((char*)fileData,len);
+    Elf *elf =
+        elf_memory((char *)const_cast<uint8_t *>(imageData->data()),
+                imageData->len());
     assert(elf != NULL);
 
     // Check that we actually have a elf file
index 0b8c79b4731e6ceeea0ec7270f0964a68079f2fa..42edc7438c4df725dc8a19d9e5debc0e0f9ce2ad 100644 (file)
  * Authors: Steve Reinhardt
  */
 
-#ifndef __ELF_OBJECT_HH__
-#define __ELF_OBJECT_HH__
+#ifndef __BASE_LOADER_ELF_OBJECT_HH__
+#define __BASE_LOADER_ELF_OBJECT_HH__
 
 #include <set>
 #include <vector>
 
 #include "base/loader/object_file.hh"
+#include "gelf.h"
+
+class ElfObjectFormat : public ObjectFileFormat
+{
+  public:
+    ObjectFile *load(ImageFileDataPtr data) override;
+};
 
 class ElfObject : public ObjectFile
 {
   protected:
+    Elf *elf;
+    GElf_Ehdr ehdr;
+
+    void determineArch();
+    void determineOpSys();
+    void handleLoadableSegment(GElf_Phdr phdr);
+
     // These values are provided to a linux process by the kernel, so we
     // need to keep them around.
-    Addr _programHeaderTable;
-    uint16_t _programHeaderSize;
-    uint16_t _programHeaderCount;
+    Addr _programHeaderTable = 0;
+    uint16_t _programHeaderSize = 0;
+    uint16_t _programHeaderCount = 0;
     std::set<std::string> sectionNames;
 
-    ElfObject *interpreter;
+    ElfObject *interpreter = nullptr;
 
     // 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;
+    Addr ldBias = 0;
 
     // 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;
+    bool relocate = true;
 
     // The ldMin and ldMax fields are required to know how large of an
     // area is required to map the interpreter.
-    Addr ldMin;
-    Addr ldMax;
+    Addr ldMin = MaxAddr;
+    Addr ldMax = MaxAddr;
 
     /// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
     bool loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask,
                          Addr base, Addr offset);
 
-    ElfObject(const std::string &_filename, size_t _len, uint8_t *_data,
-              Arch _arch, OpSys _opSys);
-
     void getSections();
     bool sectionExists(std::string sec);
 
     MemoryImage image;
 
   public:
-    virtual ~ElfObject() {}
+    ElfObject(ImageFileDataPtr ifd);
+    ~ElfObject();
 
     MemoryImage buildImage() const override { return image; }
 
@@ -111,12 +123,9 @@ class ElfObject : public ObjectFile
 
     bool hasTLS() override { return sectionExists(".tbss"); }
 
-    static ObjectFile *tryFile(const std::string &fname,
-                               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;}
 };
 
-#endif // __ELF_OBJECT_HH__
+#endif // __BASE_LOADER_ELF_OBJECT_HH__
diff --git a/src/base/loader/image_file.hh b/src/base/loader/image_file.hh
new file mode 100644 (file)
index 0000000..79d31a4
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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_IMAGE_FILE_HH__
+#define __BASE_LOADER_IMAGE_FILE_HH__
+
+#include <cstdint>
+#include <string>
+
+#include "base/loader/image_file_data.hh"
+#include "base/loader/memory_image.hh"
+
+class ImageFile
+{
+  protected:
+    ImageFileDataPtr imageData;
+    ImageFile(ImageFileDataPtr data) : imageData(data) {}
+    virtual ~ImageFile() {}
+
+  public:
+    virtual MemoryImage buildImage() const = 0;
+};
+
+#endif // __BASE_LOADER_IMAGE_FILE_HH__
diff --git a/src/base/loader/image_file_data.cc b/src/base/loader/image_file_data.cc
new file mode 100644 (file)
index 0000000..12cba77
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * 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/image_file_data.hh"
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include <cstdio>
+#include <vector>
+
+#include "base/logging.hh"
+
+static bool
+hasGzipMagic(int fd)
+{
+    uint8_t buf[2] = {0};
+    size_t sz = pread(fd, buf, 2, 0);
+    panic_if(sz != 2, "Couldn't read magic bytes from object file");
+    return ((buf[0] == 0x1f) && (buf[1] == 0x8b));
+}
+
+static int
+doGzipLoad(int fd)
+{
+    const size_t blk_sz = 4096;
+
+    gzFile fdz = gzdopen(fd, "rb");
+    if (!fdz) {
+        return -1;
+    }
+
+    size_t tmp_len = strlen(P_tmpdir);
+    char *tmpnam = (char*) malloc(tmp_len + 20);
+    strcpy(tmpnam, P_tmpdir);
+    strcpy(tmpnam+tmp_len, "/gem5-gz-obj-XXXXXX"); // 19 chars
+    fd = mkstemp(tmpnam); // repurposing fd variable for output
+    if (fd < 0) {
+        free(tmpnam);
+        gzclose(fdz);
+        return fd;
+    }
+
+    if (unlink(tmpnam) != 0)
+        warn("couldn't remove temporary file %s\n", tmpnam);
+
+    free(tmpnam);
+
+    auto buf = new uint8_t[blk_sz];
+    int r; // size of (r)emaining uncopied data in (buf)fer
+    while ((r = gzread(fdz, buf, blk_sz)) > 0) {
+        auto p = buf; // pointer into buffer
+        while (r > 0) {
+            auto sz = write(fd, p, r);
+            assert(sz <= r);
+            r -= sz;
+            p += sz;
+        }
+    }
+    delete[] buf;
+    gzclose(fdz);
+    if (r < 0) { // error
+        close(fd);
+        return -1;
+    }
+    assert(r == 0); // finished successfully
+    return fd; // return fd to decompressed temporary file for mmap()'ing
+}
+
+ImageFileData::ImageFileData(const std::string &fname)
+{
+    _filename = fname;
+
+    // Open the file.
+    int fd = open(fname.c_str(), O_RDONLY);
+    panic_if(fd < 0, "Failed to open file %s.\n", fname);
+
+    // Decompress GZ files.
+    if (hasGzipMagic(fd)) {
+        fd = doGzipLoad(fd);
+        panic_if(fd < 0, "Failed to unzip file %s.\n", fname);
+    }
+
+    // Find the length of the file by seeking to the end.
+    off_t off = lseek(fd, 0, SEEK_END);
+    fatal_if(off < 0, "Failed to determine size of file %s.\n", fname);
+    _len = static_cast<size_t>(off);
+
+    // Mmap the whole shebang.
+    _data = (uint8_t *)mmap(NULL, _len, PROT_READ, MAP_SHARED, fd, 0);
+    close(fd);
+
+    panic_if(_data == MAP_FAILED, "Failed to mmap file %s.\n", fname);
+}
+
+ImageFileData::~ImageFileData()
+{
+    munmap((void *)_data, _len);
+}
diff --git a/src/base/loader/image_file_data.hh b/src/base/loader/image_file_data.hh
new file mode 100644 (file)
index 0000000..8810ae4
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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_IMAGE_FILE_DATA_HH__
+#define __BASE_LOADER_IMAGE_FILE_DATA_HH__
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+class ImageFileData
+{
+  private:
+    std::string _filename;
+    uint8_t *_data;
+    size_t _len;
+
+  public:
+    const std::string &filename() const { return _filename; }
+    uint8_t const *data() const { return _data; }
+    size_t len() const { return _len; }
+
+    ImageFileData(const std::string &f_name);
+    virtual ~ImageFileData();
+};
+
+typedef std::shared_ptr<ImageFileData> ImageFileDataPtr;
+
+#endif // __BASE_LOADER_IMAGE_FILE_DATA_HH__
index 866e9560cf55b7be874e01c56e27aa3712ed6674..a10daba6c0673792c51498b4999b66fd5ac51036 100644 (file)
 #ifndef __BASE_LOADER_MEMORY_IMAGE_HH__
 #define __BASE_LOADER_MEMORY_IMAGE_HH__
 
+#include <algorithm>
 #include <functional>
 #include <initializer_list>
 #include <memory>
 #include <string>
 #include <vector>
 
+#include "base/loader/image_file_data.hh"
 #include "base/logging.hh"
 #include "base/types.hh"
 
 class PortProxy;
-class Process;
-class ProcessParams;
-class SymbolTable;
 
 class MemoryImage
 {
   public:
     struct Segment
     {
+        Segment(const std::string &_name, Addr _base,
+                const uint8_t *_data, size_t _size) :
+            name(_name), base(_base), data(_data), size(_size)
+        {}
+
+        Segment(const std::string &_name, Addr _base, size_t _size) :
+            name(_name), base(_base), size(_size)
+        {}
+
+        Segment(const std::string &_name, Addr _base,
+                const ImageFileDataPtr &_ifd, Addr offset, size_t _size) :
+            ifd(_ifd), name(_name), base(_base), size(_size)
+        {
+            panic_if(offset + size > ifd->len(),
+                    "Segment outside the bounds of the image data");
+            data = ifd->data() + offset;
+        }
+
+        Segment(const std::string &_name, const ImageFileDataPtr &_ifd) :
+            Segment(_name, 0, _ifd, 0, _ifd->len())
+        {}
+
+        ImageFileDataPtr ifd;
         std::string name;
-        Addr base;
-        uint8_t *data;
-        size_t size;
+        Addr base = 0;
+        const uint8_t *data = nullptr;
+        size_t size = 0;
     };
 
     MemoryImage() {}
 
-    MemoryImage(std::initializer_list<Segment> new_segs)
+    MemoryImage(const Segment &seg)
     {
-        for (auto &seg: new_segs)
-            addSegment(seg);
+        addSegment(seg);
+    }
+
+    MemoryImage(std::initializer_list<Segment> segs)
+    {
+        addSegments(segs);
     }
 
   private:
@@ -83,9 +109,10 @@ class MemoryImage
     }
 
     void
-    addSegment(std::string name, Addr base, uint8_t *data, size_t size)
+    addSegments(std::initializer_list<Segment> segs)
     {
-        _segments.push_back(Segment({name, base, data, size}));
+        for (auto &seg: segs)
+            addSegment(seg);
     }
 
     bool write(const PortProxy &proxy) const;
@@ -104,11 +131,8 @@ class MemoryImage
     maxAddr() const
     {
         Addr max = 0;
-        for (auto &seg: _segments) {
-            Addr end = seg.base + seg.size;
-            if (end > max)
-                max = end;
-        }
+        for (auto &seg: _segments)
+            max = std::max(max, seg.base + seg.size);
         return max;
     }
 
@@ -117,8 +141,7 @@ class MemoryImage
     {
         Addr min = MaxAddr;
         for (auto &seg: _segments)
-            if (seg.base < min)
-                min = seg.base;
+            min = std::min(min, seg.base);
         return min;
     }
 
index afecd21e322c8d2f58967cb014ceb5b2ff3907b8..b7e05428c42bbe25b3f08e9c02241f3990805635 100644 (file)
 
 #include "base/loader/object_file.hh"
 
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <zlib.h>
-
-#include <cstdio>
-#include <list>
 #include <string>
 #include <vector>
 
-#include "base/cprintf.hh"
-#include "base/loader/aout_object.hh"
-#include "base/loader/dtb_object.hh"
-#include "base/loader/ecoff_object.hh"
-#include "base/loader/elf_object.hh"
-#include "base/loader/raw_object.hh"
+#include "base/loader/raw_image.hh"
 #include "base/loader/symtab.hh"
 #include "mem/port_proxy.hh"
 
 using namespace std;
 
-ObjectFile::ObjectFile(const string &_filename,
-                       size_t _len, uint8_t *_data,
-                       Arch _arch, OpSys _op_sys)
-    : filename(_filename), fileData(_data), len(_len),
-      arch(_arch), opSys(_op_sys), entry(0)
-{}
-
-
-ObjectFile::~ObjectFile()
-{
-    if (fileData) {
-        ::munmap((char*)fileData, len);
-        fileData = NULL;
-    }
-}
-
+ObjectFile::ObjectFile(ImageFileDataPtr ifd) : ImageFile(ifd) {}
 
 namespace
 {
@@ -101,117 +73,37 @@ ObjectFile::tryLoaders(ProcessParams *params, ObjectFile *obj_file)
     return nullptr;
 }
 
-static bool
-hasGzipMagic(int fd)
-{
-    uint8_t buf[2] = {0};
-    size_t sz = pread(fd, buf, 2, 0);
-    panic_if(sz != 2, "Couldn't read magic bytes from object file");
-    return ((buf[0] == 0x1f) && (buf[1] == 0x8b));
-}
+namespace {
 
-static int
-doGzipLoad(int fd)
-{
-    const size_t blk_sz = 4096;
+typedef std::vector<ObjectFileFormat *> ObjectFileFormatList;
 
-    gzFile fdz = gzdopen(fd, "rb");
-    if (!fdz) {
-        return -1;
-    }
+ObjectFileFormatList &
+object_file_formats()
+{
+    static ObjectFileFormatList formats;
+    return formats;
+}
 
-    size_t tmp_len = strlen(P_tmpdir);
-    char *tmpnam = (char*) malloc(tmp_len + 20);
-    strcpy(tmpnam, P_tmpdir);
-    strcpy(tmpnam+tmp_len, "/gem5-gz-obj-XXXXXX"); // 19 chars
-    fd = mkstemp(tmpnam); // repurposing fd variable for output
-    if (fd < 0) {
-        free(tmpnam);
-        gzclose(fdz);
-        return fd;
-    }
+} // anonymous namespace
 
-    if (unlink(tmpnam) != 0)
-        warn("couldn't remove temporary file %s\n", tmpnam);
-
-    free(tmpnam);
-
-    auto buf = new uint8_t[blk_sz];
-    int r; // size of (r)emaining uncopied data in (buf)fer
-    while ((r = gzread(fdz, buf, blk_sz)) > 0) {
-        auto p = buf; // pointer into buffer
-        while (r > 0) {
-            auto sz = write(fd, p, r);
-            assert(sz <= r);
-            r -= sz;
-            p += sz;
-        }
-    }
-    delete[] buf;
-    gzclose(fdz);
-    if (r < 0) { // error
-        close(fd);
-        return -1;
-    }
-    assert(r == 0); // finished successfully
-    return fd; // return fd to decompressed temporary file for mmap()'ing
+ObjectFileFormat::ObjectFileFormat()
+{
+    object_file_formats().emplace_back(this);
 }
 
 ObjectFile *
-createObjectFile(const string &fname, bool raw)
+createObjectFile(const std::string &fname, bool raw)
 {
-    // open the file
-    int fd = open(fname.c_str(), O_RDONLY);
-    if (fd < 0) {
-        return NULL;
-    }
-
-    // decompress GZ files
-    if (hasGzipMagic(fd)) {
-        fd = doGzipLoad(fd);
-        if (fd < 0) {
-            return NULL;
-        }
-    }
-
-    // find the length of the file by seeking to the end
-    off_t off = lseek(fd, 0, SEEK_END);
-    fatal_if(off < 0,
-             "Failed to determine size of object file %s\n", fname);
-    auto len = static_cast<size_t>(off);
-
-    // mmap the whole shebang
-    uint8_t *file_data = (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED,
-                                         fd, 0);
-    close(fd);
-
-    if (file_data == MAP_FAILED) {
-        return NULL;
-    }
+    ImageFileDataPtr ifd(new ImageFileData(fname));
 
-    ObjectFile *file_obj = NULL;
-
-    // figure out what we have here
-    if ((file_obj = ElfObject::tryFile(fname, len, file_data)) != NULL) {
-        return file_obj;
-    }
-
-    if ((file_obj = EcoffObject::tryFile(fname, len, file_data)) != NULL) {
-        return file_obj;
-    }
-
-    if ((file_obj = AoutObject::tryFile(fname, len, file_data)) != NULL) {
-        return file_obj;
-    }
-
-    if ((file_obj = DtbObject::tryFile(fname, len, file_data)) != NULL) {
-        return file_obj;
+    for (auto &format: object_file_formats()) {
+        ObjectFile *file_obj = format->load(ifd);
+        if (file_obj)
+            return file_obj;
     }
 
     if (raw)
-        return RawObject::tryFile(fname, len, file_data);
+        return new RawImage(ifd);
 
-    // don't know what it is
-    munmap((char*)file_data, len);
-    return NULL;
+    return nullptr;
 }
index 669afeb11643a747e6425ee9da2e45ce7f7da8df..da35db14822ebff51584603f3a42f3f05502d839 100644 (file)
  *          Steve Reinhardt
  */
 
-#ifndef __OBJECT_FILE_HH__
-#define __OBJECT_FILE_HH__
+#ifndef __BASE_LOADER_OBJECT_FILE_HH__
+#define __BASE_LOADER_OBJECT_FILE_HH__
 
-#include <limits>
-#include <memory>
 #include <string>
-#include <vector>
 
+#include "base/loader/image_file.hh"
+#include "base/loader/image_file_data.hh"
 #include "base/loader/memory_image.hh"
 #include "base/logging.hh"
 #include "base/types.hh"
 
-class PortProxy;
 class Process;
 class ProcessParams;
 class SymbolTable;
 
-class ObjectFile
+class ObjectFile : public ImageFile
 {
   public:
 
@@ -76,37 +74,51 @@ class ObjectFile
     };
 
   protected:
-    const std::string filename;
-    uint8_t *fileData;
-    size_t len;
+    Arch arch = UnknownArch;
+    OpSys opSys = UnknownOpSys;
 
-    Arch arch;
-    OpSys opSys;
-
-    ObjectFile(const std::string &_filename, size_t _len, uint8_t *_data,
-               Arch _arch, OpSys _opSys);
+    ObjectFile(ImageFileDataPtr ifd);
 
   public:
-    virtual ~ObjectFile();
-
-    virtual MemoryImage buildImage() const = 0;
+    virtual ~ObjectFile() {};
 
-    virtual bool loadAllSymbols(SymbolTable *symtab, Addr base = 0,
-                                Addr offset=0, Addr mask=MaxAddr) = 0;
-    virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr base = 0,
-                                   Addr offset=0, Addr mask=MaxAddr) = 0;
-    virtual bool loadLocalSymbols(SymbolTable *symtab, Addr base=0,
-                                  Addr offset=0, Addr mask=MaxAddr) = 0;
-    virtual bool loadWeakSymbols(SymbolTable *symtab, Addr base=0,
-                                 Addr offset=0, Addr mask=MaxAddr)
-    { return false; }
+    virtual bool
+    loadAllSymbols(SymbolTable *symtab, Addr base=0,
+            Addr offset=0, Addr mask=MaxAddr)
+    {
+        return true;
+    };
+    virtual bool
+    loadGlobalSymbols(SymbolTable *symtab, Addr base=0,
+                      Addr offset=0, Addr mask=MaxAddr)
+    {
+        return true;
+    }
+    virtual bool
+    loadLocalSymbols(SymbolTable *symtab, Addr base=0,
+                     Addr offset=0, Addr mask=MaxAddr)
+    {
+        return true;
+    }
+    virtual bool
+    loadWeakSymbols(SymbolTable *symtab, Addr base=0,
+                    Addr offset=0, Addr mask=MaxAddr)
+    {
+        return true;
+    }
 
     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
+    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; }
@@ -115,7 +127,7 @@ class ObjectFile
     OpSys getOpSys() const { return opSys; }
 
   protected:
-    Addr entry;
+    Addr entry = 0;
 
   public:
     Addr entryPoint() const { return entry; }
@@ -153,7 +165,18 @@ class ObjectFile
     static Process *tryLoaders(ProcessParams *params, ObjectFile *obj_file);
 };
 
-ObjectFile *createObjectFile(const std::string &fname, bool raw = false);
+class ObjectFileFormat
+{
+  protected:
+    ObjectFileFormat();
+
+  public:
+    ObjectFileFormat(const ObjectFileFormat &) = delete;
+    void operator=(const ObjectFileFormat &) = delete;
+
+    virtual ObjectFile *load(ImageFileDataPtr data) = 0;
+};
 
+ObjectFile *createObjectFile(const std::string &fname, bool raw=false);
 
-#endif // __OBJECT_FILE_HH__
+#endif // __BASE_LOADER_OBJECT_FILE_HH__
diff --git a/src/base/loader/raw_image.hh b/src/base/loader/raw_image.hh
new file mode 100644 (file)
index 0000000..aae82a3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2006 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: Ali Saidi
+ */
+
+#ifndef __BASE_LOADER_RAW_IMAGE_HH__
+#define __BASE_LOADER_RAW_IMAGE_HH__
+
+#include "base/loader/object_file.hh"
+
+class RawImage: public ObjectFile
+{
+  public:
+    RawImage(ImageFileDataPtr ifd) : ObjectFile(ifd) {}
+
+    RawImage(const std::string &filename) :
+        RawImage(ImageFileDataPtr(new ImageFileData(filename)))
+    {}
+
+    MemoryImage
+    buildImage() const override
+    {
+        return {{ "data", imageData }};
+    }
+};
+
+
+
+#endif // __BASE_LOADER_RAW_IMAGE_HH__
diff --git a/src/base/loader/raw_object.cc b/src/base/loader/raw_object.cc
deleted file mode 100644 (file)
index 35ed485..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2006 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: Steve Reinhardt
- */
-
-#include "base/loader/raw_object.hh"
-
-#include "base/loader/symtab.hh"
-#include "base/trace.hh"
-#include "debug/Loader.hh"
-
-ObjectFile *
-RawObject::tryFile(const std::string &fname, size_t len, uint8_t *data)
-{
-    return new RawObject(fname, len, data, ObjectFile::UnknownArch,
-            ObjectFile::UnknownOpSys);
-}
-
-RawObject::RawObject(const std::string &_filename, size_t _len,
-        uint8_t *_data, Arch _arch, OpSys _opSys)
-    : ObjectFile(_filename, _len, _data, _arch, _opSys)
-{
-}
-
-MemoryImage
-RawObject::buildImage() const
-{
-    return {{ "data", 0, fileData, len }};
-}
-
-bool
-RawObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                          Addr addr_mask)
-{
-    return true;
-}
-
-bool
-RawObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                             Addr addr_mask)
-{
-    return true;
-}
-
-bool
-RawObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
-                            Addr addr_mask)
-{
-    return true;
-}
diff --git a/src/base/loader/raw_object.hh b/src/base/loader/raw_object.hh
deleted file mode 100644 (file)
index 6dc54c7..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2006 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: Ali Saidi
- */
-
-#ifndef __BASE_LOADER_RAW_OBJECT_HH__
-#define __BASE_LOADER_RAW_OBJECT_HH__
-
-#include "base/loader/object_file.hh"
-
-class RawObject: public ObjectFile
-{
-  protected:
-    RawObject(const std::string &_filename, size_t _len,
-              uint8_t *_data, Arch _arch, OpSys _opSys);
-
-  public:
-    virtual ~RawObject() {}
-
-    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);
-};
-
-
-
-#endif // __BASE_LOADER_RAW_OBJECT_HH__