-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsymbol_table.c
146 lines (111 loc) · 3.19 KB
/
symbol_table.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <stdlib.h>
#include <stdbool.h>
#include <bfd.h>
#include "symbol_table.h"
static int slurp_symtab(bfd *abfd, asymbol ***out_syms);
int symbol_table_build(char *path, symbol_table_t *table)
{
bfd *abfd;
int rc = -1;
bfd_init();
abfd = bfd_openr(path, NULL);
if (abfd == NULL) {
return rc;
}
abfd->flags |= BFD_DECOMPRESS;
if (bfd_check_format(abfd, bfd_archive)) {
return rc;
}
if (!bfd_check_format(abfd, bfd_object)) {
return rc;
}
if (slurp_symtab(abfd, &table->syms) == 0) {
rc = 0;
table->abfd = abfd;
} else {
bfd_close(abfd);
}
return rc;
}
bfd_boolean symbol_table_find(symbol_table_t *table, void *addr, frame_record_t *out)
{
asection *sect;
bfd_vma pc, sign, vma;
bfd_size_type size;
bfd_boolean ret = false;
asymbol **syms = table->syms;
bfd *abfd = table->abfd;
pc = (bfd_vma)addr;
if (bfd_get_flavour(abfd) == bfd_target_elf_flavour) {
sign = (bfd_vma)1 << (bfd_get_arch_size(abfd) - 1);
pc &= (sign << 1) - 1;
if (bfd_get_sign_extend_vma(abfd)) {
pc = (pc ^ sign) - sign;
}
}
for (sect = abfd->sections; sect != NULL; sect = sect->next) {
if ((bfd_section_flags(sect) & SEC_ALLOC) == 0) {
continue;
}
vma = bfd_section_vma(sect);
if (pc < vma) {
continue;
}
size = bfd_section_size(sect);
if (pc >= vma + size) {
continue;
}
ret = bfd_find_nearest_line_discriminator(abfd, sect, syms, pc - vma,
&out->filename,
&out->functionname,
&out->line,
&out->discriminator);
if (ret) {
break;
}
}
return ret;
}
// Read in the symbol table
static int
slurp_symtab(bfd *abfd, asymbol ***out_syms)
{
asymbol **res;
long storage, symcount;
bfd_boolean dynamic = FALSE;
storage = bfd_get_symtab_upper_bound(abfd);
if (storage == 0) {
storage = bfd_get_dynamic_symtab_upper_bound(abfd);
dynamic = TRUE;
}
if (storage < 0) {
return -1;
}
res = (asymbol **) malloc(storage);
if (dynamic) {
symcount = bfd_canonicalize_dynamic_symtab(abfd, res);
} else {
symcount = bfd_canonicalize_symtab(abfd, res);
}
if (symcount < 0) {
return -1;
}
/* If there are no symbols left after canonicalization and
we have not tried the dynamic symbols then give them a go. */
if (symcount == 0
&& !dynamic
&& (storage = bfd_get_dynamic_symtab_upper_bound(abfd)) > 0)
{
free(res);
res = (asymbol **) malloc(storage);
symcount = bfd_canonicalize_dynamic_symtab(abfd, res);
}
/* PR 17512: file: 2a1d3b5b.
Do not pretend that we have some symbols when we don't. */
if (symcount <= 0) {
free(res);
return -1;
}
*out_syms = res;
return 0;
}