elf_object.cc revision 11320
112SN/A/* 210037SARM gem5 Developers * Copyright (c) 2011-2013 ARM Limited 310037SARM gem5 Developers * All rights reserved 410037SARM gem5 Developers * 510037SARM gem5 Developers * The license below extends only to copyright in the software and shall 610037SARM gem5 Developers * not be construed as granting a license to any other intellectual 710037SARM gem5 Developers * property including but not limited to intellectual property relating 810037SARM gem5 Developers * to a hardware implementation of the functionality of the software 910037SARM gem5 Developers * licensed hereunder. You may use the software subject to the license 1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated 1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software, 1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form. 1310037SARM gem5 Developers * 141762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 1512SN/A * All rights reserved. 1612SN/A * 1712SN/A * Redistribution and use in source and binary forms, with or without 1812SN/A * modification, are permitted provided that the following conditions are 1912SN/A * met: redistributions of source code must retain the above copyright 2012SN/A * notice, this list of conditions and the following disclaimer; 2112SN/A * redistributions in binary form must reproduce the above copyright 2212SN/A * notice, this list of conditions and the following disclaimer in the 2312SN/A * documentation and/or other materials provided with the distribution; 2412SN/A * neither the name of the copyright holders nor the names of its 2512SN/A * contributors may be used to endorse or promote products derived from 2612SN/A * this software without specific prior written permission. 2712SN/A * 2812SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2912SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3012SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3112SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3212SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3312SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3412SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3512SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3612SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3712SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3812SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665Ssaidi@eecs.umich.edu * 402665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 412665Ssaidi@eecs.umich.edu * Ali Saidi 4212SN/A */ 4312SN/A 445616Snate@binkert.org#include <cassert> 4512SN/A#include <string> 4612SN/A 4756SN/A#include "base/loader/elf_object.hh" 484484Sbinkertn@umich.edu#include "base/loader/symtab.hh" 498229Snate@binkert.org#include "base/bitfield.hh" 502439SN/A#include "base/misc.hh" 517676Snate@binkert.org#include "base/trace.hh" 528232Snate@binkert.org#include "debug/Loader.hh" 532423SN/A#include "sim/byteswap.hh" 548229Snate@binkert.org#include "gelf.h" 552423SN/A 5612SN/Ausing namespace std; 5712SN/A 5812SN/AObjectFile * 5910880SCurtis.Dunham@arm.comElfObject::tryFile(const string &fname, size_t len, uint8_t *data) 6012SN/A{ 61443SN/A Elf *elf; 62443SN/A GElf_Ehdr ehdr; 632207SN/A Arch arch = UnknownArch; 642207SN/A OpSys opSys = UnknownOpSys; 65443SN/A 66468SN/A // check that header matches library version 671708SN/A if (elf_version(EV_CURRENT) == EV_NONE) 681708SN/A panic("wrong elf version number!"); 69443SN/A 70468SN/A // get a pointer to elf structure 71443SN/A elf = elf_memory((char*)data,len); 72443SN/A assert(elf != NULL); 73443SN/A 74468SN/A // Check that we actually have a elf file 7510037SARM gem5 Developers if (gelf_getehdr(elf, &ehdr) == 0) { 76443SN/A DPRINTFR(Loader, "Not ELF\n"); 77443SN/A elf_end(elf); 78443SN/A return NULL; 792476SN/A } else { 802207SN/A //Detect the architecture 812207SN/A //Since we don't know how to check for alpha right now, we'll 822207SN/A //just assume if it wasn't something else and it's 64 bit, that's 832207SN/A //what it must be. 842207SN/A if (ehdr.e_machine == EM_SPARC64 || 854111Sgblack@eecs.umich.edu (ehdr.e_machine == EM_SPARC && 864111Sgblack@eecs.umich.edu ehdr.e_ident[EI_CLASS] == ELFCLASS64)|| 872620SN/A ehdr.e_machine == EM_SPARCV9) { 884111Sgblack@eecs.umich.edu arch = ObjectFile::SPARC64; 894111Sgblack@eecs.umich.edu } else if (ehdr.e_machine == EM_SPARC32PLUS || 904111Sgblack@eecs.umich.edu (ehdr.e_machine == EM_SPARC && 914111Sgblack@eecs.umich.edu ehdr.e_ident[EI_CLASS] == ELFCLASS32)) { 924111Sgblack@eecs.umich.edu arch = ObjectFile::SPARC32; 932207SN/A } else if (ehdr.e_machine == EM_MIPS 942207SN/A && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 955383Sgblack@eecs.umich.edu if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { 965383Sgblack@eecs.umich.edu arch = ObjectFile::Mips; 975383Sgblack@eecs.umich.edu } else { 985383Sgblack@eecs.umich.edu fatal("The binary you're trying to load is compiled for big " 995383Sgblack@eecs.umich.edu "endian MIPS. M5\nonly supports little endian MIPS. " 1005383Sgblack@eecs.umich.edu "Please recompile your binary.\n"); 1015383Sgblack@eecs.umich.edu } 1024166Sgblack@eecs.umich.edu } else if (ehdr.e_machine == EM_X86_64 && 1034166Sgblack@eecs.umich.edu ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 1045874Sgblack@eecs.umich.edu arch = ObjectFile::X86_64; 1055874Sgblack@eecs.umich.edu } else if (ehdr.e_machine == EM_386 && 1065874Sgblack@eecs.umich.edu ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 1075874Sgblack@eecs.umich.edu arch = ObjectFile::I386; 10810037SARM gem5 Developers } else if (ehdr.e_machine == EM_ARM && 10910037SARM gem5 Developers ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 1107095Sgblack@eecs.umich.edu if (bits(ehdr.e_entry, 0)) { 1117095Sgblack@eecs.umich.edu arch = ObjectFile::Thumb; 1127095Sgblack@eecs.umich.edu } else { 1137095Sgblack@eecs.umich.edu arch = ObjectFile::Arm; 1147095Sgblack@eecs.umich.edu } 11510037SARM gem5 Developers } else if ((ehdr.e_machine == EM_AARCH64) && 11610037SARM gem5 Developers ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 11710037SARM gem5 Developers arch = ObjectFile::Arm64; 11810037SARM gem5 Developers } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 11910037SARM gem5 Developers arch = ObjectFile::Alpha; 1206691Stjones1@inf.ed.ac.uk } else if (ehdr.e_machine == EM_PPC && 1216691Stjones1@inf.ed.ac.uk ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 12210037SARM gem5 Developers if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { 12310037SARM gem5 Developers arch = ObjectFile::Power; 12410037SARM gem5 Developers } else { 12510037SARM gem5 Developers fatal("The binary you're trying to load is compiled for " 1266691Stjones1@inf.ed.ac.uk "little endian Power.\nM5 only supports big " 1276691Stjones1@inf.ed.ac.uk "endian Power. Please recompile your binary.\n"); 12810037SARM gem5 Developers } 1296691Stjones1@inf.ed.ac.uk } else if (ehdr.e_machine == EM_PPC64) { 1306691Stjones1@inf.ed.ac.uk fatal("The binary you're trying to load is compiled for 64-bit " 1316691Stjones1@inf.ed.ac.uk "Power. M5\n only supports 32-bit Power. Please " 1326691Stjones1@inf.ed.ac.uk "recompile your binary.\n"); 1332207SN/A } else { 1342600SN/A warn("Unknown architecture: %d\n", ehdr.e_machine); 1352207SN/A arch = ObjectFile::UnknownArch; 1362207SN/A } 1372207SN/A 1382207SN/A //Detect the operating system 13910037SARM gem5 Developers switch (ehdr.e_ident[EI_OSABI]) { 1402207SN/A case ELFOSABI_LINUX: 1412207SN/A opSys = ObjectFile::Linux; 1422207SN/A break; 1432207SN/A case ELFOSABI_SOLARIS: 1442207SN/A opSys = ObjectFile::Solaris; 1452238SN/A break; 1462207SN/A case ELFOSABI_TRU64: 1472207SN/A opSys = ObjectFile::Tru64; 1482238SN/A break; 1496392Ssaidi@eecs.umich.edu case ELFOSABI_ARM: 1506392Ssaidi@eecs.umich.edu opSys = ObjectFile::LinuxArmOABI; 1516392Ssaidi@eecs.umich.edu break; 15210810Sbr@bsdpad.com case ELFOSABI_FREEBSD: 15310810Sbr@bsdpad.com opSys = ObjectFile::FreeBSD; 15410810Sbr@bsdpad.com break; 1552207SN/A default: 1562207SN/A opSys = ObjectFile::UnknownOpSys; 1572207SN/A } 1582207SN/A 1592238SN/A //take a look at the .note.ABI section 1602238SN/A //It can let us know what's what. 1612600SN/A if (opSys == ObjectFile::UnknownOpSys) { 1622238SN/A Elf_Scn *section; 1632238SN/A GElf_Shdr shdr; 1642238SN/A Elf_Data *data; 16510810Sbr@bsdpad.com uint32_t osAbi; 16610810Sbr@bsdpad.com uint32_t *elem; 1672238SN/A int secIdx = 1; 1682238SN/A 1692238SN/A // Get the first section 1702238SN/A section = elf_getscn(elf, secIdx); 1712238SN/A 1722238SN/A // While there are no more sections 1732600SN/A while (section != NULL && opSys == ObjectFile::UnknownOpSys) { 1742238SN/A gelf_getshdr(section, &shdr); 1752238SN/A if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", 1762238SN/A elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 1772238SN/A // we have found a ABI note section 1782238SN/A // Check the 5th 32bit word for OS 0 == linux, 1 == hurd, 1792238SN/A // 2 == solaris, 3 == freebsd 1802238SN/A data = elf_rawdata(section, NULL); 1812238SN/A assert(data->d_buf); 1822238SN/A if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 1832238SN/A osAbi = htole(((uint32_t*)data->d_buf)[4]); 1842238SN/A else 1852238SN/A osAbi = htobe(((uint32_t*)data->d_buf)[4]); 1862238SN/A 1872238SN/A switch(osAbi) { 1882238SN/A case 0: 1892238SN/A opSys = ObjectFile::Linux; 1902238SN/A break; 1912238SN/A case 2: 1922238SN/A opSys = ObjectFile::Solaris; 1932238SN/A break; 1942238SN/A } 1952238SN/A } // if section found 1962600SN/A if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1972600SN/A opSys = ObjectFile::Solaris; 1982600SN/A if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1992600SN/A opSys = ObjectFile::Solaris; 20010810Sbr@bsdpad.com if (shdr.sh_type == SHT_NOTE && !strcmp(".note.tag", 20110810Sbr@bsdpad.com elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 20210810Sbr@bsdpad.com data = elf_rawdata(section, NULL); 20310810Sbr@bsdpad.com assert(data->d_buf); 20410810Sbr@bsdpad.com elem = (uint32_t *)data->d_buf; 20510810Sbr@bsdpad.com if (elem[0] == 0x8) { //size of name 20610810Sbr@bsdpad.com if (memcmp((void *)&elem[3], "FreeBSD", 0x8) == 0) 20710810Sbr@bsdpad.com opSys = ObjectFile::FreeBSD; 20810810Sbr@bsdpad.com } 20910810Sbr@bsdpad.com } 2102600SN/A 2112238SN/A section = elf_getscn(elf, ++secIdx); 2122238SN/A } // while sections 2132238SN/A } 2142472SN/A 21510880SCurtis.Dunham@arm.com ElfObject * result = new ElfObject(fname, len, data, arch, opSys); 2162976Sgblack@eecs.umich.edu 2172976Sgblack@eecs.umich.edu //The number of headers in the file 2182976Sgblack@eecs.umich.edu result->_programHeaderCount = ehdr.e_phnum; 2192976Sgblack@eecs.umich.edu //Record the size of each entry 2202976Sgblack@eecs.umich.edu result->_programHeaderSize = ehdr.e_phentsize; 2212976Sgblack@eecs.umich.edu if(result->_programHeaderCount) //If there is a program header table 2222976Sgblack@eecs.umich.edu { 2232976Sgblack@eecs.umich.edu //Figure out the virtual address of the header table in the 2242976Sgblack@eecs.umich.edu //final memory image. We use the program headers themselves 2252976Sgblack@eecs.umich.edu //to translate from a file offset to the address in the image. 2262976Sgblack@eecs.umich.edu GElf_Phdr phdr; 2272976Sgblack@eecs.umich.edu uint64_t e_phoff = ehdr.e_phoff; 2282976Sgblack@eecs.umich.edu result->_programHeaderTable = 0; 2292976Sgblack@eecs.umich.edu for(int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++) 2302976Sgblack@eecs.umich.edu { 2312976Sgblack@eecs.umich.edu gelf_getphdr(elf, hdrnum, &phdr); 2322976Sgblack@eecs.umich.edu //Check if we've found the segment with the headers in it 2332976Sgblack@eecs.umich.edu if(phdr.p_offset <= e_phoff && 2342976Sgblack@eecs.umich.edu phdr.p_offset + phdr.p_filesz > e_phoff) 2352976Sgblack@eecs.umich.edu { 23610037SARM gem5 Developers result->_programHeaderTable = 23710037SARM gem5 Developers phdr.p_paddr + (e_phoff - phdr.p_offset); 2382976Sgblack@eecs.umich.edu break; 2392976Sgblack@eecs.umich.edu } 2402976Sgblack@eecs.umich.edu } 2412976Sgblack@eecs.umich.edu } 2422976Sgblack@eecs.umich.edu else 2432976Sgblack@eecs.umich.edu result->_programHeaderTable = 0; 2442976Sgblack@eecs.umich.edu 2452976Sgblack@eecs.umich.edu 2462238SN/A elf_end(elf); 2472976Sgblack@eecs.umich.edu return result; 24812SN/A } 24912SN/A} 25012SN/A 25112SN/A 25210880SCurtis.Dunham@arm.comElfObject::ElfObject(const string &_filename, size_t _len, uint8_t *_data, 253360SN/A Arch _arch, OpSys _opSys) 25410880SCurtis.Dunham@arm.com : ObjectFile(_filename, _len, _data, _arch, _opSys), 25510360Sandreas.hansson@arm.com _programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0) 256443SN/A 25712SN/A{ 258443SN/A Elf *elf; 259443SN/A GElf_Ehdr ehdr; 26012SN/A 261468SN/A // check that header matches library version 2621708SN/A if (elf_version(EV_CURRENT) == EV_NONE) 2631708SN/A panic("wrong elf version number!"); 26412SN/A 265468SN/A // get a pointer to elf structure 266443SN/A elf = elf_memory((char*)fileData,len); 267443SN/A assert(elf != NULL); 26812SN/A 269468SN/A // Check that we actually have a elf file 270468SN/A if (gelf_getehdr(elf, &ehdr) ==0) { 271443SN/A panic("Not ELF, shouldn't be here"); 27212SN/A } 27312SN/A 274468SN/A entry = ehdr.e_entry; 27512SN/A 276468SN/A // initialize segment sizes to 0 in case they're not present 277468SN/A text.size = data.size = bss.size = 0; 2789186SAli.Saidi@ARM.com text.baseAddr = data.baseAddr = bss.baseAddr = 0; 279468SN/A 2805090Sgblack@eecs.umich.edu int secIdx = 1; 2815090Sgblack@eecs.umich.edu Elf_Scn *section; 2825090Sgblack@eecs.umich.edu GElf_Shdr shdr; 2835090Sgblack@eecs.umich.edu 2845090Sgblack@eecs.umich.edu // The first address of some important sections. 2855090Sgblack@eecs.umich.edu Addr textSecStart = 0; 2865090Sgblack@eecs.umich.edu Addr dataSecStart = 0; 2875090Sgblack@eecs.umich.edu Addr bssSecStart = 0; 2885090Sgblack@eecs.umich.edu 2895090Sgblack@eecs.umich.edu // Get the first section 2905090Sgblack@eecs.umich.edu section = elf_getscn(elf, secIdx); 2915090Sgblack@eecs.umich.edu 2925090Sgblack@eecs.umich.edu // Find the beginning of the most interesting sections. 2935090Sgblack@eecs.umich.edu while (section != NULL) { 2945090Sgblack@eecs.umich.edu gelf_getshdr(section, &shdr); 2955090Sgblack@eecs.umich.edu char * secName = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 2965090Sgblack@eecs.umich.edu 2978350Sgblack@eecs.umich.edu if (secName) { 2988350Sgblack@eecs.umich.edu if (!strcmp(".text", secName)) { 2998350Sgblack@eecs.umich.edu textSecStart = shdr.sh_addr; 3008350Sgblack@eecs.umich.edu } else if (!strcmp(".data", secName)) { 3018350Sgblack@eecs.umich.edu dataSecStart = shdr.sh_addr; 3028350Sgblack@eecs.umich.edu } else if (!strcmp(".bss", secName)) { 3038350Sgblack@eecs.umich.edu bssSecStart = shdr.sh_addr; 3048350Sgblack@eecs.umich.edu } 3058350Sgblack@eecs.umich.edu } else { 3068350Sgblack@eecs.umich.edu Elf_Error errorNum = (Elf_Error)elf_errno(); 3078350Sgblack@eecs.umich.edu if (errorNum != ELF_E_NONE) { 3088350Sgblack@eecs.umich.edu const char *errorMessage = elf_errmsg(errorNum); 3098350Sgblack@eecs.umich.edu fatal("Error from libelf: %s.\n", errorMessage); 3108350Sgblack@eecs.umich.edu } 3115090Sgblack@eecs.umich.edu } 3125090Sgblack@eecs.umich.edu 3135090Sgblack@eecs.umich.edu section = elf_getscn(elf, ++secIdx); 3145090Sgblack@eecs.umich.edu } 3155090Sgblack@eecs.umich.edu 3165090Sgblack@eecs.umich.edu // Go through all the segments in the program, record them, and scrape 3175090Sgblack@eecs.umich.edu // out information about the text, data, and bss areas needed by other 3185090Sgblack@eecs.umich.edu // code. 319468SN/A for (int i = 0; i < ehdr.e_phnum; ++i) { 320468SN/A GElf_Phdr phdr; 321468SN/A if (gelf_getphdr(elf, i, &phdr) == 0) { 3225090Sgblack@eecs.umich.edu panic("gelf_getphdr failed for segment %d.", i); 323468SN/A } 324468SN/A 325468SN/A // for now we don't care about non-loadable segments 326468SN/A if (!(phdr.p_type & PT_LOAD)) 327468SN/A continue; 328468SN/A 3295090Sgblack@eecs.umich.edu // Check to see if this segment contains the bss section. 3305143Sgblack@eecs.umich.edu if (phdr.p_paddr <= bssSecStart && 3315143Sgblack@eecs.umich.edu phdr.p_paddr + phdr.p_memsz > bssSecStart && 3325090Sgblack@eecs.umich.edu phdr.p_memsz - phdr.p_filesz > 0) { 3335143Sgblack@eecs.umich.edu bss.baseAddr = phdr.p_paddr + phdr.p_filesz; 3345090Sgblack@eecs.umich.edu bss.size = phdr.p_memsz - phdr.p_filesz; 3355090Sgblack@eecs.umich.edu bss.fileImage = NULL; 3365090Sgblack@eecs.umich.edu } 3375090Sgblack@eecs.umich.edu 3385090Sgblack@eecs.umich.edu // Check to see if this is the text or data segment 3395152Sgblack@eecs.umich.edu if (phdr.p_vaddr <= textSecStart && 3405152Sgblack@eecs.umich.edu phdr.p_vaddr + phdr.p_filesz > textSecStart) { 3415143Sgblack@eecs.umich.edu text.baseAddr = phdr.p_paddr; 342468SN/A text.size = phdr.p_filesz; 3432420SN/A text.fileImage = fileData + phdr.p_offset; 3445152Sgblack@eecs.umich.edu } else if (phdr.p_vaddr <= dataSecStart && 3455152Sgblack@eecs.umich.edu phdr.p_vaddr + phdr.p_filesz > dataSecStart) { 3465143Sgblack@eecs.umich.edu data.baseAddr = phdr.p_paddr; 347468SN/A data.size = phdr.p_filesz; 3482420SN/A data.fileImage = fileData + phdr.p_offset; 3492476SN/A } else { 35011320Ssteve.reinhardt@amd.com // If it's none of the above but is loadable, 3515759Shsul@eecs.umich.edu // load the filesize worth of data 3525090Sgblack@eecs.umich.edu Segment extra; 3535143Sgblack@eecs.umich.edu extra.baseAddr = phdr.p_paddr; 3545090Sgblack@eecs.umich.edu extra.size = phdr.p_filesz; 3555090Sgblack@eecs.umich.edu extra.fileImage = fileData + phdr.p_offset; 3565090Sgblack@eecs.umich.edu extraSegments.push_back(extra); 357468SN/A } 358468SN/A } 359468SN/A 360468SN/A // should have found at least one loadable segment 361468SN/A assert(text.size != 0); 362468SN/A 363468SN/A DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", 364468SN/A text.baseAddr, text.size, data.baseAddr, data.size, 365468SN/A bss.baseAddr, bss.size); 366468SN/A 367443SN/A elf_end(elf); 368443SN/A 369468SN/A // We will actually read the sections when we need to load them 37012SN/A} 37112SN/A 37212SN/A 37312SN/Abool 3747581SAli.Saidi@arm.comElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask) 37512SN/A{ 376443SN/A Elf *elf; 377766SN/A int sec_idx = 1; // there is a 0 but it is nothing, go figure 378443SN/A Elf_Scn *section; 379443SN/A GElf_Shdr shdr; 380443SN/A Elf_Data *data; 381443SN/A int count, ii; 382443SN/A bool found = false; 383443SN/A GElf_Sym sym; 384443SN/A 385443SN/A if (!symtab) 386443SN/A return false; 387443SN/A 388468SN/A // check that header matches library version 3891708SN/A if (elf_version(EV_CURRENT) == EV_NONE) 3901708SN/A panic("wrong elf version number!"); 391443SN/A 392468SN/A // get a pointer to elf structure 393443SN/A elf = elf_memory((char*)fileData,len); 394443SN/A 395443SN/A assert(elf != NULL); 396443SN/A 397468SN/A // Get the first section 398454SN/A section = elf_getscn(elf, sec_idx); 399443SN/A 400468SN/A // While there are no more sections 401468SN/A while (section != NULL) { 402443SN/A gelf_getshdr(section, &shdr); 403443SN/A 404468SN/A if (shdr.sh_type == SHT_SYMTAB) { 405443SN/A found = true; 406443SN/A data = elf_getdata(section, NULL); 407443SN/A count = shdr.sh_size / shdr.sh_entsize; 408443SN/A DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 409443SN/A 410468SN/A // loop through all the symbols, only loading global ones 411468SN/A for (ii = 0; ii < count; ++ii) { 412443SN/A gelf_getsym(data, ii, &sym); 413836SN/A if (GELF_ST_BIND(sym.st_info) == binding) { 4147589SAli.Saidi@arm.com char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name); 4157589SAli.Saidi@arm.com if (sym_name && sym_name[0] != '$') { 4167589SAli.Saidi@arm.com DPRINTF(Loader, "Symbol: %-40s value %#x\n", 4177589SAli.Saidi@arm.com sym_name, sym.st_value); 4187589SAli.Saidi@arm.com symtab->insert(sym.st_value & mask, sym_name); 4197589SAli.Saidi@arm.com } 420443SN/A } 421443SN/A } 422443SN/A } 423454SN/A ++sec_idx; 424454SN/A section = elf_getscn(elf, sec_idx); 425443SN/A } 426443SN/A 427443SN/A elf_end(elf); 428443SN/A 429443SN/A return found; 43012SN/A} 43112SN/A 43212SN/Abool 4333812Ssaidi@eecs.umich.eduElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask) 434468SN/A{ 4357581SAli.Saidi@arm.com return loadSomeSymbols(symtab, STB_GLOBAL, addrMask); 436468SN/A} 437468SN/A 438468SN/Abool 4393812Ssaidi@eecs.umich.eduElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) 44012SN/A{ 4419810Sguodeyuan@tsinghua.org.cn bool found_local = loadSomeSymbols(symtab, STB_LOCAL, addrMask); 4429810Sguodeyuan@tsinghua.org.cn bool found_weak = loadSomeSymbols(symtab, STB_WEAK, addrMask); 4439810Sguodeyuan@tsinghua.org.cn return found_local || found_weak; 44412SN/A} 4453917Ssaidi@eecs.umich.edu 4465090Sgblack@eecs.umich.edubool 4479641Sguodeyuan@tsinghua.org.cnElfObject::loadWeakSymbols(SymbolTable *symtab, Addr addrMask) 4489641Sguodeyuan@tsinghua.org.cn{ 4499641Sguodeyuan@tsinghua.org.cn return loadSomeSymbols(symtab, STB_WEAK, addrMask); 4509641Sguodeyuan@tsinghua.org.cn} 4519641Sguodeyuan@tsinghua.org.cn 4529641Sguodeyuan@tsinghua.org.cnbool 45310037SARM gem5 DevelopersElfObject::loadSections(PortProxy& memProxy, Addr addrMask, Addr offset) 4545090Sgblack@eecs.umich.edu{ 45510037SARM gem5 Developers if (!ObjectFile::loadSections(memProxy, addrMask, offset)) 4565090Sgblack@eecs.umich.edu return false; 4575090Sgblack@eecs.umich.edu 4585090Sgblack@eecs.umich.edu vector<Segment>::iterator extraIt; 4595090Sgblack@eecs.umich.edu for (extraIt = extraSegments.begin(); 4605090Sgblack@eecs.umich.edu extraIt != extraSegments.end(); extraIt++) { 46110037SARM gem5 Developers if (!loadSection(&(*extraIt), memProxy, addrMask, offset)) { 4625090Sgblack@eecs.umich.edu return false; 4635090Sgblack@eecs.umich.edu } 4645090Sgblack@eecs.umich.edu } 4655090Sgblack@eecs.umich.edu return true; 4665090Sgblack@eecs.umich.edu} 4675090Sgblack@eecs.umich.edu 4685070Ssaidi@eecs.umich.eduvoid 4695070Ssaidi@eecs.umich.eduElfObject::getSections() 4703917Ssaidi@eecs.umich.edu{ 4713917Ssaidi@eecs.umich.edu Elf *elf; 4723917Ssaidi@eecs.umich.edu int sec_idx = 1; // there is a 0 but it is nothing, go figure 4733917Ssaidi@eecs.umich.edu Elf_Scn *section; 4743917Ssaidi@eecs.umich.edu GElf_Shdr shdr; 4753917Ssaidi@eecs.umich.edu 4763917Ssaidi@eecs.umich.edu GElf_Ehdr ehdr; 4773917Ssaidi@eecs.umich.edu 4785070Ssaidi@eecs.umich.edu assert(!sectionNames.size()); 4795070Ssaidi@eecs.umich.edu 4803917Ssaidi@eecs.umich.edu // check that header matches library version 4813917Ssaidi@eecs.umich.edu if (elf_version(EV_CURRENT) == EV_NONE) 4823917Ssaidi@eecs.umich.edu panic("wrong elf version number!"); 4833917Ssaidi@eecs.umich.edu 4843917Ssaidi@eecs.umich.edu // get a pointer to elf structure 4853917Ssaidi@eecs.umich.edu elf = elf_memory((char*)fileData,len); 4863917Ssaidi@eecs.umich.edu assert(elf != NULL); 4873917Ssaidi@eecs.umich.edu 4883917Ssaidi@eecs.umich.edu // Check that we actually have a elf file 4893917Ssaidi@eecs.umich.edu if (gelf_getehdr(elf, &ehdr) ==0) { 4903917Ssaidi@eecs.umich.edu panic("Not ELF, shouldn't be here"); 4913917Ssaidi@eecs.umich.edu } 4923917Ssaidi@eecs.umich.edu 4933917Ssaidi@eecs.umich.edu // Get the first section 4943917Ssaidi@eecs.umich.edu section = elf_getscn(elf, sec_idx); 4953917Ssaidi@eecs.umich.edu 4963917Ssaidi@eecs.umich.edu // While there are no more sections 4973917Ssaidi@eecs.umich.edu while (section != NULL) { 4983917Ssaidi@eecs.umich.edu gelf_getshdr(section, &shdr); 4995070Ssaidi@eecs.umich.edu sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)); 5003917Ssaidi@eecs.umich.edu section = elf_getscn(elf, ++sec_idx); 5013917Ssaidi@eecs.umich.edu } // while sections 5023917Ssaidi@eecs.umich.edu} 5033917Ssaidi@eecs.umich.edu 5045070Ssaidi@eecs.umich.edubool 5055070Ssaidi@eecs.umich.eduElfObject::sectionExists(string sec) 5065070Ssaidi@eecs.umich.edu{ 5075070Ssaidi@eecs.umich.edu if (!sectionNames.size()) 5085070Ssaidi@eecs.umich.edu getSections(); 5095070Ssaidi@eecs.umich.edu return sectionNames.find(sec) != sectionNames.end(); 5105070Ssaidi@eecs.umich.edu} 5113917Ssaidi@eecs.umich.edu 5125070Ssaidi@eecs.umich.edu 513