source: trunk/packages/xen-3.1/xen-3.1/xen/common/libelf/libelf-loader.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 4.5 KB
Line 
1/*
2 * parse and load elf binaries
3 */
4
5#include "libelf-private.h"
6
7/* ------------------------------------------------------------------------ */
8
9int elf_init(struct elf_binary *elf, const char *image, size_t size)
10{
11    const elf_shdr *shdr;
12    uint64_t i, count, section, offset;
13
14    if ( !elf_is_elfbinary(image) )
15    {
16        elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
17        return -1;
18    }
19
20    memset(elf, 0, sizeof(*elf));
21    elf->image = image;
22    elf->size = size;
23    elf->ehdr = (elf_ehdr *) image;
24    elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
25    elf->data = elf->ehdr->e32.e_ident[EI_DATA];
26
27    /* sanity check phdr */
28    offset = elf_uval(elf, elf->ehdr, e_phoff) +
29        elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf);
30    if ( offset > elf->size )
31    {
32        elf_err(elf, "%s: phdr overflow (off %" PRIx64 " > size %lx)\n",
33                __FUNCTION__, offset, (unsigned long)elf->size);
34        return -1;
35    }
36
37    /* sanity check shdr */
38    offset = elf_uval(elf, elf->ehdr, e_shoff) +
39        elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf);
40    if ( offset > elf->size )
41    {
42        elf_err(elf, "%s: shdr overflow (off %" PRIx64 " > size %lx)\n",
43                __FUNCTION__, offset, (unsigned long)elf->size);
44        return -1;
45    }
46
47    /* find section string table */
48    section = elf_uval(elf, elf->ehdr, e_shstrndx);
49    shdr = elf_shdr_by_index(elf, section);
50    if ( shdr != NULL )
51        elf->sec_strtab = elf_section_start(elf, shdr);
52
53    /* find symbol table, symbol string table */
54    count = elf_shdr_count(elf);
55    for ( i = 0; i < count; i++ )
56    {
57        shdr = elf_shdr_by_index(elf, i);
58        if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
59            continue;
60        elf->sym_tab = shdr;
61        shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link));
62        if ( shdr == NULL )
63        {
64            elf->sym_tab = NULL;
65            continue;
66        }
67        elf->sym_strtab = elf_section_start(elf, shdr);
68        break;
69    }
70    return 0;
71}
72
73#ifndef __XEN__
74void elf_set_logfile(struct elf_binary *elf, FILE * log, int verbose)
75{
76    elf->log = log;
77    elf->verbose = verbose;
78}
79#else
80void elf_set_verbose(struct elf_binary *elf)
81{
82    elf->verbose = 1;
83}
84#endif
85
86void elf_parse_binary(struct elf_binary *elf)
87{
88    const elf_phdr *phdr;
89    uint64_t low = -1;
90    uint64_t high = 0;
91    uint64_t i, count, paddr, memsz;
92
93    count = elf_uval(elf, elf->ehdr, e_phnum);
94    for ( i = 0; i < count; i++ )
95    {
96        phdr = elf_phdr_by_index(elf, i);
97        if ( !elf_phdr_is_loadable(elf, phdr) )
98            continue;
99        paddr = elf_uval(elf, phdr, p_paddr);
100        memsz = elf_uval(elf, phdr, p_memsz);
101        elf_msg(elf, "%s: phdr: paddr=0x%" PRIx64
102                " memsz=0x%" PRIx64 "\n", __FUNCTION__, paddr, memsz);
103        if ( low > paddr )
104            low = paddr;
105        if ( high < paddr + memsz )
106            high = paddr + memsz;
107    }
108    elf->pstart = low;
109    elf->pend = high;
110    elf_msg(elf, "%s: memory: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
111            __FUNCTION__, elf->pstart, elf->pend);
112}
113
114void elf_load_binary(struct elf_binary *elf)
115{
116    const elf_phdr *phdr;
117    uint64_t i, count, paddr, offset, filesz, memsz;
118    char *dest;
119
120    count = elf_uval(elf, elf->ehdr, e_phnum);
121    for ( i = 0; i < count; i++ )
122    {
123        phdr = elf_phdr_by_index(elf, i);
124        if ( !elf_phdr_is_loadable(elf, phdr) )
125            continue;
126        paddr = elf_uval(elf, phdr, p_paddr);
127        offset = elf_uval(elf, phdr, p_offset);
128        filesz = elf_uval(elf, phdr, p_filesz);
129        memsz = elf_uval(elf, phdr, p_memsz);
130        dest = elf_get_ptr(elf, paddr);
131        elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
132                __func__, i, dest, dest + filesz);
133        memcpy(dest, elf->image + offset, filesz);
134        memset(dest + filesz, 0, memsz - filesz);
135    }
136}
137
138void *elf_get_ptr(struct elf_binary *elf, unsigned long addr)
139{
140    return elf->dest + addr - elf->pstart;
141}
142
143uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
144{
145    const elf_sym *sym;
146    uint64_t value;
147
148    sym = elf_sym_by_name(elf, symbol);
149    if ( sym == NULL )
150    {
151        elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol);
152        return -1;
153    }
154
155    value = elf_uval(elf, sym, st_value);
156    elf_msg(elf, "%s: symbol \"%s\" at 0x%" PRIx64 "\n", __FUNCTION__,
157            symbol, value);
158    return value;
159}
160
161/*
162 * Local variables:
163 * mode: C
164 * c-set-style: "BSD"
165 * c-basic-offset: 4
166 * tab-width: 4
167 * indent-tabs-mode: nil
168 * End:
169 */
Note: See TracBrowser for help on using the repository browser.