Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/common/libelf/libelf-loader.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * parse and load elf binaries
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation;
7
 * version 2.1 of the License.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
#ifdef __XEN__
19
#include <asm/guest_access.h>
20
#endif
21
22
#include "libelf-private.h"
23
24
/* ------------------------------------------------------------------------ */
25
26
/* Number of section header needed in order to fit the SYMTAB and STRTAB. */
27
5
#define ELF_BSDSYM_SECTIONS 3
28
struct elf_sym_header {
29
    uint32_t size;
30
    struct {
31
        elf_ehdr header;
32
        elf_shdr section[ELF_BSDSYM_SECTIONS];
33
    } elf_header;
34
} __attribute__((packed));
35
36
elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t size)
37
1
{
38
1
    ELF_HANDLE_DECL(elf_shdr) shdr;
39
1
    unsigned i, count, section, link;
40
1
    uint64_t offset;
41
1
42
1
    if ( !elf_is_elfbinary(image_input, size) )
43
0
    {
44
0
        elf_err(elf, "ELF: not an ELF binary\n");
45
0
        return -1;
46
0
    }
47
1
48
1
    elf_memset_unchecked(elf, 0, sizeof(*elf));
49
1
    elf->image_base = image_input;
50
1
    elf->size = size;
51
1
    elf->ehdr = ELF_MAKE_HANDLE(elf_ehdr, (elf_ptrval)image_input);
52
1
    elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]);
53
1
    elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]);
54
1
55
1
    /* Sanity check phdr. */
56
1
    offset = elf_uval(elf, elf->ehdr, e_phoff) +
57
1
        elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf);
58
1
    if ( offset > elf->size )
59
0
    {
60
0
        elf_err(elf, "ELF: phdr overflow (off %" PRIx64 " > size %lx)\n",
61
0
                offset, (unsigned long)elf->size);
62
0
        return -1;
63
0
    }
64
1
65
1
    /* Sanity check shdr. */
66
1
    offset = elf_uval(elf, elf->ehdr, e_shoff) +
67
1
        elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf);
68
1
    if ( offset > elf->size )
69
0
    {
70
0
        elf_err(elf, "ELF: shdr overflow (off %" PRIx64 " > size %lx)\n",
71
0
                offset, (unsigned long)elf->size);
72
0
        return -1;
73
0
    }
74
1
75
1
    /* Find section string table. */
76
1
    section = elf_uval(elf, elf->ehdr, e_shstrndx);
77
1
    shdr = elf_shdr_by_index(elf, section);
78
1
    if ( ELF_HANDLE_VALID(shdr) )
79
1
        elf->sec_strtab = elf_section_start(elf, shdr);
80
1
81
1
    /* Find symbol table and symbol string table. */
82
1
    count = elf_shdr_count(elf);
83
48
    for ( i = 1; i < count; i++ )
84
48
    {
85
48
        shdr = elf_shdr_by_index(elf, i);
86
48
        if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
87
48
            /* input has an insane section header count field */
88
0
            break;
89
48
        if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
90
47
            continue;
91
48
92
1
        link = elf_uval(elf, shdr, sh_link);
93
1
        if ( link == SHN_UNDEF || link >= count )
94
1
            /* out-of-bounds link value. */
95
0
            break;
96
1
97
1
        elf->sym_tab = shdr;
98
1
        shdr = elf_shdr_by_index(elf, link);
99
1
        if ( !ELF_HANDLE_VALID(shdr) )
100
0
        {
101
0
            elf->sym_tab = ELF_INVALID_HANDLE(elf_shdr);
102
0
            continue;
103
0
        }
104
1
        elf->sym_strtab = elf_section_start(elf, shdr);
105
1
        break;
106
1
    }
107
1
108
1
    return 0;
109
1
}
110
111
#ifndef __XEN__
112
void elf_call_log_callback(struct elf_binary *elf, bool iserr,
113
                           const char *fmt,...) {
114
    va_list al;
115
116
    if (!elf->log_callback)
117
        return;
118
    if (!(iserr || elf->verbose))
119
        return;
120
121
    va_start(al,fmt);
122
    elf->log_callback(elf, elf->log_caller_data, iserr, fmt, al);
123
    va_end(al);
124
}
125
    
126
void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
127
                 void *log_caller_data, bool verbose)
128
{
129
    elf->log_callback = log_callback;
130
    elf->log_caller_data = log_caller_data;
131
    elf->verbose = verbose;
132
}
133
134
static elf_errorstatus elf_load_image(struct elf_binary *elf,
135
                          elf_ptrval dst, elf_ptrval src,
136
                          uint64_t filesz, uint64_t memsz)
137
{
138
    elf_memcpy_safe(elf, dst, src, filesz);
139
    elf_memset_safe(elf, dst + filesz, 0, memsz - filesz);
140
    return 0;
141
}
142
#else
143
144
void elf_set_verbose(struct elf_binary *elf)
145
0
{
146
0
    elf->verbose = 1;
147
0
}
148
149
static elf_errorstatus elf_memcpy(struct vcpu *v, void *dst, void *src,
150
                                  uint64_t size)
151
16
{
152
16
    unsigned int res;
153
16
154
16
#ifdef CONFIG_X86
155
16
    if ( is_hvm_vcpu(v) )
156
16
    {
157
16
        enum hvm_translation_result rc;
158
16
159
16
        rc = hvm_copy_to_guest_phys((paddr_t)dst, src, size, v);
160
16
        return rc != HVMTRANS_okay ? -1 : 0;
161
16
    }
162
16
#endif
163
16
164
0
    res = src ? raw_copy_to_guest(dst, src, size) :
165
0
                raw_clear_guest(dst, size);
166
0
167
0
    return res ? -1 : 0;
168
16
}
169
170
static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz)
171
8
{
172
8
    elf_errorstatus rc;
173
8
    if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
174
0
        return -1;
175
8
    /* We trust the dom0 kernel image completely, so we don't care
176
8
     * about overruns etc. here. */
177
8
    rc = elf_memcpy(elf->vcpu, ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src),
178
8
                    filesz);
179
8
    if ( rc != 0 )
180
0
        return -1;
181
8
    rc = elf_memcpy(elf->vcpu, ELF_UNSAFE_PTR(dst + filesz), NULL,
182
8
                    memsz - filesz);
183
8
    if ( rc != 0 )
184
0
        return -1;
185
8
    return 0;
186
8
}
187
#endif
188
189
/* Calculate the required additional kernel space for the elf image */
190
void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
191
1
{
192
1
    uint64_t sz;
193
1
    ELF_HANDLE_DECL(elf_shdr) shdr;
194
1
195
1
    if ( !ELF_HANDLE_VALID(elf->sym_tab) )
196
0
    {
197
0
        elf_mark_broken(elf, "invalid ELF handle for symtab section");
198
0
        return;
199
0
    }
200
1
201
1
    pstart = elf_round_up(elf, pstart);
202
1
203
1
    /* Space to store the size of the elf image */
204
1
    sz = sizeof(uint32_t);
205
1
206
1
    /* Space for the ELF header and section headers */
207
1
    sz += offsetof(struct elf_sym_header, elf_header.section) +
208
1
          ELF_BSDSYM_SECTIONS * (elf_64bit(elf) ? sizeof(Elf64_Shdr) :
209
0
                                                  sizeof(Elf32_Shdr));
210
1
    sz = elf_round_up(elf, sz);
211
1
212
1
    /*
213
1
     * No need to search for the symtab section header again, it's handler
214
1
     * is stored in elf->sym_tab by the elf_init function.
215
1
     */
216
1
217
1
    /* Space for the symbol and string tables. */
218
1
    sz = elf_round_up(elf, sz + elf_uval(elf, elf->sym_tab, sh_size));
219
1
220
1
    shdr = elf_shdr_by_index(elf, elf_uval(elf, elf->sym_tab, sh_link));
221
1
222
1
    if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
223
1
        /* input has an insane section header count field */
224
0
        return;
225
1
226
1
    if ( elf_uval(elf, shdr, sh_type) != SHT_STRTAB )
227
1
        /* Invalid symtab -> strtab link */
228
0
        return;
229
1
230
1
    sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
231
1
232
1
    elf->bsd_symtab_pstart = pstart;
233
1
    elf->bsd_symtab_pend   = pstart + sz;
234
1
}
235
236
static void elf_load_bsdsyms(struct elf_binary *elf)
237
1
{
238
1
    /*
239
1
     * Header that is placed at the end of the kernel and allows
240
1
     * the OS to find where the symtab and strtab have been loaded.
241
1
     * It mimics a valid ELF file header, although it only contains
242
1
     * a symtab and a strtab section. The layout in memory is the
243
1
     * following:
244
1
     *
245
1
     * +------------------------+
246
1
     * |                        |
247
1
     * | KERNEL                 |
248
1
     * |                        |
249
1
     * +------------------------+ pend
250
1
     * | ALIGNMENT              |
251
1
     * +------------------------+ bsd_symtab_pstart
252
1
     * |                        |
253
1
     * | size                   | bsd_symtab_pend - bsd_symtab_pstart
254
1
     * |                        |
255
1
     * +------------------------+ bsd_symtab_pstart + 4
256
1
     * |                        |
257
1
     * | ELF header             |
258
1
     * |                        |
259
1
     * +------------------------+
260
1
     * |                        |
261
1
     * | ELF section header 0   | Undefined section header
262
1
     * |                        |
263
1
     * +------------------------+
264
1
     * |                        |
265
1
     * | ELF section header 1   | SYMTAB section header
266
1
     * |                        |
267
1
     * +------------------------+
268
1
     * |                        |
269
1
     * | ELF section header 2   | STRTAB section header
270
1
     * |                        |
271
1
     * +------------------------+
272
1
     * |                        |
273
1
     * | SYMTAB                 |
274
1
     * |                        |
275
1
     * +------------------------+
276
1
     * |                        |
277
1
     * | STRTAB                 |
278
1
     * |                        |
279
1
     * +------------------------+ bsd_symtab_pend
280
1
     *
281
1
     * NB: according to the ELF spec there's only ONE symtab per ELF
282
1
     * file, and accordingly we will only load the corresponding
283
1
     * strtab, so we only need three section headers in our fake ELF
284
1
     * header (first section header is always the undefined section).
285
1
     */
286
1
    struct elf_sym_header header;
287
1
    ELF_HANDLE_DECL(elf_ehdr) header_handle;
288
1
    unsigned long shdr_size, ehdr_size, header_size;
289
1
    ELF_HANDLE_DECL(elf_shdr) section_handle;
290
1
    unsigned int link, rc, i;
291
1
    elf_ptrval header_base;
292
1
    elf_ptrval elf_header_base;
293
1
    elf_ptrval symtab_base;
294
1
    elf_ptrval strtab_base;
295
1
296
1
    if ( !elf->bsd_symtab_pstart )
297
0
        return;
298
1
299
12
#define elf_store_field_bitness(_elf, _hdr, _elm, _val)             \
300
12
do {                                                                \
301
12
    if ( elf_64bit(_elf) )                                          \
302
12
        elf_store_field(_elf, _hdr, e64._elm, _val);                \
303
12
    else                                                            \
304
0
        elf_store_field(_elf, _hdr, e32._elm, _val);                \
305
12
} while ( 0 )
306
1
307
1
#define SYMTAB_INDEX    1
308
1
#define STRTAB_INDEX    2
309
1
310
1
    /* Allow elf_memcpy_safe to write to header. */
311
1
    elf_set_xdest(elf, &header, sizeof(header));
312
1
313
1
    /*
314
1
     * Calculate the position of the various elements in GUEST MEMORY SPACE.
315
1
     * This addresses MUST only be used with elf_load_image.
316
1
     *
317
1
     * NB: strtab_base cannot be calculated at this point because we don't
318
1
     * know the size of the symtab yet, and the strtab will be placed after it.
319
1
     */
320
1
    header_base = elf_get_ptr(elf, elf->bsd_symtab_pstart);
321
1
    elf_header_base = elf_get_ptr(elf, elf->bsd_symtab_pstart) +
322
1
                      sizeof(uint32_t);
323
1
    symtab_base = elf_round_up(elf, header_base + sizeof(header));
324
1
325
1
    /*
326
1
     * Set the size of the ELF header and the section headers, based on the
327
1
     * size of our local copy.
328
1
     */
329
1
    ehdr_size = elf_64bit(elf) ? sizeof(header.elf_header.header.e64) :
330
0
                                 sizeof(header.elf_header.header.e32);
331
1
    shdr_size = elf_64bit(elf) ? sizeof(header.elf_header.section[0].e64) :
332
0
                                 sizeof(header.elf_header.section[0].e32);
333
1
334
1
    /* Fill the ELF header, copied from the original ELF header. */
335
1
    header_handle = ELF_MAKE_HANDLE(elf_ehdr,
336
1
                                ELF_REALPTR2PTRVAL(&header.elf_header.header));
337
1
    elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(header_handle),
338
1
                    ELF_HANDLE_PTRVAL(elf->ehdr), ehdr_size);
339
1
340
1
    /*
341
1
     * Set the ELF header size, section header entry size and version
342
1
     * (in case we are dealing with an input ELF header that has extensions).
343
1
     */
344
1
    elf_store_field_bitness(elf, header_handle, e_ehsize, ehdr_size);
345
1
    elf_store_field_bitness(elf, header_handle, e_shentsize, shdr_size);
346
1
    elf_store_field_bitness(elf, header_handle, e_version, EV_CURRENT);
347
1
348
1
    /* Set the offset to the shdr array. */
349
1
    elf_store_field_bitness(elf, header_handle, e_shoff,
350
1
                            offsetof(typeof(header.elf_header), section));
351
1
352
1
    /* Set the right number of section headers. */
353
1
    elf_store_field_bitness(elf, header_handle, e_shnum, ELF_BSDSYM_SECTIONS);
354
1
355
1
    /* Clear a couple of fields we don't use. */
356
1
    elf_store_field_bitness(elf, header_handle, e_phoff, 0);
357
1
    elf_store_field_bitness(elf, header_handle, e_phentsize, 0);
358
1
    elf_store_field_bitness(elf, header_handle, e_phnum, 0);
359
1
    elf_store_field_bitness(elf, header_handle, e_shstrndx, 0);
360
1
361
1
    /*
362
1
     * The symtab section header is going to reside in section[SYMTAB_INDEX],
363
1
     * while the corresponding strtab is going to be placed in
364
1
     * section[STRTAB_INDEX]. sh_offset is mangled so it points to the offset
365
1
     * where the sections are actually loaded (relative to the ELF header
366
1
     * location).
367
1
     */
368
1
    section_handle = ELF_MAKE_HANDLE(elf_shdr,
369
1
                ELF_REALPTR2PTRVAL(&header.elf_header.section[SYMTAB_INDEX]));
370
1
371
1
    elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(section_handle),
372
1
                    ELF_HANDLE_PTRVAL(elf->sym_tab),
373
1
                    shdr_size);
374
1
375
1
    /* Copy the original sh_link field before mangling it. */
376
1
    link = elf_uval(elf, section_handle, sh_link);
377
1
378
1
    /* Load symtab into guest memory. */
379
1
    rc = elf_load_image(elf, symtab_base,
380
1
                        elf_section_start(elf, section_handle),
381
1
                        elf_uval(elf, section_handle, sh_size),
382
1
                        elf_uval(elf, section_handle, sh_size));
383
1
    if ( rc != 0 )
384
0
    {
385
0
        elf_mark_broken(elf, "unable to load symtab into guest memory");
386
0
        return;
387
0
    }
388
1
389
1
    /* Adjust the sh_offset and sh_link of the copied section header. */
390
1
    elf_store_field_bitness(elf, section_handle, sh_offset,
391
1
                            symtab_base - elf_header_base);
392
1
    elf_store_field_bitness(elf, section_handle, sh_link,
393
1
                            STRTAB_INDEX);
394
1
395
1
    /* Calculate the guest address where strtab is loaded. */
396
1
    strtab_base = elf_round_up(elf, symtab_base +
397
1
                               elf_uval(elf, section_handle, sh_size));
398
1
399
1
    /* Load strtab section header. */
400
1
    section_handle = ELF_MAKE_HANDLE(elf_shdr,
401
1
            ELF_REALPTR2PTRVAL(&header.elf_header.section[STRTAB_INDEX]));
402
1
    elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(section_handle),
403
1
                    ELF_HANDLE_PTRVAL(elf_shdr_by_index(elf, link)),
404
1
                    shdr_size);
405
1
406
1
    if ( elf_uval(elf, section_handle, sh_type) != SHT_STRTAB )
407
0
    {
408
0
        elf_mark_broken(elf, "strtab not found");
409
0
        return;
410
0
    }
411
1
412
1
    /* Load strtab into guest memory. */
413
1
    rc = elf_load_image(elf, strtab_base,
414
1
                        elf_section_start(elf, section_handle),
415
1
                        elf_uval(elf, section_handle, sh_size),
416
1
                        elf_uval(elf, section_handle, sh_size));
417
1
    if ( rc != 0 )
418
0
    {
419
0
        elf_mark_broken(elf, "unable to load strtab into guest memory");
420
0
        return;
421
0
    }
422
1
423
1
    elf_store_field_bitness(elf, section_handle, sh_offset,
424
1
                            strtab_base - elf_header_base);
425
1
426
1
    /* Store the whole size (including headers and loaded sections). */
427
1
    header.size = strtab_base + elf_uval(elf, section_handle, sh_size) -
428
1
                  elf_header_base;
429
1
430
1
    /* Load the size plus ELF header. */
431
1
    header_size = offsetof(typeof(header), elf_header.section);
432
1
    rc = elf_load_image(elf, header_base, ELF_REALPTR2PTRVAL(&header),
433
1
                        header_size, header_size);
434
1
    if ( rc != 0 )
435
0
    {
436
0
        elf_mark_broken(elf, "unable to load ELF headers into guest memory");
437
0
        return;
438
0
    }
439
1
440
1
    /*
441
1
     * Load the section headers.
442
1
     *
443
1
     * NB: this _must_ be done one by one, and taking the bitness into account,
444
1
     * so that the guest can treat this as an array of type Elf{32/64}_Shdr.
445
1
     */
446
4
    for ( i = 0; i < ELF_BSDSYM_SECTIONS; i++ )
447
3
    {
448
3
        rc = elf_load_image(elf, header_base + header_size + shdr_size * i,
449
3
                            ELF_REALPTR2PTRVAL(&header.elf_header.section[i]),
450
3
                            shdr_size, shdr_size);
451
3
        if ( rc != 0 )
452
0
        {
453
0
            elf_mark_broken(elf,
454
0
                        "unable to load ELF section header into guest memory");
455
0
            return;
456
0
        }
457
3
    }
458
1
459
1
    /* Remove permissions from elf_memcpy_safe. */
460
1
    elf_set_xdest(elf, NULL, 0);
461
1
462
1
#undef SYMTAB_INDEX
463
1
#undef STRTAB_INDEX
464
1
#undef elf_store_field_bitness
465
1
}
466
467
void elf_parse_binary(struct elf_binary *elf)
468
1
{
469
1
    ELF_HANDLE_DECL(elf_phdr) phdr;
470
1
    uint64_t low = -1, high = 0, paddr, memsz;
471
1
    unsigned i, count;
472
1
473
1
    count = elf_phdr_count(elf);
474
7
    for ( i = 0; i < count; i++ )
475
6
    {
476
6
        phdr = elf_phdr_by_index(elf, i);
477
6
        if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
478
6
            /* input has an insane program header count field */
479
0
            break;
480
6
        if ( !elf_phdr_is_loadable(elf, phdr) )
481
4
            continue;
482
2
        paddr = elf_uval(elf, phdr, p_paddr);
483
2
        memsz = elf_uval(elf, phdr, p_memsz);
484
2
        elf_msg(elf, "ELF: phdr: paddr=%#" PRIx64 " memsz=%#" PRIx64 "\n",
485
2
                paddr, memsz);
486
2
        if ( low > paddr )
487
1
            low = paddr;
488
2
        if ( high < paddr + memsz )
489
2
            high = paddr + memsz;
490
2
    }
491
1
    elf->pstart = low;
492
1
    elf->pend = high;
493
1
    elf_msg(elf, "ELF: memory: %#" PRIx64 " -> %#" PRIx64 "\n",
494
1
            elf->pstart, elf->pend);
495
1
}
496
497
elf_errorstatus elf_load_binary(struct elf_binary *elf)
498
1
{
499
1
    ELF_HANDLE_DECL(elf_phdr) phdr;
500
1
    uint64_t paddr, offset, filesz, memsz;
501
1
    unsigned i, count;
502
1
    elf_ptrval dest;
503
1
    /*
504
1
     * Let bizarre ELFs write the output image up to twice; this
505
1
     * calculation is just to ensure our copying loop is no worse than
506
1
     * O(domain_size).
507
1
     */
508
1
    uint64_t remain_allow_copy = (uint64_t)elf->dest_size * 2;
509
1
510
1
    count = elf_phdr_count(elf);
511
7
    for ( i = 0; i < count; i++ )
512
6
    {
513
6
        phdr = elf_phdr_by_index(elf, i);
514
6
        if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
515
6
            /* input has an insane program header count field */
516
0
            break;
517
6
        if ( !elf_phdr_is_loadable(elf, phdr) )
518
4
            continue;
519
2
        paddr = elf_uval(elf, phdr, p_paddr);
520
2
        offset = elf_uval(elf, phdr, p_offset);
521
2
        filesz = elf_uval(elf, phdr, p_filesz);
522
2
        memsz = elf_uval(elf, phdr, p_memsz);
523
2
        dest = elf_get_ptr(elf, paddr);
524
2
525
2
        /*
526
2
         * We need to check that the input image doesn't have us copy
527
2
         * the whole image zillions of times, as that could lead to
528
2
         * O(n^2) time behaviour and possible DoS by a malicous ELF.
529
2
         */
530
2
        if ( remain_allow_copy < memsz )
531
0
        {
532
0
            elf_mark_broken(elf, "program segments total to more"
533
0
                            " than the input image size");
534
0
            break;
535
0
        }
536
2
        remain_allow_copy -= memsz;
537
2
538
2
        elf_msg(elf,
539
2
                "ELF: phdr %u at %#"ELF_PRPTRVAL" -> %#"ELF_PRPTRVAL"\n",
540
2
                i, dest, (elf_ptrval)(dest + filesz));
541
2
        if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
542
0
            return -1;
543
2
    }
544
1
545
1
    elf_load_bsdsyms(elf);
546
1
    return 0;
547
1
}
548
549
elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr)
550
4
{
551
4
    return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
552
4
}
553
554
uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
555
0
{
556
0
    ELF_HANDLE_DECL(elf_sym) sym;
557
0
    uint64_t value;
558
0
559
0
    sym = elf_sym_by_name(elf, symbol);
560
0
    if ( !ELF_HANDLE_VALID(sym) )
561
0
    {
562
0
        elf_err(elf, "%s: not found: %s\n", __func__, symbol);
563
0
        return -1;
564
0
    }
565
0
566
0
    value = elf_uval(elf, sym, st_value);
567
0
    elf_msg(elf, "%s: symbol \"%s\" at 0x%" PRIx64 "\n", __func__,
568
0
            symbol, value);
569
0
    return value;
570
0
}
571
572
/*
573
 * Local variables:
574
 * mode: C
575
 * c-file-style: "BSD"
576
 * c-basic-offset: 4
577
 * tab-width: 4
578
 * indent-tabs-mode: nil
579
 * End:
580
 */