elf_object.cc revision 5616
12391SN/A/* 28931Sandreas.hansson@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 37733SAli.Saidi@ARM.com * All rights reserved. 47733SAli.Saidi@ARM.com * 57733SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67733SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77733SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87733SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97733SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107733SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117733SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127733SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137733SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 142391SN/A * this software without specific prior written permission. 152391SN/A * 162391SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172391SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182391SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192391SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202391SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212391SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222391SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232391SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242391SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252391SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262391SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272391SN/A * 282391SN/A * Authors: Steve Reinhardt 292391SN/A * Ali Saidi 302391SN/A */ 312391SN/A 322391SN/A#include <cassert> 332391SN/A#include <string> 342391SN/A 352391SN/A#include "gelf.h" 362665Ssaidi@eecs.umich.edu 378931Sandreas.hansson@arm.com#include "base/loader/elf_object.hh" 382391SN/A#include "base/loader/symtab.hh" 392391SN/A#include "base/misc.hh" 409293Sandreas.hansson@arm.com#include "base/trace.hh" // for DPRINTF 419293Sandreas.hansson@arm.com#include "sim/byteswap.hh" 429293Sandreas.hansson@arm.com 439293Sandreas.hansson@arm.comusing namespace std; 449293Sandreas.hansson@arm.com 459293Sandreas.hansson@arm.comObjectFile * 469293Sandreas.hansson@arm.comElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) 479293Sandreas.hansson@arm.com{ 489293Sandreas.hansson@arm.com Elf *elf; 499293Sandreas.hansson@arm.com GElf_Ehdr ehdr; 509293Sandreas.hansson@arm.com Arch arch = UnknownArch; 519293Sandreas.hansson@arm.com OpSys opSys = UnknownOpSys; 529293Sandreas.hansson@arm.com 539356Snilay@cs.wisc.edu // check that header matches library version 548931Sandreas.hansson@arm.com if (elf_version(EV_CURRENT) == EV_NONE) 559293Sandreas.hansson@arm.com panic("wrong elf version number!"); 569293Sandreas.hansson@arm.com 572394SN/A // get a pointer to elf structure 582394SN/A elf = elf_memory((char*)data,len); 592391SN/A // will only fail if fd is invalid 602391SN/A assert(elf != NULL); 619293Sandreas.hansson@arm.com 629293Sandreas.hansson@arm.com // Check that we actually have a elf file 639293Sandreas.hansson@arm.com if (gelf_getehdr(elf, &ehdr) ==0) { 642391SN/A DPRINTFR(Loader, "Not ELF\n"); 659293Sandreas.hansson@arm.com elf_end(elf); 669293Sandreas.hansson@arm.com return NULL; 678931Sandreas.hansson@arm.com } else { 688931Sandreas.hansson@arm.com //Detect the architecture 698931Sandreas.hansson@arm.com //Since we don't know how to check for alpha right now, we'll 708931Sandreas.hansson@arm.com //just assume if it wasn't something else and it's 64 bit, that's 718931Sandreas.hansson@arm.com //what it must be. 722391SN/A if (ehdr.e_machine == EM_SPARC64 || 738931Sandreas.hansson@arm.com (ehdr.e_machine == EM_SPARC && 748931Sandreas.hansson@arm.com ehdr.e_ident[EI_CLASS] == ELFCLASS64)|| 758931Sandreas.hansson@arm.com ehdr.e_machine == EM_SPARCV9) { 768931Sandreas.hansson@arm.com arch = ObjectFile::SPARC64; 778931Sandreas.hansson@arm.com } else if (ehdr.e_machine == EM_SPARC32PLUS || 788931Sandreas.hansson@arm.com (ehdr.e_machine == EM_SPARC && 798931Sandreas.hansson@arm.com ehdr.e_ident[EI_CLASS] == ELFCLASS32)) { 808931Sandreas.hansson@arm.com arch = ObjectFile::SPARC32; 819293Sandreas.hansson@arm.com } else if (ehdr.e_machine == EM_MIPS 829293Sandreas.hansson@arm.com && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 839293Sandreas.hansson@arm.com if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { 849293Sandreas.hansson@arm.com arch = ObjectFile::Mips; 859293Sandreas.hansson@arm.com } else { 869293Sandreas.hansson@arm.com fatal("The binary you're trying to load is compiled for big " 879293Sandreas.hansson@arm.com "endian MIPS. M5\nonly supports little endian MIPS. " 889293Sandreas.hansson@arm.com "Please recompile your binary.\n"); 899293Sandreas.hansson@arm.com } 909293Sandreas.hansson@arm.com } else if (ehdr.e_machine == EM_X86_64 && 919293Sandreas.hansson@arm.com ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 929293Sandreas.hansson@arm.com //In the future, we might want to differentiate between 32 bit 939293Sandreas.hansson@arm.com //and 64 bit x86 processes in case there are differences in their 949293Sandreas.hansson@arm.com //initial stack frame. 958931Sandreas.hansson@arm.com arch = ObjectFile::X86; 969293Sandreas.hansson@arm.com } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 979293Sandreas.hansson@arm.com arch = ObjectFile::Alpha; 989293Sandreas.hansson@arm.com } else if (ehdr.e_machine == EM_ARM) { 999293Sandreas.hansson@arm.com arch = ObjectFile::Arm; 1009293Sandreas.hansson@arm.com } else { 1019293Sandreas.hansson@arm.com warn("Unknown architecture: %d\n", ehdr.e_machine); 1029293Sandreas.hansson@arm.com arch = ObjectFile::UnknownArch; 1039293Sandreas.hansson@arm.com } 1049293Sandreas.hansson@arm.com 1059293Sandreas.hansson@arm.com //Detect the operating system 1069293Sandreas.hansson@arm.com switch (ehdr.e_ident[EI_OSABI]) 1079293Sandreas.hansson@arm.com { 1089293Sandreas.hansson@arm.com 1099293Sandreas.hansson@arm.com case ELFOSABI_LINUX: 1109293Sandreas.hansson@arm.com case ELFOSABI_ARM: 1119293Sandreas.hansson@arm.com opSys = ObjectFile::Linux; 1129293Sandreas.hansson@arm.com break; 1139293Sandreas.hansson@arm.com case ELFOSABI_SOLARIS: 1149293Sandreas.hansson@arm.com opSys = ObjectFile::Solaris; 1159293Sandreas.hansson@arm.com break; 1169293Sandreas.hansson@arm.com case ELFOSABI_TRU64: 1179293Sandreas.hansson@arm.com opSys = ObjectFile::Tru64; 1189293Sandreas.hansson@arm.com break; 1199293Sandreas.hansson@arm.com default: 1209293Sandreas.hansson@arm.com opSys = ObjectFile::UnknownOpSys; 1219293Sandreas.hansson@arm.com } 1229293Sandreas.hansson@arm.com 1239293Sandreas.hansson@arm.com //take a look at the .note.ABI section 1249293Sandreas.hansson@arm.com //It can let us know what's what. 1259293Sandreas.hansson@arm.com if (opSys == ObjectFile::UnknownOpSys) { 1269293Sandreas.hansson@arm.com Elf_Scn *section; 1279293Sandreas.hansson@arm.com GElf_Shdr shdr; 1289293Sandreas.hansson@arm.com Elf_Data *data; 1299293Sandreas.hansson@arm.com uint32_t osAbi;; 1309293Sandreas.hansson@arm.com int secIdx = 1; 1319293Sandreas.hansson@arm.com 1329293Sandreas.hansson@arm.com // Get the first section 1339293Sandreas.hansson@arm.com section = elf_getscn(elf, secIdx); 1349293Sandreas.hansson@arm.com 1359293Sandreas.hansson@arm.com // While there are no more sections 1369293Sandreas.hansson@arm.com while (section != NULL && opSys == ObjectFile::UnknownOpSys) { 1379293Sandreas.hansson@arm.com gelf_getshdr(section, &shdr); 1389293Sandreas.hansson@arm.com if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", 1399293Sandreas.hansson@arm.com elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 1409293Sandreas.hansson@arm.com // we have found a ABI note section 1419293Sandreas.hansson@arm.com // Check the 5th 32bit word for OS 0 == linux, 1 == hurd, 1429293Sandreas.hansson@arm.com // 2 == solaris, 3 == freebsd 1439293Sandreas.hansson@arm.com data = elf_rawdata(section, NULL); 1449293Sandreas.hansson@arm.com assert(data->d_buf); 1459293Sandreas.hansson@arm.com if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 1469293Sandreas.hansson@arm.com osAbi = htole(((uint32_t*)data->d_buf)[4]); 1479293Sandreas.hansson@arm.com else 1489293Sandreas.hansson@arm.com osAbi = htobe(((uint32_t*)data->d_buf)[4]); 1499293Sandreas.hansson@arm.com 1509293Sandreas.hansson@arm.com switch(osAbi) { 1519293Sandreas.hansson@arm.com case 0: 1529293Sandreas.hansson@arm.com opSys = ObjectFile::Linux; 1539293Sandreas.hansson@arm.com break; 1549293Sandreas.hansson@arm.com case 2: 1559293Sandreas.hansson@arm.com opSys = ObjectFile::Solaris; 1569293Sandreas.hansson@arm.com break; 1579293Sandreas.hansson@arm.com } 1589293Sandreas.hansson@arm.com } // if section found 1599293Sandreas.hansson@arm.com if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1609293Sandreas.hansson@arm.com opSys = ObjectFile::Solaris; 1619293Sandreas.hansson@arm.com if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1629293Sandreas.hansson@arm.com opSys = ObjectFile::Solaris; 1639293Sandreas.hansson@arm.com 1649293Sandreas.hansson@arm.com section = elf_getscn(elf, ++secIdx); 1659293Sandreas.hansson@arm.com } // while sections 1669293Sandreas.hansson@arm.com } 1679293Sandreas.hansson@arm.com 1689293Sandreas.hansson@arm.com ElfObject * result = new ElfObject(fname, fd, len, data, arch, opSys); 1699293Sandreas.hansson@arm.com 1709293Sandreas.hansson@arm.com //The number of headers in the file 1719293Sandreas.hansson@arm.com result->_programHeaderCount = ehdr.e_phnum; 1729293Sandreas.hansson@arm.com //Record the size of each entry 1739293Sandreas.hansson@arm.com result->_programHeaderSize = ehdr.e_phentsize; 1749293Sandreas.hansson@arm.com if(result->_programHeaderCount) //If there is a program header table 1759293Sandreas.hansson@arm.com { 1769293Sandreas.hansson@arm.com //Figure out the virtual address of the header table in the 1779293Sandreas.hansson@arm.com //final memory image. We use the program headers themselves 1789293Sandreas.hansson@arm.com //to translate from a file offset to the address in the image. 1799293Sandreas.hansson@arm.com GElf_Phdr phdr; 1808931Sandreas.hansson@arm.com uint64_t e_phoff = ehdr.e_phoff; 1819293Sandreas.hansson@arm.com result->_programHeaderTable = 0; 1829293Sandreas.hansson@arm.com for(int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++) 1839293Sandreas.hansson@arm.com { 1849293Sandreas.hansson@arm.com gelf_getphdr(elf, hdrnum, &phdr); 1859293Sandreas.hansson@arm.com //Check if we've found the segment with the headers in it 1869293Sandreas.hansson@arm.com if(phdr.p_offset <= e_phoff && 1879293Sandreas.hansson@arm.com phdr.p_offset + phdr.p_filesz > e_phoff) 1889293Sandreas.hansson@arm.com { 1898931Sandreas.hansson@arm.com result->_programHeaderTable = phdr.p_paddr + e_phoff; 1908931Sandreas.hansson@arm.com break; 1918931Sandreas.hansson@arm.com } 1929293Sandreas.hansson@arm.com } 1939293Sandreas.hansson@arm.com } 1949293Sandreas.hansson@arm.com else 1959293Sandreas.hansson@arm.com result->_programHeaderTable = 0; 1969293Sandreas.hansson@arm.com 1979293Sandreas.hansson@arm.com 1989293Sandreas.hansson@arm.com elf_end(elf); 1999293Sandreas.hansson@arm.com return result; 2008931Sandreas.hansson@arm.com } 2018931Sandreas.hansson@arm.com} 2028931Sandreas.hansson@arm.com 2038931Sandreas.hansson@arm.com 2048931Sandreas.hansson@arm.comElfObject::ElfObject(const string &_filename, int _fd, 2058931Sandreas.hansson@arm.com size_t _len, uint8_t *_data, 2069235Sandreas.hansson@arm.com Arch _arch, OpSys _opSys) 2078931Sandreas.hansson@arm.com : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys) 2088931Sandreas.hansson@arm.com 2098931Sandreas.hansson@arm.com{ 2108931Sandreas.hansson@arm.com Elf *elf; 2118931Sandreas.hansson@arm.com GElf_Ehdr ehdr; 2128931Sandreas.hansson@arm.com 2138851Sandreas.hansson@arm.com // check that header matches library version 2148851Sandreas.hansson@arm.com if (elf_version(EV_CURRENT) == EV_NONE) 2158931Sandreas.hansson@arm.com panic("wrong elf version number!"); 2165477Snate@binkert.org 2178931Sandreas.hansson@arm.com // get a pointer to elf structure 2188931Sandreas.hansson@arm.com elf = elf_memory((char*)fileData,len); 2198931Sandreas.hansson@arm.com // will only fail if fd is invalid 2207730SAli.Saidi@ARM.com assert(elf != NULL); 2218931Sandreas.hansson@arm.com 2228931Sandreas.hansson@arm.com // Check that we actually have a elf file 2238931Sandreas.hansson@arm.com if (gelf_getehdr(elf, &ehdr) ==0) { 2248931Sandreas.hansson@arm.com panic("Not ELF, shouldn't be here"); 2258931Sandreas.hansson@arm.com } 2268931Sandreas.hansson@arm.com 2278931Sandreas.hansson@arm.com entry = ehdr.e_entry; 2288931Sandreas.hansson@arm.com 2298931Sandreas.hansson@arm.com // initialize segment sizes to 0 in case they're not present 2308931Sandreas.hansson@arm.com text.size = data.size = bss.size = 0; 2318931Sandreas.hansson@arm.com 2327730SAli.Saidi@ARM.com int secIdx = 1; 2332391SN/A Elf_Scn *section; 2348931Sandreas.hansson@arm.com GElf_Shdr shdr; 2352391SN/A 2362391SN/A // The first address of some important sections. 2372541SN/A Addr textSecStart = 0; 2388931Sandreas.hansson@arm.com Addr dataSecStart = 0; 2392541SN/A Addr bssSecStart = 0; 2408931Sandreas.hansson@arm.com 2418931Sandreas.hansson@arm.com // Get the first section 2429235Sandreas.hansson@arm.com section = elf_getscn(elf, secIdx); 2438931Sandreas.hansson@arm.com 2448931Sandreas.hansson@arm.com // Find the beginning of the most interesting sections. 2452391SN/A while (section != NULL) { 2462391SN/A gelf_getshdr(section, &shdr); 2478719SAli.Saidi@ARM.com char * secName = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 2488931Sandreas.hansson@arm.com 2498719SAli.Saidi@ARM.com if (!strcmp(".text", secName)) { 2508931Sandreas.hansson@arm.com textSecStart = shdr.sh_addr; 2518931Sandreas.hansson@arm.com } else if (!strcmp(".data", secName)) { 2529235Sandreas.hansson@arm.com dataSecStart = shdr.sh_addr; 2538931Sandreas.hansson@arm.com } else if (!strcmp(".bss", secName)) { 2548931Sandreas.hansson@arm.com bssSecStart = shdr.sh_addr; 2558719SAli.Saidi@ARM.com } 2569293Sandreas.hansson@arm.com 2579293Sandreas.hansson@arm.com section = elf_getscn(elf, ++secIdx); 2589293Sandreas.hansson@arm.com } 2599293Sandreas.hansson@arm.com 2609293Sandreas.hansson@arm.com // Go through all the segments in the program, record them, and scrape 2619293Sandreas.hansson@arm.com // out information about the text, data, and bss areas needed by other 2629293Sandreas.hansson@arm.com // code. 2639293Sandreas.hansson@arm.com for (int i = 0; i < ehdr.e_phnum; ++i) { 2649293Sandreas.hansson@arm.com GElf_Phdr phdr; 2659293Sandreas.hansson@arm.com if (gelf_getphdr(elf, i, &phdr) == 0) { 2669293Sandreas.hansson@arm.com panic("gelf_getphdr failed for segment %d.", i); 2679293Sandreas.hansson@arm.com } 2689293Sandreas.hansson@arm.com 2699293Sandreas.hansson@arm.com // for now we don't care about non-loadable segments 2709293Sandreas.hansson@arm.com if (!(phdr.p_type & PT_LOAD)) 2719293Sandreas.hansson@arm.com continue; 2729293Sandreas.hansson@arm.com 2739293Sandreas.hansson@arm.com // Check to see if this segment contains the bss section. 2749293Sandreas.hansson@arm.com if (phdr.p_paddr <= bssSecStart && 2759293Sandreas.hansson@arm.com phdr.p_paddr + phdr.p_memsz > bssSecStart && 2769293Sandreas.hansson@arm.com phdr.p_memsz - phdr.p_filesz > 0) { 2779293Sandreas.hansson@arm.com bss.baseAddr = phdr.p_paddr + phdr.p_filesz; 2789293Sandreas.hansson@arm.com bss.size = phdr.p_memsz - phdr.p_filesz; 2799293Sandreas.hansson@arm.com bss.fileImage = NULL; 2809293Sandreas.hansson@arm.com } 2819293Sandreas.hansson@arm.com 2829293Sandreas.hansson@arm.com // Check to see if this is the text or data segment 2839293Sandreas.hansson@arm.com if (phdr.p_vaddr <= textSecStart && 2849293Sandreas.hansson@arm.com phdr.p_vaddr + phdr.p_filesz > textSecStart) { 2859293Sandreas.hansson@arm.com text.baseAddr = phdr.p_paddr; 2869293Sandreas.hansson@arm.com text.size = phdr.p_filesz; 2879293Sandreas.hansson@arm.com text.fileImage = fileData + phdr.p_offset; 2889293Sandreas.hansson@arm.com } else if (phdr.p_vaddr <= dataSecStart && 2899293Sandreas.hansson@arm.com phdr.p_vaddr + phdr.p_filesz > dataSecStart) { 2909293Sandreas.hansson@arm.com data.baseAddr = phdr.p_paddr; 2919293Sandreas.hansson@arm.com data.size = phdr.p_filesz; 2929293Sandreas.hansson@arm.com data.fileImage = fileData + phdr.p_offset; 2939293Sandreas.hansson@arm.com } else { 2949293Sandreas.hansson@arm.com Segment extra; 2959293Sandreas.hansson@arm.com extra.baseAddr = phdr.p_paddr; 2969293Sandreas.hansson@arm.com extra.size = phdr.p_filesz; 2979293Sandreas.hansson@arm.com extra.fileImage = fileData + phdr.p_offset; 2989293Sandreas.hansson@arm.com extraSegments.push_back(extra); 2999293Sandreas.hansson@arm.com } 3009293Sandreas.hansson@arm.com } 3019293Sandreas.hansson@arm.com 3029293Sandreas.hansson@arm.com // should have found at least one loadable segment 3039293Sandreas.hansson@arm.com assert(text.size != 0); 3049293Sandreas.hansson@arm.com 3059293Sandreas.hansson@arm.com DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", 3069293Sandreas.hansson@arm.com text.baseAddr, text.size, data.baseAddr, data.size, 3079293Sandreas.hansson@arm.com bss.baseAddr, bss.size); 3089293Sandreas.hansson@arm.com 3099293Sandreas.hansson@arm.com elf_end(elf); 3109293Sandreas.hansson@arm.com 3119293Sandreas.hansson@arm.com // We will actually read the sections when we need to load them 3129293Sandreas.hansson@arm.com} 3139293Sandreas.hansson@arm.com 3149293Sandreas.hansson@arm.com 3159293Sandreas.hansson@arm.combool 3169293Sandreas.hansson@arm.comElfObject::loadSomeSymbols(SymbolTable *symtab, int binding) 3179293Sandreas.hansson@arm.com{ 3189293Sandreas.hansson@arm.com Elf *elf; 3199293Sandreas.hansson@arm.com int sec_idx = 1; // there is a 0 but it is nothing, go figure 3209293Sandreas.hansson@arm.com Elf_Scn *section; 3219293Sandreas.hansson@arm.com GElf_Shdr shdr; 3229293Sandreas.hansson@arm.com Elf_Data *data; 3239293Sandreas.hansson@arm.com int count, ii; 3249293Sandreas.hansson@arm.com bool found = false; 3259293Sandreas.hansson@arm.com GElf_Sym sym; 3269293Sandreas.hansson@arm.com 3279293Sandreas.hansson@arm.com if (!symtab) 3289293Sandreas.hansson@arm.com return false; 3299293Sandreas.hansson@arm.com 3309293Sandreas.hansson@arm.com // check that header matches library version 3319293Sandreas.hansson@arm.com if (elf_version(EV_CURRENT) == EV_NONE) 3329293Sandreas.hansson@arm.com panic("wrong elf version number!"); 3339293Sandreas.hansson@arm.com 3349293Sandreas.hansson@arm.com // get a pointer to elf structure 3359293Sandreas.hansson@arm.com elf = elf_memory((char*)fileData,len); 3369293Sandreas.hansson@arm.com 3379293Sandreas.hansson@arm.com assert(elf != NULL); 3389293Sandreas.hansson@arm.com 3399293Sandreas.hansson@arm.com // Get the first section 3409293Sandreas.hansson@arm.com section = elf_getscn(elf, sec_idx); 3419293Sandreas.hansson@arm.com 3429293Sandreas.hansson@arm.com // While there are no more sections 3439293Sandreas.hansson@arm.com while (section != NULL) { 3449293Sandreas.hansson@arm.com gelf_getshdr(section, &shdr); 3459293Sandreas.hansson@arm.com 3469293Sandreas.hansson@arm.com if (shdr.sh_type == SHT_SYMTAB) { 3479293Sandreas.hansson@arm.com found = true; 3489293Sandreas.hansson@arm.com data = elf_getdata(section, NULL); 3499293Sandreas.hansson@arm.com count = shdr.sh_size / shdr.sh_entsize; 3509293Sandreas.hansson@arm.com DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 3519293Sandreas.hansson@arm.com 3529293Sandreas.hansson@arm.com // loop through all the symbols, only loading global ones 3539293Sandreas.hansson@arm.com for (ii = 0; ii < count; ++ii) { 3549293Sandreas.hansson@arm.com gelf_getsym(data, ii, &sym); 3559293Sandreas.hansson@arm.com if (GELF_ST_BIND(sym.st_info) == binding) { 3569293Sandreas.hansson@arm.com symtab->insert(sym.st_value, 3579293Sandreas.hansson@arm.com elf_strptr(elf, shdr.sh_link, sym.st_name)); 3589293Sandreas.hansson@arm.com } 3599293Sandreas.hansson@arm.com } 3609293Sandreas.hansson@arm.com } 3619293Sandreas.hansson@arm.com ++sec_idx; 3629293Sandreas.hansson@arm.com section = elf_getscn(elf, sec_idx); 3639293Sandreas.hansson@arm.com } 3649293Sandreas.hansson@arm.com 3659293Sandreas.hansson@arm.com elf_end(elf); 3669293Sandreas.hansson@arm.com 3679293Sandreas.hansson@arm.com return found; 3689293Sandreas.hansson@arm.com} 3699293Sandreas.hansson@arm.com 3709293Sandreas.hansson@arm.combool 3719293Sandreas.hansson@arm.comElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask) 3729293Sandreas.hansson@arm.com{ 3739293Sandreas.hansson@arm.com return loadSomeSymbols(symtab, STB_GLOBAL); 3749293Sandreas.hansson@arm.com} 3759293Sandreas.hansson@arm.com 3769293Sandreas.hansson@arm.combool 3779293Sandreas.hansson@arm.comElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) 3789293Sandreas.hansson@arm.com{ 3799293Sandreas.hansson@arm.com return loadSomeSymbols(symtab, STB_LOCAL); 3809293Sandreas.hansson@arm.com} 3819293Sandreas.hansson@arm.com 3829293Sandreas.hansson@arm.combool 3839293Sandreas.hansson@arm.comElfObject::loadSections(Port *memPort, Addr addrMask) 3849293Sandreas.hansson@arm.com{ 3859293Sandreas.hansson@arm.com if (!ObjectFile::loadSections(memPort, addrMask)) 3869293Sandreas.hansson@arm.com return false; 3879293Sandreas.hansson@arm.com 3889293Sandreas.hansson@arm.com vector<Segment>::iterator extraIt; 3899293Sandreas.hansson@arm.com for (extraIt = extraSegments.begin(); 3909293Sandreas.hansson@arm.com extraIt != extraSegments.end(); extraIt++) { 3919293Sandreas.hansson@arm.com if (!loadSection(&(*extraIt), memPort, addrMask)) { 3929293Sandreas.hansson@arm.com return false; 3939293Sandreas.hansson@arm.com } 3949293Sandreas.hansson@arm.com } 3959293Sandreas.hansson@arm.com return true; 3969293Sandreas.hansson@arm.com} 3979293Sandreas.hansson@arm.com 3989293Sandreas.hansson@arm.comvoid 3999293Sandreas.hansson@arm.comElfObject::getSections() 4009293Sandreas.hansson@arm.com{ 4019293Sandreas.hansson@arm.com Elf *elf; 4029293Sandreas.hansson@arm.com int sec_idx = 1; // there is a 0 but it is nothing, go figure 4039293Sandreas.hansson@arm.com Elf_Scn *section; 4049293Sandreas.hansson@arm.com GElf_Shdr shdr; 4059293Sandreas.hansson@arm.com 4069293Sandreas.hansson@arm.com GElf_Ehdr ehdr; 4079293Sandreas.hansson@arm.com 4089293Sandreas.hansson@arm.com assert(!sectionNames.size()); 4099293Sandreas.hansson@arm.com 4109293Sandreas.hansson@arm.com // check that header matches library version 4119293Sandreas.hansson@arm.com if (elf_version(EV_CURRENT) == EV_NONE) 4129293Sandreas.hansson@arm.com panic("wrong elf version number!"); 4139293Sandreas.hansson@arm.com 4149293Sandreas.hansson@arm.com // get a pointer to elf structure 4159293Sandreas.hansson@arm.com elf = elf_memory((char*)fileData,len); 4169293Sandreas.hansson@arm.com assert(elf != NULL); 4179293Sandreas.hansson@arm.com 4189293Sandreas.hansson@arm.com // Check that we actually have a elf file 4199293Sandreas.hansson@arm.com if (gelf_getehdr(elf, &ehdr) ==0) { 4209293Sandreas.hansson@arm.com panic("Not ELF, shouldn't be here"); 4219293Sandreas.hansson@arm.com } 4229293Sandreas.hansson@arm.com 4239293Sandreas.hansson@arm.com // Get the first section 4249293Sandreas.hansson@arm.com section = elf_getscn(elf, sec_idx); 4259293Sandreas.hansson@arm.com 4269293Sandreas.hansson@arm.com // While there are no more sections 4279293Sandreas.hansson@arm.com while (section != NULL) { 4289293Sandreas.hansson@arm.com gelf_getshdr(section, &shdr); 4299293Sandreas.hansson@arm.com sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)); 4309293Sandreas.hansson@arm.com section = elf_getscn(elf, ++sec_idx); 4319293Sandreas.hansson@arm.com } // while sections 4329293Sandreas.hansson@arm.com} 4339293Sandreas.hansson@arm.com 4349293Sandreas.hansson@arm.combool 4359293Sandreas.hansson@arm.comElfObject::sectionExists(string sec) 4369293Sandreas.hansson@arm.com{ 4379293Sandreas.hansson@arm.com if (!sectionNames.size()) 4389293Sandreas.hansson@arm.com getSections(); 4399293Sandreas.hansson@arm.com return sectionNames.find(sec) != sectionNames.end(); 4409293Sandreas.hansson@arm.com} 4419293Sandreas.hansson@arm.com 4429293Sandreas.hansson@arm.com 4439293Sandreas.hansson@arm.com