elf_object.cc revision 443
112870Sgabeblack@google.com/*
212870Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan
312870Sgabeblack@google.com * All rights reserved.
412870Sgabeblack@google.com *
512870Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612870Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712870Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812870Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912870Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012870Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112870Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212870Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312870Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412870Sgabeblack@google.com * this software without specific prior written permission.
1512870Sgabeblack@google.com *
1612870Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712870Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812870Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912870Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012870Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112870Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212870Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312870Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412870Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512870Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612870Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712870Sgabeblack@google.com */
2812870Sgabeblack@google.com
2912870Sgabeblack@google.com#include <string>
3012870Sgabeblack@google.com
3112870Sgabeblack@google.com#include "base/loader/elf_object.hh"
3212870Sgabeblack@google.com
3312870Sgabeblack@google.com#include "mem/functional_mem/functional_memory.hh"
3412870Sgabeblack@google.com#include "base/loader/symtab.hh"
3512870Sgabeblack@google.com
3612870Sgabeblack@google.com#include "base/trace.hh"	// for DPRINTF
3713000Sgabeblack@google.com
3812870Sgabeblack@google.com
3912870Sgabeblack@google.comusing namespace std;
4012870Sgabeblack@google.com
4112870Sgabeblack@google.comObjectFile *
4212870Sgabeblack@google.comElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
4312870Sgabeblack@google.com{
4412870Sgabeblack@google.com    Elf *elf;
4512870Sgabeblack@google.com    GElf_Ehdr ehdr;
4612870Sgabeblack@google.com
4712870Sgabeblack@google.com
4812870Sgabeblack@google.com    /* check that header matches library version */
4912870Sgabeblack@google.com    assert(elf_version(EV_CURRENT) != EV_NONE);
5012870Sgabeblack@google.com
5112870Sgabeblack@google.com    /* get a pointer to elf structure */
5212870Sgabeblack@google.com    elf = elf_memory((char*)data,len);
5312870Sgabeblack@google.com    /* will only fail if fd is invalid */
5412870Sgabeblack@google.com    assert(elf != NULL);
5512870Sgabeblack@google.com
5612870Sgabeblack@google.com    /*  Check that we actually have a elf file */
5712870Sgabeblack@google.com    if(gelf_getehdr(elf, &ehdr) ==0)
5812870Sgabeblack@google.com    {
5912870Sgabeblack@google.com        DPRINTFR(Loader, "Not ELF\n");
6012870Sgabeblack@google.com        elf_end(elf);
6112870Sgabeblack@google.com        return NULL;
6212870Sgabeblack@google.com    }
6312870Sgabeblack@google.com    else
6412870Sgabeblack@google.com    {
6512870Sgabeblack@google.com        if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
6612870Sgabeblack@google.com            panic("32 bit ELF Binary, Not Supported");
6712870Sgabeblack@google.com        if (ehdr.e_machine != EM_ALPHA)
6812870Sgabeblack@google.com            panic("Non Alpha Binary, Not Supported");
6912870Sgabeblack@google.com
7012870Sgabeblack@google.com        elf_end(elf);
7112897Sgabeblack@google.com
7212870Sgabeblack@google.com        return new ElfObject(fname, fd, len, data,
7312870Sgabeblack@google.com                             ObjectFile::Alpha, ObjectFile::Linux);
7412870Sgabeblack@google.com    }
7512870Sgabeblack@google.com}
7612870Sgabeblack@google.com
7712870Sgabeblack@google.com
7812870Sgabeblack@google.comElfObject::ElfObject(const string &_filename, int _fd,
7912870Sgabeblack@google.com                     size_t _len, uint8_t *_data,
8012870Sgabeblack@google.com                     Arch _arch, OpSys _opSys)
8112870Sgabeblack@google.com    : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
8212870Sgabeblack@google.com
8312870Sgabeblack@google.com{
8412870Sgabeblack@google.com
8513002Sgabeblack@google.com    Elf *elf;
8613002Sgabeblack@google.com    GElf_Ehdr ehdr;
8713002Sgabeblack@google.com
8812870Sgabeblack@google.com    /* check that header matches library version */
8912870Sgabeblack@google.com    assert(elf_version(EV_CURRENT) != EV_NONE);
9012870Sgabeblack@google.com
9112870Sgabeblack@google.com    /* get a pointer to elf structure */
9212870Sgabeblack@google.com    elf = elf_memory((char*)fileData,len);
9312870Sgabeblack@google.com    /* will only fail if fd is invalid */
9412870Sgabeblack@google.com    assert(elf != NULL);
9512870Sgabeblack@google.com
9612870Sgabeblack@google.com    /*  Check that we actually have a elf file */
9712870Sgabeblack@google.com    if(gelf_getehdr(elf, &ehdr) ==0)
9812870Sgabeblack@google.com    {
9912870Sgabeblack@google.com        panic("Not ELF, shouldn't be here");
10012870Sgabeblack@google.com    }
10112870Sgabeblack@google.com
10212870Sgabeblack@google.com
10312870Sgabeblack@google.com    entry = ehdr.e_entry;
10412870Sgabeblack@google.com    elf_end(elf);
10512870Sgabeblack@google.com
10612870Sgabeblack@google.com    /* We will actually read the sections when we need to load them*/
10712870Sgabeblack@google.com}
10812870Sgabeblack@google.com
10912870Sgabeblack@google.com
11012870Sgabeblack@google.combool
11112870Sgabeblack@google.comElfObject::loadSections(FunctionalMemory *mem, bool loadPhys)
11212870Sgabeblack@google.com{
11312870Sgabeblack@google.com    Elf *elf;
11412870Sgabeblack@google.com    int secidx = 1; /* there is a 0 but it is nothing, go figure*/
11512870Sgabeblack@google.com    Elf_Scn *section;
11612870Sgabeblack@google.com    GElf_Shdr shdr;
11712870Sgabeblack@google.com    GElf_Ehdr ehdr;
11812870Sgabeblack@google.com
11912870Sgabeblack@google.com    Addr address;
12012870Sgabeblack@google.com    char *secname;
12112870Sgabeblack@google.com
12212870Sgabeblack@google.com    /* check that header matches library version */
12312870Sgabeblack@google.com    assert(elf_version(EV_CURRENT) != EV_NONE);
12413000Sgabeblack@google.com
12513000Sgabeblack@google.com
12613000Sgabeblack@google.com    /* get a pointer to elf structure */
12713000Sgabeblack@google.com    elf = elf_memory((char*)fileData,len);
12813000Sgabeblack@google.com
12913000Sgabeblack@google.com    assert(elf != NULL);
13013000Sgabeblack@google.com
13113000Sgabeblack@google.com    /*  Check that we actually have a elf file */
13213000Sgabeblack@google.com    if(gelf_getehdr(elf, &ehdr) ==0)
13313000Sgabeblack@google.com    {
13413000Sgabeblack@google.com        panic("Not ELF, shouldn't be here");
13513000Sgabeblack@google.com    }
13613000Sgabeblack@google.com
13713000Sgabeblack@google.com
13813000Sgabeblack@google.com
13913000Sgabeblack@google.com    /* Get the first section */
14013000Sgabeblack@google.com    section = elf_getscn(elf, secidx);
14113000Sgabeblack@google.com
14212870Sgabeblack@google.com    /* While there are no more sections */
14312870Sgabeblack@google.com    while (section != NULL)
14412870Sgabeblack@google.com    {
14512870Sgabeblack@google.com        gelf_getshdr(section, &shdr);
14613000Sgabeblack@google.com
14713002Sgabeblack@google.com
14813002Sgabeblack@google.com        if (shdr.sh_flags & SHF_ALLOC)
14913002Sgabeblack@google.com        {
15013001Sgabeblack@google.com            /* we should load this */
15113001Sgabeblack@google.com            DPRINTF(Loader,"Name: %20s Address: 0x%016llx Size: 0x%08llx Offset: 0x%08llx   Flags:0x%08llx %s\n",
15213001Sgabeblack@google.com                    elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name), shdr.sh_addr,
15313001Sgabeblack@google.com                    shdr.sh_size, shdr.sh_offset, shdr.sh_flags, shdr.sh_flags &    SHF_ALLOC ? "ALLOC" : "");
15413001Sgabeblack@google.com            secname = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
15513001Sgabeblack@google.com            if(secname)
15613002Sgabeblack@google.com            {
15713001Sgabeblack@google.com                if (strcmp(secname, ".text")==0)
15813000Sgabeblack@google.com                {
15913000Sgabeblack@google.com                    text.baseAddr = shdr.sh_addr;
16013000Sgabeblack@google.com                    text.size = shdr.sh_size;
16113000Sgabeblack@google.com                }
16213000Sgabeblack@google.com                if (strcmp(secname, ".data")==0)
16313000Sgabeblack@google.com                {
16413000Sgabeblack@google.com                    data.baseAddr = shdr.sh_addr;
16513000Sgabeblack@google.com                    data.size = shdr.sh_size;
16613000Sgabeblack@google.com                }
16712870Sgabeblack@google.com                if (strcmp(secname, ".bss")==0)
16812870Sgabeblack@google.com                {
16912870Sgabeblack@google.com                    bss.baseAddr = shdr.sh_addr;
17012870Sgabeblack@google.com                    bss.size = shdr.sh_size;
17112870Sgabeblack@google.com                }
17213002Sgabeblack@google.com            }
17313002Sgabeblack@google.com            if(shdr.sh_size != 0)
17413002Sgabeblack@google.com            {
17513002Sgabeblack@google.com                if (loadPhys)
17613002Sgabeblack@google.com                {
17713002Sgabeblack@google.com                    address = shdr.sh_addr &= (ULL(1) << 40) - 1;
17813002Sgabeblack@google.com                    mem->prot_write(address, fileData + shdr.sh_offset, shdr.sh_size);
17913002Sgabeblack@google.com                }
18013002Sgabeblack@google.com                else
18113002Sgabeblack@google.com                {
18213002Sgabeblack@google.com                    mem->prot_write(shdr.sh_addr, fileData + shdr.sh_offset, shdr.sh_size);
18313002Sgabeblack@google.com                }
18413002Sgabeblack@google.com            }
18513002Sgabeblack@google.com
18613002Sgabeblack@google.com        }
18713002Sgabeblack@google.com
18813002Sgabeblack@google.com        ++secidx;
18913002Sgabeblack@google.com        section = elf_getscn(elf, secidx);
19013002Sgabeblack@google.com    }
19113002Sgabeblack@google.com
19213002Sgabeblack@google.com    elf_end(elf);
19313002Sgabeblack@google.com
19413002Sgabeblack@google.com    return true;
19513002Sgabeblack@google.com}
19613002Sgabeblack@google.com
19713002Sgabeblack@google.com
19813002Sgabeblack@google.combool
19913002Sgabeblack@google.comElfObject::loadGlobalSymbols(SymbolTable *symtab)
20013002Sgabeblack@google.com{
20113002Sgabeblack@google.com    Elf *elf;
20213002Sgabeblack@google.com    int secidx = 1; /* there is a 0 but it is nothing, go figure*/
20313002Sgabeblack@google.com    Elf_Scn *section;
20413002Sgabeblack@google.com    GElf_Shdr shdr;
20513002Sgabeblack@google.com    Elf_Data *data;
20613002Sgabeblack@google.com    int count, ii;
20713002Sgabeblack@google.com    bool found = false;
20813002Sgabeblack@google.com    GElf_Sym sym;
20913002Sgabeblack@google.com
21013002Sgabeblack@google.com    if (!symtab)
21113002Sgabeblack@google.com        return false;
21213002Sgabeblack@google.com
21313002Sgabeblack@google.com    /* check that header matches library version */
21413002Sgabeblack@google.com    assert(elf_version(EV_CURRENT) != EV_NONE);
21513002Sgabeblack@google.com
21613002Sgabeblack@google.com    /* get a pointer to elf structure */
21713002Sgabeblack@google.com    elf = elf_memory((char*)fileData,len);
21813002Sgabeblack@google.com
21913002Sgabeblack@google.com    assert(elf != NULL);
22013002Sgabeblack@google.com
22113002Sgabeblack@google.com
22213002Sgabeblack@google.com    /* Get the first section */
22313002Sgabeblack@google.com    section = elf_getscn(elf, secidx);
22413002Sgabeblack@google.com
22513002Sgabeblack@google.com    /* While there are no more sections */
22613002Sgabeblack@google.com    while (section != NULL)
22713002Sgabeblack@google.com    {
22813002Sgabeblack@google.com        gelf_getshdr(section, &shdr);
22912870Sgabeblack@google.com
23013002Sgabeblack@google.com
23113002Sgabeblack@google.com        if(shdr.sh_type == SHT_SYMTAB)
23213002Sgabeblack@google.com        {
23313002Sgabeblack@google.com            found = true;
23413002Sgabeblack@google.com            data = elf_getdata(section, NULL);
23513002Sgabeblack@google.com            count = shdr.sh_size / shdr.sh_entsize;
23613002Sgabeblack@google.com            DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
23713002Sgabeblack@google.com
23813002Sgabeblack@google.com            /* loop through all the symbols, only loading global ones*/
23912870Sgabeblack@google.com            for (ii = 0; ii < count; ++ii)
24013002Sgabeblack@google.com            {
24113002Sgabeblack@google.com                gelf_getsym(data, ii, &sym);
24213002Sgabeblack@google.com                if (GELF_ST_BIND(sym.st_info) & STB_GLOBAL)
24313002Sgabeblack@google.com                {
24413002Sgabeblack@google.com                   symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name));
24513002Sgabeblack@google.com                }
24613002Sgabeblack@google.com            }
24713002Sgabeblack@google.com        }
24813002Sgabeblack@google.com        ++secidx;
24913002Sgabeblack@google.com        section = elf_getscn(elf, secidx);
25013002Sgabeblack@google.com    }
25113002Sgabeblack@google.com
25213002Sgabeblack@google.com    elf_end(elf);
25313002Sgabeblack@google.com
25413002Sgabeblack@google.com    return found;
25513002Sgabeblack@google.com}
25613002Sgabeblack@google.com
25713002Sgabeblack@google.combool
25813002Sgabeblack@google.comElfObject::loadLocalSymbols(SymbolTable *symtab)
25913002Sgabeblack@google.com{
26013002Sgabeblack@google.com
26113002Sgabeblack@google.com    Elf *elf;
26213002Sgabeblack@google.com    int secidx = 1; /* there is a 0 but it is nothing, go figure*/
26313002Sgabeblack@google.com    Elf_Scn *section;
26413002Sgabeblack@google.com    GElf_Shdr shdr;
26513002Sgabeblack@google.com    Elf_Data *data;
26613002Sgabeblack@google.com    int count, ii;
26713002Sgabeblack@google.com    bool found = false;
26813002Sgabeblack@google.com    GElf_Sym sym;
26913002Sgabeblack@google.com
27013002Sgabeblack@google.com    if (!symtab)
27113002Sgabeblack@google.com        return false;
27213002Sgabeblack@google.com
27313002Sgabeblack@google.com    /* check that header matches library version */
27413002Sgabeblack@google.com    assert(elf_version(EV_CURRENT) != EV_NONE);
27512870Sgabeblack@google.com
27612870Sgabeblack@google.com    /* get a pointer to elf structure */
27712870Sgabeblack@google.com    elf = elf_memory((char*)fileData,len);
27812870Sgabeblack@google.com
27912870Sgabeblack@google.com    assert(elf != NULL);
28012870Sgabeblack@google.com
28112870Sgabeblack@google.com
28212870Sgabeblack@google.com    /* Get the first section */
28312870Sgabeblack@google.com    section = elf_getscn(elf, secidx);
28412870Sgabeblack@google.com
28512870Sgabeblack@google.com    /* While there are no more sections */
28612870Sgabeblack@google.com    while (section != NULL)
28712870Sgabeblack@google.com    {
28812870Sgabeblack@google.com        gelf_getshdr(section, &shdr);
28912870Sgabeblack@google.com
29012870Sgabeblack@google.com
29112870Sgabeblack@google.com        if(shdr.sh_type == SHT_SYMTAB)
29212903Sgabeblack@google.com        {
29312903Sgabeblack@google.com            found = true;
29412903Sgabeblack@google.com            data = elf_getdata(section, NULL);
29512903Sgabeblack@google.com            count = shdr.sh_size / shdr.sh_entsize;
29612903Sgabeblack@google.com            DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
29712903Sgabeblack@google.com
29812903Sgabeblack@google.com            /* loop through all the symbols, only loading global ones*/
29912870Sgabeblack@google.com            for (ii = 0; ii < count; ++ii)
30012870Sgabeblack@google.com            {
30112870Sgabeblack@google.com                gelf_getsym(data, ii, &sym);
30212870Sgabeblack@google.com                if (GELF_ST_BIND(sym.st_info) & STB_LOCAL)
30312870Sgabeblack@google.com                {
30412870Sgabeblack@google.com                   symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name));
30512870Sgabeblack@google.com                }
30612870Sgabeblack@google.com            }
30712870Sgabeblack@google.com        }
30812870Sgabeblack@google.com        ++secidx;
30912870Sgabeblack@google.com        section = elf_getscn(elf, secidx);
31012870Sgabeblack@google.com    }
31112870Sgabeblack@google.com
31212870Sgabeblack@google.com    elf_end(elf);
31312870Sgabeblack@google.com
31412870Sgabeblack@google.com    return found;
31512870Sgabeblack@google.com}
31612870Sgabeblack@google.com