elf_object.cc revision 10810
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 * 5912SN/AElfObject::tryFile(const string &fname, int fd, 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); 72468SN/A // will only fail if fd is invalid 73443SN/A assert(elf != NULL); 74443SN/A 75468SN/A // Check that we actually have a elf file 7610037SARM gem5 Developers if (gelf_getehdr(elf, &ehdr) == 0) { 77443SN/A DPRINTFR(Loader, "Not ELF\n"); 78443SN/A elf_end(elf); 79443SN/A return NULL; 802476SN/A } else { 812207SN/A //Detect the architecture 822207SN/A //Since we don't know how to check for alpha right now, we'll 832207SN/A //just assume if it wasn't something else and it's 64 bit, that's 842207SN/A //what it must be. 852207SN/A if (ehdr.e_machine == EM_SPARC64 || 864111Sgblack@eecs.umich.edu (ehdr.e_machine == EM_SPARC && 874111Sgblack@eecs.umich.edu ehdr.e_ident[EI_CLASS] == ELFCLASS64)|| 882620SN/A ehdr.e_machine == EM_SPARCV9) { 894111Sgblack@eecs.umich.edu arch = ObjectFile::SPARC64; 904111Sgblack@eecs.umich.edu } else if (ehdr.e_machine == EM_SPARC32PLUS || 914111Sgblack@eecs.umich.edu (ehdr.e_machine == EM_SPARC && 924111Sgblack@eecs.umich.edu ehdr.e_ident[EI_CLASS] == ELFCLASS32)) { 934111Sgblack@eecs.umich.edu arch = ObjectFile::SPARC32; 942207SN/A } else if (ehdr.e_machine == EM_MIPS 952207SN/A && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 965383Sgblack@eecs.umich.edu if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { 975383Sgblack@eecs.umich.edu arch = ObjectFile::Mips; 985383Sgblack@eecs.umich.edu } else { 995383Sgblack@eecs.umich.edu fatal("The binary you're trying to load is compiled for big " 1005383Sgblack@eecs.umich.edu "endian MIPS. M5\nonly supports little endian MIPS. " 1015383Sgblack@eecs.umich.edu "Please recompile your binary.\n"); 1025383Sgblack@eecs.umich.edu } 1034166Sgblack@eecs.umich.edu } else if (ehdr.e_machine == EM_X86_64 && 1044166Sgblack@eecs.umich.edu ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 1055874Sgblack@eecs.umich.edu arch = ObjectFile::X86_64; 1065874Sgblack@eecs.umich.edu } else if (ehdr.e_machine == EM_386 && 1075874Sgblack@eecs.umich.edu ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 1085874Sgblack@eecs.umich.edu arch = ObjectFile::I386; 10910037SARM gem5 Developers } else if (ehdr.e_machine == EM_ARM && 11010037SARM gem5 Developers ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 1117095Sgblack@eecs.umich.edu if (bits(ehdr.e_entry, 0)) { 1127095Sgblack@eecs.umich.edu arch = ObjectFile::Thumb; 1137095Sgblack@eecs.umich.edu } else { 1147095Sgblack@eecs.umich.edu arch = ObjectFile::Arm; 1157095Sgblack@eecs.umich.edu } 11610037SARM gem5 Developers } else if ((ehdr.e_machine == EM_AARCH64) && 11710037SARM gem5 Developers ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 11810037SARM gem5 Developers arch = ObjectFile::Arm64; 11910037SARM gem5 Developers } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 12010037SARM gem5 Developers arch = ObjectFile::Alpha; 1216691Stjones1@inf.ed.ac.uk } else if (ehdr.e_machine == EM_PPC && 1226691Stjones1@inf.ed.ac.uk ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 12310037SARM gem5 Developers if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { 12410037SARM gem5 Developers arch = ObjectFile::Power; 12510037SARM gem5 Developers } else { 12610037SARM gem5 Developers fatal("The binary you're trying to load is compiled for " 1276691Stjones1@inf.ed.ac.uk "little endian Power.\nM5 only supports big " 1286691Stjones1@inf.ed.ac.uk "endian Power. Please recompile your binary.\n"); 12910037SARM gem5 Developers } 1306691Stjones1@inf.ed.ac.uk } else if (ehdr.e_machine == EM_PPC64) { 1316691Stjones1@inf.ed.ac.uk fatal("The binary you're trying to load is compiled for 64-bit " 1326691Stjones1@inf.ed.ac.uk "Power. M5\n only supports 32-bit Power. Please " 1336691Stjones1@inf.ed.ac.uk "recompile your binary.\n"); 1342207SN/A } else { 1352600SN/A warn("Unknown architecture: %d\n", ehdr.e_machine); 1362207SN/A arch = ObjectFile::UnknownArch; 1372207SN/A } 1382207SN/A 1392207SN/A //Detect the operating system 14010037SARM gem5 Developers switch (ehdr.e_ident[EI_OSABI]) { 1412207SN/A case ELFOSABI_LINUX: 1422207SN/A opSys = ObjectFile::Linux; 1432207SN/A break; 1442207SN/A case ELFOSABI_SOLARIS: 1452207SN/A opSys = ObjectFile::Solaris; 1462238SN/A break; 1472207SN/A case ELFOSABI_TRU64: 1482207SN/A opSys = ObjectFile::Tru64; 1492238SN/A break; 1506392Ssaidi@eecs.umich.edu case ELFOSABI_ARM: 1516392Ssaidi@eecs.umich.edu opSys = ObjectFile::LinuxArmOABI; 1526392Ssaidi@eecs.umich.edu break; 15310810Sbr@bsdpad.com case ELFOSABI_FREEBSD: 15410810Sbr@bsdpad.com opSys = ObjectFile::FreeBSD; 15510810Sbr@bsdpad.com break; 1562207SN/A default: 1572207SN/A opSys = ObjectFile::UnknownOpSys; 1582207SN/A } 1592207SN/A 1602238SN/A //take a look at the .note.ABI section 1612238SN/A //It can let us know what's what. 1622600SN/A if (opSys == ObjectFile::UnknownOpSys) { 1632238SN/A Elf_Scn *section; 1642238SN/A GElf_Shdr shdr; 1652238SN/A Elf_Data *data; 16610810Sbr@bsdpad.com uint32_t osAbi; 16710810Sbr@bsdpad.com uint32_t *elem; 1682238SN/A int secIdx = 1; 1692238SN/A 1702238SN/A // Get the first section 1712238SN/A section = elf_getscn(elf, secIdx); 1722238SN/A 1732238SN/A // While there are no more sections 1742600SN/A while (section != NULL && opSys == ObjectFile::UnknownOpSys) { 1752238SN/A gelf_getshdr(section, &shdr); 1762238SN/A if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", 1772238SN/A elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 1782238SN/A // we have found a ABI note section 1792238SN/A // Check the 5th 32bit word for OS 0 == linux, 1 == hurd, 1802238SN/A // 2 == solaris, 3 == freebsd 1812238SN/A data = elf_rawdata(section, NULL); 1822238SN/A assert(data->d_buf); 1832238SN/A if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 1842238SN/A osAbi = htole(((uint32_t*)data->d_buf)[4]); 1852238SN/A else 1862238SN/A osAbi = htobe(((uint32_t*)data->d_buf)[4]); 1872238SN/A 1882238SN/A switch(osAbi) { 1892238SN/A case 0: 1902238SN/A opSys = ObjectFile::Linux; 1912238SN/A break; 1922238SN/A case 2: 1932238SN/A opSys = ObjectFile::Solaris; 1942238SN/A break; 1952238SN/A } 1962238SN/A } // if section found 1972600SN/A if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 1982600SN/A opSys = ObjectFile::Solaris; 1992600SN/A if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 2002600SN/A opSys = ObjectFile::Solaris; 20110810Sbr@bsdpad.com if (shdr.sh_type == SHT_NOTE && !strcmp(".note.tag", 20210810Sbr@bsdpad.com elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 20310810Sbr@bsdpad.com data = elf_rawdata(section, NULL); 20410810Sbr@bsdpad.com assert(data->d_buf); 20510810Sbr@bsdpad.com elem = (uint32_t *)data->d_buf; 20610810Sbr@bsdpad.com if (elem[0] == 0x8) { //size of name 20710810Sbr@bsdpad.com if (memcmp((void *)&elem[3], "FreeBSD", 0x8) == 0) 20810810Sbr@bsdpad.com opSys = ObjectFile::FreeBSD; 20910810Sbr@bsdpad.com } 21010810Sbr@bsdpad.com } 2112600SN/A 2122238SN/A section = elf_getscn(elf, ++secIdx); 2132238SN/A } // while sections 2142238SN/A } 2152472SN/A 2162976Sgblack@eecs.umich.edu ElfObject * result = new ElfObject(fname, fd, len, data, arch, opSys); 2172976Sgblack@eecs.umich.edu 2182976Sgblack@eecs.umich.edu //The number of headers in the file 2192976Sgblack@eecs.umich.edu result->_programHeaderCount = ehdr.e_phnum; 2202976Sgblack@eecs.umich.edu //Record the size of each entry 2212976Sgblack@eecs.umich.edu result->_programHeaderSize = ehdr.e_phentsize; 2222976Sgblack@eecs.umich.edu if(result->_programHeaderCount) //If there is a program header table 2232976Sgblack@eecs.umich.edu { 2242976Sgblack@eecs.umich.edu //Figure out the virtual address of the header table in the 2252976Sgblack@eecs.umich.edu //final memory image. We use the program headers themselves 2262976Sgblack@eecs.umich.edu //to translate from a file offset to the address in the image. 2272976Sgblack@eecs.umich.edu GElf_Phdr phdr; 2282976Sgblack@eecs.umich.edu uint64_t e_phoff = ehdr.e_phoff; 2292976Sgblack@eecs.umich.edu result->_programHeaderTable = 0; 2302976Sgblack@eecs.umich.edu for(int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++) 2312976Sgblack@eecs.umich.edu { 2322976Sgblack@eecs.umich.edu gelf_getphdr(elf, hdrnum, &phdr); 2332976Sgblack@eecs.umich.edu //Check if we've found the segment with the headers in it 2342976Sgblack@eecs.umich.edu if(phdr.p_offset <= e_phoff && 2352976Sgblack@eecs.umich.edu phdr.p_offset + phdr.p_filesz > e_phoff) 2362976Sgblack@eecs.umich.edu { 23710037SARM gem5 Developers result->_programHeaderTable = 23810037SARM gem5 Developers phdr.p_paddr + (e_phoff - phdr.p_offset); 2392976Sgblack@eecs.umich.edu break; 2402976Sgblack@eecs.umich.edu } 2412976Sgblack@eecs.umich.edu } 2422976Sgblack@eecs.umich.edu } 2432976Sgblack@eecs.umich.edu else 2442976Sgblack@eecs.umich.edu result->_programHeaderTable = 0; 2452976Sgblack@eecs.umich.edu 2462976Sgblack@eecs.umich.edu 2472238SN/A elf_end(elf); 2482976Sgblack@eecs.umich.edu return result; 24912SN/A } 25012SN/A} 25112SN/A 25212SN/A 25312SN/AElfObject::ElfObject(const string &_filename, int _fd, 254360SN/A size_t _len, uint8_t *_data, 255360SN/A Arch _arch, OpSys _opSys) 25610360Sandreas.hansson@arm.com : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys), 25710360Sandreas.hansson@arm.com _programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0) 258443SN/A 25912SN/A{ 260443SN/A Elf *elf; 261443SN/A GElf_Ehdr ehdr; 26212SN/A 263468SN/A // check that header matches library version 2641708SN/A if (elf_version(EV_CURRENT) == EV_NONE) 2651708SN/A panic("wrong elf version number!"); 26612SN/A 267468SN/A // get a pointer to elf structure 268443SN/A elf = elf_memory((char*)fileData,len); 269468SN/A // will only fail if fd is invalid 270443SN/A assert(elf != NULL); 27112SN/A 272468SN/A // Check that we actually have a elf file 273468SN/A if (gelf_getehdr(elf, &ehdr) ==0) { 274443SN/A panic("Not ELF, shouldn't be here"); 27512SN/A } 27612SN/A 277468SN/A entry = ehdr.e_entry; 27812SN/A 279468SN/A // initialize segment sizes to 0 in case they're not present 280468SN/A text.size = data.size = bss.size = 0; 2819186SAli.Saidi@ARM.com text.baseAddr = data.baseAddr = bss.baseAddr = 0; 282468SN/A 2835090Sgblack@eecs.umich.edu int secIdx = 1; 2845090Sgblack@eecs.umich.edu Elf_Scn *section; 2855090Sgblack@eecs.umich.edu GElf_Shdr shdr; 2865090Sgblack@eecs.umich.edu 2875090Sgblack@eecs.umich.edu // The first address of some important sections. 2885090Sgblack@eecs.umich.edu Addr textSecStart = 0; 2895090Sgblack@eecs.umich.edu Addr dataSecStart = 0; 2905090Sgblack@eecs.umich.edu Addr bssSecStart = 0; 2915090Sgblack@eecs.umich.edu 2925090Sgblack@eecs.umich.edu // Get the first section 2935090Sgblack@eecs.umich.edu section = elf_getscn(elf, secIdx); 2945090Sgblack@eecs.umich.edu 2955090Sgblack@eecs.umich.edu // Find the beginning of the most interesting sections. 2965090Sgblack@eecs.umich.edu while (section != NULL) { 2975090Sgblack@eecs.umich.edu gelf_getshdr(section, &shdr); 2985090Sgblack@eecs.umich.edu char * secName = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 2995090Sgblack@eecs.umich.edu 3008350Sgblack@eecs.umich.edu if (secName) { 3018350Sgblack@eecs.umich.edu if (!strcmp(".text", secName)) { 3028350Sgblack@eecs.umich.edu textSecStart = shdr.sh_addr; 3038350Sgblack@eecs.umich.edu } else if (!strcmp(".data", secName)) { 3048350Sgblack@eecs.umich.edu dataSecStart = shdr.sh_addr; 3058350Sgblack@eecs.umich.edu } else if (!strcmp(".bss", secName)) { 3068350Sgblack@eecs.umich.edu bssSecStart = shdr.sh_addr; 3078350Sgblack@eecs.umich.edu } 3088350Sgblack@eecs.umich.edu } else { 3098350Sgblack@eecs.umich.edu Elf_Error errorNum = (Elf_Error)elf_errno(); 3108350Sgblack@eecs.umich.edu if (errorNum != ELF_E_NONE) { 3118350Sgblack@eecs.umich.edu const char *errorMessage = elf_errmsg(errorNum); 3128350Sgblack@eecs.umich.edu fatal("Error from libelf: %s.\n", errorMessage); 3138350Sgblack@eecs.umich.edu } 3145090Sgblack@eecs.umich.edu } 3155090Sgblack@eecs.umich.edu 3165090Sgblack@eecs.umich.edu section = elf_getscn(elf, ++secIdx); 3175090Sgblack@eecs.umich.edu } 3185090Sgblack@eecs.umich.edu 3195090Sgblack@eecs.umich.edu // Go through all the segments in the program, record them, and scrape 3205090Sgblack@eecs.umich.edu // out information about the text, data, and bss areas needed by other 3215090Sgblack@eecs.umich.edu // code. 322468SN/A for (int i = 0; i < ehdr.e_phnum; ++i) { 323468SN/A GElf_Phdr phdr; 324468SN/A if (gelf_getphdr(elf, i, &phdr) == 0) { 3255090Sgblack@eecs.umich.edu panic("gelf_getphdr failed for segment %d.", i); 326468SN/A } 327468SN/A 328468SN/A // for now we don't care about non-loadable segments 329468SN/A if (!(phdr.p_type & PT_LOAD)) 330468SN/A continue; 331468SN/A 3325090Sgblack@eecs.umich.edu // Check to see if this segment contains the bss section. 3335143Sgblack@eecs.umich.edu if (phdr.p_paddr <= bssSecStart && 3345143Sgblack@eecs.umich.edu phdr.p_paddr + phdr.p_memsz > bssSecStart && 3355090Sgblack@eecs.umich.edu phdr.p_memsz - phdr.p_filesz > 0) { 3365143Sgblack@eecs.umich.edu bss.baseAddr = phdr.p_paddr + phdr.p_filesz; 3375090Sgblack@eecs.umich.edu bss.size = phdr.p_memsz - phdr.p_filesz; 3385090Sgblack@eecs.umich.edu bss.fileImage = NULL; 3395090Sgblack@eecs.umich.edu } 3405090Sgblack@eecs.umich.edu 3415090Sgblack@eecs.umich.edu // Check to see if this is the text or data segment 3425152Sgblack@eecs.umich.edu if (phdr.p_vaddr <= textSecStart && 3435152Sgblack@eecs.umich.edu phdr.p_vaddr + phdr.p_filesz > textSecStart) { 3445143Sgblack@eecs.umich.edu text.baseAddr = phdr.p_paddr; 345468SN/A text.size = phdr.p_filesz; 3462420SN/A text.fileImage = fileData + phdr.p_offset; 3475152Sgblack@eecs.umich.edu } else if (phdr.p_vaddr <= dataSecStart && 3485152Sgblack@eecs.umich.edu phdr.p_vaddr + phdr.p_filesz > dataSecStart) { 3495143Sgblack@eecs.umich.edu data.baseAddr = phdr.p_paddr; 350468SN/A data.size = phdr.p_filesz; 3512420SN/A data.fileImage = fileData + phdr.p_offset; 3522476SN/A } else { 3535759Shsul@eecs.umich.edu // If it's none of the above but is loadable, 3545759Shsul@eecs.umich.edu // load the filesize worth of data 3555090Sgblack@eecs.umich.edu Segment extra; 3565143Sgblack@eecs.umich.edu extra.baseAddr = phdr.p_paddr; 3575090Sgblack@eecs.umich.edu extra.size = phdr.p_filesz; 3585090Sgblack@eecs.umich.edu extra.fileImage = fileData + phdr.p_offset; 3595090Sgblack@eecs.umich.edu extraSegments.push_back(extra); 360468SN/A } 361468SN/A } 362468SN/A 363468SN/A // should have found at least one loadable segment 364468SN/A assert(text.size != 0); 365468SN/A 366468SN/A DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", 367468SN/A text.baseAddr, text.size, data.baseAddr, data.size, 368468SN/A bss.baseAddr, bss.size); 369468SN/A 370443SN/A elf_end(elf); 371443SN/A 372468SN/A // We will actually read the sections when we need to load them 37312SN/A} 37412SN/A 37512SN/A 37612SN/Abool 3777581SAli.Saidi@arm.comElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask) 37812SN/A{ 379443SN/A Elf *elf; 380766SN/A int sec_idx = 1; // there is a 0 but it is nothing, go figure 381443SN/A Elf_Scn *section; 382443SN/A GElf_Shdr shdr; 383443SN/A Elf_Data *data; 384443SN/A int count, ii; 385443SN/A bool found = false; 386443SN/A GElf_Sym sym; 387443SN/A 388443SN/A if (!symtab) 389443SN/A return false; 390443SN/A 391468SN/A // check that header matches library version 3921708SN/A if (elf_version(EV_CURRENT) == EV_NONE) 3931708SN/A panic("wrong elf version number!"); 394443SN/A 395468SN/A // get a pointer to elf structure 396443SN/A elf = elf_memory((char*)fileData,len); 397443SN/A 398443SN/A assert(elf != NULL); 399443SN/A 400468SN/A // Get the first section 401454SN/A section = elf_getscn(elf, sec_idx); 402443SN/A 403468SN/A // While there are no more sections 404468SN/A while (section != NULL) { 405443SN/A gelf_getshdr(section, &shdr); 406443SN/A 407468SN/A if (shdr.sh_type == SHT_SYMTAB) { 408443SN/A found = true; 409443SN/A data = elf_getdata(section, NULL); 410443SN/A count = shdr.sh_size / shdr.sh_entsize; 411443SN/A DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 412443SN/A 413468SN/A // loop through all the symbols, only loading global ones 414468SN/A for (ii = 0; ii < count; ++ii) { 415443SN/A gelf_getsym(data, ii, &sym); 416836SN/A if (GELF_ST_BIND(sym.st_info) == binding) { 4177589SAli.Saidi@arm.com char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name); 4187589SAli.Saidi@arm.com if (sym_name && sym_name[0] != '$') { 4197589SAli.Saidi@arm.com DPRINTF(Loader, "Symbol: %-40s value %#x\n", 4207589SAli.Saidi@arm.com sym_name, sym.st_value); 4217589SAli.Saidi@arm.com symtab->insert(sym.st_value & mask, sym_name); 4227589SAli.Saidi@arm.com } 423443SN/A } 424443SN/A } 425443SN/A } 426454SN/A ++sec_idx; 427454SN/A section = elf_getscn(elf, sec_idx); 428443SN/A } 429443SN/A 430443SN/A elf_end(elf); 431443SN/A 432443SN/A return found; 43312SN/A} 43412SN/A 43512SN/Abool 4363812Ssaidi@eecs.umich.eduElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask) 437468SN/A{ 4387581SAli.Saidi@arm.com return loadSomeSymbols(symtab, STB_GLOBAL, addrMask); 439468SN/A} 440468SN/A 441468SN/Abool 4423812Ssaidi@eecs.umich.eduElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) 44312SN/A{ 4449810Sguodeyuan@tsinghua.org.cn bool found_local = loadSomeSymbols(symtab, STB_LOCAL, addrMask); 4459810Sguodeyuan@tsinghua.org.cn bool found_weak = loadSomeSymbols(symtab, STB_WEAK, addrMask); 4469810Sguodeyuan@tsinghua.org.cn return found_local || found_weak; 44712SN/A} 4483917Ssaidi@eecs.umich.edu 4495090Sgblack@eecs.umich.edubool 4509641Sguodeyuan@tsinghua.org.cnElfObject::loadWeakSymbols(SymbolTable *symtab, Addr addrMask) 4519641Sguodeyuan@tsinghua.org.cn{ 4529641Sguodeyuan@tsinghua.org.cn return loadSomeSymbols(symtab, STB_WEAK, addrMask); 4539641Sguodeyuan@tsinghua.org.cn} 4549641Sguodeyuan@tsinghua.org.cn 4559641Sguodeyuan@tsinghua.org.cnbool 45610037SARM gem5 DevelopersElfObject::loadSections(PortProxy& memProxy, Addr addrMask, Addr offset) 4575090Sgblack@eecs.umich.edu{ 45810037SARM gem5 Developers if (!ObjectFile::loadSections(memProxy, addrMask, offset)) 4595090Sgblack@eecs.umich.edu return false; 4605090Sgblack@eecs.umich.edu 4615090Sgblack@eecs.umich.edu vector<Segment>::iterator extraIt; 4625090Sgblack@eecs.umich.edu for (extraIt = extraSegments.begin(); 4635090Sgblack@eecs.umich.edu extraIt != extraSegments.end(); extraIt++) { 46410037SARM gem5 Developers if (!loadSection(&(*extraIt), memProxy, addrMask, offset)) { 4655090Sgblack@eecs.umich.edu return false; 4665090Sgblack@eecs.umich.edu } 4675090Sgblack@eecs.umich.edu } 4685090Sgblack@eecs.umich.edu return true; 4695090Sgblack@eecs.umich.edu} 4705090Sgblack@eecs.umich.edu 4715070Ssaidi@eecs.umich.eduvoid 4725070Ssaidi@eecs.umich.eduElfObject::getSections() 4733917Ssaidi@eecs.umich.edu{ 4743917Ssaidi@eecs.umich.edu Elf *elf; 4753917Ssaidi@eecs.umich.edu int sec_idx = 1; // there is a 0 but it is nothing, go figure 4763917Ssaidi@eecs.umich.edu Elf_Scn *section; 4773917Ssaidi@eecs.umich.edu GElf_Shdr shdr; 4783917Ssaidi@eecs.umich.edu 4793917Ssaidi@eecs.umich.edu GElf_Ehdr ehdr; 4803917Ssaidi@eecs.umich.edu 4815070Ssaidi@eecs.umich.edu assert(!sectionNames.size()); 4825070Ssaidi@eecs.umich.edu 4833917Ssaidi@eecs.umich.edu // check that header matches library version 4843917Ssaidi@eecs.umich.edu if (elf_version(EV_CURRENT) == EV_NONE) 4853917Ssaidi@eecs.umich.edu panic("wrong elf version number!"); 4863917Ssaidi@eecs.umich.edu 4873917Ssaidi@eecs.umich.edu // get a pointer to elf structure 4883917Ssaidi@eecs.umich.edu elf = elf_memory((char*)fileData,len); 4893917Ssaidi@eecs.umich.edu assert(elf != NULL); 4903917Ssaidi@eecs.umich.edu 4913917Ssaidi@eecs.umich.edu // Check that we actually have a elf file 4923917Ssaidi@eecs.umich.edu if (gelf_getehdr(elf, &ehdr) ==0) { 4933917Ssaidi@eecs.umich.edu panic("Not ELF, shouldn't be here"); 4943917Ssaidi@eecs.umich.edu } 4953917Ssaidi@eecs.umich.edu 4963917Ssaidi@eecs.umich.edu // Get the first section 4973917Ssaidi@eecs.umich.edu section = elf_getscn(elf, sec_idx); 4983917Ssaidi@eecs.umich.edu 4993917Ssaidi@eecs.umich.edu // While there are no more sections 5003917Ssaidi@eecs.umich.edu while (section != NULL) { 5013917Ssaidi@eecs.umich.edu gelf_getshdr(section, &shdr); 5025070Ssaidi@eecs.umich.edu sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)); 5033917Ssaidi@eecs.umich.edu section = elf_getscn(elf, ++sec_idx); 5043917Ssaidi@eecs.umich.edu } // while sections 5053917Ssaidi@eecs.umich.edu} 5063917Ssaidi@eecs.umich.edu 5075070Ssaidi@eecs.umich.edubool 5085070Ssaidi@eecs.umich.eduElfObject::sectionExists(string sec) 5095070Ssaidi@eecs.umich.edu{ 5105070Ssaidi@eecs.umich.edu if (!sectionNames.size()) 5115070Ssaidi@eecs.umich.edu getSections(); 5125070Ssaidi@eecs.umich.edu return sectionNames.find(sec) != sectionNames.end(); 5135070Ssaidi@eecs.umich.edu} 5143917Ssaidi@eecs.umich.edu 5155070Ssaidi@eecs.umich.edu 516