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