summaryrefslogtreecommitdiff
path: root/src/base/loader/image_file_data.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/loader/image_file_data.cc')
-rw-r--r--src/base/loader/image_file_data.cc130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/base/loader/image_file_data.cc b/src/base/loader/image_file_data.cc
new file mode 100644
index 000000000..12cba77e0
--- /dev/null
+++ b/src/base/loader/image_file_data.cc
@@ -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);
+}