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