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> 4313982Sgabeblack@google.com#include <vector> 442SN/A 4511793Sbrandon.potter@amd.com#include "base/cprintf.hh" 468229Snate@binkert.org#include "base/loader/aout_object.hh" 479538Satgutier@umich.edu#include "base/loader/dtb_object.hh" 488229Snate@binkert.org#include "base/loader/ecoff_object.hh" 498229Snate@binkert.org#include "base/loader/elf_object.hh" 508229Snate@binkert.org#include "base/loader/raw_object.hh" 518229Snate@binkert.org#include "base/loader/symtab.hh" 528706Sandreas.hansson@arm.com#include "mem/port_proxy.hh" 532420SN/A 542SN/Ausing namespace std; 552SN/A 5610880SCurtis.Dunham@arm.comObjectFile::ObjectFile(const string &_filename, 57360SN/A size_t _len, uint8_t *_data, 5811391Sbrandon.potter@amd.com Arch _arch, OpSys _op_sys) 5910880SCurtis.Dunham@arm.com : filename(_filename), fileData(_data), len(_len), 6011391Sbrandon.potter@amd.com arch(_arch), opSys(_op_sys), entry(0), globalPtr(0), 6110422Sandreas.hansson@arm.com text{0, nullptr, 0}, data{0, nullptr, 0}, bss{0, nullptr, 0} 6212SN/A{ 6312SN/A} 642SN/A 652SN/A 662SN/AObjectFile::~ObjectFile() 672SN/A{ 6811391Sbrandon.potter@amd.com if (fileData) { 6911391Sbrandon.potter@amd.com ::munmap((char*)fileData, len); 7011391Sbrandon.potter@amd.com fileData = NULL; 7111391Sbrandon.potter@amd.com } 7212SN/A} 732SN/A 742SN/A 752420SN/Abool 7614017Sbrandon.potter@amd.comObjectFile::loadSection(Section *sec, const PortProxy& mem_proxy, 7714017Sbrandon.potter@amd.com Addr addr_mask, Addr offset) 782420SN/A{ 792420SN/A if (sec->size != 0) { 8011391Sbrandon.potter@amd.com Addr addr = (sec->baseAddr & addr_mask) + offset; 812420SN/A if (sec->fileImage) { 8211391Sbrandon.potter@amd.com mem_proxy.writeBlob(addr, sec->fileImage, sec->size); 832420SN/A } 842420SN/A else { 852420SN/A // no image: must be bss 8611391Sbrandon.potter@amd.com mem_proxy.memsetBlob(addr, 0, sec->size); 872420SN/A } 882420SN/A } 892420SN/A return true; 902420SN/A} 912420SN/A 922420SN/A 932420SN/Abool 9414017Sbrandon.potter@amd.comObjectFile::loadSections(const PortProxy& mem_proxy, Addr addr_mask, 9514017Sbrandon.potter@amd.com Addr offset) 962420SN/A{ 9711391Sbrandon.potter@amd.com return (loadSection(&text, mem_proxy, addr_mask, offset) 9811391Sbrandon.potter@amd.com && loadSection(&data, mem_proxy, addr_mask, offset) 9911391Sbrandon.potter@amd.com && loadSection(&bss, mem_proxy, addr_mask, offset)); 1002SN/A} 1012SN/A 10213982Sgabeblack@google.comnamespace 10313982Sgabeblack@google.com{ 10413982Sgabeblack@google.com 10513982Sgabeblack@google.comtypedef std::vector<ObjectFile::Loader *> LoaderList; 10613982Sgabeblack@google.com 10713982Sgabeblack@google.comLoaderList & 10813982Sgabeblack@google.comobject_file_loaders() 10913982Sgabeblack@google.com{ 11013982Sgabeblack@google.com static LoaderList loaders; 11113982Sgabeblack@google.com return loaders; 11213982Sgabeblack@google.com} 11313982Sgabeblack@google.com 11413982Sgabeblack@google.com} // anonymous namespace 11513982Sgabeblack@google.com 11613982Sgabeblack@google.comObjectFile::Loader::Loader() 11713982Sgabeblack@google.com{ 11813982Sgabeblack@google.com object_file_loaders().emplace_back(this); 11913982Sgabeblack@google.com} 12013982Sgabeblack@google.com 12113982Sgabeblack@google.comProcess * 12213982Sgabeblack@google.comObjectFile::tryLoaders(ProcessParams *params, ObjectFile *obj_file) 12313982Sgabeblack@google.com{ 12413982Sgabeblack@google.com for (auto &loader: object_file_loaders()) { 12513982Sgabeblack@google.com Process *p = loader->load(params, obj_file); 12613982Sgabeblack@google.com if (p) 12713982Sgabeblack@google.com return p; 12813982Sgabeblack@google.com } 12913982Sgabeblack@google.com 13013982Sgabeblack@google.com return nullptr; 13113982Sgabeblack@google.com} 13213982Sgabeblack@google.com 13311354SCurtis.Dunham@arm.comstatic bool 13411354SCurtis.Dunham@arm.comhasGzipMagic(int fd) 13511354SCurtis.Dunham@arm.com{ 13611354SCurtis.Dunham@arm.com uint8_t buf[2] = {0}; 13711354SCurtis.Dunham@arm.com size_t sz = pread(fd, buf, 2, 0); 13811354SCurtis.Dunham@arm.com panic_if(sz != 2, "Couldn't read magic bytes from object file"); 13911354SCurtis.Dunham@arm.com return ((buf[0] == 0x1f) && (buf[1] == 0x8b)); 14011354SCurtis.Dunham@arm.com} 14111354SCurtis.Dunham@arm.com 14211354SCurtis.Dunham@arm.comstatic int 14311354SCurtis.Dunham@arm.comdoGzipLoad(int fd) 14411354SCurtis.Dunham@arm.com{ 14511354SCurtis.Dunham@arm.com const size_t blk_sz = 4096; 14611354SCurtis.Dunham@arm.com 14711354SCurtis.Dunham@arm.com gzFile fdz = gzdopen(fd, "rb"); 14811354SCurtis.Dunham@arm.com if (!fdz) { 14911354SCurtis.Dunham@arm.com return -1; 15011354SCurtis.Dunham@arm.com } 15111354SCurtis.Dunham@arm.com 15211354SCurtis.Dunham@arm.com size_t tmp_len = strlen(P_tmpdir); 15311354SCurtis.Dunham@arm.com char *tmpnam = (char*) malloc(tmp_len + 20); 15411354SCurtis.Dunham@arm.com strcpy(tmpnam, P_tmpdir); 15511354SCurtis.Dunham@arm.com strcpy(tmpnam+tmp_len, "/gem5-gz-obj-XXXXXX"); // 19 chars 15611354SCurtis.Dunham@arm.com fd = mkstemp(tmpnam); // repurposing fd variable for output 15711354SCurtis.Dunham@arm.com if (fd < 0) { 15811354SCurtis.Dunham@arm.com free(tmpnam); 15911354SCurtis.Dunham@arm.com gzclose(fdz); 16011354SCurtis.Dunham@arm.com return fd; 16111354SCurtis.Dunham@arm.com } 16211354SCurtis.Dunham@arm.com 16311354SCurtis.Dunham@arm.com if (unlink(tmpnam) != 0) 16411354SCurtis.Dunham@arm.com warn("couldn't remove temporary file %s\n", tmpnam); 16511354SCurtis.Dunham@arm.com 16611354SCurtis.Dunham@arm.com free(tmpnam); 16711354SCurtis.Dunham@arm.com 16811354SCurtis.Dunham@arm.com auto buf = new uint8_t[blk_sz]; 16911354SCurtis.Dunham@arm.com int r; // size of (r)emaining uncopied data in (buf)fer 17011354SCurtis.Dunham@arm.com while ((r = gzread(fdz, buf, blk_sz)) > 0) { 17111354SCurtis.Dunham@arm.com auto p = buf; // pointer into buffer 17211354SCurtis.Dunham@arm.com while (r > 0) { 17311354SCurtis.Dunham@arm.com auto sz = write(fd, p, r); 17411354SCurtis.Dunham@arm.com assert(sz <= r); 17511354SCurtis.Dunham@arm.com r -= sz; 17611354SCurtis.Dunham@arm.com p += sz; 17711354SCurtis.Dunham@arm.com } 17811354SCurtis.Dunham@arm.com } 17911354SCurtis.Dunham@arm.com delete[] buf; 18011354SCurtis.Dunham@arm.com gzclose(fdz); 18111354SCurtis.Dunham@arm.com if (r < 0) { // error 18211354SCurtis.Dunham@arm.com close(fd); 18311354SCurtis.Dunham@arm.com return -1; 18411354SCurtis.Dunham@arm.com } 18511354SCurtis.Dunham@arm.com assert(r == 0); // finished successfully 18611354SCurtis.Dunham@arm.com return fd; // return fd to decompressed temporary file for mmap()'ing 18711354SCurtis.Dunham@arm.com} 18812SN/A 18912SN/AObjectFile * 1903584Ssaidi@eecs.umich.educreateObjectFile(const string &fname, bool raw) 1912SN/A{ 19212SN/A // open the file 19312SN/A int fd = open(fname.c_str(), O_RDONLY); 19412SN/A if (fd < 0) { 19512SN/A return NULL; 1962SN/A } 1972SN/A 19811354SCurtis.Dunham@arm.com // decompress GZ files 19911354SCurtis.Dunham@arm.com if (hasGzipMagic(fd)) { 20011354SCurtis.Dunham@arm.com fd = doGzipLoad(fd); 20111354SCurtis.Dunham@arm.com if (fd < 0) { 20211354SCurtis.Dunham@arm.com return NULL; 20311354SCurtis.Dunham@arm.com } 20411354SCurtis.Dunham@arm.com } 20511354SCurtis.Dunham@arm.com 20612SN/A // find the length of the file by seeking to the end 20710422Sandreas.hansson@arm.com off_t off = lseek(fd, 0, SEEK_END); 20811354SCurtis.Dunham@arm.com fatal_if(off < 0, 20911354SCurtis.Dunham@arm.com "Failed to determine size of object file %s\n", fname); 21011354SCurtis.Dunham@arm.com auto len = static_cast<size_t>(off); 21112SN/A 21212SN/A // mmap the whole shebang 21311391Sbrandon.potter@amd.com uint8_t *file_data = (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, 21411391Sbrandon.potter@amd.com fd, 0); 21510880SCurtis.Dunham@arm.com close(fd); 21611354SCurtis.Dunham@arm.com 21711391Sbrandon.potter@amd.com if (file_data == MAP_FAILED) { 21812SN/A return NULL; 2192SN/A } 2202SN/A 22111391Sbrandon.potter@amd.com ObjectFile *file_obj = NULL; 2222SN/A 22312SN/A // figure out what we have here 22411391Sbrandon.potter@amd.com if ((file_obj = ElfObject::tryFile(fname, len, file_data)) != NULL) { 22511391Sbrandon.potter@amd.com return file_obj; 2262SN/A } 2272SN/A 22811391Sbrandon.potter@amd.com if ((file_obj = EcoffObject::tryFile(fname, len, file_data)) != NULL) { 22911391Sbrandon.potter@amd.com return file_obj; 2302SN/A } 2312SN/A 23211391Sbrandon.potter@amd.com if ((file_obj = AoutObject::tryFile(fname, len, file_data)) != NULL) { 23311391Sbrandon.potter@amd.com return file_obj; 2342SN/A } 2352SN/A 23611391Sbrandon.potter@amd.com if ((file_obj = DtbObject::tryFile(fname, len, file_data)) != NULL) { 23711391Sbrandon.potter@amd.com return file_obj; 2389538Satgutier@umich.edu } 2399538Satgutier@umich.edu 2403584Ssaidi@eecs.umich.edu if (raw) 24111391Sbrandon.potter@amd.com return RawObject::tryFile(fname, len, file_data); 2423584Ssaidi@eecs.umich.edu 24312SN/A // don't know what it is 24411391Sbrandon.potter@amd.com munmap((char*)file_data, len); 24512SN/A return NULL; 2462SN/A} 247