elf_object.cc revision 443
112870Sgabeblack@google.com/* 212870Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan 312870Sgabeblack@google.com * All rights reserved. 412870Sgabeblack@google.com * 512870Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612870Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712870Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812870Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912870Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012870Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112870Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212870Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312870Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412870Sgabeblack@google.com * this software without specific prior written permission. 1512870Sgabeblack@google.com * 1612870Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712870Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812870Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912870Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012870Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112870Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212870Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312870Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412870Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512870Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612870Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712870Sgabeblack@google.com */ 2812870Sgabeblack@google.com 2912870Sgabeblack@google.com#include <string> 3012870Sgabeblack@google.com 3112870Sgabeblack@google.com#include "base/loader/elf_object.hh" 3212870Sgabeblack@google.com 3312870Sgabeblack@google.com#include "mem/functional_mem/functional_memory.hh" 3412870Sgabeblack@google.com#include "base/loader/symtab.hh" 3512870Sgabeblack@google.com 3612870Sgabeblack@google.com#include "base/trace.hh" // for DPRINTF 3713000Sgabeblack@google.com 3812870Sgabeblack@google.com 3912870Sgabeblack@google.comusing namespace std; 4012870Sgabeblack@google.com 4112870Sgabeblack@google.comObjectFile * 4212870Sgabeblack@google.comElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) 4312870Sgabeblack@google.com{ 4412870Sgabeblack@google.com Elf *elf; 4512870Sgabeblack@google.com GElf_Ehdr ehdr; 4612870Sgabeblack@google.com 4712870Sgabeblack@google.com 4812870Sgabeblack@google.com /* check that header matches library version */ 4912870Sgabeblack@google.com assert(elf_version(EV_CURRENT) != EV_NONE); 5012870Sgabeblack@google.com 5112870Sgabeblack@google.com /* get a pointer to elf structure */ 5212870Sgabeblack@google.com elf = elf_memory((char*)data,len); 5312870Sgabeblack@google.com /* will only fail if fd is invalid */ 5412870Sgabeblack@google.com assert(elf != NULL); 5512870Sgabeblack@google.com 5612870Sgabeblack@google.com /* Check that we actually have a elf file */ 5712870Sgabeblack@google.com if(gelf_getehdr(elf, &ehdr) ==0) 5812870Sgabeblack@google.com { 5912870Sgabeblack@google.com DPRINTFR(Loader, "Not ELF\n"); 6012870Sgabeblack@google.com elf_end(elf); 6112870Sgabeblack@google.com return NULL; 6212870Sgabeblack@google.com } 6312870Sgabeblack@google.com else 6412870Sgabeblack@google.com { 6512870Sgabeblack@google.com if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 6612870Sgabeblack@google.com panic("32 bit ELF Binary, Not Supported"); 6712870Sgabeblack@google.com if (ehdr.e_machine != EM_ALPHA) 6812870Sgabeblack@google.com panic("Non Alpha Binary, Not Supported"); 6912870Sgabeblack@google.com 7012870Sgabeblack@google.com elf_end(elf); 7112897Sgabeblack@google.com 7212870Sgabeblack@google.com return new ElfObject(fname, fd, len, data, 7312870Sgabeblack@google.com ObjectFile::Alpha, ObjectFile::Linux); 7412870Sgabeblack@google.com } 7512870Sgabeblack@google.com} 7612870Sgabeblack@google.com 7712870Sgabeblack@google.com 7812870Sgabeblack@google.comElfObject::ElfObject(const string &_filename, int _fd, 7912870Sgabeblack@google.com size_t _len, uint8_t *_data, 8012870Sgabeblack@google.com Arch _arch, OpSys _opSys) 8112870Sgabeblack@google.com : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys) 8212870Sgabeblack@google.com 8312870Sgabeblack@google.com{ 8412870Sgabeblack@google.com 8513002Sgabeblack@google.com Elf *elf; 8613002Sgabeblack@google.com GElf_Ehdr ehdr; 8713002Sgabeblack@google.com 8812870Sgabeblack@google.com /* check that header matches library version */ 8912870Sgabeblack@google.com assert(elf_version(EV_CURRENT) != EV_NONE); 9012870Sgabeblack@google.com 9112870Sgabeblack@google.com /* get a pointer to elf structure */ 9212870Sgabeblack@google.com elf = elf_memory((char*)fileData,len); 9312870Sgabeblack@google.com /* will only fail if fd is invalid */ 9412870Sgabeblack@google.com assert(elf != NULL); 9512870Sgabeblack@google.com 9612870Sgabeblack@google.com /* Check that we actually have a elf file */ 9712870Sgabeblack@google.com if(gelf_getehdr(elf, &ehdr) ==0) 9812870Sgabeblack@google.com { 9912870Sgabeblack@google.com panic("Not ELF, shouldn't be here"); 10012870Sgabeblack@google.com } 10112870Sgabeblack@google.com 10212870Sgabeblack@google.com 10312870Sgabeblack@google.com entry = ehdr.e_entry; 10412870Sgabeblack@google.com elf_end(elf); 10512870Sgabeblack@google.com 10612870Sgabeblack@google.com /* We will actually read the sections when we need to load them*/ 10712870Sgabeblack@google.com} 10812870Sgabeblack@google.com 10912870Sgabeblack@google.com 11012870Sgabeblack@google.combool 11112870Sgabeblack@google.comElfObject::loadSections(FunctionalMemory *mem, bool loadPhys) 11212870Sgabeblack@google.com{ 11312870Sgabeblack@google.com Elf *elf; 11412870Sgabeblack@google.com int secidx = 1; /* there is a 0 but it is nothing, go figure*/ 11512870Sgabeblack@google.com Elf_Scn *section; 11612870Sgabeblack@google.com GElf_Shdr shdr; 11712870Sgabeblack@google.com GElf_Ehdr ehdr; 11812870Sgabeblack@google.com 11912870Sgabeblack@google.com Addr address; 12012870Sgabeblack@google.com char *secname; 12112870Sgabeblack@google.com 12212870Sgabeblack@google.com /* check that header matches library version */ 12312870Sgabeblack@google.com assert(elf_version(EV_CURRENT) != EV_NONE); 12413000Sgabeblack@google.com 12513000Sgabeblack@google.com 12613000Sgabeblack@google.com /* get a pointer to elf structure */ 12713000Sgabeblack@google.com elf = elf_memory((char*)fileData,len); 12813000Sgabeblack@google.com 12913000Sgabeblack@google.com assert(elf != NULL); 13013000Sgabeblack@google.com 13113000Sgabeblack@google.com /* Check that we actually have a elf file */ 13213000Sgabeblack@google.com if(gelf_getehdr(elf, &ehdr) ==0) 13313000Sgabeblack@google.com { 13413000Sgabeblack@google.com panic("Not ELF, shouldn't be here"); 13513000Sgabeblack@google.com } 13613000Sgabeblack@google.com 13713000Sgabeblack@google.com 13813000Sgabeblack@google.com 13913000Sgabeblack@google.com /* Get the first section */ 14013000Sgabeblack@google.com section = elf_getscn(elf, secidx); 14113000Sgabeblack@google.com 14212870Sgabeblack@google.com /* While there are no more sections */ 14312870Sgabeblack@google.com while (section != NULL) 14412870Sgabeblack@google.com { 14512870Sgabeblack@google.com gelf_getshdr(section, &shdr); 14613000Sgabeblack@google.com 14713002Sgabeblack@google.com 14813002Sgabeblack@google.com if (shdr.sh_flags & SHF_ALLOC) 14913002Sgabeblack@google.com { 15013001Sgabeblack@google.com /* we should load this */ 15113001Sgabeblack@google.com DPRINTF(Loader,"Name: %20s Address: 0x%016llx Size: 0x%08llx Offset: 0x%08llx Flags:0x%08llx %s\n", 15213001Sgabeblack@google.com elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name), shdr.sh_addr, 15313001Sgabeblack@google.com shdr.sh_size, shdr.sh_offset, shdr.sh_flags, shdr.sh_flags & SHF_ALLOC ? "ALLOC" : ""); 15413001Sgabeblack@google.com secname = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 15513001Sgabeblack@google.com if(secname) 15613002Sgabeblack@google.com { 15713001Sgabeblack@google.com if (strcmp(secname, ".text")==0) 15813000Sgabeblack@google.com { 15913000Sgabeblack@google.com text.baseAddr = shdr.sh_addr; 16013000Sgabeblack@google.com text.size = shdr.sh_size; 16113000Sgabeblack@google.com } 16213000Sgabeblack@google.com if (strcmp(secname, ".data")==0) 16313000Sgabeblack@google.com { 16413000Sgabeblack@google.com data.baseAddr = shdr.sh_addr; 16513000Sgabeblack@google.com data.size = shdr.sh_size; 16613000Sgabeblack@google.com } 16712870Sgabeblack@google.com if (strcmp(secname, ".bss")==0) 16812870Sgabeblack@google.com { 16912870Sgabeblack@google.com bss.baseAddr = shdr.sh_addr; 17012870Sgabeblack@google.com bss.size = shdr.sh_size; 17112870Sgabeblack@google.com } 17213002Sgabeblack@google.com } 17313002Sgabeblack@google.com if(shdr.sh_size != 0) 17413002Sgabeblack@google.com { 17513002Sgabeblack@google.com if (loadPhys) 17613002Sgabeblack@google.com { 17713002Sgabeblack@google.com address = shdr.sh_addr &= (ULL(1) << 40) - 1; 17813002Sgabeblack@google.com mem->prot_write(address, fileData + shdr.sh_offset, shdr.sh_size); 17913002Sgabeblack@google.com } 18013002Sgabeblack@google.com else 18113002Sgabeblack@google.com { 18213002Sgabeblack@google.com mem->prot_write(shdr.sh_addr, fileData + shdr.sh_offset, shdr.sh_size); 18313002Sgabeblack@google.com } 18413002Sgabeblack@google.com } 18513002Sgabeblack@google.com 18613002Sgabeblack@google.com } 18713002Sgabeblack@google.com 18813002Sgabeblack@google.com ++secidx; 18913002Sgabeblack@google.com section = elf_getscn(elf, secidx); 19013002Sgabeblack@google.com } 19113002Sgabeblack@google.com 19213002Sgabeblack@google.com elf_end(elf); 19313002Sgabeblack@google.com 19413002Sgabeblack@google.com return true; 19513002Sgabeblack@google.com} 19613002Sgabeblack@google.com 19713002Sgabeblack@google.com 19813002Sgabeblack@google.combool 19913002Sgabeblack@google.comElfObject::loadGlobalSymbols(SymbolTable *symtab) 20013002Sgabeblack@google.com{ 20113002Sgabeblack@google.com Elf *elf; 20213002Sgabeblack@google.com int secidx = 1; /* there is a 0 but it is nothing, go figure*/ 20313002Sgabeblack@google.com Elf_Scn *section; 20413002Sgabeblack@google.com GElf_Shdr shdr; 20513002Sgabeblack@google.com Elf_Data *data; 20613002Sgabeblack@google.com int count, ii; 20713002Sgabeblack@google.com bool found = false; 20813002Sgabeblack@google.com GElf_Sym sym; 20913002Sgabeblack@google.com 21013002Sgabeblack@google.com if (!symtab) 21113002Sgabeblack@google.com return false; 21213002Sgabeblack@google.com 21313002Sgabeblack@google.com /* check that header matches library version */ 21413002Sgabeblack@google.com assert(elf_version(EV_CURRENT) != EV_NONE); 21513002Sgabeblack@google.com 21613002Sgabeblack@google.com /* get a pointer to elf structure */ 21713002Sgabeblack@google.com elf = elf_memory((char*)fileData,len); 21813002Sgabeblack@google.com 21913002Sgabeblack@google.com assert(elf != NULL); 22013002Sgabeblack@google.com 22113002Sgabeblack@google.com 22213002Sgabeblack@google.com /* Get the first section */ 22313002Sgabeblack@google.com section = elf_getscn(elf, secidx); 22413002Sgabeblack@google.com 22513002Sgabeblack@google.com /* While there are no more sections */ 22613002Sgabeblack@google.com while (section != NULL) 22713002Sgabeblack@google.com { 22813002Sgabeblack@google.com gelf_getshdr(section, &shdr); 22912870Sgabeblack@google.com 23013002Sgabeblack@google.com 23113002Sgabeblack@google.com if(shdr.sh_type == SHT_SYMTAB) 23213002Sgabeblack@google.com { 23313002Sgabeblack@google.com found = true; 23413002Sgabeblack@google.com data = elf_getdata(section, NULL); 23513002Sgabeblack@google.com count = shdr.sh_size / shdr.sh_entsize; 23613002Sgabeblack@google.com DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 23713002Sgabeblack@google.com 23813002Sgabeblack@google.com /* loop through all the symbols, only loading global ones*/ 23912870Sgabeblack@google.com for (ii = 0; ii < count; ++ii) 24013002Sgabeblack@google.com { 24113002Sgabeblack@google.com gelf_getsym(data, ii, &sym); 24213002Sgabeblack@google.com if (GELF_ST_BIND(sym.st_info) & STB_GLOBAL) 24313002Sgabeblack@google.com { 24413002Sgabeblack@google.com symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name)); 24513002Sgabeblack@google.com } 24613002Sgabeblack@google.com } 24713002Sgabeblack@google.com } 24813002Sgabeblack@google.com ++secidx; 24913002Sgabeblack@google.com section = elf_getscn(elf, secidx); 25013002Sgabeblack@google.com } 25113002Sgabeblack@google.com 25213002Sgabeblack@google.com elf_end(elf); 25313002Sgabeblack@google.com 25413002Sgabeblack@google.com return found; 25513002Sgabeblack@google.com} 25613002Sgabeblack@google.com 25713002Sgabeblack@google.combool 25813002Sgabeblack@google.comElfObject::loadLocalSymbols(SymbolTable *symtab) 25913002Sgabeblack@google.com{ 26013002Sgabeblack@google.com 26113002Sgabeblack@google.com Elf *elf; 26213002Sgabeblack@google.com int secidx = 1; /* there is a 0 but it is nothing, go figure*/ 26313002Sgabeblack@google.com Elf_Scn *section; 26413002Sgabeblack@google.com GElf_Shdr shdr; 26513002Sgabeblack@google.com Elf_Data *data; 26613002Sgabeblack@google.com int count, ii; 26713002Sgabeblack@google.com bool found = false; 26813002Sgabeblack@google.com GElf_Sym sym; 26913002Sgabeblack@google.com 27013002Sgabeblack@google.com if (!symtab) 27113002Sgabeblack@google.com return false; 27213002Sgabeblack@google.com 27313002Sgabeblack@google.com /* check that header matches library version */ 27413002Sgabeblack@google.com assert(elf_version(EV_CURRENT) != EV_NONE); 27512870Sgabeblack@google.com 27612870Sgabeblack@google.com /* get a pointer to elf structure */ 27712870Sgabeblack@google.com elf = elf_memory((char*)fileData,len); 27812870Sgabeblack@google.com 27912870Sgabeblack@google.com assert(elf != NULL); 28012870Sgabeblack@google.com 28112870Sgabeblack@google.com 28212870Sgabeblack@google.com /* Get the first section */ 28312870Sgabeblack@google.com section = elf_getscn(elf, secidx); 28412870Sgabeblack@google.com 28512870Sgabeblack@google.com /* While there are no more sections */ 28612870Sgabeblack@google.com while (section != NULL) 28712870Sgabeblack@google.com { 28812870Sgabeblack@google.com gelf_getshdr(section, &shdr); 28912870Sgabeblack@google.com 29012870Sgabeblack@google.com 29112870Sgabeblack@google.com if(shdr.sh_type == SHT_SYMTAB) 29212903Sgabeblack@google.com { 29312903Sgabeblack@google.com found = true; 29412903Sgabeblack@google.com data = elf_getdata(section, NULL); 29512903Sgabeblack@google.com count = shdr.sh_size / shdr.sh_entsize; 29612903Sgabeblack@google.com DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 29712903Sgabeblack@google.com 29812903Sgabeblack@google.com /* loop through all the symbols, only loading global ones*/ 29912870Sgabeblack@google.com for (ii = 0; ii < count; ++ii) 30012870Sgabeblack@google.com { 30112870Sgabeblack@google.com gelf_getsym(data, ii, &sym); 30212870Sgabeblack@google.com if (GELF_ST_BIND(sym.st_info) & STB_LOCAL) 30312870Sgabeblack@google.com { 30412870Sgabeblack@google.com symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name)); 30512870Sgabeblack@google.com } 30612870Sgabeblack@google.com } 30712870Sgabeblack@google.com } 30812870Sgabeblack@google.com ++secidx; 30912870Sgabeblack@google.com section = elf_getscn(elf, secidx); 31012870Sgabeblack@google.com } 31112870Sgabeblack@google.com 31212870Sgabeblack@google.com elf_end(elf); 31312870Sgabeblack@google.com 31412870Sgabeblack@google.com return found; 31512870Sgabeblack@google.com} 31612870Sgabeblack@google.com