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