elf_object.cc revision 9186
17585SAli.Saidi@arm.com/* 210037SARM gem5 Developers * Copyright (c) 2003-2005 The Regents of The University of Michigan 37585SAli.Saidi@arm.com * All rights reserved. 47585SAli.Saidi@arm.com * 57585SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without 67585SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are 77585SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright 87585SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer; 97585SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright 107585SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the 117585SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution; 127585SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its 137585SAli.Saidi@arm.com * contributors may be used to endorse or promote products derived from 147585SAli.Saidi@arm.com * this software without specific prior written permission. 157585SAli.Saidi@arm.com * 167585SAli.Saidi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177585SAli.Saidi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187585SAli.Saidi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197585SAli.Saidi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207585SAli.Saidi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217585SAli.Saidi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227585SAli.Saidi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237585SAli.Saidi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247585SAli.Saidi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257585SAli.Saidi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267585SAli.Saidi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277585SAli.Saidi@arm.com * 287585SAli.Saidi@arm.com * Authors: Steve Reinhardt 297585SAli.Saidi@arm.com * Ali Saidi 307585SAli.Saidi@arm.com */ 317585SAli.Saidi@arm.com 327585SAli.Saidi@arm.com#include <cassert> 337585SAli.Saidi@arm.com#include <string> 347585SAli.Saidi@arm.com 357585SAli.Saidi@arm.com#include "base/loader/elf_object.hh" 367585SAli.Saidi@arm.com#include "base/loader/symtab.hh" 377585SAli.Saidi@arm.com#include "base/bitfield.hh" 387585SAli.Saidi@arm.com#include "base/misc.hh" 397585SAli.Saidi@arm.com#include "base/trace.hh" 407585SAli.Saidi@arm.com#include "debug/Loader.hh" 417585SAli.Saidi@arm.com#include "sim/byteswap.hh" 427585SAli.Saidi@arm.com#include "gelf.h" 437585SAli.Saidi@arm.com 447585SAli.Saidi@arm.comusing namespace std; 458229Snate@binkert.org 467723SAli.Saidi@ARM.comObjectFile * 479332Sdam.sunwoo@arm.comElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) 489538Satgutier@umich.edu{ 497585SAli.Saidi@arm.com Elf *elf; 507585SAli.Saidi@arm.com GElf_Ehdr ehdr; 519332Sdam.sunwoo@arm.com Arch arch = UnknownArch; 529332Sdam.sunwoo@arm.com OpSys opSys = UnknownOpSys; 537723SAli.Saidi@ARM.com 548245Snate@binkert.org // check that header matches library version 558143SAli.Saidi@ARM.com if (elf_version(EV_CURRENT) == EV_NONE) 568706Sandreas.hansson@arm.com panic("wrong elf version number!"); 577585SAli.Saidi@arm.com 589332Sdam.sunwoo@arm.com // get a pointer to elf structure 597585SAli.Saidi@arm.com elf = elf_memory((char*)data,len); 607585SAli.Saidi@arm.com // will only fail if fd is invalid 618143SAli.Saidi@ARM.com assert(elf != NULL); 627585SAli.Saidi@arm.com 637585SAli.Saidi@arm.com // Check that we actually have a elf file 6410810Sbr@bsdpad.com if (gelf_getehdr(elf, &ehdr) ==0) { 659649SAndreas.Sandberg@ARM.com DPRINTFR(Loader, "Not ELF\n"); 6610822Sandreas.hansson@arm.com elf_end(elf); 677585SAli.Saidi@arm.com return NULL; 689649SAndreas.Sandberg@ARM.com } else { 699649SAndreas.Sandberg@ARM.com //Detect the architecture 709649SAndreas.Sandberg@ARM.com //Since we don't know how to check for alpha right now, we'll 719649SAndreas.Sandberg@ARM.com //just assume if it wasn't something else and it's 64 bit, that's 728885SAli.Saidi@ARM.com //what it must be. 739649SAndreas.Sandberg@ARM.com if (ehdr.e_machine == EM_SPARC64 || 748885SAli.Saidi@ARM.com (ehdr.e_machine == EM_SPARC && 759649SAndreas.Sandberg@ARM.com ehdr.e_ident[EI_CLASS] == ELFCLASS64)|| 769649SAndreas.Sandberg@ARM.com ehdr.e_machine == EM_SPARCV9) { 779649SAndreas.Sandberg@ARM.com arch = ObjectFile::SPARC64; 789649SAndreas.Sandberg@ARM.com } else if (ehdr.e_machine == EM_SPARC32PLUS || 799649SAndreas.Sandberg@ARM.com (ehdr.e_machine == EM_SPARC && 809649SAndreas.Sandberg@ARM.com ehdr.e_ident[EI_CLASS] == ELFCLASS32)) { 818885SAli.Saidi@ARM.com arch = ObjectFile::SPARC32; 828885SAli.Saidi@ARM.com } else if (ehdr.e_machine == EM_MIPS 839934SEric.VanHensbergen@ARM.com && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 849934SEric.VanHensbergen@ARM.com if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { 859934SEric.VanHensbergen@ARM.com arch = ObjectFile::Mips; 869934SEric.VanHensbergen@ARM.com } else { 879934SEric.VanHensbergen@ARM.com fatal("The binary you're trying to load is compiled for big " 889934SEric.VanHensbergen@ARM.com "endian MIPS. M5\nonly supports little endian MIPS. " 898885SAli.Saidi@ARM.com "Please recompile your binary.\n"); 908885SAli.Saidi@ARM.com } 918885SAli.Saidi@ARM.com } else if (ehdr.e_machine == EM_X86_64 && 929934SEric.VanHensbergen@ARM.com ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 939934SEric.VanHensbergen@ARM.com arch = ObjectFile::X86_64; 949934SEric.VanHensbergen@ARM.com } else if (ehdr.e_machine == EM_386 && 959934SEric.VanHensbergen@ARM.com ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 969934SEric.VanHensbergen@ARM.com arch = ObjectFile::I386; 978885SAli.Saidi@ARM.com } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 988706Sandreas.hansson@arm.com arch = ObjectFile::Alpha; 998706Sandreas.hansson@arm.com } else if (ehdr.e_machine == EM_ARM) { 1008706Sandreas.hansson@arm.com if (bits(ehdr.e_entry, 0)) { 1018706Sandreas.hansson@arm.com arch = ObjectFile::Thumb; 1028706Sandreas.hansson@arm.com } else { 1038706Sandreas.hansson@arm.com arch = ObjectFile::Arm; 1048706Sandreas.hansson@arm.com } 1058706Sandreas.hansson@arm.com } else if (ehdr.e_machine == EM_PPC && 1068706Sandreas.hansson@arm.com ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 10710810Sbr@bsdpad.com if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { 1088706Sandreas.hansson@arm.com arch = ObjectFile::Power; 1097585SAli.Saidi@arm.com } else { 1108997Sdam.sunwoo@arm.com fatal("The binary you're trying to load is compiled for " 1118997Sdam.sunwoo@arm.com "little endian Power.\nM5 only supports big " 1128997Sdam.sunwoo@arm.com "endian Power. Please recompile your binary.\n"); 1138997Sdam.sunwoo@arm.com } 1148997Sdam.sunwoo@arm.com } else if (ehdr.e_machine == EM_PPC64) { 1158997Sdam.sunwoo@arm.com fatal("The binary you're trying to load is compiled for 64-bit " 1167585SAli.Saidi@arm.com "Power. M5\n only supports 32-bit Power. Please " 1177585SAli.Saidi@arm.com "recompile your binary.\n"); 1189261Sdam.sunwoo@arm.com } else { 1199261Sdam.sunwoo@arm.com warn("Unknown architecture: %d\n", ehdr.e_machine); 1209261Sdam.sunwoo@arm.com arch = ObjectFile::UnknownArch; 1219261Sdam.sunwoo@arm.com } 1229261Sdam.sunwoo@arm.com 1239261Sdam.sunwoo@arm.com //Detect the operating system 1247585SAli.Saidi@arm.com switch (ehdr.e_ident[EI_OSABI]) 1259261Sdam.sunwoo@arm.com { 1269261Sdam.sunwoo@arm.com 1279261Sdam.sunwoo@arm.com case ELFOSABI_LINUX: 12810037SARM gem5 Developers opSys = ObjectFile::Linux; 12910037SARM gem5 Developers break; 1309261Sdam.sunwoo@arm.com case ELFOSABI_SOLARIS: 1319261Sdam.sunwoo@arm.com opSys = ObjectFile::Solaris; 1329261Sdam.sunwoo@arm.com break; 1339261Sdam.sunwoo@arm.com case ELFOSABI_TRU64: 1349261Sdam.sunwoo@arm.com opSys = ObjectFile::Tru64; 1359538Satgutier@umich.edu break; 1369538Satgutier@umich.edu case ELFOSABI_ARM: 1379538Satgutier@umich.edu opSys = ObjectFile::LinuxArmOABI; 1389538Satgutier@umich.edu break; 1399538Satgutier@umich.edu default: 1409538Satgutier@umich.edu opSys = ObjectFile::UnknownOpSys; 1419538Satgutier@umich.edu } 1429538Satgutier@umich.edu 1439538Satgutier@umich.edu //take a look at the .note.ABI section 1449538Satgutier@umich.edu //It can let us know what's what. 1459538Satgutier@umich.edu if (opSys == ObjectFile::UnknownOpSys) { 1469538Satgutier@umich.edu Elf_Scn *section; 1479538Satgutier@umich.edu GElf_Shdr shdr; 1489538Satgutier@umich.edu Elf_Data *data; 14910037SARM gem5 Developers uint32_t osAbi;; 1509261Sdam.sunwoo@arm.com int secIdx = 1; 1519261Sdam.sunwoo@arm.com 1529261Sdam.sunwoo@arm.com // Get the first section 1539261Sdam.sunwoo@arm.com section = elf_getscn(elf, secIdx); 1549261Sdam.sunwoo@arm.com 1559261Sdam.sunwoo@arm.com // While there are no more sections 1569261Sdam.sunwoo@arm.com while (section != NULL && opSys == ObjectFile::UnknownOpSys) { 1579261Sdam.sunwoo@arm.com gelf_getshdr(section, &shdr); 1589261Sdam.sunwoo@arm.com if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", 1599261Sdam.sunwoo@arm.com elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 1609261Sdam.sunwoo@arm.com // we have found a ABI note section 1619261Sdam.sunwoo@arm.com // Check the 5th 32bit word for OS 0 == linux, 1 == hurd, 1629261Sdam.sunwoo@arm.com // 2 == solaris, 3 == freebsd 1639261Sdam.sunwoo@arm.com data = elf_rawdata(section, NULL); 1649261Sdam.sunwoo@arm.com assert(data->d_buf); 1659290Sandreas.hansson@arm.com if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 1669290Sandreas.hansson@arm.com osAbi = htole(((uint32_t*)data->d_buf)[4]); 1679290Sandreas.hansson@arm.com else 1689290Sandreas.hansson@arm.com osAbi = htobe(((uint32_t*)data->d_buf)[4]); 1699261Sdam.sunwoo@arm.com 1709261Sdam.sunwoo@arm.com switch(osAbi) { 1719261Sdam.sunwoo@arm.com case 0: 1729261Sdam.sunwoo@arm.com opSys = ObjectFile::Linux; 1739261Sdam.sunwoo@arm.com break; 1749261Sdam.sunwoo@arm.com case 2: 1759290Sandreas.hansson@arm.com opSys = ObjectFile::Solaris; 1769290Sandreas.hansson@arm.com break; 1779405Sandreas.hansson@arm.com } 1789261Sdam.sunwoo@arm.com } // if section found 1799290Sandreas.hansson@arm.com if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1809290Sandreas.hansson@arm.com opSys = ObjectFile::Solaris; 1819261Sdam.sunwoo@arm.com if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1829290Sandreas.hansson@arm.com opSys = ObjectFile::Solaris; 1839290Sandreas.hansson@arm.com 1849261Sdam.sunwoo@arm.com section = elf_getscn(elf, ++secIdx); 1859290Sandreas.hansson@arm.com } // while sections 1869261Sdam.sunwoo@arm.com } 1879290Sandreas.hansson@arm.com 1889261Sdam.sunwoo@arm.com ElfObject * result = new ElfObject(fname, fd, len, data, arch, opSys); 1899261Sdam.sunwoo@arm.com 1909261Sdam.sunwoo@arm.com //The number of headers in the file 1919290Sandreas.hansson@arm.com result->_programHeaderCount = ehdr.e_phnum; 1929290Sandreas.hansson@arm.com //Record the size of each entry 1939290Sandreas.hansson@arm.com result->_programHeaderSize = ehdr.e_phentsize; 1949290Sandreas.hansson@arm.com if(result->_programHeaderCount) //If there is a program header table 1959261Sdam.sunwoo@arm.com { 1969261Sdam.sunwoo@arm.com //Figure out the virtual address of the header table in the 1979261Sdam.sunwoo@arm.com //final memory image. We use the program headers themselves 1989261Sdam.sunwoo@arm.com //to translate from a file offset to the address in the image. 19910037SARM gem5 Developers GElf_Phdr phdr; 20010037SARM gem5 Developers uint64_t e_phoff = ehdr.e_phoff; 2019290Sandreas.hansson@arm.com result->_programHeaderTable = 0; 2029290Sandreas.hansson@arm.com for(int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++) 2038931Sandreas.hansson@arm.com { 2047585SAli.Saidi@arm.com gelf_getphdr(elf, hdrnum, &phdr); 20510037SARM gem5 Developers //Check if we've found the segment with the headers in it 2068286SAli.Saidi@ARM.com if(phdr.p_offset <= e_phoff && 2078286SAli.Saidi@ARM.com phdr.p_offset + phdr.p_filesz > e_phoff) 2088286SAli.Saidi@ARM.com { 20910037SARM gem5 Developers result->_programHeaderTable = phdr.p_paddr + e_phoff; 2108286SAli.Saidi@ARM.com break; 2117585SAli.Saidi@arm.com } 2127585SAli.Saidi@arm.com } 2137585SAli.Saidi@arm.com } 2147585SAli.Saidi@arm.com else 2158143SAli.Saidi@ARM.com result->_programHeaderTable = 0; 2168143SAli.Saidi@ARM.com 2178143SAli.Saidi@ARM.com 2188143SAli.Saidi@ARM.com elf_end(elf); 2199332Sdam.sunwoo@arm.com return result; 2209332Sdam.sunwoo@arm.com } 2219332Sdam.sunwoo@arm.com} 2227585SAli.Saidi@arm.com 2237585SAli.Saidi@arm.com 2247585SAli.Saidi@arm.comElfObject::ElfObject(const string &_filename, int _fd, 2257585SAli.Saidi@arm.com size_t _len, uint8_t *_data, 2267585SAli.Saidi@arm.com Arch _arch, OpSys _opSys) 2277585SAli.Saidi@arm.com : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys) 2287585SAli.Saidi@arm.com 2299332Sdam.sunwoo@arm.com{ 2309332Sdam.sunwoo@arm.com Elf *elf; 2319332Sdam.sunwoo@arm.com GElf_Ehdr ehdr; 2329332Sdam.sunwoo@arm.com 2339332Sdam.sunwoo@arm.com // check that header matches library version 2349332Sdam.sunwoo@arm.com if (elf_version(EV_CURRENT) == EV_NONE) 2359332Sdam.sunwoo@arm.com panic("wrong elf version number!"); 2369332Sdam.sunwoo@arm.com 2379332Sdam.sunwoo@arm.com // get a pointer to elf structure 2389332Sdam.sunwoo@arm.com elf = elf_memory((char*)fileData,len); 2399332Sdam.sunwoo@arm.com // will only fail if fd is invalid 2409332Sdam.sunwoo@arm.com assert(elf != NULL); 2419332Sdam.sunwoo@arm.com 2429332Sdam.sunwoo@arm.com // Check that we actually have a elf file 2439332Sdam.sunwoo@arm.com if (gelf_getehdr(elf, &ehdr) ==0) { 2449332Sdam.sunwoo@arm.com panic("Not ELF, shouldn't be here"); 2459332Sdam.sunwoo@arm.com } 2469332Sdam.sunwoo@arm.com 2479332Sdam.sunwoo@arm.com entry = ehdr.e_entry; 2489332Sdam.sunwoo@arm.com 2499332Sdam.sunwoo@arm.com // initialize segment sizes to 0 in case they're not present 2509332Sdam.sunwoo@arm.com text.size = data.size = bss.size = 0; 2519332Sdam.sunwoo@arm.com text.baseAddr = data.baseAddr = bss.baseAddr = 0; 2529332Sdam.sunwoo@arm.com 2539332Sdam.sunwoo@arm.com int secIdx = 1; 2549332Sdam.sunwoo@arm.com Elf_Scn *section; 2559332Sdam.sunwoo@arm.com GElf_Shdr shdr; 2569332Sdam.sunwoo@arm.com 2579332Sdam.sunwoo@arm.com // The first address of some important sections. 2589332Sdam.sunwoo@arm.com Addr textSecStart = 0; 2599332Sdam.sunwoo@arm.com Addr dataSecStart = 0; 2609332Sdam.sunwoo@arm.com Addr bssSecStart = 0; 2619332Sdam.sunwoo@arm.com 2629332Sdam.sunwoo@arm.com // Get the first section 2639332Sdam.sunwoo@arm.com section = elf_getscn(elf, secIdx); 2649332Sdam.sunwoo@arm.com 2659332Sdam.sunwoo@arm.com // Find the beginning of the most interesting sections. 2669332Sdam.sunwoo@arm.com while (section != NULL) { 2679332Sdam.sunwoo@arm.com gelf_getshdr(section, &shdr); 2689332Sdam.sunwoo@arm.com char * secName = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 2699332Sdam.sunwoo@arm.com 2709332Sdam.sunwoo@arm.com if (secName) { 2719332Sdam.sunwoo@arm.com if (!strcmp(".text", secName)) { 2729332Sdam.sunwoo@arm.com textSecStart = shdr.sh_addr; 2739332Sdam.sunwoo@arm.com } else if (!strcmp(".data", secName)) { 2749332Sdam.sunwoo@arm.com dataSecStart = shdr.sh_addr; 2759332Sdam.sunwoo@arm.com } else if (!strcmp(".bss", secName)) { 2769332Sdam.sunwoo@arm.com bssSecStart = shdr.sh_addr; 2779332Sdam.sunwoo@arm.com } 2789332Sdam.sunwoo@arm.com } else { 2799332Sdam.sunwoo@arm.com Elf_Error errorNum = (Elf_Error)elf_errno(); 2809332Sdam.sunwoo@arm.com if (errorNum != ELF_E_NONE) { 2819332Sdam.sunwoo@arm.com const char *errorMessage = elf_errmsg(errorNum); 2829332Sdam.sunwoo@arm.com fatal("Error from libelf: %s.\n", errorMessage); 2839332Sdam.sunwoo@arm.com } 2849332Sdam.sunwoo@arm.com } 2859332Sdam.sunwoo@arm.com 2869332Sdam.sunwoo@arm.com section = elf_getscn(elf, ++secIdx); 2879332Sdam.sunwoo@arm.com } 2889332Sdam.sunwoo@arm.com 2899332Sdam.sunwoo@arm.com // Go through all the segments in the program, record them, and scrape 2909332Sdam.sunwoo@arm.com // out information about the text, data, and bss areas needed by other 2919332Sdam.sunwoo@arm.com // code. 2929332Sdam.sunwoo@arm.com for (int i = 0; i < ehdr.e_phnum; ++i) { 2939332Sdam.sunwoo@arm.com GElf_Phdr phdr; 2949332Sdam.sunwoo@arm.com if (gelf_getphdr(elf, i, &phdr) == 0) { 2959332Sdam.sunwoo@arm.com panic("gelf_getphdr failed for segment %d.", i); 2969332Sdam.sunwoo@arm.com } 2979332Sdam.sunwoo@arm.com 2989332Sdam.sunwoo@arm.com // for now we don't care about non-loadable segments 2999332Sdam.sunwoo@arm.com if (!(phdr.p_type & PT_LOAD)) 3009332Sdam.sunwoo@arm.com continue; 3019332Sdam.sunwoo@arm.com 3029332Sdam.sunwoo@arm.com // Check to see if this segment contains the bss section. 3039332Sdam.sunwoo@arm.com if (phdr.p_paddr <= bssSecStart && 3049332Sdam.sunwoo@arm.com phdr.p_paddr + phdr.p_memsz > bssSecStart && 3059332Sdam.sunwoo@arm.com phdr.p_memsz - phdr.p_filesz > 0) { 3069332Sdam.sunwoo@arm.com bss.baseAddr = phdr.p_paddr + phdr.p_filesz; 3079332Sdam.sunwoo@arm.com bss.size = phdr.p_memsz - phdr.p_filesz; 3089332Sdam.sunwoo@arm.com bss.fileImage = NULL; 3099332Sdam.sunwoo@arm.com } 3109332Sdam.sunwoo@arm.com 3119332Sdam.sunwoo@arm.com // Check to see if this is the text or data segment 3129332Sdam.sunwoo@arm.com if (phdr.p_vaddr <= textSecStart && 3139332Sdam.sunwoo@arm.com phdr.p_vaddr + phdr.p_filesz > textSecStart) { 3149332Sdam.sunwoo@arm.com text.baseAddr = phdr.p_paddr; 3159332Sdam.sunwoo@arm.com text.size = phdr.p_filesz; 3169332Sdam.sunwoo@arm.com text.fileImage = fileData + phdr.p_offset; 3179332Sdam.sunwoo@arm.com } else if (phdr.p_vaddr <= dataSecStart && 3189332Sdam.sunwoo@arm.com phdr.p_vaddr + phdr.p_filesz > dataSecStart) { 3199332Sdam.sunwoo@arm.com data.baseAddr = phdr.p_paddr; 3209332Sdam.sunwoo@arm.com data.size = phdr.p_filesz; 321 data.fileImage = fileData + phdr.p_offset; 322 } else { 323 // If it's none of the above but is loadable, 324 // load the filesize worth of data 325 Segment extra; 326 extra.baseAddr = phdr.p_paddr; 327 extra.size = phdr.p_filesz; 328 extra.fileImage = fileData + phdr.p_offset; 329 extraSegments.push_back(extra); 330 } 331 } 332 333 // should have found at least one loadable segment 334 assert(text.size != 0); 335 336 DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", 337 text.baseAddr, text.size, data.baseAddr, data.size, 338 bss.baseAddr, bss.size); 339 340 elf_end(elf); 341 342 // We will actually read the sections when we need to load them 343} 344 345 346bool 347ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask) 348{ 349 Elf *elf; 350 int sec_idx = 1; // there is a 0 but it is nothing, go figure 351 Elf_Scn *section; 352 GElf_Shdr shdr; 353 Elf_Data *data; 354 int count, ii; 355 bool found = false; 356 GElf_Sym sym; 357 358 if (!symtab) 359 return false; 360 361 // check that header matches library version 362 if (elf_version(EV_CURRENT) == EV_NONE) 363 panic("wrong elf version number!"); 364 365 // get a pointer to elf structure 366 elf = elf_memory((char*)fileData,len); 367 368 assert(elf != NULL); 369 370 // Get the first section 371 section = elf_getscn(elf, sec_idx); 372 373 // While there are no more sections 374 while (section != NULL) { 375 gelf_getshdr(section, &shdr); 376 377 if (shdr.sh_type == SHT_SYMTAB) { 378 found = true; 379 data = elf_getdata(section, NULL); 380 count = shdr.sh_size / shdr.sh_entsize; 381 DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 382 383 // loop through all the symbols, only loading global ones 384 for (ii = 0; ii < count; ++ii) { 385 gelf_getsym(data, ii, &sym); 386 if (GELF_ST_BIND(sym.st_info) == binding) { 387 char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name); 388 if (sym_name && sym_name[0] != '$') { 389 DPRINTF(Loader, "Symbol: %-40s value %#x\n", 390 sym_name, sym.st_value); 391 symtab->insert(sym.st_value & mask, sym_name); 392 } 393 } 394 } 395 } 396 ++sec_idx; 397 section = elf_getscn(elf, sec_idx); 398 } 399 400 elf_end(elf); 401 402 return found; 403} 404 405bool 406ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask) 407{ 408 return loadSomeSymbols(symtab, STB_GLOBAL, addrMask); 409} 410 411bool 412ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) 413{ 414 return loadSomeSymbols(symtab, STB_LOCAL, addrMask); 415} 416 417bool 418ElfObject::loadSections(PortProxy& memProxy, Addr addrMask) 419{ 420 if (!ObjectFile::loadSections(memProxy, addrMask)) 421 return false; 422 423 vector<Segment>::iterator extraIt; 424 for (extraIt = extraSegments.begin(); 425 extraIt != extraSegments.end(); extraIt++) { 426 if (!loadSection(&(*extraIt), memProxy, addrMask)) { 427 return false; 428 } 429 } 430 return true; 431} 432 433void 434ElfObject::getSections() 435{ 436 Elf *elf; 437 int sec_idx = 1; // there is a 0 but it is nothing, go figure 438 Elf_Scn *section; 439 GElf_Shdr shdr; 440 441 GElf_Ehdr ehdr; 442 443 assert(!sectionNames.size()); 444 445 // check that header matches library version 446 if (elf_version(EV_CURRENT) == EV_NONE) 447 panic("wrong elf version number!"); 448 449 // get a pointer to elf structure 450 elf = elf_memory((char*)fileData,len); 451 assert(elf != NULL); 452 453 // Check that we actually have a elf file 454 if (gelf_getehdr(elf, &ehdr) ==0) { 455 panic("Not ELF, shouldn't be here"); 456 } 457 458 // Get the first section 459 section = elf_getscn(elf, sec_idx); 460 461 // While there are no more sections 462 while (section != NULL) { 463 gelf_getshdr(section, &shdr); 464 sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)); 465 section = elf_getscn(elf, ++sec_idx); 466 } // while sections 467} 468 469bool 470ElfObject::sectionExists(string sec) 471{ 472 if (!sectionNames.size()) 473 getSections(); 474 return sectionNames.find(sec) != sectionNames.end(); 475} 476 477 478