object_file.cc revision 11391
12SN/A/*
21762SN/A * Copyright (c) 2002-2004 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
292665Ssaidi@eecs.umich.edu *          Steve Reinhardt
302SN/A */
312SN/A
328229Snate@binkert.org#include <sys/mman.h>
338229Snate@binkert.org#include <sys/types.h>
348229Snate@binkert.org#include <fcntl.h>
358229Snate@binkert.org#include <unistd.h>
3611354SCurtis.Dunham@arm.com#include <zlib.h>
378229Snate@binkert.org
388229Snate@binkert.org#include <cstdio>
392SN/A#include <list>
402SN/A#include <string>
412SN/A
428229Snate@binkert.org#include "base/loader/aout_object.hh"
439538Satgutier@umich.edu#include "base/loader/dtb_object.hh"
448229Snate@binkert.org#include "base/loader/ecoff_object.hh"
458229Snate@binkert.org#include "base/loader/elf_object.hh"
468229Snate@binkert.org#include "base/loader/object_file.hh"
478229Snate@binkert.org#include "base/loader/raw_object.hh"
488229Snate@binkert.org#include "base/loader/symtab.hh"
4956SN/A#include "base/cprintf.hh"
508706Sandreas.hansson@arm.com#include "mem/port_proxy.hh"
512420SN/A
522SN/Ausing namespace std;
532SN/A
5410880SCurtis.Dunham@arm.comObjectFile::ObjectFile(const string &_filename,
55360SN/A                       size_t _len, uint8_t *_data,
5611391Sbrandon.potter@amd.com                       Arch _arch, OpSys _op_sys)
5710880SCurtis.Dunham@arm.com    : filename(_filename), fileData(_data), len(_len),
5811391Sbrandon.potter@amd.com      arch(_arch), opSys(_op_sys), entry(0), globalPtr(0),
5910422Sandreas.hansson@arm.com      text{0, nullptr, 0}, data{0, nullptr, 0}, bss{0, nullptr, 0}
6012SN/A{
6112SN/A}
622SN/A
632SN/A
642SN/AObjectFile::~ObjectFile()
652SN/A{
6611391Sbrandon.potter@amd.com    if (fileData) {
6711391Sbrandon.potter@amd.com        ::munmap((char*)fileData, len);
6811391Sbrandon.potter@amd.com        fileData = NULL;
6911391Sbrandon.potter@amd.com    }
7012SN/A}
712SN/A
722SN/A
732420SN/Abool
7411391Sbrandon.potter@amd.comObjectFile::loadSection(Section *sec, PortProxy& mem_proxy, Addr addr_mask,
7511391Sbrandon.potter@amd.com                        Addr offset)
762420SN/A{
772420SN/A    if (sec->size != 0) {
7811391Sbrandon.potter@amd.com        Addr addr = (sec->baseAddr & addr_mask) + offset;
792420SN/A        if (sec->fileImage) {
8011391Sbrandon.potter@amd.com            mem_proxy.writeBlob(addr, sec->fileImage, sec->size);
812420SN/A        }
822420SN/A        else {
832420SN/A            // no image: must be bss
8411391Sbrandon.potter@amd.com            mem_proxy.memsetBlob(addr, 0, sec->size);
852420SN/A        }
862420SN/A    }
872420SN/A    return true;
882420SN/A}
892420SN/A
902420SN/A
912420SN/Abool
9211391Sbrandon.potter@amd.comObjectFile::loadSections(PortProxy& mem_proxy, Addr addr_mask, Addr offset)
932420SN/A{
9411391Sbrandon.potter@amd.com    return (loadSection(&text, mem_proxy, addr_mask, offset)
9511391Sbrandon.potter@amd.com            && loadSection(&data, mem_proxy, addr_mask, offset)
9611391Sbrandon.potter@amd.com            && loadSection(&bss, mem_proxy, addr_mask, offset));
972SN/A}
982SN/A
9911354SCurtis.Dunham@arm.comstatic bool
10011354SCurtis.Dunham@arm.comhasGzipMagic(int fd)
10111354SCurtis.Dunham@arm.com{
10211354SCurtis.Dunham@arm.com    uint8_t buf[2] = {0};
10311354SCurtis.Dunham@arm.com    size_t sz = pread(fd, buf, 2, 0);
10411354SCurtis.Dunham@arm.com    panic_if(sz != 2, "Couldn't read magic bytes from object file");
10511354SCurtis.Dunham@arm.com    return ((buf[0] == 0x1f) && (buf[1] == 0x8b));
10611354SCurtis.Dunham@arm.com}
10711354SCurtis.Dunham@arm.com
10811354SCurtis.Dunham@arm.comstatic int
10911354SCurtis.Dunham@arm.comdoGzipLoad(int fd)
11011354SCurtis.Dunham@arm.com{
11111354SCurtis.Dunham@arm.com    const size_t blk_sz = 4096;
11211354SCurtis.Dunham@arm.com
11311354SCurtis.Dunham@arm.com    gzFile fdz = gzdopen(fd, "rb");
11411354SCurtis.Dunham@arm.com    if (!fdz) {
11511354SCurtis.Dunham@arm.com        return -1;
11611354SCurtis.Dunham@arm.com    }
11711354SCurtis.Dunham@arm.com
11811354SCurtis.Dunham@arm.com    size_t tmp_len = strlen(P_tmpdir);
11911354SCurtis.Dunham@arm.com    char *tmpnam = (char*) malloc(tmp_len + 20);
12011354SCurtis.Dunham@arm.com    strcpy(tmpnam, P_tmpdir);
12111354SCurtis.Dunham@arm.com    strcpy(tmpnam+tmp_len, "/gem5-gz-obj-XXXXXX"); // 19 chars
12211354SCurtis.Dunham@arm.com    fd = mkstemp(tmpnam); // repurposing fd variable for output
12311354SCurtis.Dunham@arm.com    if (fd < 0) {
12411354SCurtis.Dunham@arm.com        free(tmpnam);
12511354SCurtis.Dunham@arm.com        gzclose(fdz);
12611354SCurtis.Dunham@arm.com        return fd;
12711354SCurtis.Dunham@arm.com    }
12811354SCurtis.Dunham@arm.com
12911354SCurtis.Dunham@arm.com    if (unlink(tmpnam) != 0)
13011354SCurtis.Dunham@arm.com        warn("couldn't remove temporary file %s\n", tmpnam);
13111354SCurtis.Dunham@arm.com
13211354SCurtis.Dunham@arm.com    free(tmpnam);
13311354SCurtis.Dunham@arm.com
13411354SCurtis.Dunham@arm.com    auto buf = new uint8_t[blk_sz];
13511354SCurtis.Dunham@arm.com    int r; // size of (r)emaining uncopied data in (buf)fer
13611354SCurtis.Dunham@arm.com    while ((r = gzread(fdz, buf, blk_sz)) > 0) {
13711354SCurtis.Dunham@arm.com        auto p = buf; // pointer into buffer
13811354SCurtis.Dunham@arm.com        while (r > 0) {
13911354SCurtis.Dunham@arm.com            auto sz = write(fd, p, r);
14011354SCurtis.Dunham@arm.com            assert(sz <= r);
14111354SCurtis.Dunham@arm.com            r -= sz;
14211354SCurtis.Dunham@arm.com            p += sz;
14311354SCurtis.Dunham@arm.com        }
14411354SCurtis.Dunham@arm.com    }
14511354SCurtis.Dunham@arm.com    delete[] buf;
14611354SCurtis.Dunham@arm.com    gzclose(fdz);
14711354SCurtis.Dunham@arm.com    if (r < 0) { // error
14811354SCurtis.Dunham@arm.com        close(fd);
14911354SCurtis.Dunham@arm.com        return -1;
15011354SCurtis.Dunham@arm.com    }
15111354SCurtis.Dunham@arm.com    assert(r == 0); // finished successfully
15211354SCurtis.Dunham@arm.com    return fd; // return fd to decompressed temporary file for mmap()'ing
15311354SCurtis.Dunham@arm.com}
15412SN/A
15512SN/AObjectFile *
1563584Ssaidi@eecs.umich.educreateObjectFile(const string &fname, bool raw)
1572SN/A{
15812SN/A    // open the file
15912SN/A    int fd = open(fname.c_str(), O_RDONLY);
16012SN/A    if (fd < 0) {
16112SN/A        return NULL;
1622SN/A    }
1632SN/A
16411354SCurtis.Dunham@arm.com    // decompress GZ files
16511354SCurtis.Dunham@arm.com    if (hasGzipMagic(fd)) {
16611354SCurtis.Dunham@arm.com        fd = doGzipLoad(fd);
16711354SCurtis.Dunham@arm.com        if (fd < 0) {
16811354SCurtis.Dunham@arm.com            return NULL;
16911354SCurtis.Dunham@arm.com        }
17011354SCurtis.Dunham@arm.com    }
17111354SCurtis.Dunham@arm.com
17212SN/A    // find the length of the file by seeking to the end
17310422Sandreas.hansson@arm.com    off_t off = lseek(fd, 0, SEEK_END);
17411354SCurtis.Dunham@arm.com    fatal_if(off < 0,
17511354SCurtis.Dunham@arm.com             "Failed to determine size of object file %s\n", fname);
17611354SCurtis.Dunham@arm.com    auto len = static_cast<size_t>(off);
17712SN/A
17812SN/A    // mmap the whole shebang
17911391Sbrandon.potter@amd.com    uint8_t *file_data = (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED,
18011391Sbrandon.potter@amd.com                                         fd, 0);
18110880SCurtis.Dunham@arm.com    close(fd);
18211354SCurtis.Dunham@arm.com
18311391Sbrandon.potter@amd.com    if (file_data == MAP_FAILED) {
18412SN/A        return NULL;
1852SN/A    }
1862SN/A
18711391Sbrandon.potter@amd.com    ObjectFile *file_obj = NULL;
1882SN/A
18912SN/A    // figure out what we have here
19011391Sbrandon.potter@amd.com    if ((file_obj = ElfObject::tryFile(fname, len, file_data)) != NULL) {
19111391Sbrandon.potter@amd.com        return file_obj;
1922SN/A    }
1932SN/A
19411391Sbrandon.potter@amd.com    if ((file_obj = EcoffObject::tryFile(fname, len, file_data)) != NULL) {
19511391Sbrandon.potter@amd.com        return file_obj;
1962SN/A    }
1972SN/A
19811391Sbrandon.potter@amd.com    if ((file_obj = AoutObject::tryFile(fname, len, file_data)) != NULL) {
19911391Sbrandon.potter@amd.com        return file_obj;
2002SN/A    }
2012SN/A
20211391Sbrandon.potter@amd.com    if ((file_obj = DtbObject::tryFile(fname, len, file_data)) != NULL) {
20311391Sbrandon.potter@amd.com        return file_obj;
2049538Satgutier@umich.edu    }
2059538Satgutier@umich.edu
2063584Ssaidi@eecs.umich.edu    if (raw)
20711391Sbrandon.potter@amd.com        return RawObject::tryFile(fname, len, file_data);
2083584Ssaidi@eecs.umich.edu
20912SN/A    // don't know what it is
21011391Sbrandon.potter@amd.com    munmap((char*)file_data, len);
21112SN/A    return NULL;
2122SN/A}
213