elf_object.cc revision 5383
17513SN/A/* 27513SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 37513SN/A * All rights reserved. 410036SN/A * 58835SN/A * Redistribution and use in source and binary forms, with or without 610036SN/A * modification, are permitted provided that the following conditions are 77935SN/A * met: redistributions of source code must retain the above copyright 87935SN/A * notice, this list of conditions and the following disclaimer; 97935SN/A * redistributions in binary form must reproduce the above copyright 107513SN/A * notice, this list of conditions and the following disclaimer in the 117513SN/A * documentation and/or other materials provided with the distribution; 127513SN/A * neither the name of the copyright holders nor the names of its 1310315SN/A * contributors may be used to endorse or promote products derived from 148835SN/A * this software without specific prior written permission. 159885SN/A * 169885SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710036SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811312Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 198835SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 208835SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110315SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 228835SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310038SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249481SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259481SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 268721SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711066Snilay@cs.wisc.edu * 2811219Snilay@cs.wisc.edu * Authors: Steve Reinhardt 298721SN/A * Ali Saidi 308835SN/A */ 318835SN/A 3211440SCurtis.Dunham@arm.com#include <string> 3311440SCurtis.Dunham@arm.com 347935SN/A#include "gelf.h" 357935SN/A 367935SN/A#include "base/loader/elf_object.hh" 377935SN/A#include "base/loader/symtab.hh" 387935SN/A#include "base/misc.hh" 397935SN/A#include "base/trace.hh" // for DPRINTF 407935SN/A#include "sim/byteswap.hh" 418893SN/A 427513SN/Ausing namespace std; 439885SN/A 449885SN/AObjectFile * 459885SN/AElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) 4610315SN/A{ 4710036SN/A Elf *elf; 4810315SN/A GElf_Ehdr ehdr; 499885SN/A Arch arch = UnknownArch; 509885SN/A OpSys opSys = UnknownOpSys; 517513SN/A 527513SN/A // check that header matches library version 5310038SN/A if (elf_version(EV_CURRENT) == EV_NONE) 5410315SN/A panic("wrong elf version number!"); 557513SN/A 569885SN/A // get a pointer to elf structure 577513SN/A elf = elf_memory((char*)data,len); 587513SN/A // will only fail if fd is invalid 598835SN/A assert(elf != NULL); 607513SN/A 6110038SN/A // Check that we actually have a elf file 627513SN/A if (gelf_getehdr(elf, &ehdr) ==0) { 6310036SN/A DPRINTFR(Loader, "Not ELF\n"); 647513SN/A elf_end(elf); 657513SN/A return NULL; 668835SN/A } else { 679481SN/A //Detect the architecture 6810038SN/A //Since we don't know how to check for alpha right now, we'll 697513SN/A //just assume if it wasn't something else and it's 64 bit, that's 707513SN/A //what it must be. 717513SN/A if (ehdr.e_machine == EM_SPARC64 || 727513SN/A (ehdr.e_machine == EM_SPARC && 737513SN/A ehdr.e_ident[EI_CLASS] == ELFCLASS64)|| 747513SN/A ehdr.e_machine == EM_SPARCV9) { 758835SN/A arch = ObjectFile::SPARC64; 767513SN/A } else if (ehdr.e_machine == EM_SPARC32PLUS || 779885SN/A (ehdr.e_machine == EM_SPARC && 7810315SN/A ehdr.e_ident[EI_CLASS] == ELFCLASS32)) { 799481SN/A arch = ObjectFile::SPARC32; 807513SN/A } else if (ehdr.e_machine == EM_MIPS 817513SN/A && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 827513SN/A if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { 837513SN/A arch = ObjectFile::Mips; 847513SN/A } else { 857513SN/A fatal("The binary you're trying to load is compiled for big " 867513SN/A "endian MIPS. M5\nonly supports little endian MIPS. " 8711066Snilay@cs.wisc.edu "Please recompile your binary.\n"); 889885SN/A } 898893SN/A } else if (ehdr.e_machine == EM_X86_64 && 907513SN/A ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 919885SN/A //In the future, we might want to differentiate between 32 bit 9211219Snilay@cs.wisc.edu //and 64 bit x86 processes in case there are differences in their 9311066Snilay@cs.wisc.edu //initial stack frame. 9410036SN/A arch = ObjectFile::X86; 959481SN/A } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 9611066Snilay@cs.wisc.edu arch = ObjectFile::Alpha; 977513SN/A } else if (ehdr.e_machine == EM_ARM) { 989481SN/A arch = ObjectFile::Arm; 997513SN/A } else { 1008835SN/A warn("Unknown architecture: %d\n", ehdr.e_machine); 1019481SN/A arch = ObjectFile::UnknownArch; 10210036SN/A } 1037513SN/A 1048835SN/A //Detect the operating system 1059885SN/A switch (ehdr.e_ident[EI_OSABI]) 1069481SN/A { 1077513SN/A 10811219Snilay@cs.wisc.edu case ELFOSABI_LINUX: 1097513SN/A case ELFOSABI_ARM: 1108893SN/A opSys = ObjectFile::Linux; 1117513SN/A break; 1129885SN/A case ELFOSABI_SOLARIS: 1139885SN/A opSys = ObjectFile::Solaris; 1149885SN/A break; 1159885SN/A case ELFOSABI_TRU64: 1169885SN/A opSys = ObjectFile::Tru64; 11710036SN/A break; 1189885SN/A default: 11910036SN/A opSys = ObjectFile::UnknownOpSys; 1209885SN/A } 1219885SN/A 12210038SN/A //take a look at the .note.ABI section 12310038SN/A //It can let us know what's what. 12410038SN/A if (opSys == ObjectFile::UnknownOpSys) { 12510038SN/A Elf_Scn *section; 12610038SN/A GElf_Shdr shdr; 12711066Snilay@cs.wisc.edu Elf_Data *data; 12810038SN/A uint32_t osAbi;; 12910038SN/A int secIdx = 1; 13010038SN/A 13110038SN/A // Get the first section 13210038SN/A section = elf_getscn(elf, secIdx); 13310038SN/A 13410038SN/A // While there are no more sections 13510038SN/A while (section != NULL && opSys == ObjectFile::UnknownOpSys) { 13610038SN/A gelf_getshdr(section, &shdr); 13710038SN/A if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", 13810038SN/A elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 13910038SN/A // we have found a ABI note section 14010038SN/A // Check the 5th 32bit word for OS 0 == linux, 1 == hurd, 14110038SN/A // 2 == solaris, 3 == freebsd 14210038SN/A data = elf_rawdata(section, NULL); 14310038SN/A assert(data->d_buf); 14410038SN/A if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 14510038SN/A osAbi = htole(((uint32_t*)data->d_buf)[4]); 1467513SN/A else 1477513SN/A osAbi = htobe(((uint32_t*)data->d_buf)[4]); 1488835SN/A 14910036SN/A switch(osAbi) { 15010038SN/A case 0: 1517513SN/A opSys = ObjectFile::Linux; 1528835SN/A break; 1538835SN/A case 2: 1548835SN/A opSys = ObjectFile::Solaris; 1558835SN/A break; 1569885SN/A } 15710036SN/A } // if section found 15810038SN/A if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1599265SN/A opSys = ObjectFile::Solaris; 1608835SN/A if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1618893SN/A opSys = ObjectFile::Solaris; 1627513SN/A 1637513SN/A section = elf_getscn(elf, ++secIdx); 16411066Snilay@cs.wisc.edu } // while sections 1659885SN/A } 1668893SN/A 1677513SN/A ElfObject * result = new ElfObject(fname, fd, len, data, arch, opSys); 1689885SN/A 16911219Snilay@cs.wisc.edu //The number of headers in the file 17011066Snilay@cs.wisc.edu result->_programHeaderCount = ehdr.e_phnum; 17110036SN/A //Record the size of each entry 1729481SN/A result->_programHeaderSize = ehdr.e_phentsize; 17311066Snilay@cs.wisc.edu if(result->_programHeaderCount) //If there is a program header table 1747513SN/A { 1759481SN/A //Figure out the virtual address of the header table in the 1767513SN/A //final memory image. We use the program headers themselves 1778835SN/A //to translate from a file offset to the address in the image. 1789481SN/A GElf_Phdr phdr; 17910036SN/A uint64_t e_phoff = ehdr.e_phoff; 1807513SN/A result->_programHeaderTable = 0; 1818835SN/A for(int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++) 1829885SN/A { 1839481SN/A gelf_getphdr(elf, hdrnum, &phdr); 1847513SN/A //Check if we've found the segment with the headers in it 18511219Snilay@cs.wisc.edu if(phdr.p_offset <= e_phoff && 1867513SN/A phdr.p_offset + phdr.p_filesz > e_phoff) 1878893SN/A { 1887513SN/A result->_programHeaderTable = phdr.p_paddr + e_phoff; 1899885SN/A break; 1909885SN/A } 1919885SN/A } 1929885SN/A } 1939885SN/A else 19410036SN/A result->_programHeaderTable = 0; 1959885SN/A 19610036SN/A 1979885SN/A elf_end(elf); 1989885SN/A return result; 1998835SN/A } 2008835SN/A} 20110036SN/A 2028835SN/A 2039481SN/AElfObject::ElfObject(const string &_filename, int _fd, 2049481SN/A size_t _len, uint8_t *_data, 20511219Snilay@cs.wisc.edu Arch _arch, OpSys _opSys) 20610036SN/A : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys) 2079481SN/A 20810038SN/A{ 20910038SN/A Elf *elf; 21010038SN/A GElf_Ehdr ehdr; 21110038SN/A 21210038SN/A // check that header matches library version 21310038SN/A if (elf_version(EV_CURRENT) == EV_NONE) 21410038SN/A panic("wrong elf version number!"); 21510038SN/A 21610038SN/A // get a pointer to elf structure 21710038SN/A elf = elf_memory((char*)fileData,len); 2189481SN/A // will only fail if fd is invalid 2199481SN/A assert(elf != NULL); 2209481SN/A 2219481SN/A // Check that we actually have a elf file 2229481SN/A if (gelf_getehdr(elf, &ehdr) ==0) { 2239481SN/A panic("Not ELF, shouldn't be here"); 22410038SN/A } 2259481SN/A 2269481SN/A entry = ehdr.e_entry; 22710038SN/A 2289481SN/A // initialize segment sizes to 0 in case they're not present 22910038SN/A text.size = data.size = bss.size = 0; 23010038SN/A 23111066Snilay@cs.wisc.edu int secIdx = 1; 23210038SN/A Elf_Scn *section; 23310038SN/A GElf_Shdr shdr; 23410038SN/A 23510038SN/A // The first address of some important sections. 23610038SN/A Addr textSecStart = 0; 23710038SN/A Addr dataSecStart = 0; 23810038SN/A Addr bssSecStart = 0; 23911066Snilay@cs.wisc.edu 24010038SN/A // Get the first section 24110038SN/A section = elf_getscn(elf, secIdx); 24210038SN/A 24310038SN/A // Find the beginning of the most interesting sections. 24410038SN/A while (section != NULL) { 24510038SN/A gelf_getshdr(section, &shdr); 24610038SN/A char * secName = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 24710038SN/A 24810038SN/A if (!strcmp(".text", secName)) { 24910038SN/A textSecStart = shdr.sh_addr; 25010038SN/A } else if (!strcmp(".data", secName)) { 25110038SN/A dataSecStart = shdr.sh_addr; 25210038SN/A } else if (!strcmp(".bss", secName)) { 25310038SN/A bssSecStart = shdr.sh_addr; 25410038SN/A } 25510038SN/A 25610038SN/A section = elf_getscn(elf, ++secIdx); 2579481SN/A } 2587513SN/A 2597513SN/A // Go through all the segments in the program, record them, and scrape 2608835SN/A // out information about the text, data, and bss areas needed by other 26110036SN/A // code. 26210038SN/A for (int i = 0; i < ehdr.e_phnum; ++i) { 2637513SN/A GElf_Phdr phdr; 2648835SN/A if (gelf_getphdr(elf, i, &phdr) == 0) { 2658835SN/A panic("gelf_getphdr failed for segment %d.", i); 2668835SN/A } 2678835SN/A 2689885SN/A // for now we don't care about non-loadable segments 26910036SN/A if (!(phdr.p_type & PT_LOAD)) 27010038SN/A continue; 2719265SN/A 2728835SN/A // Check to see if this segment contains the bss section. 2738893SN/A if (phdr.p_paddr <= bssSecStart && 2747513SN/A phdr.p_paddr + phdr.p_memsz > bssSecStart && 2757513SN/A phdr.p_memsz - phdr.p_filesz > 0) { 27611066Snilay@cs.wisc.edu bss.baseAddr = phdr.p_paddr + phdr.p_filesz; 2779885SN/A bss.size = phdr.p_memsz - phdr.p_filesz; 2788893SN/A bss.fileImage = NULL; 2799481SN/A } 2809885SN/A 28111219Snilay@cs.wisc.edu // Check to see if this is the text or data segment 28211066Snilay@cs.wisc.edu if (phdr.p_vaddr <= textSecStart && 28310036SN/A phdr.p_vaddr + phdr.p_filesz > textSecStart) { 2849481SN/A text.baseAddr = phdr.p_paddr; 28511066Snilay@cs.wisc.edu text.size = phdr.p_filesz; 2867513SN/A text.fileImage = fileData + phdr.p_offset; 2879481SN/A } else if (phdr.p_vaddr <= dataSecStart && 2887513SN/A phdr.p_vaddr + phdr.p_filesz > dataSecStart) { 2898835SN/A data.baseAddr = phdr.p_paddr; 2909481SN/A data.size = phdr.p_filesz; 29110036SN/A data.fileImage = fileData + phdr.p_offset; 2927513SN/A } else { 2938835SN/A Segment extra; 2949885SN/A extra.baseAddr = phdr.p_paddr; 2959481SN/A extra.size = phdr.p_filesz; 2967513SN/A extra.fileImage = fileData + phdr.p_offset; 29711219Snilay@cs.wisc.edu extraSegments.push_back(extra); 2988893SN/A } 2998893SN/A } 3007513SN/A 3019885SN/A // should have found at least one loadable segment 3029885SN/A assert(text.size != 0); 3039885SN/A 3049885SN/A DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", 3059885SN/A text.baseAddr, text.size, data.baseAddr, data.size, 30610036SN/A bss.baseAddr, bss.size); 3079885SN/A 30810036SN/A elf_end(elf); 3099885SN/A 3109885SN/A // We will actually read the sections when we need to load them 3117513SN/A} 31210451SN/A 31311219Snilay@cs.wisc.edu 3149885SN/Abool 31510036SN/AElfObject::loadSomeSymbols(SymbolTable *symtab, int binding) 31611066Snilay@cs.wisc.edu{ 31711066Snilay@cs.wisc.edu Elf *elf; 31811388Ssteve.reinhardt@amd.com int sec_idx = 1; // there is a 0 but it is nothing, go figure 31911066Snilay@cs.wisc.edu Elf_Scn *section; 32011219Snilay@cs.wisc.edu GElf_Shdr shdr; 32111066Snilay@cs.wisc.edu Elf_Data *data; 3229885SN/A int count, ii; 3237524SN/A bool found = false; 3249481SN/A GElf_Sym sym; 3258893SN/A 32611066Snilay@cs.wisc.edu if (!symtab) 3277513SN/A return false; 32811219Snilay@cs.wisc.edu 32911219Snilay@cs.wisc.edu // check that header matches library version 33011219Snilay@cs.wisc.edu if (elf_version(EV_CURRENT) == EV_NONE) 33111219Snilay@cs.wisc.edu panic("wrong elf version number!"); 33211219Snilay@cs.wisc.edu 33311219Snilay@cs.wisc.edu // get a pointer to elf structure 33411219Snilay@cs.wisc.edu elf = elf_memory((char*)fileData,len); 3357513SN/A 3367513SN/A assert(elf != NULL); 33710036SN/A 3387513SN/A // Get the first section 3397513SN/A section = elf_getscn(elf, sec_idx); 3407513SN/A 3417513SN/A // While there are no more sections 34211066Snilay@cs.wisc.edu while (section != NULL) { 34311066Snilay@cs.wisc.edu gelf_getshdr(section, &shdr); 3447513SN/A 3457513SN/A if (shdr.sh_type == SHT_SYMTAB) { 3467513SN/A found = true; 3477513SN/A data = elf_getdata(section, NULL); 34810036SN/A count = shdr.sh_size / shdr.sh_entsize; 34911388Ssteve.reinhardt@amd.com DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 3507513SN/A 3517513SN/A // loop through all the symbols, only loading global ones 35211066Snilay@cs.wisc.edu for (ii = 0; ii < count; ++ii) { 3537513SN/A gelf_getsym(data, ii, &sym); 3547513SN/A if (GELF_ST_BIND(sym.st_info) == binding) { 3557513SN/A symtab->insert(sym.st_value, 3567513SN/A elf_strptr(elf, shdr.sh_link, sym.st_name)); 3577513SN/A } 3587513SN/A } 3597513SN/A } 36010451SN/A ++sec_idx; 3617513SN/A section = elf_getscn(elf, sec_idx); 3629885SN/A } 3639885SN/A 3649885SN/A elf_end(elf); 36510315SN/A 36610036SN/A return found; 36710315SN/A} 3689885SN/A 3699885SN/Abool 37010315SN/AElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask) 37110315SN/A{ 37210315SN/A return loadSomeSymbols(symtab, STB_GLOBAL); 37310315SN/A} 37410315SN/A 37510315SN/Abool 37610315SN/AElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) 37710315SN/A{ 3787513SN/A return loadSomeSymbols(symtab, STB_LOCAL); 37910451SN/A} 3809885SN/A 38110036SN/Abool 38211066Snilay@cs.wisc.eduElfObject::loadSections(Port *memPort, Addr addrMask) 38311066Snilay@cs.wisc.edu{ 38411388Ssteve.reinhardt@amd.com if (!ObjectFile::loadSections(memPort, addrMask)) 38511066Snilay@cs.wisc.edu return false; 38610451SN/A 38711066Snilay@cs.wisc.edu vector<Segment>::iterator extraIt; 3889885SN/A for (extraIt = extraSegments.begin(); 3897524SN/A extraIt != extraSegments.end(); extraIt++) { 39011066Snilay@cs.wisc.edu if (!loadSection(&(*extraIt), memPort, addrMask)) { 3919265SN/A return false; 3928893SN/A } 3937513SN/A } 3947513SN/A return true; 3958983SN/A} 3969265SN/A 3979885SN/Avoid 3989885SN/AElfObject::getSections() 39910036SN/A{ 4008983SN/A Elf *elf; 4017513SN/A int sec_idx = 1; // there is a 0 but it is nothing, go figure 4027513SN/A Elf_Scn *section; 4037513SN/A GElf_Shdr shdr; 4047513SN/A 4058893SN/A GElf_Ehdr ehdr; 4067513SN/A 4079885SN/A assert(!sectionNames.size()); 4089885SN/A 40910036SN/A // check that header matches library version 4109885SN/A if (elf_version(EV_CURRENT) == EV_NONE) 4119885SN/A panic("wrong elf version number!"); 412 413 // get a pointer to elf structure 414 elf = elf_memory((char*)fileData,len); 415 assert(elf != NULL); 416 417 // Check that we actually have a elf file 418 if (gelf_getehdr(elf, &ehdr) ==0) { 419 panic("Not ELF, shouldn't be here"); 420 } 421 422 // Get the first section 423 section = elf_getscn(elf, sec_idx); 424 425 // While there are no more sections 426 while (section != NULL) { 427 gelf_getshdr(section, &shdr); 428 sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)); 429 section = elf_getscn(elf, ++sec_idx); 430 } // while sections 431} 432 433bool 434ElfObject::sectionExists(string sec) 435{ 436 if (!sectionNames.size()) 437 getSections(); 438 return sectionNames.find(sec) != sectionNames.end(); 439} 440 441 442