elf_object.cc revision 443
1/*
2 * Copyright (c) 2003 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <string>
30
31#include "base/loader/elf_object.hh"
32
33#include "mem/functional_mem/functional_memory.hh"
34#include "base/loader/symtab.hh"
35
36#include "base/trace.hh"	// for DPRINTF
37
38
39using namespace std;
40
41ObjectFile *
42ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
43{
44    Elf *elf;
45    GElf_Ehdr ehdr;
46
47
48    /* check that header matches library version */
49    assert(elf_version(EV_CURRENT) != EV_NONE);
50
51    /* get a pointer to elf structure */
52    elf = elf_memory((char*)data,len);
53    /* will only fail if fd is invalid */
54    assert(elf != NULL);
55
56    /*  Check that we actually have a elf file */
57    if(gelf_getehdr(elf, &ehdr) ==0)
58    {
59        DPRINTFR(Loader, "Not ELF\n");
60        elf_end(elf);
61        return NULL;
62    }
63    else
64    {
65        if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
66            panic("32 bit ELF Binary, Not Supported");
67        if (ehdr.e_machine != EM_ALPHA)
68            panic("Non Alpha Binary, Not Supported");
69
70        elf_end(elf);
71
72        return new ElfObject(fname, fd, len, data,
73                             ObjectFile::Alpha, ObjectFile::Linux);
74    }
75}
76
77
78ElfObject::ElfObject(const string &_filename, int _fd,
79                     size_t _len, uint8_t *_data,
80                     Arch _arch, OpSys _opSys)
81    : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
82
83{
84
85    Elf *elf;
86    GElf_Ehdr ehdr;
87
88    /* check that header matches library version */
89    assert(elf_version(EV_CURRENT) != EV_NONE);
90
91    /* get a pointer to elf structure */
92    elf = elf_memory((char*)fileData,len);
93    /* will only fail if fd is invalid */
94    assert(elf != NULL);
95
96    /*  Check that we actually have a elf file */
97    if(gelf_getehdr(elf, &ehdr) ==0)
98    {
99        panic("Not ELF, shouldn't be here");
100    }
101
102
103    entry = ehdr.e_entry;
104    elf_end(elf);
105
106    /* We will actually read the sections when we need to load them*/
107}
108
109
110bool
111ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys)
112{
113    Elf *elf;
114    int secidx = 1; /* there is a 0 but it is nothing, go figure*/
115    Elf_Scn *section;
116    GElf_Shdr shdr;
117    GElf_Ehdr ehdr;
118
119    Addr address;
120    char *secname;
121
122    /* check that header matches library version */
123    assert(elf_version(EV_CURRENT) != EV_NONE);
124
125
126    /* get a pointer to elf structure */
127    elf = elf_memory((char*)fileData,len);
128
129    assert(elf != NULL);
130
131    /*  Check that we actually have a elf file */
132    if(gelf_getehdr(elf, &ehdr) ==0)
133    {
134        panic("Not ELF, shouldn't be here");
135    }
136
137
138
139    /* Get the first section */
140    section = elf_getscn(elf, secidx);
141
142    /* While there are no more sections */
143    while (section != NULL)
144    {
145        gelf_getshdr(section, &shdr);
146
147
148        if (shdr.sh_flags & SHF_ALLOC)
149        {
150            /* we should load this */
151            DPRINTF(Loader,"Name: %20s Address: 0x%016llx Size: 0x%08llx Offset: 0x%08llx   Flags:0x%08llx %s\n",
152                    elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name), shdr.sh_addr,
153                    shdr.sh_size, shdr.sh_offset, shdr.sh_flags, shdr.sh_flags &    SHF_ALLOC ? "ALLOC" : "");
154            secname = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
155            if(secname)
156            {
157                if (strcmp(secname, ".text")==0)
158                {
159                    text.baseAddr = shdr.sh_addr;
160                    text.size = shdr.sh_size;
161                }
162                if (strcmp(secname, ".data")==0)
163                {
164                    data.baseAddr = shdr.sh_addr;
165                    data.size = shdr.sh_size;
166                }
167                if (strcmp(secname, ".bss")==0)
168                {
169                    bss.baseAddr = shdr.sh_addr;
170                    bss.size = shdr.sh_size;
171                }
172            }
173            if(shdr.sh_size != 0)
174            {
175                if (loadPhys)
176                {
177                    address = shdr.sh_addr &= (ULL(1) << 40) - 1;
178                    mem->prot_write(address, fileData + shdr.sh_offset, shdr.sh_size);
179                }
180                else
181                {
182                    mem->prot_write(shdr.sh_addr, fileData + shdr.sh_offset, shdr.sh_size);
183                }
184            }
185
186        }
187
188        ++secidx;
189        section = elf_getscn(elf, secidx);
190    }
191
192    elf_end(elf);
193
194    return true;
195}
196
197
198bool
199ElfObject::loadGlobalSymbols(SymbolTable *symtab)
200{
201    Elf *elf;
202    int secidx = 1; /* there is a 0 but it is nothing, go figure*/
203    Elf_Scn *section;
204    GElf_Shdr shdr;
205    Elf_Data *data;
206    int count, ii;
207    bool found = false;
208    GElf_Sym sym;
209
210    if (!symtab)
211        return false;
212
213    /* check that header matches library version */
214    assert(elf_version(EV_CURRENT) != EV_NONE);
215
216    /* get a pointer to elf structure */
217    elf = elf_memory((char*)fileData,len);
218
219    assert(elf != NULL);
220
221
222    /* Get the first section */
223    section = elf_getscn(elf, secidx);
224
225    /* While there are no more sections */
226    while (section != NULL)
227    {
228        gelf_getshdr(section, &shdr);
229
230
231        if(shdr.sh_type == SHT_SYMTAB)
232        {
233            found = true;
234            data = elf_getdata(section, NULL);
235            count = shdr.sh_size / shdr.sh_entsize;
236            DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
237
238            /* loop through all the symbols, only loading global ones*/
239            for (ii = 0; ii < count; ++ii)
240            {
241                gelf_getsym(data, ii, &sym);
242                if (GELF_ST_BIND(sym.st_info) & STB_GLOBAL)
243                {
244                   symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name));
245                }
246            }
247        }
248        ++secidx;
249        section = elf_getscn(elf, secidx);
250    }
251
252    elf_end(elf);
253
254    return found;
255}
256
257bool
258ElfObject::loadLocalSymbols(SymbolTable *symtab)
259{
260
261    Elf *elf;
262    int secidx = 1; /* there is a 0 but it is nothing, go figure*/
263    Elf_Scn *section;
264    GElf_Shdr shdr;
265    Elf_Data *data;
266    int count, ii;
267    bool found = false;
268    GElf_Sym sym;
269
270    if (!symtab)
271        return false;
272
273    /* check that header matches library version */
274    assert(elf_version(EV_CURRENT) != EV_NONE);
275
276    /* get a pointer to elf structure */
277    elf = elf_memory((char*)fileData,len);
278
279    assert(elf != NULL);
280
281
282    /* Get the first section */
283    section = elf_getscn(elf, secidx);
284
285    /* While there are no more sections */
286    while (section != NULL)
287    {
288        gelf_getshdr(section, &shdr);
289
290
291        if(shdr.sh_type == SHT_SYMTAB)
292        {
293            found = true;
294            data = elf_getdata(section, NULL);
295            count = shdr.sh_size / shdr.sh_entsize;
296            DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
297
298            /* loop through all the symbols, only loading global ones*/
299            for (ii = 0; ii < count; ++ii)
300            {
301                gelf_getsym(data, ii, &sym);
302                if (GELF_ST_BIND(sym.st_info) & STB_LOCAL)
303                {
304                   symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name));
305                }
306            }
307        }
308        ++secidx;
309        section = elf_getscn(elf, secidx);
310    }
311
312    elf_end(elf);
313
314    return found;
315}
316