Branch data Line data Source code
1 : : /* Find debugging and symbol information for a module in libdwfl.
2 : : Copyright (C) 2006-2010 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #include "libdwflP.h"
30 : :
31 : : const char *
32 : 458052789 : dwfl_module_getsym (Dwfl_Module *mod, int ndx,
33 : : GElf_Sym *sym, GElf_Word *shndxp)
34 : : {
35 [ + - ]: 458052789 : if (unlikely (mod == NULL))
36 : : return NULL;
37 : :
38 [ - + ]: 458052789 : if (unlikely (mod->symdata == NULL))
39 : : {
40 : 0 : int result = INTUSE(dwfl_module_getsymtab) (mod);
41 [ # # ]: 0 : if (result < 0)
42 : : return NULL;
43 : : }
44 : :
45 : : GElf_Word shndx;
46 : 458052789 : sym = gelf_getsymshndx (mod->symdata, mod->symxndxdata, ndx, sym, &shndx);
47 [ - + ]: 458052789 : if (unlikely (sym == NULL))
48 : : {
49 : 0 : __libdwfl_seterrno (DWFL_E_LIBELF);
50 : : return NULL;
51 : : }
52 : :
53 [ + - ]: 458052789 : if (sym->st_shndx != SHN_XINDEX)
54 : 458052789 : shndx = sym->st_shndx;
55 : :
56 : : /* Figure out whether this symbol points into an SHF_ALLOC section. */
57 : 458052789 : bool alloc = true;
58 [ - + ][ # # ]: 458052789 : if ((shndxp != NULL || mod->e_type != ET_REL)
59 [ + + ]: 458052789 : && (sym->st_shndx == SHN_XINDEX
60 : 458052789 : || (sym->st_shndx < SHN_LORESERVE && sym->st_shndx != SHN_UNDEF)))
61 : : {
62 : : GElf_Shdr shdr_mem;
63 : 375161914 : GElf_Shdr *shdr = gelf_getshdr (elf_getscn (mod->symfile->elf, shndx),
64 : : &shdr_mem);
65 [ + + ][ + + ]: 375161914 : alloc = unlikely (shdr == NULL) || (shdr->sh_flags & SHF_ALLOC);
66 : : }
67 : :
68 [ + - ]: 458052789 : if (shndxp != NULL)
69 : : /* Yield -1 in case of a non-SHF_ALLOC section. */
70 [ + + ]: 458052789 : *shndxp = alloc ? shndx : (GElf_Word) -1;
71 : :
72 [ + + ]: 458052789 : switch (sym->st_shndx)
73 : : {
74 : : case SHN_ABS: /* XXX sometimes should use bias?? */
75 : : case SHN_UNDEF:
76 : : case SHN_COMMON:
77 : : break;
78 : :
79 : : default:
80 [ + + ]: 375161914 : if (mod->e_type == ET_REL)
81 : : {
82 : : /* In an ET_REL file, the symbol table values are relative
83 : : to the section, not to the module's load base. */
84 : 828626 : size_t symshstrndx = SHN_UNDEF;
85 : 828626 : Dwfl_Error result = __libdwfl_relocate_value (mod, mod->symfile->elf,
86 : : &symshstrndx,
87 : 828626 : shndx, &sym->st_value);
88 [ - + ]: 828626 : if (unlikely (result != DWFL_E_NOERROR))
89 : : {
90 : 828626 : __libdwfl_seterrno (result);
91 : : return NULL;
92 : : }
93 : : }
94 [ + + ]: 374333288 : else if (alloc)
95 : : /* Apply the bias to the symbol value. */
96 : 371753045 : sym->st_value = dwfl_adjusted_st_value (mod, sym->st_value);
97 : : break;
98 : : }
99 : :
100 [ - + ]: 458052789 : if (unlikely (sym->st_name >= mod->symstrdata->d_size))
101 : : {
102 : 0 : __libdwfl_seterrno (DWFL_E_BADSTROFF);
103 : : return NULL;
104 : : }
105 : 458052789 : return (const char *) mod->symstrdata->d_buf + sym->st_name;
106 : : }
107 : 371753045 : INTDEF (dwfl_module_getsym)
|