Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
symbol.c
Go to the documentation of this file.
1 /*
2  * Use the awesome dwarf debug library.
3  */
4 #include <assert.h>
5 
6 #include <bts.h>
7 #include <dwdebug.h>
8 
9 static struct debugfile_load_opts opts = {
11 #if 0
13 #endif
14 };
15 
16 static struct symmap *mymap;
17 static int mymapsize;
18 
19 int
20 symlist_init(struct symmap map[], int nmap)
21 {
22  int i, j;
23  struct debugfile *dbfile;
24 
25  dwdebug_init();
26 
27  for (i = 0; i < nmap; i++) {
28  if (map[i].symfile) {
29  dbfile = debugfile_from_file(map[i].symfile,NULL,NULL);
30  if (!dbfile) {
31  fprintf(stderr, "ERROR: could not load debugfile from %s!\n",
32  map[i].symfile);
33  goto bad;
34  }
35  map[i].dbfile = dbfile;
36  }
37  }
38 
39  mymap = map;
40  mymapsize = nmap;
41  return 0;
42 
43  bad:
44  if (dbfile)
45  debugfile_release(dbfile);
46  for (j = 0; j < i; j++) {
47  if (map[j].dbfile) {
48  debugfile_release(map[j].dbfile);
49  map[j].dbfile = NULL;
50  }
51  }
52  dwdebug_fini();
53  return -1;
54 }
55 
56 static inline struct lsymbol *
57 symlist_find(uint32_t addr, struct symmap **map)
58 {
59  struct lsymbol *lsymbol = NULL;
60  int i;
61 
62  for (i = 0; i < mymapsize; i++) {
63  if (addr >= mymap[i].loaddr && addr <= mymap[i].hiaddr &&
64  mymap[i].dbfile) {
65  lsymbol = debugfile_lookup_addr(mymap[i].dbfile, addr);
66  break;
67  }
68  }
69  if (lsymbol == NULL)
70  return NULL;
71 
72  assert(lsymbol->symbol != NULL);
73  if (map)
74  *map = &mymap[i];
75 
76  return lsymbol;
77 }
78 
79 int
80 symlist_isfunc_2(uint32_t addr, char **namep, int *isinlined,
81  uint32_t *loaddr, uint32_t *hiaddr)
82 {
83  struct lsymbol *lsymbol;
84  ADDR saddr, lo, hi;
85 
86  /*
87  * XXX if symbol is found and our address matches, we consider it
88  * a function! I'm sure there is better info in the lsymbol to base
89  * our decision on...
90  */
91  lsymbol = symlist_find(addr, NULL);
92  if (lsymbol && lsymbol->symbol->type == SYMBOL_TYPE_FUNCTION &&
93  symbol_get_location_addr(lsymbol->symbol, &saddr) == 0 &&
94  saddr == addr) {
95  char *name = lsymbol_get_name(lsymbol);
96 #if 0
97  printf("isfunc_2: addr=%x, name='%s'/%x\n",
98  addr, name, lsymbol->symbol->base_addr);
99 #endif
100  if (isinlined) {
101  struct symbol *s = lsymbol_get_noninline_parent_symbol(lsymbol);
102  if (strncmp(name, "__INLINED", 9) == 0)
103  *isinlined = 1;
104  else
105  *isinlined = 0;
106  if (s)
107  name = symbol_get_name(s);
108  }
109  if (namep)
110  *namep = strdup(name);
111 
112  if (loaddr || hiaddr) {
113 #if 0
114  if (strcmp(name, "find_vma") == 0 ||
115  strcmp(name, "follow_page") == 0) {
116  struct dump_info udn = {
117  .stream = stderr,
118  .prefix = "",
119  .detail = 1,
120  .meta = 1,
121  };
122  lsymbol_dump(lsymbol, &udn);
123  fprintf(stderr, "\n");
124  }
125 #endif
126  if (symbol_get_location_range(lsymbol->symbol, &lo, &hi, NULL)) {
127  if (loaddr)
128  *loaddr = 0;
129  if (hiaddr)
130  *hiaddr = 0;
131  } else {
132  if (loaddr)
133  *loaddr = lo;
134  if (hiaddr)
135  *hiaddr = hi;
136 #if 0
137  fprintf(stderr, "%s range is pc %x/%x\n", name, lo, hi);
138 #endif
139  }
140  }
141  lsymbol_release(lsymbol);
142  return 1;
143  }
144 
145  if (lsymbol)
146  lsymbol_release(lsymbol);
147  return 0;
148 }
149 
150 int
151 symlist_isfunc(uint32_t addr)
152 {
153  return symlist_isfunc_2(addr, NULL, NULL, NULL, NULL);
154 }
155 
156 static void
157 __symlist_string(uint32_t addr, char *buf, int bufsize, int gdbstyle)
158 {
159  struct lsymbol *lsymbol;
160  struct symbol *osymbol;
161  char *name, *oname;
162  unsigned long offset, ooffset;
163  struct symmap *map;
164  char *prefix;
165  ADDR saddr;
166 
167  assert(buf != NULL);
168  assert(bufsize > 0);
169 
170  lsymbol = symlist_find(addr, &map);
171  if (lsymbol == NULL) {
172  snprintf(buf, bufsize, "0x%08x", addr);
173  return;
174  }
175 
176  prefix = map->prefix ? map->prefix : "";
177 
178 #if 1
179  /*
180  * XXX this is apparently some sort of inlined anonomous symbol
181  */
182  if (lsymbol->symbol->name == NULL) {
183 #if 1
184  struct dump_info udn = {
185  .stream = stderr,
186  .prefix = "",
187  .detail = 1,
188  .meta = 1,
189  };
190  fprintf(stderr, "======== ADDR 0x%x\n", addr);
191  lsymbol_dump(lsymbol, &udn);
192  fprintf(stderr, "\n========\n");
193  osymbol = lsymbol_get_noninline_parent_symbol(lsymbol);
194  fprintf(stderr, "non-inline returns %p (%s)\n",
195  osymbol, osymbol ? osymbol->name : "<UNDEF>");
196  assert(lsymbol->symbol->name != NULL);
197 #else
198  snprintf(buf, bufsize, "0x%08x", addr);
199  goto done;
200 #endif
201  }
202 #endif
203 
204  /*
205  * Get name and location of the returned symbol.
206  */
207  name = lsymbol_get_name(lsymbol);
208  if (symbol_get_location_addr(lsymbol->symbol, &saddr))
209  saddr = addr;
210  offset = addr - saddr;
211 
212  /*
213  * If the symbol is an INLINE function, it will have a whacky name.
214  * So we lookup the nearest containing function and get the name and
215  * location of that. If the original name and the name returned here
216  * (the "outer" name) are the same, then it wasn't an inline function
217  * symbol.
218  *
219  * We use the outer name when presenting in "GDB style" since that is
220  * what GDB does. We also use it to give a more exact specification
221  * for an inlined function, see below.
222  */
223  osymbol = lsymbol_get_noninline_parent_symbol(lsymbol);
224  if (osymbol) {
225  oname = symbol_get_name(osymbol);
226  if (symbol_get_location_addr(osymbol, &saddr))
227  saddr = addr;
228  ooffset = addr - saddr;
229  } else {
230  /*
231  * XXX if the name is __INLINED(...) then we have
232  * an inline-able function that was not actually inlined.
233  * Extract the true name and run with that.
234  */
235  if (strncmp(name, "__INLINED", 9) == 0) {
236 #if 0
237  printf("addr=%x, name=%s...hacking!\n", addr, name);
238 #endif
239  name = oname = symbol_get_name_inline(lsymbol->symbol);
240  ooffset = offset;
241  } else {
242  oname = name;
243  ooffset = offset;
244  }
245  }
246  assert(strncmp(oname, "__INLINED", 9) != 0);
247 
248 #if 0
249  printf("addr=%x, name='%s'/%x, outername='%s'/%x, innername='%s'\n",
250  addr,
251  name, lsymbol->symbol->base_addr,
252  oname, osymbol ? osymbol->base_addr : ~0U,
253  symbol_get_name_inline(lsymbol->symbol));
254 #endif
255 #if 0
256  if (/*lsymbol->symbol->name == NULL || */addr == 0xc011e552) {
257  struct dump_info udn = {
258  .stream = stderr,
259  .prefix = "",
260  .detail = 1,
261  .meta = 1,
262  };
263  fprintf(stderr, "======== ADDR 0x%x\n", addr);
264  lsymbol_dump(lsymbol, &udn);
265  fprintf(stderr, "\n========\n");
266  assert(lsymbol->symbol->name != NULL);
267  }
268 #endif
269 
270  /*
271  * "Real" GDB does not reflect inlined function calls,
272  * so don't even worry about them.
273  */
274  if (gdbstyle) {
275  if (ooffset == 0)
276  snprintf(buf, bufsize, "0x%08x <%s%s>",
277  addr, prefix, oname);
278  else
279  snprintf(buf, bufsize, "0x%08x <%s%s+%lu>",
280  addr, prefix, oname, ooffset);
281  goto done;
282  }
283 
284  /*
285  * Handle inlined functions. We show them as:
286  * <foo+MM @ bar+NN>
287  * which says that our location is at inlined function foo+MM
288  * which was inlined at bar+NN.
289  */
290  if (strcmp(name, oname) != 0) {
291  char *iname = symbol_get_name_inline(lsymbol->symbol);
292 
293  if (ooffset == 0) {
294  if (offset == 0)
295  snprintf(buf, bufsize, "0x%08x <%s%s @ %s%s>",
296  addr, prefix, iname, prefix, oname);
297  else
298  snprintf(buf, bufsize, "0x%08x <%s%s%+ld @ %s%s>",
299  addr, prefix, iname, offset, prefix, oname);
300  } else {
301  if (offset == 0)
302  snprintf(buf, bufsize, "0x%08x <%s%s @ %s%s+%lu>",
303  addr, prefix, iname, prefix, oname, ooffset);
304  else
305  snprintf(buf, bufsize, "0x%08x <%s%s%+ld @ %s%s+%lu>",
306  addr, prefix, iname, offset, prefix, oname, ooffset);
307  }
308  goto done;
309  }
310 
311  /*
312  * Regular functions.
313  */
314  if (offset == 0)
315  snprintf(buf, bufsize, "0x%08x <%s%s>",
316  addr, prefix, name);
317  else
318  snprintf(buf, bufsize, "0x%08x <%s%s+%lu>",
319  addr, prefix, name, offset);
320 
321  done:
322  lsymbol_release(lsymbol);
323 }
324 
325 void
326 symlist_gdb_string(uint32_t addr, char *buf, int bufsize)
327 {
328  __symlist_string(addr, buf, bufsize, 1);
329 }
330 
331 void
332 symlist_string(uint32_t addr, char *buf, int bufsize)
333 {
334  __symlist_string(addr, buf, bufsize, 0);
335 }
336 
337 struct lsymbol *
339 {
340  struct lsymbol *lsymbol;
341  int i;
342 
343  for (i = 0; i < mymapsize; i++) {
344  if (mymap[i].dbfile) {
345  lsymbol = debugfile_lookup_sym(mymap[i].dbfile, name, ".",
346  NULL, SYMBOL_TYPE_FLAG_NONE);
347  if (lsymbol)
348  return lsymbol;
349  }
350  }
351 
352  return 0;
353 }
354 
355 void
357 {
358  int i;
359 
360  if (mymap == 0)
361  return;
362 
363  for (i = 0; i < mymapsize; i++) {
364  if (mymap[i].dbfile) {
365  debugfile_release(mymap[i].dbfile);
366  mymap[i].dbfile = NULL;
367  }
368  }
369  mymap = NULL;
370  mymapsize = 0;
371 
372  dwdebug_fini();
373 }
374 
375 /*
376  * Local variables:
377  * mode: C
378  * c-set-style: "BSD"
379  * c-basic-offset: 4
380  * End:
381  */
char * symbol_get_name_inline(struct symbol *symbol)
Definition: debug.c:2600
void symlist_string(uint32_t addr, char *buf, int bufsize)
Definition: symbol.c:332
struct debugfile * debugfile_from_file(char *filename, char *root_prefix, struct array_list *debugfile_load_opts_list)
Definition: debug.c:1584
REFCNT lsymbol_release(struct lsymbol *lsymbol)
Definition: debug.c:4805
struct symbol * symbol
Definition: dwdebug.h:1010
struct symbol * lsymbol_get_noninline_parent_symbol(struct lsymbol *lsymbol)
Definition: debug.c:4742
static uint64_t unsigned int i
#define assert(x)
Definition: dlmalloc.c:1456
void * dbfile
Definition: bts.h:12
char * prefix
Definition: bts.h:9
int symlist_isfunc_2(uint32_t addr, char **namep, int *isinlined, uint32_t *loaddr, uint32_t *hiaddr)
Definition: symbol.c:80
symbol_type_t type
Definition: dwdebug_priv.h:833
struct lsymbol * debugfile_lookup_addr(struct debugfile *debugfile, ADDR addr)
Definition: debug.c:667
void dwdebug_init(void)
Definition: debug.c:83
void lsymbol_dump(struct lsymbol *lsymbol, struct dump_info *ud)
Definition: debug.c:5622
int gdbstyle
Definition: bts_dump.c:35
void symlist_gdb_string(uint32_t addr, char *buf, int bufsize)
Definition: symbol.c:326
void symlist_deinit(void)
Definition: symbol.c:356
char * lsymbol_get_name(struct lsymbol *lsymbol)
Definition: debug.c:4732
void dwdebug_fini(void)
Definition: debug.c:143
uint32_t offset
Definition: dwdebug_priv.h:906
struct dt_argp_state opts
Definition: dumptarget.c:111
char * name
Definition: dwdebug_priv.h:788
FILE * stream
Definition: output.h:26
struct lsymbol * debugfile_lookup_sym(struct debugfile *debugfile, char *name, const char *delim, struct rfilter *srcfile_filter, symbol_type_flag_t flags)
Definition: debug.c:1021
struct lsymbol * symlist_lookup_name(char *name)
Definition: symbol.c:338
int symlist_isfunc(uint32_t addr)
Definition: symbol.c:151
int symlist_init(struct symmap map[], int nmap)
Definition: symbol.c:20
uint32_t ADDR
Definition: common.h:64
Definition: bts.h:7
char * symbol_get_name(struct symbol *symbol)
Definition: debug.c:2587