object_file.cc revision 11793
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
3211793Sbrandon.potter@amd.com#include "base/loader/object_file.hh"
3311793Sbrandon.potter@amd.com
3411793Sbrandon.potter@amd.com#include <fcntl.h>
358229Snate@binkert.org#include <sys/mman.h>
368229Snate@binkert.org#include <sys/types.h>
378229Snate@binkert.org#include <unistd.h>
3811354SCurtis.Dunham@arm.com#include <zlib.h>
398229Snate@binkert.org
408229Snate@binkert.org#include <cstdio>
412SN/A#include <list>
422SN/A#include <string>
432SN/A
4411793Sbrandon.potter@amd.com#include "base/cprintf.hh"
458229Snate@binkert.org#include "base/loader/aout_object.hh"
469538Satgutier@umich.edu#include "base/loader/dtb_object.hh"
478229Snate@binkert.org#include "base/loader/ecoff_object.hh"
488229Snate@binkert.org#include "base/loader/elf_object.hh"
498229Snate@binkert.org#include "base/loader/raw_object.hh"
508229Snate@binkert.org#include "base/loader/symtab.hh"
518706Sandreas.hansson@arm.com#include "mem/port_proxy.hh"
522420SN/A
532SN/Ausing namespace std;
542SN/A
5510880SCurtis.Dunham@arm.comObjectFile::ObjectFile(const string &_filename,
56360SN/A                       size_t _len, uint8_t *_data,
5711391Sbrandon.potter@amd.com                       Arch _arch, OpSys _op_sys)
5810880SCurtis.Dunham@arm.com    : filename(_filename), fileData(_data), len(_len),
5911391Sbrandon.potter@amd.com      arch(_arch), opSys(_op_sys), entry(0), globalPtr(0),
6010422Sandreas.hansson@arm.com      text{0, nullptr, 0}, data{0, nullptr, 0}, bss{0, nullptr, 0}
6112SN/A{
6212SN/A}
632SN/A
642SN/A
652SN/AObjectFile::~ObjectFile()
662SN/A{
6711391Sbrandon.potter@amd.com    if (fileData) {
6811391Sbrandon.potter@amd.com        ::munmap((char*)fileData, len);
6911391Sbrandon.potter@amd.com        fileData = NULL;
7011391Sbrandon.potter@amd.com    }
7112SN/A}
722SN/A
732SN/A
742420SN/Abool
7511391Sbrandon.potter@amd.comObjectFile::loadSection(Section *sec, PortProxy& mem_proxy, Addr addr_mask,
7611391Sbrandon.potter@amd.com                        Addr offset)
772420SN/A{
782420SN/A    if (sec->size != 0) {
7911391Sbrandon.potter@amd.com        Addr addr = (sec->baseAddr & addr_mask) + offset;
802420SN/A        if (sec->fileImage) {
8111391Sbrandon.potter@amd.com            mem_proxy.writeBlob(addr, sec->fileImage, sec->size);
822420SN/A        }
832420SN/A        else {
842420SN/A            // no image: must be bss
8511391Sbrandon.potter@amd.com            mem_proxy.memsetBlob(addr, 0, sec->size);
862420SN/A        }
872420SN/A    }
882420SN/A    return true;
892420SN/A}
902420SN/A
912420SN/A
922420SN/Abool
9311391Sbrandon.potter@amd.comObjectFile::loadSections(PortProxy& mem_proxy, Addr addr_mask, Addr offset)
942420SN/A{
9511391Sbrandon.potter@amd.com    return (loadSection(&text, mem_proxy, addr_mask, offset)
9611391Sbrandon.potter@amd.com            && loadSection(&data, mem_proxy, addr_mask, offset)
9711391Sbrandon.potter@amd.com            && loadSection(&bss, mem_proxy, addr_mask, offset));
982SN/A}
992SN/A
10011354SCurtis.Dunham@arm.comstatic bool
10111354SCurtis.Dunham@arm.comhasGzipMagic(int fd)
10211354SCurtis.Dunham@arm.com{
10311354SCurtis.Dunham@arm.com    uint8_t buf[2] = {0};
10411354SCurtis.Dunham@arm.com    size_t sz = pread(fd, buf, 2, 0);
10511354SCurtis.Dunham@arm.com    panic_if(sz != 2, "Couldn't read magic bytes from object file");
10611354SCurtis.Dunham@arm.com    return ((buf[0] == 0x1f) && (buf[1] == 0x8b));
10711354SCurtis.Dunham@arm.com}
10811354SCurtis.Dunham@arm.com
10911354SCurtis.Dunham@arm.comstatic int
11011354SCurtis.Dunham@arm.comdoGzipLoad(int fd)
11111354SCurtis.Dunham@arm.com{
11211354SCurtis.Dunham@arm.com    const size_t blk_sz = 4096;
11311354SCurtis.Dunham@arm.com
11411354SCurtis.Dunham@arm.com    gzFile fdz = gzdopen(fd, "rb");
11511354SCurtis.Dunham@arm.com    if (!fdz) {
11611354SCurtis.Dunham@arm.com        return -1;
11711354SCurtis.Dunham@arm.com    }
11811354SCurtis.Dunham@arm.com
11911354SCurtis.Dunham@arm.com    size_t tmp_len = strlen(P_tmpdir);
12011354SCurtis.Dunham@arm.com    char *tmpnam = (char*) malloc(tmp_len + 20);
12111354SCurtis.Dunham@arm.com    strcpy(tmpnam, P_tmpdir);
12211354SCurtis.Dunham@arm.com    strcpy(tmpnam+tmp_len, "/gem5-gz-obj-XXXXXX"); // 19 chars
12311354SCurtis.Dunham@arm.com    fd = mkstemp(tmpnam); // repurposing fd variable for output
12411354SCurtis.Dunham@arm.com    if (fd < 0) {
12511354SCurtis.Dunham@arm.com        free(tmpnam);
12611354SCurtis.Dunham@arm.com        gzclose(fdz);
12711354SCurtis.Dunham@arm.com        return fd;
12811354SCurtis.Dunham@arm.com    }
12911354SCurtis.Dunham@arm.com
13011354SCurtis.Dunham@arm.com    if (unlink(tmpnam) != 0)
13111354SCurtis.Dunham@arm.com        warn("couldn't remove temporary file %s\n", tmpnam);
13211354SCurtis.Dunham@arm.com
13311354SCurtis.Dunham@arm.com    free(tmpnam);
13411354SCurtis.Dunham@arm.com
13511354SCurtis.Dunham@arm.com    auto buf = new uint8_t[blk_sz];
13611354SCurtis.Dunham@arm.com    int r; // size of (r)emaining uncopied data in (buf)fer
13711354SCurtis.Dunham@arm.com    while ((r = gzread(fdz, buf, blk_sz)) > 0) {
13811354SCurtis.Dunham@arm.com        auto p = buf; // pointer into buffer
13911354SCurtis.Dunham@arm.com        while (r > 0) {
14011354SCurtis.Dunham@arm.com            auto sz = write(fd, p, r);
14111354SCurtis.Dunham@arm.com            assert(sz <= r);
14211354SCurtis.Dunham@arm.com            r -= sz;
14311354SCurtis.Dunham@arm.com            p += sz;
14411354SCurtis.Dunham@arm.com        }
14511354SCurtis.Dunham@arm.com    }
14611354SCurtis.Dunham@arm.com    delete[] buf;
14711354SCurtis.Dunham@arm.com    gzclose(fdz);
14811354SCurtis.Dunham@arm.com    if (r < 0) { // error
14911354SCurtis.Dunham@arm.com        close(fd);
15011354SCurtis.Dunham@arm.com        return -1;
15111354SCurtis.Dunham@arm.com    }
15211354SCurtis.Dunham@arm.com    assert(r == 0); // finished successfully
15311354SCurtis.Dunham@arm.com    return fd; // return fd to decompressed temporary file for mmap()'ing
15411354SCurtis.Dunham@arm.com}
15512SN/A
15612SN/AObjectFile *
1573584Ssaidi@eecs.umich.educreateObjectFile(const string &fname, bool raw)
1582SN/A{
15912SN/A    // open the file
16012SN/A    int fd = open(fname.c_str(), O_RDONLY);
16112SN/A    if (fd < 0) {
16212SN/A        return NULL;
1632SN/A    }
1642SN/A
16511354SCurtis.Dunham@arm.com    // decompress GZ files
16611354SCurtis.Dunham@arm.com    if (hasGzipMagic(fd)) {
16711354SCurtis.Dunham@arm.com        fd = doGzipLoad(fd);
16811354SCurtis.Dunham@arm.com        if (fd < 0) {
16911354SCurtis.Dunham@arm.com            return NULL;
17011354SCurtis.Dunham@arm.com        }
17111354SCurtis.Dunham@arm.com    }
17211354SCurtis.Dunham@arm.com
17312SN/A    // find the length of the file by seeking to the end
17410422Sandreas.hansson@arm.com    off_t off = lseek(fd, 0, SEEK_END);
17511354SCurtis.Dunham@arm.com    fatal_if(off < 0,
17611354SCurtis.Dunham@arm.com             "Failed to determine size of object file %s\n", fname);
17711354SCurtis.Dunham@arm.com    auto len = static_cast<size_t>(off);
17812SN/A
17912SN/A    // mmap the whole shebang
18011391Sbrandon.potter@amd.com    uint8_t *file_data = (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED,
18111391Sbrandon.potter@amd.com                                         fd, 0);
18210880SCurtis.Dunham@arm.com    close(fd);
18311354SCurtis.Dunham@arm.com
18411391Sbrandon.potter@amd.com    if (file_data == MAP_FAILED) {
18512SN/A        return NULL;
1862SN/A    }
1872SN/A
18811391Sbrandon.potter@amd.com    ObjectFile *file_obj = NULL;
1892SN/A
19012SN/A    // figure out what we have here
19111391Sbrandon.potter@amd.com    if ((file_obj = ElfObject::tryFile(fname, len, file_data)) != NULL) {
19211391Sbrandon.potter@amd.com        return file_obj;
1932SN/A    }
1942SN/A
19511391Sbrandon.potter@amd.com    if ((file_obj = EcoffObject::tryFile(fname, len, file_data)) != NULL) {
19611391Sbrandon.potter@amd.com        return file_obj;
1972SN/A    }
1982SN/A
19911391Sbrandon.potter@amd.com    if ((file_obj = AoutObject::tryFile(fname, len, file_data)) != NULL) {
20011391Sbrandon.potter@amd.com        return file_obj;
2012SN/A    }
2022SN/A
20311391Sbrandon.potter@amd.com    if ((file_obj = DtbObject::tryFile(fname, len, file_data)) != NULL) {
20411391Sbrandon.potter@amd.com        return file_obj;
2059538Satgutier@umich.edu    }
2069538Satgutier@umich.edu
2073584Ssaidi@eecs.umich.edu    if (raw)
20811391Sbrandon.potter@amd.com        return RawObject::tryFile(fname, len, file_data);
2093584Ssaidi@eecs.umich.edu
21012SN/A    // don't know what it is
21111391Sbrandon.potter@amd.com    munmap((char*)file_data, len);
21212SN/A    return NULL;
2132SN/A}
214