#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"
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);
#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"
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().
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')
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;
}
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__
--- /dev/null
+/*
+ * 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 }};
+}
--- /dev/null
+/*
+ * 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__
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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__
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())
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);
}
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)
}
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);
}
* 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"
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;
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__
#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)
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
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)) {
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
* 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; }
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__
--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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__
#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:
}
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;
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;
}
{
Addr min = MaxAddr;
for (auto &seg: _segments)
- if (seg.base < min)
- min = seg.base;
+ min = std::min(min, seg.base);
return min;
}
#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
{
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;
}
* 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:
};
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; }
OpSys getOpSys() const { return opSys; }
protected:
- Addr entry;
+ Addr entry = 0;
public:
Addr entryPoint() const { return entry; }
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__
--- /dev/null
+/*
+ * 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__
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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__