elf_object.cc revision 11389
1/*
2 * Copyright (c) 2011-2013 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Steve Reinhardt
41 *          Ali Saidi
42 */
43
44#include "base/loader/elf_object.hh"
45
46#include <fcntl.h>
47#include <sys/mman.h>
48#include <sys/stat.h>
49#include <sys/types.h>
50#include <unistd.h>
51
52#include <cassert>
53#include <string>
54
55#include "base/bitfield.hh"
56#include "base/loader/symtab.hh"
57#include "base/misc.hh"
58#include "base/trace.hh"
59#include "debug/Loader.hh"
60#include "gelf.h"
61#include "sim/byteswap.hh"
62
63using namespace std;
64
65ObjectFile *
66ElfObject::tryFile(const string &fname, size_t len, uint8_t *data,
67                   bool skip_interp_check)
68{
69    Elf *elf;
70    GElf_Ehdr ehdr;
71    Arch arch = UnknownArch;
72    OpSys opSys = UnknownOpSys;
73
74    // check that header matches library version
75    if (elf_version(EV_CURRENT) == EV_NONE)
76        panic("wrong elf version number!");
77
78    // get a pointer to elf structure
79    elf = elf_memory((char*)data,len);
80    assert(elf != NULL);
81
82    // Check that we actually have a elf file
83    if (gelf_getehdr(elf, &ehdr) == 0) {
84        DPRINTFR(Loader, "Not ELF\n");
85        elf_end(elf);
86        return NULL;
87    } else {
88        //Detect the architecture
89        //Since we don't know how to check for alpha right now, we'll
90        //just assume if it wasn't something else and it's 64 bit, that's
91        //what it must be.
92        if (ehdr.e_machine == EM_SPARC64 ||
93                (ehdr.e_machine == EM_SPARC &&
94                 ehdr.e_ident[EI_CLASS] == ELFCLASS64)||
95                ehdr.e_machine == EM_SPARCV9) {
96            arch = ObjectFile::SPARC64;
97        } else if (ehdr.e_machine == EM_SPARC32PLUS ||
98                        (ehdr.e_machine == EM_SPARC &&
99                         ehdr.e_ident[EI_CLASS] == ELFCLASS32)) {
100            arch = ObjectFile::SPARC32;
101        } else if (ehdr.e_machine == EM_MIPS
102                && ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
103            if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) {
104                arch = ObjectFile::Mips;
105            } else {
106                fatal("The binary you're trying to load is compiled for big "
107                        "endian MIPS. M5\nonly supports little endian MIPS. "
108                        "Please recompile your binary.\n");
109            }
110        } else if (ehdr.e_machine == EM_X86_64 &&
111                ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
112            arch = ObjectFile::X86_64;
113        } else if (ehdr.e_machine == EM_386 &&
114                ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
115            arch = ObjectFile::I386;
116        } else if (ehdr.e_machine == EM_ARM &&
117                ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
118            if (bits(ehdr.e_entry, 0)) {
119                arch = ObjectFile::Thumb;
120            } else {
121                arch = ObjectFile::Arm;
122            }
123        } else if ((ehdr.e_machine == EM_AARCH64) &&
124                ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
125            arch = ObjectFile::Arm64;
126        } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
127            arch = ObjectFile::Alpha;
128        } else if (ehdr.e_machine == EM_PPC &&
129                ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
130            if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) {
131                  arch = ObjectFile::Power;
132            } else {
133                  fatal("The binary you're trying to load is compiled for "
134                        "little endian Power.\nM5 only supports big "
135                        "endian Power. Please recompile your binary.\n");
136            }
137        } else if (ehdr.e_machine == EM_PPC64) {
138            fatal("The binary you're trying to load is compiled for 64-bit "
139                  "Power. M5\n only supports 32-bit Power. Please "
140                  "recompile your binary.\n");
141        } else {
142            warn("Unknown architecture: %d\n", ehdr.e_machine);
143            arch = ObjectFile::UnknownArch;
144        }
145
146        //Detect the operating system
147        switch (ehdr.e_ident[EI_OSABI]) {
148          case ELFOSABI_LINUX:
149            opSys = ObjectFile::Linux;
150            break;
151          case ELFOSABI_SOLARIS:
152            opSys = ObjectFile::Solaris;
153            break;
154          case ELFOSABI_TRU64:
155            opSys = ObjectFile::Tru64;
156            break;
157          case ELFOSABI_ARM:
158            opSys = ObjectFile::LinuxArmOABI;
159            break;
160          case ELFOSABI_FREEBSD:
161            opSys = ObjectFile::FreeBSD;
162            break;
163          default:
164            opSys = ObjectFile::UnknownOpSys;
165        }
166
167        //take a look at the .note.ABI section
168        //It can let us know what's what.
169        if (opSys == ObjectFile::UnknownOpSys) {
170            Elf_Scn *section;
171            GElf_Shdr shdr;
172            Elf_Data *data;
173            uint32_t osAbi;
174            uint32_t *elem;
175            int secIdx = 1;
176
177            // Get the first section
178            section = elf_getscn(elf, secIdx);
179
180            // While there are no more sections
181            while (section != NULL && opSys == ObjectFile::UnknownOpSys) {
182                gelf_getshdr(section, &shdr);
183                if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag",
184                            elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
185                    // we have found a ABI note section
186                    // Check the 5th 32bit word for OS  0 == linux, 1 == hurd,
187                    // 2 == solaris, 3 == freebsd
188                    data = elf_rawdata(section, NULL);
189                    assert(data->d_buf);
190                    if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
191                        osAbi = htole(((uint32_t*)data->d_buf)[4]);
192                    else
193                        osAbi = htobe(((uint32_t*)data->d_buf)[4]);
194
195                    switch(osAbi) {
196                      case 0:
197                        opSys = ObjectFile::Linux;
198                        break;
199                      case 2:
200                        opSys = ObjectFile::Solaris;
201                        break;
202                    }
203                } // if section found
204                if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
205                        opSys = ObjectFile::Solaris;
206                if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
207                        opSys = ObjectFile::Solaris;
208                if (shdr.sh_type == SHT_NOTE && !strcmp(".note.tag",
209                            elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
210                    data = elf_rawdata(section, NULL);
211                    assert(data->d_buf);
212                    elem = (uint32_t *)data->d_buf;
213                    if (elem[0] == 0x8) { //size of name
214                        if (memcmp((void *)&elem[3], "FreeBSD", 0x8) == 0)
215                                opSys = ObjectFile::FreeBSD;
216                    }
217                }
218
219            section = elf_getscn(elf, ++secIdx);
220            } // while sections
221        }
222
223        ElfObject * result = new ElfObject(fname, len, data, arch, opSys);
224
225        //The number of headers in the file
226        result->_programHeaderCount = ehdr.e_phnum;
227        //Record the size of each entry
228        result->_programHeaderSize = ehdr.e_phentsize;
229        if (result->_programHeaderCount) //If there is a program header table
230        {
231            //Figure out the virtual address of the header table in the
232            //final memory image. We use the program headers themselves
233            //to translate from a file offset to the address in the image.
234            GElf_Phdr phdr;
235            uint64_t e_phoff = ehdr.e_phoff;
236            result->_programHeaderTable = 0;
237            for (int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++)
238            {
239                gelf_getphdr(elf, hdrnum, &phdr);
240                //Check if we've found the segment with the headers in it
241                if (phdr.p_offset <= e_phoff &&
242                        phdr.p_offset + phdr.p_filesz > e_phoff)
243                {
244                    result->_programHeaderTable =
245                        phdr.p_paddr + (e_phoff - phdr.p_offset);
246                    break;
247                }
248            }
249        }
250        else
251            result->_programHeaderTable = 0;
252
253
254        if (!skip_interp_check) {
255            for (int i = 0; i < ehdr.e_phnum; i++) {
256                GElf_Phdr phdr;
257                M5_VAR_USED void *check_p = gelf_getphdr(elf, i, &phdr);
258                assert(check_p != nullptr);
259
260                if (phdr.p_type != PT_INTERP)
261                    continue;
262
263                char *interp_path = (char*)data + phdr.p_offset;
264                int fd = open(interp_path, O_RDONLY);
265                if (fd == -1) {
266                    fatal("Unable to open dynamic executable's "
267                          "interpreter.\n");
268                }
269
270                struct stat sb;
271                M5_VAR_USED int check_i = fstat(fd, &sb);
272                assert(check_i == 0);
273
274                void *mm = mmap(nullptr, sb.st_size, PROT_READ,
275                                MAP_PRIVATE, fd, 0);
276                assert(mm != MAP_FAILED);
277                ::close(fd);
278
279                uint8_t *interp_image = (uint8_t*)mm;
280                ObjectFile *obj = tryFile(interp_path, sb.st_size,
281                                          interp_image, true);
282                assert(obj != nullptr);
283                result->interpreter = dynamic_cast<ElfObject*>(obj);
284                assert(result->interpreter != nullptr);
285                break;
286            }
287        }
288
289        elf_end(elf);
290        return result;
291    }
292}
293
294
295ElfObject::ElfObject(const string &_filename, size_t _len, uint8_t *_data,
296                     Arch _arch, OpSys _opSys)
297    : ObjectFile(_filename, _len, _data, _arch, _opSys),
298      _programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0),
299      interpreter(nullptr), ldBias(0), relocate(true),
300      ldMin(std::numeric_limits<Addr>::max()),
301      ldMax(std::numeric_limits<Addr>::min())
302{
303    Elf *elf;
304    GElf_Ehdr ehdr;
305
306    // check that header matches library version
307    if (elf_version(EV_CURRENT) == EV_NONE)
308        panic("wrong elf version number!");
309
310    // get a pointer to elf structure
311    elf = elf_memory((char*)fileData,len);
312    assert(elf != NULL);
313
314    // Check that we actually have a elf file
315    if (gelf_getehdr(elf, &ehdr) ==0) {
316        panic("Not ELF, shouldn't be here");
317    }
318
319    entry = ehdr.e_entry;
320
321    // initialize segment sizes to 0 in case they're not present
322    text.size = data.size = bss.size = 0;
323    text.baseAddr = data.baseAddr = bss.baseAddr = 0;
324
325    int secIdx = 1;
326    Elf_Scn *section;
327    GElf_Shdr shdr;
328
329    // The first address of some important sections.
330    Addr textSecStart = 0;
331    Addr dataSecStart = 0;
332    Addr bssSecStart = 0;
333
334    // Get the first section
335    section = elf_getscn(elf, secIdx);
336
337    // Find the beginning of the most interesting sections.
338    while (section != NULL) {
339        gelf_getshdr(section, &shdr);
340        char * secName = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
341
342        if (secName) {
343            if (!strcmp(".text", secName)) {
344                textSecStart = shdr.sh_addr;
345            } else if (!strcmp(".data", secName)) {
346                dataSecStart = shdr.sh_addr;
347            } else if (!strcmp(".bss", secName)) {
348                bssSecStart = shdr.sh_addr;
349            }
350        } else {
351            Elf_Error errorNum = (Elf_Error)elf_errno();
352            if (errorNum != ELF_E_NONE) {
353                const char *errorMessage = elf_errmsg(errorNum);
354                fatal("Error from libelf: %s.\n", errorMessage);
355            }
356        }
357
358        section = elf_getscn(elf, ++secIdx);
359    }
360
361    // Go through all the segments in the program, record them, and scrape
362    // out information about the text, data, and bss areas needed by other
363    // code.
364    for (int i = 0; i < ehdr.e_phnum; ++i) {
365        GElf_Phdr phdr;
366        if (gelf_getphdr(elf, i, &phdr) == 0) {
367            panic("gelf_getphdr failed for segment %d.", i);
368        }
369
370        // for now we don't care about non-loadable segments
371        if (!(phdr.p_type & PT_LOAD))
372            continue;
373
374        ldMin = std::min(ldMin, phdr.p_vaddr);
375        ldMax = std::max(ldMax, phdr.p_vaddr + phdr.p_memsz);
376
377        // Check to see if this segment contains the bss section.
378        if (phdr.p_paddr <= bssSecStart &&
379                phdr.p_paddr + phdr.p_memsz > bssSecStart &&
380                phdr.p_memsz - phdr.p_filesz > 0) {
381            bss.baseAddr = phdr.p_paddr + phdr.p_filesz;
382            bss.size = phdr.p_memsz - phdr.p_filesz;
383            bss.fileImage = NULL;
384        }
385
386        // Check to see if this is the text or data segment
387        if (phdr.p_vaddr <= textSecStart &&
388                phdr.p_vaddr + phdr.p_filesz > textSecStart) {
389
390            // If this value is nonzero, we need to flip the relocate flag.
391            if (phdr.p_vaddr != 0)
392                relocate = false;
393
394            text.baseAddr = phdr.p_paddr;
395            text.size = phdr.p_filesz;
396            text.fileImage = fileData + phdr.p_offset;
397        } else if (phdr.p_vaddr <= dataSecStart &&
398                phdr.p_vaddr + phdr.p_filesz > dataSecStart) {
399            data.baseAddr = phdr.p_paddr;
400            data.size = phdr.p_filesz;
401            data.fileImage = fileData + phdr.p_offset;
402        } else {
403            // If it's none of the above but is loadable,
404            // load the filesize worth of data
405            Segment extra;
406            extra.baseAddr = phdr.p_paddr;
407            extra.size = phdr.p_filesz;
408            extra.fileImage = fileData + phdr.p_offset;
409            extraSegments.push_back(extra);
410        }
411    }
412
413    // should have found at least one loadable segment
414    assert(text.size != 0);
415
416    DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
417             text.baseAddr, text.size, data.baseAddr, data.size,
418             bss.baseAddr, bss.size);
419
420    elf_end(elf);
421
422    // We will actually read the sections when we need to load them
423}
424
425
426bool
427ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask)
428{
429    Elf *elf;
430    int sec_idx = 1; // there is a 0 but it is nothing, go figure
431    Elf_Scn *section;
432    GElf_Shdr shdr;
433    Elf_Data *data;
434    int count, ii;
435    bool found = false;
436    GElf_Sym sym;
437
438    if (!symtab)
439        return false;
440
441    // check that header matches library version
442    if (elf_version(EV_CURRENT) == EV_NONE)
443        panic("wrong elf version number!");
444
445    // get a pointer to elf structure
446    elf = elf_memory((char*)fileData,len);
447
448    assert(elf != NULL);
449
450    // Get the first section
451    section = elf_getscn(elf, sec_idx);
452
453    // While there are no more sections
454    while (section != NULL) {
455        gelf_getshdr(section, &shdr);
456
457        if (shdr.sh_type == SHT_SYMTAB) {
458            found = true;
459            data = elf_getdata(section, NULL);
460            count = shdr.sh_size / shdr.sh_entsize;
461            DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
462
463            // loop through all the symbols, only loading global ones
464            for (ii = 0; ii < count; ++ii) {
465                gelf_getsym(data, ii, &sym);
466                if (GELF_ST_BIND(sym.st_info) == binding) {
467                    char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
468                    if (sym_name && sym_name[0] != '$') {
469                        DPRINTF(Loader, "Symbol: %-40s value %#x\n",
470                                sym_name, sym.st_value);
471                        symtab->insert(sym.st_value & mask, sym_name);
472                    }
473                }
474            }
475        }
476        ++sec_idx;
477        section = elf_getscn(elf, sec_idx);
478    }
479
480    elf_end(elf);
481
482    return found;
483}
484
485bool
486ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
487{
488    return loadSomeSymbols(symtab, STB_GLOBAL, addrMask);
489}
490
491bool
492ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
493{
494    bool found_local = loadSomeSymbols(symtab, STB_LOCAL, addrMask);
495    bool found_weak = loadSomeSymbols(symtab, STB_WEAK, addrMask);
496    return found_local || found_weak;
497}
498
499bool
500ElfObject::loadWeakSymbols(SymbolTable *symtab, Addr addrMask)
501{
502    return loadSomeSymbols(symtab, STB_WEAK, addrMask);
503}
504
505bool
506ElfObject::loadSections(PortProxy& memProxy, Addr addrMask, Addr offset)
507{
508    if (!ObjectFile::loadSections(memProxy, addrMask, offset))
509        return false;
510
511    vector<Segment>::iterator extraIt;
512    for (extraIt = extraSegments.begin();
513            extraIt != extraSegments.end(); extraIt++) {
514        if (!loadSection(&(*extraIt), memProxy, addrMask, offset)) {
515            return false;
516        }
517    }
518
519    if (interpreter)
520        interpreter->loadSections(memProxy, addrMask, offset);
521
522    return true;
523}
524
525void
526ElfObject::getSections()
527{
528    Elf *elf;
529    int sec_idx = 1; // there is a 0 but it is nothing, go figure
530    Elf_Scn *section;
531    GElf_Shdr shdr;
532
533    GElf_Ehdr ehdr;
534
535    assert(!sectionNames.size());
536
537    // check that header matches library version
538    if (elf_version(EV_CURRENT) == EV_NONE)
539        panic("wrong elf version number!");
540
541    // get a pointer to elf structure
542    elf = elf_memory((char*)fileData,len);
543    assert(elf != NULL);
544
545    // Check that we actually have a elf file
546    if (gelf_getehdr(elf, &ehdr) ==0) {
547        panic("Not ELF, shouldn't be here");
548    }
549
550    // Get the first section
551    section = elf_getscn(elf, sec_idx);
552
553    // While there are no more sections
554    while (section != NULL) {
555        gelf_getshdr(section, &shdr);
556        sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name));
557        section = elf_getscn(elf, ++sec_idx);
558    } // while sections
559}
560
561bool
562ElfObject::sectionExists(string sec)
563{
564    if (!sectionNames.size())
565        getSections();
566    return sectionNames.find(sec) != sectionNames.end();
567}
568
569
570void
571ElfObject::updateBias(Addr bias_addr)
572{
573    // Record the bias.
574    ldBias = bias_addr;
575
576    // Patch the entry point with bias_addr.
577    entry += bias_addr;
578
579    // Patch segments with the bias_addr.
580    text.baseAddr += bias_addr;
581    data.baseAddr += bias_addr;
582    bss.baseAddr  += bias_addr;
583    for (auto &segment : extraSegments)
584        segment.baseAddr += bias_addr;
585}
586