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
debug.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, 2012, 2013, 2014 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program 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
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <stdio.h>
20 #include <string.h>
21 #include <assert.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <regex.h>
29 #include <limits.h>
30 #include <stdint.h>
31 #include <inttypes.h>
32 #include <stdarg.h>
33 #include <glib.h>
34 #include <dwarf.h>
35 #ifdef DWDEBUG_MEMDEBUG
36 #include <malloc.h>
37 #endif
38 
39 #include "common.h"
40 #include "log.h"
41 #include "output.h"
42 #include "list.h"
43 #include "alist.h"
44 #include "glib_wrapper.h"
45 #include "rfilter.h"
46 #include "binfile.h"
47 #include "dwdebug.h"
48 #include "dwdebug_priv.h"
49 
50 /* These are the known, loaded (maybe partially) debuginfo files. */
51 /* debug filename -> struct debugfile */
52 static GHashTable *debugfile_tab = NULL;
53 static GHashTable *debugfile_id_tab = NULL;
54 
55 static int debugfile_id_idx = 0;
56 
58  .debugfile_filter = NULL,
59  .srcfile_filter = NULL,
60  .symbol_filter = NULL,
62 };
63 
64 static const char *DEBUGPATHS[] = {
65  "/usr/lib/debug",
66  "/usr/local/lib/debug",
67  NULL
68 };
69 
70 static int init_done = 0;
71 
72 #if DWDEBUG_MEMDEBUG
73 static GMemVTable system_malloc_gmemvtable = {
74  .malloc = malloc,
75  .realloc = realloc,
76  .free = free,
77  .calloc = calloc,
78  .try_malloc = NULL,
79  .try_realloc = NULL,
80 };
81 #endif
82 
83 void dwdebug_init(void) {
84  if (init_done)
85  return;
86 
87 #ifdef DWDEBUG_MEMDEBUG
88  if (getenv("G_SLICE") && strcmp(getenv("G_SLICE"),"always-malloc") == 0)
89  g_mem_set_vtable(glib_mem_profiler_table);
90  //g_mem_set_vtable(&system_malloc_gmemvtable);
91 #endif
92 
93  binfile_init();
94 
95  debugfile_tab = g_hash_table_new_full(g_str_hash,g_str_equal,
96  NULL,NULL);
97  debugfile_id_tab = g_hash_table_new_full(g_direct_hash,g_direct_equal,
98  NULL,NULL);
99 
100  init_done = 1;
101 }
102 
103 static void dwdebug_save(struct debugfile *debugfile) {
104  /*
105  * Add it to our global hash if the user init'd the lib!
106  */
107  if (debugfile_tab) {
108  g_hash_table_insert(debugfile_tab,debugfile->filename,debugfile);
109  g_hash_table_insert(debugfile_id_tab,
110  (gpointer)(uintptr_t)debugfile->id,debugfile);
111  RHOLD(debugfile,debugfile_tab);
112  }
113 }
114 
115 void dwdebug_evict(struct debugfile *debugfile) {
116  REFCNT trefcnt;
117 
118  if (debugfile_id_tab) {
119  if (g_hash_table_lookup(debugfile_id_tab,
120  (gpointer)(uintptr_t)debugfile->id)
121  == debugfile) {
122  g_hash_table_remove(debugfile_id_tab,
123  (gpointer)(uintptr_t)debugfile->id);
124  g_hash_table_remove(debugfile_tab,debugfile->filename);
125  RPUT(debugfile,debugfile,debugfile_id_tab,trefcnt);
126  }
127  }
128 }
129 
130 void dwdebug_evict_all(void) {
131  GList *list,*t1;
132  struct debugfile *debugfile;
133 
134  if (debugfile_id_tab) {
135  list = g_hash_table_get_values(debugfile_id_tab);
136  v_g_list_foreach(list,t1,debugfile) {
137  dwdebug_evict(debugfile);
138  }
139  g_list_free(list);
140  }
141 }
142 
143 void dwdebug_fini(void) {
144  GHashTableIter iter;
145  struct debugfile *df;
146 
147  if (!init_done)
148  return;
149 
150  /* Try to uncache everything naturally first. */
152 
153  /* Double-iterate so that internal loop can remove hashtable nodes. */
154  while (g_hash_table_size(debugfile_tab) > 0) {
155  g_hash_table_iter_init(&iter,debugfile_tab);
156  while (g_hash_table_iter_next(&iter,NULL,(gpointer)&df)) {
157  debugfile_free(df,1);
158  break;
159  }
160  }
161  g_hash_table_destroy(debugfile_tab);
162  debugfile_tab = NULL;
163  g_hash_table_destroy(debugfile_id_tab);
164  debugfile_id_tab = NULL;
165 
166  init_done = 0;
167 }
168 
169 /*
170  * Prototypes.
171  */
172 
177 struct symbol *symbol_get_sym(struct symbol *symbol,const char *name,
178  symbol_type_flag_t flags) {
179  struct scope *scope;
180 
181  if (!SYMBOL_IS_CONTAINER(symbol))
182  return NULL;
183 
184  /*
185  * Don't try to expand the symbol; this is not a lookup function!
186  */
187 
188  scope = symbol_read_owned_scope(symbol);
189  if (scope)
190  return scope_get_sym(scope,name,flags);
191 
192  return NULL;
193 }
194 
196  const char *name,const char *delim) {
197 
198  char *next;
199  char *lname = NULL;
200  char *saveptr = NULL;
201  struct array_list *anonchain = NULL;
202  int i;
203  struct lsymbol *lsymbol = NULL;
204  struct array_list *chain;
205 
206  if (!SYMBOL_IS_CONTAINER(symbol)) {
207  verror("symbol %s is not a container!\n",
208  symbol_get_name(symbol));
209  return NULL;
210  }
211 
212  SYMBOL_EXPAND_WARN(symbol);
213 
214  lname = strdup(name);
215  chain = array_list_create(0);
216 
217  /* Add the first one to our chain and start looking up members. */
218  lsymbol = lsymbol_create(symbol,chain);
219  lsymbol_append(lsymbol,symbol);
220 
222  "starting at top-level %s: checking members\n",
223  symbol_get_name(symbol));
224 
225  if (!delim)
226  delim = DWDEBUG_DEF_DELIM;
227 
228  while ((next = strtok_r(!saveptr ? lname : NULL,delim,&saveptr))) {
229  if (!(symbol = __symbol_get_one_member__int(symbol,next,&anonchain)))
230  goto errout;
231  else if (anonchain && array_list_len(anonchain)) {
232  /* If anonchain has any members, we now have to glue those
233  * members into our overall chain, BEFORE gluing the actual
234  * found symbol onto the tail end of the chain.
235  */
236  for (i = 0; i < array_list_len(anonchain); ++i) {
237  lsymbol_append(lsymbol,
238  (struct symbol *)array_list_item(anonchain,i));
239  }
240  /* free the anonchain (and its members!) and reset our pointer */
241  array_list_free(anonchain);
242  anonchain = NULL;
243  }
244  /* now slap the retval on, too! */
245  lsymbol_append(lsymbol,symbol);
246  }
247 
248  free(lname);
249 
250  /* downsize */
251  array_list_compact(chain);
252 
253  return lsymbol;
254 
255  errout:
256  if (lname)
257  free(lname);
258  if (lsymbol)
259  lsymbol_free(lsymbol,0);
260 
261  return NULL;
262 }
263 
265  const char *name,const char *delim) {
266  struct lsymbol *lsymbol = symbol_lookup_sym__int(symbol,name,delim);
267  if (!lsymbol)
268  return NULL;
269 
270  RHOLD(lsymbol,lsymbol);
271 
272  return lsymbol;
273 }
274 
276  const char *name,const char *delim) {
277  struct lsymbol *ls;
278  int i;
279 
280  /*
281  * Very simple -- we just lookup @name in @symbol, then, prepend the
282  * first N - 1 items in @lsymbol's chain (i.e., not including
283  * @symbol itself, which is at the head of @ls's chain) to @ls, and
284  * RHOLD those N - 1 items.
285  */
286  ls = symbol_lookup_sym__int(lsymbol->symbol,name,delim);
287  if (!ls)
288  return NULL;
289 
290  array_list_prepend_sublist(ls->chain,lsymbol->chain,-1);
291 
292  /* We have to take refs to each symbol of the cloned chain. */
293  for (i = 0; i < array_list_len(lsymbol->chain) - 1; ++i)
294  RHOLD((struct symbol *)array_list_item(ls->chain,i),ls);
295 
296  return ls;
297 }
298 
300  const char *name,const char *delim) {
301  struct lsymbol *ls;
302 
303  ls = lsymbol_lookup_sym__int(lsymbol,name,delim);
304 
305  /* This is a lookup function, so it has to hold a ref to its return
306  * value.
307  */
308  if (ls)
309  RHOLD(ls,ls);
310 
311  return ls;
312 }
313 
315  const char *name,const char *delim) {
316  struct symbol *s;
317  struct symbol *datatype;
318  struct lsymbol *ls;
319  OFFSET retval = 0;
320  int i;
321  struct location *loc;
322 
323  SYMBOL_EXPAND_WARN(symbol);
324 
325  if (SYMBOL_IST_STUN(symbol))
326  datatype = symbol;
327  else if (SYMBOL_IS_VAR(symbol)) {
328  datatype = symbol_get_datatype(symbol);
329  if (!SYMBOL_IST_STUN(datatype)) {
330  errno = EINVAL;
331  return 0;
332  }
333  }
334  else {
335  errno = EINVAL;
336  return 0;
337  }
338 
339  ls = symbol_lookup_sym__int(datatype,name,delim);
340  if (!ls) {
341  if (!errno)
342  errno = ESRCH;
343  return 0;
344  }
345 
346  /*
347  * Now that we have the symbol chain, just trace the offsets.
348  */
349  i = 1;
351  loc = SYMBOLX_VAR_LOC(s);
352  if (!loc || !LOCATION_IS_M_OFFSET(loc)) {
353  lsymbol_free(ls,1);
354  errno = EINVAL;
355  return 0;
356  }
357  retval += LOCATION_OFFSET(loc);
358  }
359 
360  lsymbol_free(ls,1);
361  return retval;
362 }
363 
365  const char *name,const char *delim) {
366  return symbol_offsetof(lsymbol->symbol,name,delim);
367 }
368 
369 struct lsymbol *lsymbol_clone(struct lsymbol *lsymbol,struct symbol *newchild) {
370  struct lsymbol *ls;
371  struct array_list *chain;
372 
373  chain = array_list_clone(lsymbol->chain,(newchild) ? 1 : 0);
374  ls = lsymbol_create(lsymbol->symbol,chain);
375 
376  if (newchild)
377  lsymbol_append(ls,newchild);
378 
379  /* This is a lookup function, so it has to hold a ref to its return
380  * value.
381  */
382  RHOLD(ls,ls);
383 
384  return ls;
385 }
386 
387 struct array_list *debugfile_lookup_addrs_line(struct debugfile *debugfile,
388  char *filename,int line) {
389  GHashTableIter iter;
390  gpointer key;
391  gpointer value;
392  clmatch_t clf;
393  char *srcfile;
394 
395  g_hash_table_iter_init(&iter,debugfile->srclines);
396  while (g_hash_table_iter_next(&iter,&key,&value)) {
397  srcfile = (char *)key;
398  clf = (clmatch_t)value;
399  vdebug(9,LA_DEBUG,LF_DLOOKUP,"checking srcfile %s for filename %s\n",
400  srcfile,filename);
401  if (strstr(srcfile,filename)) {
402  vdebug(9,LA_DEBUG,LF_DLOOKUP,"found match: srcfile %s for filename %s\n",
403  srcfile,filename);
404  return clmatch_find(&clf,line);
405  }
406  }
407 
408  return NULL;
409 }
410 
411 int debugfile_lookup_line_addr(struct debugfile *debugfile,
412  char *filename,ADDR addr) {
413  GHashTableIter iter;
414  gpointer key;
415  gpointer value;
416  clmatch_t clf;
417  char *srcfile;
418  int retval = -1;
419 
420  g_hash_table_iter_init(&iter,debugfile->srcaddrlines);
421  while (g_hash_table_iter_next(&iter,&key,&value)) {
422  srcfile = (char *)key;
423  clf = (clmatch_t)value;
424  if (filename && !strstr(srcfile,filename))
425  continue;
426 
427  vdebug(9,LA_DEBUG,LF_DLOOKUP,"checking srcfile %s for filename %s\n",
428  srcfile,filename);
429  retval = (int)(uintptr_t)clmatch_find(&clf,addr);
430  if (retval > 0)
431  return retval;
432  }
433 
434  return -1;
435 }
436 
437 int debugfile_lookup_filename_line_addr(struct debugfile *debugfile,
438  ADDR addr,char **filename,int *line) {
439  GHashTableIter iter;
440  gpointer key;
441  gpointer value;
442  clmatch_t clf;
443  int retval;
444 
445  g_hash_table_iter_init(&iter,debugfile->srcaddrlines);
446  while (g_hash_table_iter_next(&iter,&key,&value)) {
447  clf = (clmatch_t)value;
448 
449  vdebug(9,LA_DEBUG,LF_DLOOKUP,"checking srcfile %s\n",(char *)key);
450  retval = (int)(uintptr_t)clmatch_find(&clf,addr);
451  if (retval > 0) {
452  if (filename)
453  *filename = (char *)key;
454  if (line)
455  *line = retval;
456  return 0;
457  }
458  }
459 
460  return -1;
461 }
462 
463 struct lsymbol *debugfile_lookup_sym_line__int(struct debugfile *debugfile,
464  char *filename,int line,
465  SMOFFSET *offset,ADDR *addr) {
466  struct array_list *addrs;
467  struct lsymbol *ls = NULL;
468  int i;
469  ADDR iaddr;
470 
471  addrs = debugfile_lookup_addrs_line(debugfile,filename,line);
472  if (!addrs)
473  return NULL;
474 
475  for (i = 0; i < array_list_len(addrs); ++i) {
476  iaddr = (ADDR)array_list_item(addrs,i);
477  ls = debugfile_lookup_addr__int(debugfile,iaddr);
478  if (ls) {
479  if (addr)
480  *addr = iaddr;
481  if (offset && symbol_has_addr(ls->symbol)) {
482  *offset = iaddr - symbol_get_addr(ls->symbol);
483  }
484  return ls;
485  }
486  }
487 
488  return NULL;
489 }
490 
491 struct lsymbol *debugfile_lookup_sym_line(struct debugfile *debugfile,
492  char *filename,int line,
493  SMOFFSET *offset,ADDR *addr) {
494  struct lsymbol *ls;
495 
496  ls = debugfile_lookup_sym_line__int(debugfile,filename,line,offset,addr);
497  if (ls)
498  RHOLD(ls,ls);
499 
500  return ls;
501 }
502 
503 struct lsymbol *debugfile_lookup_addr__int(struct debugfile *debugfile,ADDR addr) {
504  struct scope *scope;
505  struct lsymbol *ls;
506  struct symbol *s = (struct symbol *)g_hash_table_lookup(debugfile->addresses,
507  (gpointer)addr);
508 
509  if (!s) {
510  /* If we didn't find it, try our scope search struct! */
511  scope = (struct scope *)clrange_find(&debugfile->ranges,addr);
512 
513  /*
514  * If ALLRANGES was not set, scope will be the CU scope;
515  * otherwise it will be the absolute tightest. So -- if it was
516  * not set, we have to call scope_lookup_addr to find the
517  * tightest bound.
518  */
519  if (scope && !(debugfile->opts->flags & DEBUGFILE_LOAD_FLAG_ALLRANGES))
520  scope = scope_lookup_addr(scope,addr);
521 
522  if (scope) {
523  if (scope->symbol) {
525  "found scope(0x%"PRIxADDR",0x%"PRIxADDR"%s)"
526  " (symbol %s:0x%"PRIxSMOFFSET")\n",
527  scope->range->start,scope->range->end,
528  (scope->range->next != NULL) ? ";..." : "",
529  symbol_get_name(scope->symbol),scope->symbol->ref);
530 
531  /*
532  * Make sure the symbol is fully loaded; then repeat the
533  * search to be sure we have the tightest bound.
534  */
535  if (!SYMBOL_IS_FULL(scope->symbol)) {
536  SYMBOL_EXPAND_WARN(scope->symbol);
537 
538  scope = (struct scope *)clrange_find(&debugfile->ranges,addr);
539 
540  if (scope && !(debugfile->opts->flags & DEBUGFILE_LOAD_FLAG_ALLRANGES))
541  scope = scope_lookup_addr(scope,addr);
542  }
543  }
544  else {
546  "found scope(0x%"PRIxADDR",0x%"PRIxADDR"%s)\n",
547  scope->range->start,scope->range->end,
548  (scope->range->next != NULL) ? ";..." : "");
549  }
550  }
551 
552  while (scope) {
553  if (scope->symbol) {
554  s = scope->symbol;
555  break;
556  }
557  scope = scope->parent;
558  }
559  }
560 
561  /*
562  * If we still didn't find it, check the binfile and
563  * binfile_pointing symtabs as necessary.
564  */
565  if (!s && debugfile->binfile && debugfile->binfile->ranges)
566  s = (struct symbol *)clrange_find(&debugfile->binfile->ranges,addr);
567  else if (!s && debugfile->binfile_pointing
568  && debugfile->binfile_pointing->ranges)
569  s = (struct symbol *)clrange_find(&debugfile->binfile_pointing->ranges,
570  addr);
571 
572  if (s)
574  else
575  ls = NULL;
576 
577  return ls;
578 }
579 
580 int debugfile_lookup_addr_alt__int(struct debugfile *debugfile,ADDR addr,
581  struct lsymbol **primary,struct lsymbol **alt) {
582  struct scope *scope;
583  struct symbol *s = NULL,*p = NULL,*a = NULL;
584 
585  if (primary) {
586  s = (struct symbol *)g_hash_table_lookup(debugfile->addresses,
587  (gpointer)addr);
588 
589  if (!s) {
590  /* If we didn't find it, try our scope search struct! */
591  scope = (struct scope *)clrange_find(&debugfile->ranges,addr);
592 
593  /*
594  * If ALLRANGES was not set, scope will be the CU scope;
595  * otherwise it will be the absolute tightest. So -- if it was
596  * not set, we have to call scope_lookup_addr to find the
597  * tightest bound.
598  */
599  if (scope && !(debugfile->opts->flags & DEBUGFILE_LOAD_FLAG_ALLRANGES))
600  scope = scope_lookup_addr(scope,addr);
601 
602  if (scope) {
603  if (scope->symbol) {
605  "found scope(0x%"PRIxADDR",0x%"PRIxADDR"%s)"
606  " (symbol %s:0x%"PRIxSMOFFSET")\n",
607  scope->range->start,scope->range->end,
608  (scope->range->next != NULL) ? ";..." : "",
609  symbol_get_name(scope->symbol),scope->symbol->ref);
610 
611  /*
612  * Make sure the symbol is fully loaded; then repeat the
613  * search to be sure we have the tightest bound.
614  */
615  if (!SYMBOL_IS_FULL(scope->symbol)) {
616  SYMBOL_EXPAND_WARN(scope->symbol);
617 
618  scope = (struct scope *)clrange_find(&debugfile->ranges,addr);
619 
620  if (scope && !(debugfile->opts->flags & DEBUGFILE_LOAD_FLAG_ALLRANGES))
621  scope = scope_lookup_addr(scope,addr);
622  }
623  }
624  else {
626  "found scope(0x%"PRIxADDR",0x%"PRIxADDR"%s)\n",
627  scope->range->start,scope->range->end,
628  (scope->range->next != NULL) ? ";..." : "");
629  }
630  }
631 
632  while (scope) {
633  if (scope->symbol) {
634  s = scope->symbol;
635  break;
636  }
637  scope = scope->parent;
638  }
639  }
640 
641  p = s;
642  if (p)
643  *primary = lsymbol_create_from_symbol__int(p);
644  }
645 
646  if (alt) {
647  if (debugfile->binfile && debugfile->binfile->ranges)
648  s = (struct symbol *)clrange_find(&debugfile->binfile->ranges,addr);
649  else if (!s && debugfile->binfile_pointing
650  && debugfile->binfile_pointing->ranges)
651  s = (struct symbol *) \
652  clrange_find(&debugfile->binfile_pointing->ranges,addr);
653 
654  a = s;
655  if (a)
657  }
658 
659  if (p)
660  return 0;
661  else if (a)
662  return 0;
663  else
664  return -1;
665 }
666 
667 struct lsymbol *debugfile_lookup_addr(struct debugfile *debugfile,ADDR addr) {
668  struct lsymbol *ls;
669 
670  ls = debugfile_lookup_addr__int(debugfile,addr);
671  if (ls)
672  RHOLD(ls,ls);
673 
674  return ls;
675 }
676 
677 struct lsymbol *debugfile_lookup_sym__int(struct debugfile *debugfile,
678  char *name,const char *delim,
679  struct rfilter *srcfile_filter,
680  symbol_type_flag_t flags) {
681  char *next = NULL;
682  char *lname = NULL;
683  char *saveptr = NULL;
684  struct array_list *anonchain = NULL;
685  int i;
686  struct lsymbol *lsymbol = NULL;
687  struct lsymbol *lsymbol_tmp = NULL;
688  struct symbol *symbol = NULL;
689  struct symbol *root;
690  struct scope *root_scope;
691  struct array_list *chain = NULL;
692  GHashTableIter iter;
693  gpointer key;
694  gpointer value;
695  struct rfilter_entry *rfe;
696  int accept = RF_ACCEPT;
697  struct array_list *root_list;
698 
699  if (!delim)
700  delim = DWDEBUG_DEF_DELIM;
701 
702  if (delim && strstr(name,delim)) {
703  lname = strdup(name);
704  next = strtok_r(!saveptr ? lname : NULL,delim,&saveptr);
705  chain = array_list_create(1);
706  }
707  else
708  next = name;
709 
710  /*
711  * Always check globals first, then types, then srcfile tables.
712  */
713  if ((flags & SYMBOL_TYPE_FLAG_VAR || flags & SYMBOL_TYPE_FLAG_FUNC
714  || flags & SYMBOL_TYPE_FLAG_LABEL || flags == SYMBOL_TYPE_FLAG_NONE)
715  && (symbol = g_hash_table_lookup(debugfile->globals,next))) {
716  if (srcfile_filter) {
717  rfilter_check(srcfile_filter,symbol_get_srcfile(symbol),&accept,&rfe);
718  if (accept == RF_ACCEPT) {
719  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"found rf global %s\n",
720  symbol->name);
721  goto found;
722  }
723  }
724  else {
725  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"found global %s\n",
726  symbol->name);
727  goto found;
728  }
729  }
730 
731  if ((flags & SYMBOL_TYPE_FLAG_TYPE || flags == SYMBOL_TYPE_FLAG_NONE)
732  && (symbol = g_hash_table_lookup(debugfile->types,next))) {
733  if (srcfile_filter) {
734  rfilter_check(srcfile_filter,symbol_get_srcfile(symbol),&accept,&rfe);
735  if (accept == RF_ACCEPT) {
736  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"found rf type %s\n",
737  symbol->name);
738  goto found;
739  }
740  }
741  else {
742  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"found type %s\n",
743  symbol->name);
744  goto found;
745  }
746  }
747 
748  /*
749  * Check all the srcfiles, or check according to the rfilter.
750  */
751  g_hash_table_iter_init(&iter,debugfile->srcfiles);
752  while (g_hash_table_iter_next(&iter,&key,&value)) {
753  root = (struct symbol *)value;
754  root_scope = symbol_read_owned_scope(root);
755  if (srcfile_filter) {
756  rfilter_check(srcfile_filter,key,&accept,&rfe);
757  if (accept == RF_REJECT)
758  continue;
759  }
760  if (!root_scope)
761  continue;
762 
763  lsymbol_tmp = scope_lookup_sym__int(root_scope,name,delim,flags);
764  if (lsymbol_tmp) {
765  /* If we do find a match, and it's a type, take it! */
766  if (SYMBOL_IS_TYPE(lsymbol_tmp->symbol)) {
767  lsymbol = lsymbol_tmp;
768  goto found;
769  }
770  /* Or if we find a match and it is a definition (which
771  * implies it should have a location!), take it!
772  */
773  else if (!symbol_is_declaration(lsymbol_tmp->symbol)) {
774  //SYMBOL_IS_FULL(lsymbol_tmp->symbol)
775  // && lsymbol_tmp->symbol->s.ii->l.loctype
776  // != LOCTYPE_UNKNOWN) {
777  lsymbol = lsymbol_tmp;
778  goto found;
779  }
780  /* Otherwise, if we haven't found anything else yet, save it
781  * off as our "first match", and keep looking. If we find
782  * nothing better later on, we'll use it.
783  */
784  else if (!lsymbol) {
785  lsymbol = lsymbol_tmp;
786  }
787  /* We are never going to use this match, so free it. */
788  else {
789  /* Don't force free; somebody else might have a ref! */
790  lsymbol_free(lsymbol_tmp,0);
791  }
792  }
793  }
794  /*
795  * There will probably never be any hits in here, but we have to check.
796  */
797  g_hash_table_iter_init(&iter,debugfile->srcfiles_multiuse);
798  while (g_hash_table_iter_next(&iter,&key,&value)) {
799  root_list = (struct array_list *)value;
800  if (srcfile_filter) {
801  rfilter_check(srcfile_filter,key,&accept,&rfe);
802  if (accept == RF_REJECT)
803  continue;
804  }
805 
806  array_list_foreach(root_list,i,root) {
807  root_scope = symbol_read_owned_scope(root);
808  lsymbol_tmp = scope_lookup_sym__int(root_scope,name,delim,flags);
809  if (lsymbol_tmp) {
810  /* If we do find a match, and it's a type, take it! */
811  if (SYMBOL_IS_TYPE(lsymbol_tmp->symbol)) {
812  lsymbol = lsymbol_tmp;
813  goto found;
814  }
815  /* Or if we find a match and it is a definition (which
816  * implies it should have a location!), take it!
817  */
818  else if (!symbol_is_declaration(lsymbol_tmp->symbol)) {
819  //SYMBOL_IS_FULL(lsymbol_tmp->symbol)
820  // && lsymbol_tmp->symbol->s.ii->l.loctype
821  // != LOCTYPE_UNKNOWN) {
822  lsymbol = lsymbol_tmp;
823  goto found;
824  }
825  /* Otherwise, if we haven't found anything else yet, save it
826  * off as our "first match", and keep looking. If we find
827  * nothing better later on, we'll use it.
828  */
829  else if (!lsymbol) {
830  lsymbol = lsymbol_tmp;
831  }
832  /* We are never going to use this match, so free it. */
833  else {
834  /* Don't force free; somebody else might have a ref! */
835  lsymbol_free(lsymbol_tmp,0);
836  }
837  }
838  }
839  }
840 
841  /*
842  * If we don't have a srcfile filter, check the binfile and
843  * binfile_pointing symtabs.
844  */
845  if (!lsymbol && debugfile->binfile && debugfile->binfile->root) {
846  if (srcfile_filter) {
847  rfilter_check(srcfile_filter,
848  symbol_get_srcfile(debugfile->binfile->root),
849  &accept,&rfe);
850  if (accept == RF_ACCEPT) {
852  "matched rf binfile srcfile %s; will check it\n",
853  debugfile->binfile->root->name);
854  }
855  else {
857  "did not match rf binfile srcfile %s; not searching\n",
858  debugfile->binfile->root->name);
859  return NULL;
860  }
861  }
862 
863  root_scope = symbol_read_owned_scope(debugfile->binfile->root);
864  lsymbol = scope_lookup_sym__int(root_scope,name,delim,flags);
865  }
866  else if (!lsymbol && debugfile->binfile_pointing
867  && debugfile->binfile_pointing->root) {
868  if (srcfile_filter) {
869  rfilter_check(srcfile_filter,
871  &accept,&rfe);
872  if (accept == RF_ACCEPT) {
874  "matched rf binfile srcfile %s; will check it\n",
875  debugfile->binfile_pointing->root->name);
876  }
877  else {
879  "did not match rf binfile srcfile %s; not searching\n",
880  debugfile->binfile_pointing->root->name);
881  return NULL;
882  }
883  }
884 
885  root_scope = symbol_read_owned_scope(debugfile->binfile_pointing->root);
886  lsymbol = scope_lookup_sym__int(root_scope,name,delim,flags);
887  }
888 
889  /* If we didn't find anything in our srcfiles traversal, we're
890  * done.
891  */
892  if (!lsymbol)
893  return NULL;
894 
895  found:
896  /*
897  * If we found a symbol match in our srcfiles, and it is not a
898  * declaration, return it! Why do we just return it? Because
899  * symtab_lookup_sym will have *already* finished searching for any
900  * children in the fully-qualified symbol name.
901  *
902  * XXX: this can be very wasteful! We may search fully down a long
903  * chain, only to find that the end of the chain is a type or
904  * declaration, and then keep on searching! We may never find
905  * something better :).
906  *
907  * So, we have to expose this to the user as a param of some sort:
908  * LOOKUP_OPT_FIRST_MATCH; LOOKUP_OPT_FIND_DEFINITION; or
909  * something.
910  */
911  if (lsymbol && !symbol_is_declaration(lsymbol->symbol)) {
912  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"found best %s in symtab\n",
913  lsymbol->symbol->name);
914  /* If we found a match, fully load it (and its children and
915  * dependent DIEs if it hasn't been yet!).
916  */
917  if (!SYMBOL_IS_FULL(lsymbol->symbol)) {
918  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"expanding partial lsymbol %s\n",
919  symbol_get_name(lsymbol->symbol));
920  SYMBOL_EXPAND_WARN(lsymbol->symbol);
921  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"expanded partial lsymbol %s\n",
922  symbol_get_name(lsymbol->symbol));
923  }
924 
925  goto out;
926  }
927  /* We're not going to use it; it is no better than symbol. */
928  else if (symbol) {
929  if (lsymbol) {
930  /* Don't force free; somebody might have a ref to it. */
931  lsymbol_free(lsymbol,0);
932  lsymbol = NULL;
933  }
934  }
935 
936  /* If we only have the result from types/globals search, use that! */
937  if (!lsymbol) {
938  /* If we found a match, fully load it (and its children and
939  * dependent DIEs if it hasn't been yet!).
940  */
941  if (!SYMBOL_IS_FULL(symbol)) {
942  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"expanding partial symbol %s\n",
943  symbol_get_name(symbol));
944  SYMBOL_EXPAND_WARN(symbol);
945  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"expanded partial symbol %s\n",
946  symbol_get_name(symbol));
947  }
948 
949  lsymbol = lsymbol_create(symbol,chain);
950 
951  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"found plain %s\n",
952  lsymbol->symbol->name);
953 
954  lsymbol_append(lsymbol,symbol);
955  }
956  else {
957  /* If we found a match, fully load it (and its children and
958  * dependent DIEs if it hasn't been yet!).
959  */
960  if (!SYMBOL_IS_FULL(lsymbol->symbol)) {
961  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"expanding partial lsymbol %s\n",
962  symbol_get_name(lsymbol->symbol));
963  SYMBOL_EXPAND_WARN(lsymbol->symbol);
964  vdebug(3,LA_DEBUG,LF_DFILE | LF_DLOOKUP,"expanded partial lsymbol %s\n",
965  symbol_get_name(lsymbol->symbol));
966  }
967  }
968 
969  /* If it's not a delimited string, stop now, successfully. */
970  if (!lname) {
971 
972  goto out;
973  }
974 
976  "found top-level %s; checking members\n",lsymbol->symbol->name);
977 
978  if (!delim)
979  delim = DWDEBUG_DEF_DELIM;
980 
981  while ((next = strtok_r(!saveptr ? lname : NULL,delim,&saveptr))) {
982  if (!(symbol = __symbol_get_one_member__int(symbol,next,&anonchain))) {
983  vwarnopt(3,LA_DEBUG,LF_DLOOKUP,"did not find symbol for %s\n",next);
984  goto errout;
985  }
986  else if (anonchain && array_list_len(anonchain)) {
987  /* If anonchain has any members, we now have to glue those
988  * members into our overall chain, BEFORE gluing the actual
989  * found symbol onto the tail end of the chain.
990  */
991  for (i = 0; i < array_list_len(anonchain); ++i) {
992  lsymbol_append(lsymbol,
993  (struct symbol *)array_list_item(anonchain,i));
994  }
995  /* free the anonchain (and its members!) and reset our pointer */
996  array_list_free(anonchain);
997  anonchain = NULL;
998  }
999  /* now slap the retval on, too! */
1000  lsymbol_append(lsymbol,symbol);
1001  }
1002 
1003  free(lname);
1004 
1005  /* downsize */
1006  array_list_compact(chain);
1007 
1008  out:
1009  return lsymbol;
1010 
1011  errout:
1012  if (lname)
1013  free(lname);
1014  if (lsymbol)
1015  /* Don't force free; somebody might have a ref to it! */
1016  lsymbol_free(lsymbol,0);
1017 
1018  return NULL;
1019 }
1020 
1021 struct lsymbol *debugfile_lookup_sym(struct debugfile *debugfile,
1022  char *name,const char *delim,
1023  struct rfilter *srcfile_filter,
1024  symbol_type_flag_t flags) {
1025  struct lsymbol *lsymbol = debugfile_lookup_sym__int(debugfile,name,delim,
1026  srcfile_filter,flags);
1027 
1028  if (lsymbol)
1029  RHOLD(lsymbol,lsymbol);
1030 
1031  return lsymbol;
1032 }
1033 
1034 GSList *debugfile_match_syms(struct debugfile *debugfile,
1035  struct rfilter *symbol_filter,
1036  symbol_type_flag_t flags,
1037  struct rfilter *srcfile_filter) {
1038  GSList *retval = NULL;
1039  GSList *retlist;
1040  GHashTableIter iter;
1041  char *name;
1042  struct symbol *symbol;
1043  GHashTableIter iter2;
1044  char *srcfile_name;
1045  struct symbol *root;
1046  struct scope *scope;
1047  int accept;
1048  gpointer key;
1049  gpointer value;
1050  struct array_list *root_list;
1051  int i;
1052 
1053  if (!symbol_filter) {
1054  errno = EINVAL;
1055  return NULL;
1056  }
1057 
1058  if (flags & SYMBOL_TYPE_FLAG_VAR_GLOBAL && !srcfile_filter) {
1059  if (flags == SYMBOL_TYPE_FLAG_NONE
1060  || flags & SYMBOL_TYPE_FLAG_TYPE) {
1061  g_hash_table_iter_init(&iter,debugfile->types);
1062  while (g_hash_table_iter_next(&iter,&key,&value)) {
1063  name = (char *)key;
1064  symbol = (struct symbol *)value;
1065  rfilter_check(symbol_filter,name,&accept,NULL);
1066  if (accept == RF_ACCEPT)
1067  retval = g_slist_prepend(retval,symbol);
1068  }
1069  g_hash_table_iter_init(&iter,debugfile->shared_types);
1070  while (g_hash_table_iter_next(&iter,&key,&value)) {
1071  name = (char *)key;
1072  symbol = (struct symbol *)value;
1073  rfilter_check(symbol_filter,name,&accept,NULL);
1074  if (accept == RF_ACCEPT)
1075  retval = g_slist_prepend(retval,symbol);
1076  }
1077  }
1078 
1079  g_hash_table_iter_init(&iter,debugfile->globals);
1080  while (g_hash_table_iter_next(&iter,&key,&value)) {
1081  name = (char *)key;
1082  symbol = (struct symbol *)value;
1083  if (SYMBOL_TYPE_FLAG_MATCHES(symbol,flags)) {
1084  rfilter_check(symbol_filter,name,&accept,NULL);
1085  if (accept == RF_ACCEPT)
1086  retval = g_slist_prepend(retval,symbol);
1087  }
1088  }
1089  }
1090  else {
1091  g_hash_table_iter_init(&iter2,debugfile->srcfiles);
1092  while (g_hash_table_iter_next(&iter2,&key,&value)) {
1093  srcfile_name = (char *)key;
1094  root = (struct symbol *)value;
1095 
1096  if (srcfile_filter) {
1097  rfilter_check(srcfile_filter,srcfile_name,&accept,NULL);
1098  if (accept == RF_REJECT)
1099  continue;
1100  }
1101 
1102  scope = symbol_read_owned_scope(root);
1103  if (scope) {
1104  retlist = scope_match_syms(scope,symbol_filter,flags);
1105  if (retlist)
1106  retval = g_slist_concat(retval,retlist);
1107  }
1108  }
1109  g_hash_table_iter_init(&iter2,debugfile->srcfiles_multiuse);
1110  while (g_hash_table_iter_next(&iter2,&key,&value)) {
1111  srcfile_name = (char *)key;
1112  root_list = (struct array_list *)value;
1113  if (srcfile_filter) {
1114  rfilter_check(srcfile_filter,srcfile_name,&accept,NULL);
1115  if (accept == RF_REJECT)
1116  continue;
1117  }
1118 
1119  array_list_foreach(root_list,i,root) {
1120  scope = symbol_read_owned_scope(root);
1121  if (scope) {
1122  retlist = scope_match_syms(scope,symbol_filter,flags);
1123  if (retlist)
1124  retval = g_slist_concat(retval,retlist);
1125  }
1126  }
1127  }
1128  }
1129 
1130  return retval;
1131 }
1132 
1149  char *token2 = NULL;
1150  char *saveptr2;
1151  debugfile_load_flags_t flags = 0;
1152 
1153  if (!delim)
1154  delim = ",";
1155 
1156  while ((token2 = strtok_r((!token2)?flagstr:NULL,delim,&saveptr2))) {
1157  vdebug(7,LA_DEBUG,LF_DFILE,"token2 = '%s'\n",token2);
1158  if (strcmp(token2,"NONE") == 0 || strcmp(token2,"*") == 0) {
1159  flags = DEBUGFILE_LOAD_FLAG_NONE;
1160  return 0;
1161  }
1162  else if (strcmp(token2,"CUHEADERS") == 0)
1164  else if (strcmp(token2,"PUBNAMES") == 0)
1166  else if (strcmp(token2,"NODWARF") == 0)
1167  flags |= DEBUGFILE_LOAD_FLAG_NODWARF;
1168  else if (strcmp(token2,"ALLRANGES") == 0)
1170  else if (strcmp(token2,"KEEPDECLS") == 0)
1172  else if (strcmp(token2,"PARTIALSYM") == 0)
1174  else if (strcmp(token2,"REDUCETYPES") == 0)
1176  else if (strcmp(token2,"REDUCETYPES_FULL_EQUIV") == 0)
1178  else {
1179  verror("unknown flag '%s'\n",token2);
1180  errno = EINVAL;
1181  return 0;
1182  }
1183  }
1184 
1185  return flags;
1186 }
1187 
1188 /*
1189  * FLAG,FLAG,FLAG|| \
1190  * [<A|1|R|0>::][<A|1|R|0>:]dfn;[<A|1|R|0>:]dfn;[<A|1|R|0>:]dfn|| \
1191  * [<A|1|R|0>::][<A|1|R|0>:]sfn;[<A|1|R|0>:]sfn;[<A|1|R|0>:]sfn|| \
1192  * [<A|1|R|0>::][<A|1|R|0>:]ss;[<A|1|R|0>:]ss;[<A|1|R|0>:]ss
1193  */
1195  int i;
1196  char *token;
1197  char *saveptr;
1198  struct rfilter *rf;
1199 
1200  struct debugfile_load_opts *opts = \
1201  (struct debugfile_load_opts *)malloc(sizeof(*opts));
1202  memset(opts,0,sizeof(*opts));
1203 
1204  vdebug(5,LA_DEBUG,LF_DFILE,"starting\n");
1205 
1206  token = NULL;
1207  saveptr = NULL;
1208  i = 0;
1209  /* Skip flags parse if there aren't any. */
1210  if (optstr && *optstr == '|' && *(optstr + 1) == '|')
1211  i = 1;
1212  while ((token = strtok_r((!token)?optstr:NULL,"||",&saveptr))) {
1213  vdebug(7,LA_DEBUG,LF_DFILE,"token = '%s' at %d\n",token,i);
1214 
1215  if (i == 0) {
1216  opts->flags = debugfile_load_flags_parse(token,NULL);
1217  if (errno) {
1218  verror("could not load flags!\n");
1219  goto errout;
1220  }
1221  }
1222  else if (i < 4) {
1223  rf = rfilter_create_parse(token);
1224  if (!rf) {
1225  goto errout;
1226  }
1227  else if (i == 1)
1228  opts->debugfile_filter = rf;
1229  else if (i == 2)
1230  opts->srcfile_filter = rf;
1231  else if (i == 3)
1232  opts->symbol_filter = rf;
1233  }
1234  ++i;
1235  }
1236 
1237  return opts;
1238 
1239  errout:
1241  return NULL;
1242 }
1243 
1244 int debugfile_load_opts_checklist(struct array_list *opts_list,char *name,
1245  struct debugfile_load_opts **match_saveptr) {
1246  struct debugfile_load_opts *opts = NULL;
1247  int accept = RF_REJECT;
1248  int i;
1249 
1250  vdebug(2,LA_DEBUG,LF_DFILE,"checking debugfile load opts list against '%s'\n",
1251  name);
1252  array_list_foreach(opts_list,i,opts) {
1253  /*
1254  * We only care if there was a match (or no match and the
1255  * filter defaulted to accept) that accepted our filename
1256  * for processing.
1257  */
1258  rfilter_check(opts->debugfile_filter,name,&accept,NULL);
1259  if (accept == RF_ACCEPT) {
1261  "debugfile opts %p matched '%s'\n",opts,name);
1262  if (match_saveptr) {
1263  *match_saveptr = opts;
1264  return accept;
1265  }
1266  }
1267  else
1269  "not using debugfile opts %p for '%s'\n",opts,name);
1270  }
1271 
1272  return accept;
1273 }
1274 
1276  if (opts->debugfile_filter)
1277  rfilter_free(opts->debugfile_filter);
1278  if (opts->srcfile_filter)
1279  rfilter_free(opts->srcfile_filter);
1280  if (opts->symbol_filter)
1281  rfilter_free(opts->symbol_filter);
1282 
1283  free(opts);
1284 }
1285 
1286 char * debugfile_get_name(struct debugfile *debugfile) {
1287  return debugfile->filename;
1288 }
1289 
1290 char *debugfile_get_version(struct debugfile *debugfile) {
1291  if (debugfile->binfile)
1292  return debugfile->binfile->version;
1293  return NULL;
1294 }
1295 
1296 void debugfile_init_internal(struct debugfile *debugfile);
1297 
1299  debugfile_type_flags_t dtflags,
1300  char *filename,
1301  struct debugfile_load_opts *opts) {
1302  struct debugfile *debugfile;
1303 
1304  if (!dtype) {
1305  verror("invalid dtype %d!\n",dtype);
1306  errno = EINVAL;
1307  return NULL;
1308  }
1309 
1310  /* create a new one */
1311  debugfile = (struct debugfile *)calloc(1,sizeof(*debugfile));
1312  if (!debugfile) {
1313  errno = ENOMEM;
1314  return NULL;
1315  }
1316 
1317  if (!opts)
1319 
1320  debugfile->type = dtype;
1321  debugfile->opts = opts;
1322 
1323  debugfile->filename = strdup(filename);
1324  debugfile->id = ++debugfile_id_idx;
1325  debugfile->flags = dtflags;
1326  debugfile->refcnt = 0;
1327 
1328  if (dtype == DEBUGFILE_TYPE_DWARF)
1329  debugfile->ops = &dwarf_debugfile_ops;
1330 
1331  debugfile_init_internal(debugfile);
1332 
1333  return debugfile;
1334 }
1335 
1336 struct debugfile *debugfile_create(debugfile_type_t dtype,
1337  debugfile_type_flags_t dtflags,
1338  struct binfile *binfile,
1339  struct debugfile_load_opts *opts,
1340  struct binfile *binfile_pointing) {
1341  struct debugfile *debugfile;
1342 
1343  /* create a new one */
1344  debugfile = (struct debugfile *)calloc(1,sizeof(*debugfile));
1345  if (!debugfile) {
1346  errno = ENOMEM;
1347  return NULL;
1348  }
1349 
1350  if (!opts)
1352 
1353  debugfile->type = dtype;
1354  debugfile->opts = opts;
1355 
1356  if (binfile)
1357  debugfile->filename = strdup(binfile->filename);
1358  debugfile->id = ++debugfile_id_idx;
1359  debugfile->flags = dtflags;
1360  debugfile->refcnt = 0;
1361 
1362  if (binfile) {
1363  debugfile->binfile = binfile;
1364  RHOLD(binfile,debugfile);
1365  }
1366 
1367  if (binfile_pointing) {
1368  debugfile->binfile_pointing = binfile_pointing;
1369  RHOLD(binfile_pointing,debugfile);
1370  }
1371 
1372  /*
1373  * Figure out what type it was from the binfile.
1374  *
1375  * XXX: hack until we have more than DWARF.
1376  */
1377  if (!dtype && binfile) {
1378  if (binfile->has_debuginfo) {
1379  debugfile->type = DEBUGFILE_TYPE_DWARF;
1380  }
1381  else {
1382  debugfile->type = DEBUGFILE_TYPE_ELF;
1383  debugfile->ops = NULL;
1384  }
1385  }
1386  else if (!dtype) {
1387  verror("no debugfile_type_t nor binfile!\n");
1388  errno = EINVAL;
1389  debugfile_free(debugfile,1);
1390  return NULL;
1391  }
1392 
1393  if (dtype == DEBUGFILE_TYPE_DWARF)
1394  debugfile->ops = &dwarf_debugfile_ops;
1395 
1396  debugfile_init_internal(debugfile);
1397 
1398  return debugfile;
1399 }
1400 
1401 void debugfile_init_internal(struct debugfile *debugfile) {
1402  /* initialize hashtables */
1403 
1404  /* This is the primary symtab hashtable -- they are cleaned up in
1405  * debugfile_free.
1406  */
1407  debugfile->srcfiles = g_hash_table_new_full(g_str_hash,g_str_equal,
1408  NULL,NULL);
1409 
1410  debugfile->srcfiles_multiuse = g_hash_table_new_full(g_str_hash,g_str_equal,
1411  NULL,NULL);
1412 
1413  /* This is an optimization lookup hashtable, so we don't provide
1414  * *any* key or value destructors since we don't want them freed
1415  * when the hashtable is destroyed.
1416  */
1417  debugfile->cuoffsets = g_hash_table_new(g_direct_hash,g_direct_equal);
1418 
1419  /* This is an optimization lookup hashtable, so we don't provide
1420  * *any* key or value destructors since we don't want them freed
1421  * when the hashtable is destroyed.
1422  */
1423  debugfile->globals = g_hash_table_new(g_str_hash,g_str_equal);
1424 
1425  /* This is an optimization lookup hashtable, so we don't provide
1426  * *any* key or value destructors since we don't want them freed
1427  * when the hashtable is destroyed.
1428  */
1429  debugfile->types = g_hash_table_new(g_str_hash,g_str_equal);
1430 
1431  debugfile->shared_types = g_hash_table_new(g_str_hash,g_str_equal);
1432 
1433  debugfile->decllists = g_hash_table_new_full(g_str_hash,g_str_equal,
1434  free,
1435  (GDestroyNotify)array_list_free);
1436 
1437  debugfile->decldefnsused = g_hash_table_new(g_direct_hash,g_direct_equal);
1438 
1439  /* This is an optimization lookup hashtable, so we don't provide
1440  * *any* key or value destructors since we don't want them freed
1441  * when the hashtable is destroyed.
1442  */
1443  debugfile->addresses = g_hash_table_new(g_direct_hash,g_direct_equal);
1444 
1445  /*
1446  * We *do* have to strdup the keys... so free them when we destroy!
1447  * Also, our values are dwarf_cu_die_ref structs, so free those too!
1448  */
1449  debugfile->pubnames = g_hash_table_new_full(g_str_hash,g_str_equal,
1450  free,free);
1451 
1452  debugfile->ranges = clrange_create();
1453 
1454  /*
1455  * We *do* have to strdup the keys... so free them when we destroy!
1456  */
1457  debugfile->srclines = g_hash_table_new_full(g_str_hash,g_str_equal,
1458  free,clmatch_free);
1459  debugfile->srcaddrlines = g_hash_table_new_full(g_str_hash,g_str_equal,
1461 
1462  if (debugfile->ops && debugfile->ops->init)
1463  debugfile->ops->init(debugfile);
1464 
1465 }
1466 
1467 static int __realpath(char *filename,char **realfilename) {
1468  char *rpname;
1469 
1470  rpname = realpath(filename,NULL);
1471  if (!rpname)
1472  return -1;
1473  else {
1474  *realfilename = calloc(strlen(rpname)+1,sizeof(char));
1475  sprintf(*realfilename,"%s",rpname);
1476  free(rpname);
1477  return 0;
1478  }
1479 }
1480 
1481 static int _debugfile_filename_info(char *filename,char **realfilename,
1482  debugfile_type_flags_t *dtflags) {
1483  struct stat sbuf;
1484  char *realname = NULL;
1485 
1486  if (__realpath(filename,&realname) == 0
1487  && realname
1488  && strcmp(realname,filename) == 0) {
1489  free(realname);
1490  realname = filename;
1491  }
1492  else if (!realname) {
1493  verror("realpath(%s): %s\n",filename,strerror(errno));
1494  return -1;
1495  }
1496 
1497  if (stat(realname,&sbuf) < 0) {
1498  verror("stat(%s): %s\n",realname,strerror(errno));
1499  if (realname != filename)
1500  free(realname);
1501  return -1;
1502  }
1503 
1504  if (realfilename)
1505  *realfilename = realname;
1506 
1507  return 0;
1508 }
1509 
1510 char *debugfile_search_path(char *filename,char *root_prefix,char *debug_postfix,
1511  const char *DFPATH[],char *buf,int buflen) {
1512  char pbuf[PATH_MAX];
1513  int rc;
1514  int i;
1515 
1516  if (!debug_postfix)
1517  debug_postfix = ".debug";
1518  if (!DFPATH)
1519  DFPATH = DEBUGPATHS;
1520 
1521  for (i = 0; DFPATH[i]; ++i) {
1522  rc = 0;
1523 
1524  /* Prefix the prefix. */
1525  if (root_prefix)
1526  rc += snprintf(pbuf + rc,PATH_MAX - rc,"%s",root_prefix);
1527 
1528  /* Add in the PATH component. */
1529  rc += snprintf(pbuf + rc,PATH_MAX - rc,"/%s",DFPATH[i]);
1530 
1531  /* Add in the filename. */
1532  rc += snprintf(pbuf + rc,PATH_MAX - rc,"/%s",filename);
1533 
1534  /* Try the filename in this part of the path. */
1535  if (access(pbuf,R_OK) == 0)
1536  goto out;
1537 
1538  /* Try the postfix. */
1539  rc += snprintf(pbuf + rc,PATH_MAX - rc,"%s",debug_postfix);
1540  if (access(pbuf,R_OK) == 0)
1541  goto out;
1542  }
1543 
1544  if (root_prefix)
1546  "could not find '%s' (root_prefix='%s') in DFPATH!\n",
1547  filename,root_prefix);
1548  else
1550  "could not find '%s' (root_prefix='%s') in DFPATH!\n",
1551  filename,root_prefix);
1552 
1553  errno = ESRCH;
1554  return NULL;
1555 
1556  out:
1557  if (buf) {
1558  strncpy(buf,pbuf,buflen);
1559  /* Make sure it is NULL-term. */
1560  buf[buflen - 1] = '\0';
1561  }
1562  else {
1563  buf = malloc(rc + 1);
1564  strncpy(buf,pbuf,rc + 1);
1565  }
1566  return buf;
1567 }
1568 
1569 /*
1570  * There are several scenarios in which we want to load a debugfile.
1571  * 1) We have a filename, and we want to load the debuginfo that it
1572  * contains, or that it points to (via symlink, or internal
1573  * content).
1574  * 2a) We have a binfile_instance with a binfile associated with it.
1575  * In this case, we must first open a copy of the binfile
1576  * associated with the instance data, UNLESS the binfile is already
1577  * associated with this exact instance (if that is true, we just
1578  * return the binfile).
1579  * 2b) We have a binfile_instance with a filename, and no associated
1580  * binfile. We just open the filename against the instance.
1581  * 3) We have a binfile; just load debuginfo from that file, or from
1582  * the file that that binfile points to.
1583  */
1584 struct debugfile *debugfile_from_file(char *filename,char *root_prefix,
1585  struct array_list *debugfile_load_opts_list) {
1586  char *realname;
1587  struct debugfile_load_opts *opts = NULL;
1588  struct debugfile *debugfile = NULL;
1589  struct binfile *binfile = NULL;
1590  struct binfile *binfile_debuginfo = NULL;
1591  debugfile_type_t dtype;
1593  char pbuf[PATH_MAX];
1594 
1595  /*
1596  * If the caller has not prefixed the @root_prefix to the "real"
1597  * part of @filename, we don't let this through straightaway -- we
1598  * instead cons up a filename with the prefix prefixed! If we did
1599  * just let it through, we could get confusing results, like the
1600  * binfile being loaded from a non-root_prefix dir; but then the
1601  * debuginfo file being loaded from inside the root_prefix dir!
1602  */
1603  if (root_prefix) {
1604  if (strstr(filename,root_prefix) != filename) {
1606  "BUG: filename '%s' does not start with root_prefix '%s';"
1607  " prefixing it!\n",
1608  filename,root_prefix);
1609  snprintf(pbuf,sizeof(pbuf),"%s%s",root_prefix,filename);
1610  filename = strdup(pbuf);
1611  }
1612  }
1613 
1614  realname = filename;
1615  if (_debugfile_filename_info(filename,&realname,&dtflags)) {
1617  "failed to get filename info for (%s): %s\n",
1618  filename,strerror(errno));
1619  }
1620 
1621  if (debugfile_load_opts_list
1622  && debugfile_load_opts_checklist(debugfile_load_opts_list,
1623  realname,&opts) == RF_REJECT) {
1625  "opts prohibit loading of debugfile '%s'\n",realname);
1626  goto out;
1627  }
1628  else if ((debugfile = (struct debugfile *) \
1629  g_hash_table_lookup(debugfile_tab,realname))) {
1630  if ((root_prefix == NULL && debugfile->binfile->root_prefix == NULL)
1631  || (root_prefix != NULL
1632  && debugfile->binfile->root_prefix != NULL
1633  && strcmp(root_prefix,debugfile->binfile->root_prefix) == 0)) {
1634  vdebug(2,LA_DEBUG,LF_DFILE,"reusing debugfile %s (%s)\n",
1635  debugfile->filename,filename);
1636  //RHOLD(debugfile,debugfile);
1637  goto out;
1638  }
1639  else
1640  /*
1641  * Cannot used cached copy; we need to load from a special
1642  * @root_prefix dir.
1643  */
1644  debugfile = NULL;
1645  }
1646 
1647  /*
1648  * Load realname. Then ask it to load a binfile with its debuginfo;
1649  * might be the same binfile.
1650  *
1651  * Don't take any refs to binfiles; debugfile_create will do that!
1652  * Also make sure to use our __int() calls so that they don't take
1653  * refs to those binfiles needlessly.
1654  */
1655  binfile = binfile_open__int(realname,root_prefix,NULL);
1656  if (!binfile)
1657  goto errout;
1658 
1659  binfile_debuginfo = binfile_open_debuginfo__int(binfile,NULL,DEBUGPATHS);
1660  if (!binfile_debuginfo) {
1661  if (errno != ENODATA) {
1662  verror("could not open debuginfo for binfile %s: %s!\n",
1663  binfile->filename,strerror(errno));
1664  goto errout;
1665  }
1666  else {
1667  /* Do the best we can. */
1668  binfile_debuginfo = binfile;
1669  dtype = DEBUGFILE_TYPE_ELF;
1670  }
1671  }
1672  else
1673  dtype = DEBUGFILE_TYPE_DWARF;
1674 
1675  /* Check the cache! */
1676  if ((debugfile = (struct debugfile *) \
1677  g_hash_table_lookup(debugfile_tab,binfile_debuginfo->filename))) {
1678  if ((root_prefix == NULL && debugfile->binfile->root_prefix == NULL)
1679  || (root_prefix != NULL
1680  && debugfile->binfile->root_prefix != NULL
1681  && strcmp(root_prefix,debugfile->binfile->root_prefix) == 0)) {
1682  vdebug(2,LA_DEBUG,LF_DFILE,"reusing debugfile %s (%s)\n",
1683  debugfile->filename,filename);
1684  RHOLD(debugfile,debugfile);
1685  goto out;
1686  }
1687  else
1688  /*
1689  * Cannot used cached copy; we need to load from a special
1690  * @root_prefix dir.
1691  */
1692  debugfile = NULL;
1693  }
1694 
1695  /*
1696  * Need to create a new debugfile.
1697  */
1698  debugfile = debugfile_create(dtype,dtflags,
1699  binfile_debuginfo ? binfile_debuginfo : binfile,
1700  opts,
1701  (binfile_debuginfo && binfile_debuginfo != binfile) \
1702  ? binfile : NULL);
1703  if (!debugfile)
1704  goto errout;
1705 
1706  /*
1707  * Now, actually load its debuginfo, according to options.
1708  */
1709  if (debugfile->ops && debugfile->ops->load
1710  && (!opts || !(opts->flags & DEBUGFILE_LOAD_FLAG_NODWARF)))
1711  debugfile->ops->load(debugfile);
1712 
1713  dwdebug_save(debugfile);
1714  //RHOLD(debugfile,debugfile);
1715 
1716  goto out;
1717 
1718  errout:
1719  out:
1720  if (realname != filename)
1721  free(realname);
1722 
1723  return debugfile;
1724 }
1725 
1726 struct debugfile *debugfile_from_instance(struct binfile_instance *bfinst,
1727  struct array_list *debugfile_load_opts_list) {
1728  char *filename = bfinst->filename;
1729  char *realname = filename;
1730  struct debugfile_load_opts *opts = NULL;
1731  struct debugfile *debugfile = NULL;
1732  struct binfile *binfile = NULL;
1733  struct binfile *binfile_debuginfo = NULL;
1734  debugfile_type_t dtype;
1736 
1737  if (_debugfile_filename_info(filename,&realname,&dtflags)) {
1739  "failed to get filename info for (%s): %s\n",
1740  filename,strerror(errno));
1741  }
1742 
1743  if (debugfile_load_opts_list
1744  && debugfile_load_opts_checklist(debugfile_load_opts_list,
1745  realname,&opts) == RF_REJECT) {
1747  "opts prohibit loading of debugfile '%s'\n",realname);
1748  goto out;
1749  }
1750 
1751  /*
1752  * Load realname. Then ask it to load a binfile with its debuginfo;
1753  * might be the same binfile.
1754  */
1755  binfile = binfile_open__int(realname,bfinst->root_prefix,bfinst);
1756  if (!binfile)
1757  goto errout;
1758  binfile_debuginfo = binfile_open_debuginfo__int(binfile,bfinst,DEBUGPATHS);
1759  if (!binfile_debuginfo) {
1760  if (errno != ENODATA) {
1761  verror("could not open debuginfo for binfile %s: %s!\n",
1762  binfile->filename,strerror(errno));
1763  goto errout;
1764  }
1765  else {
1766  /* Do the best we can. */
1767  binfile_debuginfo = binfile;
1768  dtype = DEBUGFILE_TYPE_ELF;
1769  }
1770  }
1771  else
1772  dtype = DEBUGFILE_TYPE_DWARF;
1773 
1774  /*
1775  * Need to create a new debugfile.
1776  */
1777  debugfile = debugfile_create(dtype,dtflags,
1778  binfile_debuginfo ? binfile_debuginfo : binfile,
1779  opts,
1780  (binfile_debuginfo && binfile_debuginfo != binfile) \
1781  ? binfile : NULL);
1782  if (!debugfile)
1783  goto errout;
1784 
1785  /*
1786  * Now, actually load its debuginfo, according to options.
1787  */
1788  if (debugfile->ops && debugfile->ops->load
1789  && (!opts || !(opts->flags & DEBUGFILE_LOAD_FLAG_NODWARF)))
1790  debugfile->ops->load(debugfile);
1791 
1792  /* Don't cache debugfiles from binfile instances! */
1793  //RHOLD(debugfile,debugfile);
1794 
1795  goto out;
1796 
1797  errout:
1798  out:
1799  if (realname != filename)
1800  free(realname);
1801 
1802  return debugfile;
1803 }
1804 
1805 struct debugfile *debugfile_from_binfile(struct binfile *binfile,
1806  struct array_list *debugfile_load_opts_list) {
1807 
1808 }
1809 
1811  struct array_list *retval;
1812  GHashTableIter iter;
1813  struct debugfile *df;
1814 
1815  if (!debugfile_tab || g_hash_table_size(debugfile_tab) == 0)
1816  return NULL;
1817 
1818  retval = array_list_create(g_hash_table_size(debugfile_tab));
1819  g_hash_table_iter_init(&iter,debugfile_tab);
1820  while (g_hash_table_iter_next(&iter,NULL,(gpointer)&df))
1821  array_list_append(retval,df);
1822 
1823  return retval;
1824 }
1825 
1826 int debugfile_update_root(struct debugfile *debugfile,struct symbol *symbol) {
1827  struct symbol *tsymbol;
1828  struct array_list *symbol_list;
1829 
1830  if (!SYMBOL_IS_ROOT(symbol)) {
1831  vwarn("symbol(%s:0x%"PRIxSMOFFSET") is not a root symbol!\n",
1832  symbol_get_name(symbol),symbol->ref);
1833  return -1;
1834  }
1835  else if (!symbol->name) {
1836  vwarn("symbol(%s:0x%"PRIxSMOFFSET") must have a name!\n",
1837  symbol_get_name(symbol),symbol->ref);
1838  return -1;
1839  }
1840 
1841  symbol_list = (struct array_list *) \
1842  g_hash_table_lookup(debugfile->srcfiles_multiuse,symbol->name);
1843  if (symbol_list) {
1844  if (array_list_find(symbol_list,symbol) >= 0) {
1846  "symbol at 0x%"PRIxSMOFFSET" already on the dup list!",
1847  symbol->ref);
1848  }
1849  else {
1850  array_list_append(symbol_list,symbol);
1852  "added symbol 0x%"PRIxSMOFFSET
1853  " to existing duplist for srcfile name %s\n",
1854  symbol->ref,symbol->name);
1855  }
1856  }
1857  else if ((tsymbol = g_hash_table_lookup(debugfile->srcfiles,symbol->name))
1858  && tsymbol != symbol) {
1859  /*
1860  * Since this is a symbol with a duplicate srcfile name, we
1861  * have to move it, and the new one, to srcfiles_multiuse.
1862  *
1863  * Have to _steal() it so the hashtable's per-value
1864  * destructor is not called; we don't want the symbol freed,
1865  * just moved.
1866  */
1867  g_hash_table_steal(debugfile->srcfiles,tsymbol->name);
1868  symbol_list = array_list_create(0);
1869  array_list_append(symbol_list,tsymbol);
1870  g_hash_table_insert(debugfile->srcfiles_multiuse,
1871  strdup(tsymbol->name),symbol_list);
1872  array_list_append(symbol_list,symbol);
1873 
1875  "moved symbols 0x%"PRIxSMOFFSET" and 0x%"PRIxSMOFFSET
1876  " to new duplist for srcfile name %s\n",
1877  tsymbol->ref,symbol->ref,tsymbol->name);
1878  }
1879  else if (tsymbol == symbol)
1880  ;
1881  else {
1883  "adding top-level symbol %s:%s\n",
1884  debugfile->filename,symbol->name);
1885  g_hash_table_insert(debugfile->srcfiles,symbol->name,symbol);
1886  }
1887 
1888  return 0;
1889 }
1890 
1891 int debugfile_insert_root(struct debugfile *debugfile,struct symbol *symbol) {
1892  struct symbol *tsymbol;
1893  int rc;
1894 
1895  if ((tsymbol = (struct symbol *) \
1896  g_hash_table_lookup(debugfile->cuoffsets,
1897  (gpointer)(uintptr_t)symbol->ref))
1898  && tsymbol != symbol) {
1899  verror("symbol(%s:0x%"PRIxSMOFFSET") is duplicate;"
1900  " symbol(%s:0x%"PRIxSMOFFSET") already in debugfile %s!\n",
1901  symbol->name,symbol->ref,tsymbol->name,tsymbol->ref,
1902  debugfile->filename);
1903  return 2;
1904  }
1905  else if (tsymbol == symbol)
1906  ;
1907  else {
1908  SYMBOL_WX_ROOT(symbol,sr,-5);
1909  sr->debugfile = debugfile;
1910 
1911  g_hash_table_insert(debugfile->cuoffsets,
1912  (gpointer)(uintptr_t)symbol->ref,symbol);
1914  "adding top-level symbol %s:0x%"PRIxSMOFFSET"\n",
1915  debugfile->filename,symbol->ref);
1916 
1917  /*
1918  * We hold the symbol here, because this *always* gets done at
1919  * least once. We release on it when we debugfile_free, and
1920  * when we free the
1921  */
1922  RHOLD(symbol,debugfile);
1923  }
1924 
1925  if (symbol->name)
1926  rc = debugfile_update_root(debugfile,symbol);
1927  else
1928  rc = 0;
1929 
1930  return rc;
1931 }
1932 
1933 int debugfile_remove_root(struct debugfile *debugfile,struct symbol *symbol) {
1934  struct symbol *tsymbol;
1935  REFCNT trefcnt;
1936 
1937  if ((tsymbol = (struct symbol *) \
1938  g_hash_table_lookup(debugfile->cuoffsets,
1939  (gpointer)(uintptr_t)symbol->ref))
1940  && tsymbol != symbol) {
1941  verror("symbol(%s:0x%"PRIxSMOFFSET") is not the one it should be;"
1942  " symbol(%s:0x%"PRIxSMOFFSET") already in debugfile %s!\n",
1943  symbol->name,symbol->ref,tsymbol->name,tsymbol->ref,
1944  debugfile->filename);
1945  return 1;
1946  }
1947  else if (tsymbol == symbol)
1948  g_hash_table_remove(debugfile->cuoffsets,
1949  (gpointer)(uintptr_t)symbol->ref);
1950 
1951  if ((tsymbol = g_hash_table_lookup(debugfile->srcfiles,symbol->name))
1952  && tsymbol != symbol) {
1953  verror("symbol(%s:0x%"PRIxSMOFFSET") is not the one it should be;"
1954  " symbol(%s:0x%"PRIxSMOFFSET") already in debugfile %s!\n",
1955  symbol->name,symbol->ref,tsymbol->name,tsymbol->ref,
1956  debugfile->filename);
1957  return 2;
1958  }
1959  else if (tsymbol == symbol)
1960  g_hash_table_remove(debugfile->srcfiles,symbol->name);
1961 
1962  /*
1963  * We put the symbol here; no point in RPUTNF because nobody would
1964  * need to keep the symbol. This is mostly a function for debuginfo
1965  * backends to call during errors.
1966  */
1967  RPUT(symbol,symbol,debugfile,trefcnt);
1968 
1969  return 0;
1970 }
1971 
1972 struct symbol *debugfile_lookup_root(struct debugfile *debugfile,
1973  SMOFFSET offset) {
1974  return (struct symbol *)g_hash_table_lookup(debugfile->cuoffsets,
1975  (gpointer)(uintptr_t)offset);
1976 }
1977 
1978 struct symbol *debugfile_lookup_root_name(struct debugfile *debugfile,
1979  char *name) {
1980  struct symbol *symbol;
1981  struct array_list *alist;
1982 
1983  symbol = (struct symbol *)g_hash_table_lookup(debugfile->srcfiles,name);
1984  if (symbol)
1985  return symbol;
1986  alist = (struct array_list *) \
1987  g_hash_table_lookup(debugfile->srcfiles_multiuse,name);
1988  if (alist)
1989  return (struct symbol *)array_list_item(alist,0);
1990 
1991  return NULL;
1992 }
1993 
1994 int debugfile_declaration_copy_definition(struct debugfile *debugfile,
1995  struct symbol *declaration,
1996  struct symbol *definition) {
1997  REFCNT trefcnt;
1998 
1999  assert(declaration->isdeclaration);
2000  assert(!definition->isdeclaration);
2001  if (declaration->type != definition->type) {
2002  verror("declaration %s type %s (%p) != definition %s type %s (%p)!\n",
2003  symbol_get_name(declaration),SYMBOL_TYPE(declaration->type),
2004  declaration,
2005  symbol_get_name(definition),SYMBOL_TYPE(definition->type),
2006  definition);
2007  return -1;
2008  }
2009  //assert(declaration->type == definition->type);
2010 
2011  //return 0;
2012 
2013  if (definition->datatype_ref
2014  && !symbol_get_datatype(definition) && !SYMBOL_IS_OWN_DATATYPE(definition))
2015  return -1;
2016  else {
2017  /*
2018  * Free up its guts.
2019  */
2020  symbol_free_extra(declaration);
2021 
2022  /*
2023  * Its definition has already been loaded; take a ref to it and
2024  * copy in its guts.
2025  *
2026  * Well, it turns out that we cannot "take a ref" to it in such
2027  * a way we can just free it, because there is no space in the
2028  * symbol struct to waste on a pointer to the definition -- so
2029  * we don't know what to release. Furthermore, if we stored the
2030  * fact that we took the ref in the debugfile struct, we cannot
2031  * guarantee during symbol_free that we can trace back to the
2032  * root symbol, and thus the debugfile (the parent hierarchy may
2033  * have been broken already) -- so we wouldn't be able to access
2034  * the held definition. So instead, place it in the
2035  * debugfile->decldefinitions table if it's not there, and hold
2036  * a ref on it there until the debugfile is destroyed. One ref
2037  * for any definition; could be used by multiple declarations;
2038  * but they don't need to know it. Could be wasteful, but it
2039  * saves us from corruption, which could occur if we freed the
2040  * definition symbol who owns the copied data before we freed
2041  * the declaration symbol.
2042  */
2043  if (g_hash_table_lookup_extended(debugfile->decldefnsused,definition,
2044  NULL,NULL) == FALSE) {
2045  g_hash_table_insert(debugfile->decldefnsused,
2046  definition,definition);
2047  RHOLD(definition,debugfile->decldefnsused);
2048  }
2049  declaration->decldefined = 1;
2050 
2051  declaration->has_addr = definition->has_addr;
2052  declaration->addr = definition->addr;
2053  declaration->size_is_bits = definition->size_is_bits;
2054  declaration->size_is_bytes = definition->size_is_bytes;
2055  declaration->guessed_size = definition->guessed_size;
2056  memcpy(&declaration->size,&definition->size,sizeof(definition->size));
2057 
2058  if (declaration->datatype && declaration->usesshareddatatype) {
2059  RPUT(declaration->datatype,symbol,declaration,trefcnt);
2060  declaration->usesshareddatatype = 0;
2061  }
2062 
2063  if (definition->datatype) {
2064  declaration->datatype = definition->datatype;
2065  declaration->usesshareddatatype = definition->usesshareddatatype;
2066  RHOLD(definition->datatype,declaration);
2067  declaration->decltypedefined = 1;
2068  }
2069 
2070  declaration->extra.exists = definition->extra.exists;
2071 
2073  "used definition at 0x%"PRIxSMOFFSET" for declaration"
2074  " %s at 0x%"PRIxSMOFFSET"\n",
2075  definition->ref,symbol_get_name(declaration),declaration->ref);
2076 
2077  return 0;
2078  }
2079 }
2080 
2081 void debugfile_save_declaration(struct debugfile *debugfile,
2082  struct symbol *symbol) {
2083  struct array_list *decllist;
2084 
2085  assert(symbol->isdeclaration);
2086 
2087  if (!symbol->name)
2088  return;
2089 
2090  decllist = (struct array_list *) \
2091  g_hash_table_lookup(debugfile->decllists,symbol->name);
2092  if (!decllist) {
2093  decllist = array_list_create(1);
2094  g_hash_table_insert(debugfile->decllists,
2095  strdup(symbol->name),decllist);
2096  }
2097  array_list_append(decllist,symbol);
2098 }
2099 
2100 void debugfile_handle_declaration(struct debugfile *debugfile,
2101  struct symbol *symbol) {
2102  struct symbol *definition;
2103  struct array_list *decllist;
2104 
2105  assert(symbol->isdeclaration);
2106 
2107  if (!symbol->name)
2108  return;
2109 
2110  if (!SYMBOL_IS_TYPE(symbol)) {
2111  definition = (struct symbol *) \
2112  g_hash_table_lookup(debugfile->globals,symbol_get_name(symbol));
2113  if (definition)
2115  "globals lookup found definition '%s' type %s (%p)"
2116  " for declaration '%s' type %s (%p; trying to copy\n",
2117  symbol_get_name(definition),SYMBOL_TYPE(definition->type),
2118  definition,
2119  symbol_get_name(symbol),SYMBOL_TYPE(symbol->type),symbol);
2120  }
2121  else {
2122  definition = debugfile_find_type(debugfile,symbol_get_name(symbol));
2123  if (definition)
2125  "find_type found definition '%s' type %s (%p)"
2126  " for declaration '%s' type %s (%p; trying to copy\n",
2127  symbol_get_name(definition),SYMBOL_TYPE(definition->type),
2128  definition,
2129  symbol_get_name(symbol),SYMBOL_TYPE(symbol->type),symbol);
2130  }
2131 
2132  if (!definition
2133  || debugfile_declaration_copy_definition(debugfile,symbol,definition)) {
2134  /*
2135  * Maybe its definition hasn't been loaded yet, or the
2136  * definition's type hasn't been resolved yet; save it off and
2137  * handle it later.
2138  */
2139  decllist = (struct array_list *) \
2140  g_hash_table_lookup(debugfile->decllists,symbol->name);
2141  if (!decllist) {
2142  decllist = array_list_create(1);
2143  g_hash_table_insert(debugfile->decllists,
2144  strdup(symbol->name),decllist);
2145  }
2146  array_list_append(decllist,symbol);
2147  }
2148 }
2149 
2150 static void __debugfile_resolve_decllist(struct debugfile *debugfile,
2151  char *name,struct array_list *decllist,
2152  GHashTableIter *current_iter) {
2153  struct symbol *type_definition;
2154  struct symbol *instance_definition;
2155  struct symbol *definition;
2156  struct symbol *declaration;
2157  int total;
2158  int copied;
2159  int mapped;
2160  int i;
2161  int rc;
2162  struct scope *declscope;
2163 
2164  type_definition = debugfile_find_type(debugfile,name);
2165  instance_definition = (struct symbol *) \
2166  g_hash_table_lookup(debugfile->globals,name);
2167 
2168  if (!type_definition && !instance_definition) {
2170  "could not find any definitions for declarations named '%s'\n",
2171  name);
2172  return;
2173  }
2174 
2175  total = array_list_len(decllist);
2176  copied = mapped = 0;
2177  array_list_foreach(decllist,i,declaration) {
2178  if (SYMBOL_IS_TYPE(declaration))
2179  definition = type_definition;
2180  else
2181  definition = instance_definition;
2182 
2183  if (!definition) {
2185  "could not find definition for declaration '%s'\n",
2186  name);
2187  continue;
2188  }
2189 
2190  if (debugfile->opts->flags & DEBUGFILE_LOAD_FLAG_KEEPDECLS) {
2191  rc = debugfile_declaration_copy_definition(debugfile,declaration,
2192  definition);
2193  if (rc) {
2195  "could not copy definition for declaration '%s'\n",
2196  name);
2197  continue;
2198  }
2199 
2200  ++copied;
2201  /* Not optimized, but no big deal. */
2202  array_list_foreach_delete(decllist,i);
2203  }
2204  else if (debugfile->ops && debugfile->ops->symbol_replace) {
2205  /*
2206  * Tell the backend that a symbol substitution needs to
2207  * happen, so that it can propagate that resolution to any
2208  * other symbols that have a pointer reference to the one
2209  * being replaced.
2210  */
2211  debugfile->ops->symbol_replace(debugfile,declaration,definition);
2212 
2213  ++mapped;
2214  /* Not optimized, but no big deal. */
2215  array_list_foreach_delete(decllist,i);
2216  }
2217  else {
2218  declscope = symbol_containing_scope(declaration);
2219  scope_remove_symbol(declscope,declaration);
2220  scope_hold_symbol(declscope,definition);
2221 
2222  ++mapped;
2223  /* Not optimized, but no big deal. */
2224  array_list_foreach_delete(decllist,i);
2225  }
2226  }
2227 
2229  "resolved %d (copied %d, mapped %d) of %d declarations named '%s'\n",
2230  copied+mapped,copied,mapped,total,name);
2231 
2232  if (array_list_len(decllist) == 0) {
2233  /* NB: this frees the decllist and the hashed name. */
2234  if (current_iter)
2235  g_hash_table_iter_remove(current_iter);
2236  else
2237  g_hash_table_remove(debugfile->decllists,name);
2238  }
2239 }
2240 
2241 void debugfile_resolve_one_declaration(struct debugfile *debugfile,char *name) {
2242  struct array_list *decllist = NULL;
2243 
2244  decllist = (struct array_list *)g_hash_table_lookup(debugfile->decllists,
2245  (gpointer)name);
2246  if (decllist)
2247  __debugfile_resolve_decllist(debugfile,name,decllist,NULL);
2248 }
2249 
2250 void debugfile_resolve_declarations(struct debugfile *debugfile) {
2251  GHashTableIter iter;
2252  char *name = NULL;
2253  struct array_list *decllist = NULL;
2254 
2255  g_hash_table_iter_init(&iter,debugfile->decllists);
2256  while (g_hash_table_iter_next(&iter,
2257  (gpointer *)&name,(gpointer *)&decllist)) {
2258  __debugfile_resolve_decllist(debugfile,name,decllist,&iter);
2259  }
2260 }
2261 
2262 int debugfile_add_global(struct debugfile *debugfile,struct symbol *symbol) {
2263  assert(SYMBOL_IS_INSTANCE(symbol));
2264 
2265  if (unlikely(g_hash_table_lookup(debugfile->globals,symbol->name)))
2266  return 1;
2267  g_hash_table_insert(debugfile->globals,symbol->name,symbol);
2268 
2269  vdebug(8,LA_DEBUG,LF_SYMBOL,"added global '%s' type %s (%p)\n",
2270  symbol_get_name(symbol),SYMBOL_TYPE(symbol->type),symbol);
2271 
2272 //#if 0
2273  if (!symbol->isdeclaration) {
2274  /*
2275  * Also check if there were declarations pending on this global;
2276  * link those symbols up if so!
2277  */
2278  struct array_list *decllist = (struct array_list *) \
2279  g_hash_table_lookup(debugfile->decllists,symbol->name);
2280  if (decllist)
2281  __debugfile_resolve_decllist(debugfile,symbol->name,decllist,NULL);
2282  }
2283 //#endif
2284 
2285  return 0;
2286 }
2287 
2288 struct symbol *debugfile_find_type(struct debugfile *debugfile,
2289  char *typename) {
2290  struct symbol *s;
2291 
2292  s = (struct symbol *)g_hash_table_lookup(debugfile->shared_types,typename);
2293 
2294  if (!s)
2295  s = (struct symbol *)g_hash_table_lookup(debugfile->types,typename);
2296 
2297  return s;
2298 }
2299 
2300 int debugfile_add_type(struct debugfile *debugfile,struct symbol *symbol) {
2301  char *name;
2302 
2303  assert(SYMBOL_IS_TYPE(symbol));
2304 
2305  name = symbol_get_name(symbol);
2306 
2307  /*
2308  * If it exists, fail (see debugfile_replace_type).
2309  */
2310  if (unlikely(g_hash_table_lookup(debugfile->types,name)))
2311  return 1;
2312  g_hash_table_insert(debugfile->types,name,symbol);
2313  RHOLD(symbol,debugfile->types);
2314 
2315  vdebug(8,LA_DEBUG,LF_SYMBOL,"added global type '%s' type %s (%p)\n",
2316  symbol_get_name(symbol),SYMBOL_TYPE(symbol->type),symbol);
2317 
2318 //#if 0
2319  if (!symbol->isdeclaration) {
2320  /*
2321  * Also check if there were declarations pending on this global;
2322  * link those symbols up if so!
2323  */
2324  struct array_list *decllist = (struct array_list *) \
2325  g_hash_table_lookup(debugfile->decllists,symbol->name);
2326  if (decllist)
2327  __debugfile_resolve_decllist(debugfile,symbol->name,decllist,NULL);
2328  }
2329 //#endif
2330 
2331  return 0;
2332 }
2333 
2334 int debugfile_replace_type(struct debugfile *debugfile,struct symbol *symbol) {
2335  char *name;
2336  struct symbol *existing;
2337  REFCNT trefcnt;
2338 
2339  assert(SYMBOL_IS_TYPE(symbol));
2340 
2341  name = symbol_get_name(symbol);
2342 
2343  /*
2344  * If it exists, unhold the previous type and use this one. We use
2345  * this to make sure shared types replace other global types.
2346  */
2347  existing = (struct symbol *)g_hash_table_lookup(debugfile->types,name);
2348  if (existing == symbol)
2349  return 0;
2350  if (existing) {
2351  RPUT(existing,symbol,debugfile->types,trefcnt);
2352  }
2353  g_hash_table_insert(debugfile->types,name,symbol);
2354  RHOLD(symbol,debugfile->types);
2355 
2356  vdebug(8,LA_DEBUG,LF_SYMBOL,"%s global type '%s' type %s (%p)\n",
2357  existing ? "replaced" : "added",symbol_get_name(symbol),
2358  SYMBOL_TYPE(symbol->type),symbol);
2359 
2360 //#if 0
2361  if (!symbol->isdeclaration) {
2362  /*
2363  * Also check if there were declarations pending on this global;
2364  * link those symbols up if so!
2365  */
2366  struct array_list *decllist = (struct array_list *) \
2367  g_hash_table_lookup(debugfile->decllists,symbol->name);
2368  if (decllist)
2369  __debugfile_resolve_decllist(debugfile,symbol->name,decllist,NULL);
2370  }
2371 //#endif
2372 
2373  return 0;
2374 }
2375 
2376 /*
2377 REFCNT debugfile_release(struct debugfile *debugfile) {
2378  REFCNT refcnt;
2379  RPUT(debugfile,debugfile,debugfile,refcnt);
2380  return refcnt;
2381 }
2382 */
2383 
2384 REFCNT debugfile_free(struct debugfile *debugfile,int force) {
2385  int retval = debugfile->refcnt;
2386  REFCNT trefcnt;
2387  GHashTableIter iter;
2388  struct symbol *symbol;
2389  struct array_list *symbol_list;
2390  int i;
2391  gpointer kp, vp;
2392 
2393  vdebug(5,LA_DEBUG,LF_DFILE,"freeing debugfile(%s)\n",debugfile->filename);
2394 #ifdef DWDEBUG_MEMDEBUG
2395  vdebug(5,LA_DEBUG,LF_DFILE,"dumping current VM usage:\n");
2396  if (vdebug_is_on(5,LA_DEBUG,LF_DFILE)) {
2397  char cmd[128];
2398  unsigned long *x;
2399 
2400  /*
2401  * Force sbrk() so that stats are good.
2402  */
2404  x = malloc(sizeof(*x));
2405  free(x);
2406  /* man mallopt says 128*1024 is the default, ok. */
2407  mallopt(M_TRIM_THRESHOLD,128*1024);
2408 
2409  fflush(stdout);
2410  fflush(stderr);
2411  vdebug(5,LA_DEBUG,LF_DFILE,"malloc:\n");
2412  malloc_stats();
2413  vdebug(5,LA_DEBUG,LF_DFILE,"glib:\n");
2414  g_mem_profile();
2415  vdebug(5,LA_DEBUG,LF_DFILE,"procfs:\n");
2416  snprintf(cmd,sizeof(cmd),"cat /proc/%d/status | grep Vm",getpid());
2417  if (system(cmd)) {
2418  /* gcc */;
2419  }
2420  fflush(stdout);
2421  fflush(stderr);
2422  }
2423  vdebug(5,LA_DEBUG,LF_DFILE,"finished dumping current VM usage\n");
2424 #endif
2425 
2426  if (debugfile->refcnt) {
2427  if (!force) {
2428  verror("cannot free (%d refs) debugfile(%s)\n",
2429  debugfile->refcnt,debugfile->filename);
2430  return debugfile->refcnt;
2431  }
2432  else {
2433  vwarn("forced free (%d refs) debugfile(%s)\n",
2434  debugfile->refcnt,debugfile->filename);
2435  }
2436  }
2437 
2438  if (debugfile->ops && debugfile->ops->fini)
2439  debugfile->ops->fini(debugfile);
2440 
2441  /*
2442  * Only remove it if the value matches us. This is necessary
2443  * because if we loaded debugfile against a binfile_instance, and
2444  * there were relocations, this debugfile will not be in the
2445  * hashtable -- but another debugfile (that was NOT relocated!)
2446  * could still be in the hashtable. :)
2447  */
2448  if (g_hash_table_lookup(debugfile_tab,debugfile->filename) == debugfile)
2449  g_hash_table_remove(debugfile_tab,debugfile->filename);
2450  if (g_hash_table_lookup(debugfile_id_tab,(gpointer)(uintptr_t)debugfile->id)
2451  == debugfile)
2452  g_hash_table_remove(debugfile_id_tab,(gpointer)(uintptr_t)debugfile->id);
2453 
2454  g_hash_table_destroy(debugfile->pubnames);
2455  g_hash_table_destroy(debugfile->addresses);
2456  g_hash_table_destroy(debugfile->globals);
2457  g_hash_table_iter_init(&iter,debugfile->types);
2458  while (g_hash_table_iter_next(&iter,NULL,(gpointer *)&symbol)) {
2459  RPUT(symbol,symbol,debugfile->types,trefcnt);
2460  }
2461  g_hash_table_destroy(debugfile->types);
2462  g_hash_table_destroy(debugfile->cuoffsets);
2463 
2464  /*
2465  * We remove all the CU symbols in these hashtables manually so we
2466  * can release our refs to them!
2467  */
2468  g_hash_table_iter_init(&iter,debugfile->srcfiles);
2469  while (g_hash_table_iter_next(&iter,NULL,(gpointer *)&symbol)) {
2471  "releasing symbol(%s:0x%"PRIxSMOFFSET")\n",
2472  symbol->name,symbol->ref);
2473  RPUT(symbol,symbol,debugfile,trefcnt);
2474  g_hash_table_iter_remove(&iter);
2475  }
2476  g_hash_table_destroy(debugfile->srcfiles);
2477  g_hash_table_iter_init(&iter,debugfile->srcfiles_multiuse);
2478  while (g_hash_table_iter_next(&iter,NULL,(gpointer *)&symbol_list)) {
2479  array_list_foreach(symbol_list,i,symbol) {
2481  "releasing symbol(%s:0x%"PRIxSMOFFSET")\n",
2482  symbol->name,symbol->ref);
2483  RPUT(symbol,symbol,debugfile,trefcnt);
2484  }
2485  array_list_free(symbol_list);
2486  g_hash_table_iter_remove(&iter);
2487  }
2488  g_hash_table_destroy(debugfile->srcfiles_multiuse);
2489 
2490  /*
2491  * RPUT all the shared type symbols.
2492  */
2493  g_hash_table_iter_init(&iter,debugfile->shared_types);
2494  while (g_hash_table_iter_next(&iter,&kp,&vp)) {
2495  symbol = (struct symbol *)vp;
2496  RPUT(symbol,symbol,debugfile,trefcnt);
2497  }
2498  g_hash_table_destroy(debugfile->shared_types);
2499 
2500  g_hash_table_destroy(debugfile->decllists);
2501 
2502  /*
2503  * RPUT all the definitions whose parts were copied to fill in
2504  * declarations.
2505  */
2506  g_hash_table_iter_init(&iter,debugfile->decldefnsused);
2507  while (g_hash_table_iter_next(&iter,&kp,NULL)) {
2508  symbol = (struct symbol *)kp;
2510  "releasing definition symbol(%s:0x%"PRIxSMOFFSET")"
2511  " held by declaration symbols\n",
2512  symbol_get_name(symbol),symbol->ref);
2513  RPUT(symbol,symbol,debugfile->decldefnsused,trefcnt);
2514  g_hash_table_iter_remove(&iter);
2515  }
2516  g_hash_table_destroy(debugfile->decldefnsused);
2517 
2518  clrange_free(debugfile->ranges);
2519 
2520  g_hash_table_destroy(debugfile->srclines);
2521  g_hash_table_destroy(debugfile->srcaddrlines);
2522 
2523  if (debugfile->dbg_strtab)
2524  free(debugfile->dbg_strtab);
2525  if (debugfile->loctab)
2526  free(debugfile->loctab);
2527  if (debugfile->rangetab)
2528  free(debugfile->rangetab);
2529  if (debugfile->linetab)
2530  free(debugfile->linetab);
2531  if (debugfile->frametab)
2532  free(debugfile->frametab);
2533 
2534  if (debugfile->binfile)
2535  RPUT(debugfile->binfile,binfile,debugfile,trefcnt);
2536  if (debugfile->binfile_pointing)
2537  RPUT(debugfile->binfile_pointing,binfile,debugfile,trefcnt);
2538 
2539  free(debugfile->filename);
2540  free(debugfile);
2541 
2542  vdebug(5,LA_DEBUG,LF_DFILE,"freed debugfile\n");
2543 
2544  return retval;
2545 }
2546 
2551  char *name,int name_copy,SMOFFSET offset,
2552  load_type_t loadtype,struct scope *scope) {
2553  struct symbol *symbol;
2554 
2555  symbol = (struct symbol *)malloc(sizeof(*symbol));
2556  if (!symbol)
2557  return NULL;
2558  memset(symbol,0,sizeof(*symbol));
2559 
2560  symbol->type = symtype;
2561  symbol->source = source;
2562  symbol->loadtag = loadtype;
2563  symbol->ref = offset;
2564 
2565  /* Comparison functions in dwarf_debuginfo need this set nonzero! */
2566  symbol->addr = ADDRMAX;
2567  symbol->has_addr = 0;
2568 
2569  if (name)
2570  symbol_set_name(symbol,name,name_copy);
2571 
2572  symbol->refcnt = 0;
2573 
2574  /* This must be set before the call to symbol_link_owned_scope()! */
2575  symbol->scope = scope;
2576 
2577  vdebug(5,LA_DEBUG,LF_SYMBOL,"offset %"PRIxSMOFFSET" %p\n",offset,symbol);
2578 
2579  return symbol;
2580 }
2581 
2582 /*
2583  * Getters/Setters. Internal versions don't hold; the external wrappers do.
2584  */
2585 
2586 /* @name */
2588  struct symbol *origin;
2589 
2590  if (!symbol->name && symbol->isinlineinstance) {
2591  origin = symbol_get_inline_origin(symbol);
2592  if (!origin)
2593  return NULL;
2594  else
2595  return symbol_get_name(origin);
2596  }
2597 
2598  return symbol->name;
2599 }
2601  struct symbol *origin;
2602 
2603  if (!symbol->isinlineinstance)
2604  return symbol_get_name(symbol);
2605 
2606  origin = symbol_get_inline_origin(symbol);
2607  if (!origin)
2608  return symbol_get_name(symbol);
2609  else
2610  return symbol_get_name(origin);
2611 }
2613  return symbol->name + symbol->orig_name_offset;
2614 }
2615 void symbol_set_name(struct symbol *symbol,char *name,int copy) {
2616  if (!copy && symbol->name && strcmp(symbol->name,name) == 0)
2617  return;
2618 
2619  if (copy) {
2620  symbol->name = strdup(name);
2621  symbol->name_nofree = 0;
2622  }
2623  else {
2624  symbol->name = name;
2625  symbol->name_nofree = 1;
2626  }
2627 }
2629  char *symbol_name = symbol_get_name_orig(symbol);
2630  char *insert_name;
2631  int foffset = 0;
2632 
2633  if (SYMBOL_IST_ENUM(symbol)) {
2634  foffset = 5;
2635  insert_name = malloc(strlen(symbol_name)+6);
2636  sprintf(insert_name,"enum %s",symbol_name);
2637  }
2638  else if (SYMBOL_IST_STRUCT(symbol)) {
2639  foffset = 7;
2640  insert_name = malloc(strlen(symbol_name)+8);
2641  sprintf(insert_name,"struct %s",symbol_name);
2642  }
2643  else if (SYMBOL_IST_UNION(symbol)) {
2644  foffset = 6;
2645  insert_name = malloc(strlen(symbol_name)+7);
2646  sprintf(insert_name,"union %s",symbol_name);
2647  }
2648  else if (SYMBOL_IS_TYPE(symbol)) {
2649  verror("cannot build extname for datatype %s!\n",
2650  DATATYPE(symbol->datatype_code));
2651  return;
2652  }
2653  else {
2654  verror("cannot build extname for type %s!\n",
2655  SYMBOL_TYPE(symbol->type));
2656  return;
2657  }
2658 
2659  if (symbol_name && !symbol->name_nofree)
2660  free(symbol_name);
2661 
2662  symbol->name = insert_name;
2663  symbol->name_nofree = 0;
2664 
2665  symbol->orig_name_offset = foffset;
2666 }
2668  return (symbol->orig_name_offset > 0) ? 1 : 0;
2669 }
2670 /* @scope */
2672  return symbol->scope;
2673 }
2675  if (!SYMBOL_HAS_EXTRA(symbol))
2676  return NULL;
2677 
2678  if (SYMBOL_IST_CONTAINER(symbol))
2679  return symbol->extra.container->scope;
2680  else if (SYMBOL_IS_ROOT(symbol))
2681  return symbol->extra.root->scope;
2682  else if (SYMBOL_IS_FUNC(symbol))
2683  return symbol->extra.function->scope;
2684  else if (SYMBOL_IS_BLOCK(symbol))
2685  return symbol->extra.block->scope;
2686  else
2687  return NULL;
2688 }
2690  struct scope **scope = NULL;
2691 
2692  if (!symbol->scope && !SYMBOL_IS_ROOT(symbol)) {
2693  verror("symbol(%s:0x%"PRIxSMOFFSET") is not root but has no"
2694  " containing scope!\n",
2695  symbol_get_name(symbol),symbol->ref);
2696  }
2697 
2698  if (SYMBOL_IST_CONTAINER(symbol)) {
2699  SYMBOL_WX_CONTAINER(symbol,sc,NULL);
2700  scope = &sc->scope;
2701  }
2702  else if (SYMBOL_IS_ROOT(symbol)) {
2703  SYMBOL_WX_ROOT(symbol,sr,NULL);
2704  scope = &sr->scope;
2705  }
2706  else if (SYMBOL_IS_FUNC(symbol)) {
2707  SYMBOL_WX_FUNC(symbol,sf,NULL);
2708  scope = &sf->scope;
2709  }
2710  else if (SYMBOL_IS_BLOCK(symbol)) {
2711  SYMBOL_WX_BLOCK(symbol,sb,NULL);
2712  scope = &sb->scope;
2713  }
2714  else
2715  return NULL;
2716 
2717  if (*scope)
2718  /* We already created one. */
2719  return *scope;
2720  else {
2721  *scope = scope_create(symbol,symbol->ref);
2722  RHOLD(*scope,symbol);
2723  return *scope;
2724  }
2725 }
2727  struct scope *new_parent) {
2728  struct scope *scope = NULL;
2729 
2730  scope = symbol_write_owned_scope(symbol);
2731 
2732  /*
2733  * Make sure it is linked to its parent! This accomplishes a
2734  * ton of magic. The scope is only linked in when it is
2735  * actually built. It might not be built until it is used; that
2736  * is the most efficient way!
2737  *
2738  * So -- *anything* that wants to write to a symbol's owned
2739  * scope *must* get the scope this way!!!
2740  */
2741  if (scope && (symbol->scope || new_parent) && !scope->parent) {
2742  if (new_parent && new_parent != symbol->scope)
2743  symbol->scope = new_parent;
2744  scope_insert_scope(symbol->scope,scope);
2745  }
2746  return scope;
2747 }
2748 
2749 /*
2750  * @parent must be SYMBOL_IS_CONTAINER() (i.e., it must own a scope).
2751  * @child->scope should already be set to symbol_read_owned_scope(@parent);
2752  * @child->scope was preset so that any calls to
2753  * symbol_write_owned_scope (i.e., to update a function's range info or
2754  * something) could succeed, even if we weren't yet ready to insert
2755  * @child into @parent's owned scope yet. So just check and warn on
2756  * that.
2757  */
2758 int symbol_insert_symbol(struct symbol *parent,struct symbol *child) {
2759  struct scope *scope;
2760 
2761  if (!SYMBOL_HAS_MEMBERS(parent)) {
2762  verror("");
2763  ERRORDUMPSYMBOL(parent);
2764  verrorc(" not a container; cannot insert child ");
2765  ERRORDUMPSYMBOL_NL(child);
2766  return -1;
2767  }
2768  if (SYMBOL_IST_ENUM(parent)
2769  && symbol_containing_scope(child) != symbol_containing_scope(parent)) {
2770  verror("enum child ");
2771  ERRORDUMPSYMBOL(child);
2772  verrorc(" not set to go on containing scope of parent enum type ");
2773  ERRORDUMPSYMBOL(parent);
2774  verrorc("; cannot insert!\n");
2775  return -1;
2776  }
2777  else if (!SYMBOL_IST_ENUM(parent)
2778  && symbol_containing_scope(child)
2779  && symbol_containing_scope(child) != symbol_read_owned_scope(parent)) {
2780  verror("child ");
2781  ERRORDUMPSYMBOL(child);
2782  verrorc(" not set to go on owned scope of parent ");
2783  ERRORDUMPSYMBOL(parent);
2784  verrorc("; cannot insert!\n");
2785  return -1;
2786  }
2787 
2788  /*
2789  * For any type container that is not an ENUM, we insert it into the
2790  * members list, and into the scope. For ENUM, just into the member
2791  * list (ENUMs do not have scope of their own).
2792  */
2793  if (SYMBOL_IST_ENUM(parent) && child->isenumval) {
2794  parent->extra.members = g_slist_append(parent->extra.members,child);
2795  RHOLD(child,parent);
2796  }
2797  else if ((SYMBOL_IST_FUNC(parent) && child->isparam)
2798  || (SYMBOL_IST_STUNC(parent)
2799  && (child->ismember || SYMBOL_IS_FUNC(child)))) {
2800  SYMBOL_WX_CONTAINER(parent,sc,-1);
2801  sc->members = g_slist_append(sc->members,child);
2802  RHOLD(child,parent);
2803  }
2804  else if (SYMBOL_IS_FUNC(parent) && child->isparam) {
2805  SYMBOL_WX_FUNC(parent,sf,-1);
2806  sf->members = g_slist_append(sf->members,child);
2807  RHOLD(child,parent);
2808  }
2809  else if (SYMBOL_IS_BLOCK(parent) && child->isparam) {
2810  SYMBOL_WX_FUNC(parent,sb,-1);
2811  sb->members = g_slist_append(sb->members,child);
2812  RHOLD(child,parent);
2813  }
2814 
2815  /*
2816  * Now add it to the scope if we have one.
2817  */
2818  if (SYMBOL_IST_ENUM(parent)) {
2819  scope = symbol_containing_scope(parent);
2820  if (!scope) {
2821  verror("BUG? parent ");
2822  ERRORDUMPSYMBOL(parent);
2823  verrorc(" does not have containing scope??\n");
2824  return -1;
2825  }
2826  }
2827  else {
2828  /*
2829  * This must be _link_, not _write_!!! It is possible to arrive
2830  * here and for @parent's scope to not have been created. So if
2831  * we create one, we have to link it too.
2832  */
2833  scope = symbol_link_owned_scope(parent,NULL);
2834  if (!scope) {
2835  verror("BUG? parent ");
2836  ERRORDUMPSYMBOL(parent);
2837  verrorc(" does not have owned scope??\n");
2838  return -1;
2839  }
2840  }
2841 
2842  return scope_insert_symbol(scope,child);
2843 }
2844 
2845 int symbol_remove_symbol(struct symbol *parent,struct symbol *child) {
2846  struct scope *scope;
2847  REFCNT trefcnt;
2848 
2849  /*
2850  * Remove it from the current parent's scope.
2851  */
2852  scope = symbol_read_owned_scope(parent);
2853  if (scope)
2854  scope_remove_symbol(scope,child);
2855 
2856  /*
2857  * Remove it from the member list if appropriate; see symbol_insert_symbol.
2858  */
2859  if (SYMBOL_IST_ENUM(parent) && child->isenumval) {
2860  parent->extra.members = g_slist_remove(parent->extra.members,child);
2861  RPUT(child,symbol,parent,trefcnt);
2862  }
2863  else if ((SYMBOL_IST_FUNC(parent) && child->isparam)
2864  || (SYMBOL_IST_STUNC(parent)
2865  && (child->ismember || SYMBOL_IS_FUNC(child)))) {
2866  SYMBOL_WX_CONTAINER(parent,sc,-1);
2867  sc->members = g_slist_remove(sc->members,child);
2868  RPUT(child,symbol,parent,trefcnt);
2869  }
2870  else if (SYMBOL_IS_FUNC(parent) && child->isparam) {
2871  SYMBOL_WX_FUNC(parent,sf,-1);
2872  sf->members = g_slist_remove(sf->members,child);
2873  RPUT(child,symbol,parent,trefcnt);
2874  }
2875  else if (SYMBOL_IS_BLOCK(parent) && child->isparam) {
2876  SYMBOL_WX_FUNC(parent,sb,-1);
2877  sb->members = g_slist_append(sb->members,child);
2878  RPUT(child,symbol,parent,trefcnt);
2879  }
2880 
2881  return 0;
2882 }
2883 
2884 int symbol_change_parent(struct symbol *parent,struct symbol *child,
2885  struct symbol *newparent) {
2886  struct scope *scope;
2887  REFCNT trefcnt;
2888 
2889  /* Take a temp ref so it doesn't disappear. */
2890  RHOLD(child,(void *)0xdeadbeef);
2891 
2892  /*
2893  * Remove it from the current parent's scope.
2894  */
2895  scope = symbol_read_owned_scope(parent);
2896  if (scope)
2897  scope_remove_symbol(scope,child);
2898 
2899  /*
2900  * Remove it from the member list if appropriate; see symbol_insert_symbol.
2901  */
2902  if (SYMBOL_IST_ENUM(parent) && child->isenumval) {
2903  parent->extra.members = g_slist_remove(parent->extra.members,child);
2904  RPUT(child,symbol,parent,trefcnt);
2905  }
2906  else if ((SYMBOL_IST_FUNC(parent) && child->isparam)
2907  || (SYMBOL_IST_STUNC(parent)
2908  && (child->ismember || SYMBOL_IS_FUNC(child)))) {
2909  SYMBOL_WX_CONTAINER(parent,sc,-1);
2910  sc->members = g_slist_remove(sc->members,child);
2911  RPUT(child,symbol,parent,trefcnt);
2912  }
2913  else if (SYMBOL_IS_FUNC(parent) && child->isparam) {
2914  SYMBOL_WX_FUNC(parent,sf,-1);
2915  sf->members = g_slist_remove(sf->members,child);
2916  RPUT(child,symbol,parent,trefcnt);
2917  }
2918  else if (SYMBOL_IS_BLOCK(parent) && child->isparam) {
2919  SYMBOL_WX_FUNC(parent,sb,-1);
2920  sb->members = g_slist_append(sb->members,child);
2921  RPUT(child,symbol,parent,trefcnt);
2922  }
2923 
2924  /*
2925  * Ok, now insert it into the new parent!
2926  */
2927  child->scope = symbol_read_owned_scope(newparent);
2928  symbol_insert_symbol(newparent,child);
2929 
2930  /* Release the temp ref! */
2931  RPUT(child,symbol,(void *)0xdeadbeef,trefcnt);
2932 
2933  return 0;
2934 }
2935 
2936 /* @srcline */
2938  return symbol->srcline;
2939 }
2940 /* @srcfile */
2942  symbol = symbol_find_root(symbol);
2943  if (!symbol)
2944  return NULL;
2945 
2946  return symbol->name;
2947 }
2948 /* @compdirname */
2950  struct symbol_root *root;
2951 
2952  symbol = symbol_find_root(symbol);
2953  if (!symbol)
2954  return NULL;
2955  root = SYMBOLX_ROOT(symbol);
2956  if (!root)
2957  return NULL;
2958 
2959  return root->compdirname;
2960 }
2961 /* @type */
2963  return symbol->type;
2964 }
2965 /* @source */
2967  return symbol->source;
2968 }
2969 /* @datatype -- not all symbols have it of course. */
2971  struct symbol *origin;
2972 
2973  /*
2974  * Find the real-est datatype we can; that might validly be on the
2975  * abstract origin symbol!
2976  */
2977  if (symbol->datatype) {
2978  SYMBOL_EXPAND_WARN(symbol->datatype);
2979  return symbol->datatype;
2980  }
2981  else if (symbol->isinlineinstance) {
2982  origin = symbol_get_inline_origin(symbol);
2983  if (origin)
2984  return symbol_get_datatype_real(origin);
2985  }
2986 
2987  return NULL;
2988 }
2990  struct symbol *retval;
2991  struct symbol *origin;
2992 
2993  if (!symbol->datatype && symbol->isinlineinstance) {
2994  origin = symbol_get_inline_origin(symbol);
2995  if (origin)
2996  return symbol_get_datatype(origin);
2997  }
2998 
2999  if (!SYMBOL_IS_TYPE(symbol))
3000  retval = symbol->datatype;
3001  else if (symbol->datatype) {
3002  retval = symbol_type_skip_qualifiers(symbol->datatype);
3003  }
3004  else {
3005  retval = symbol;
3006  }
3007 
3008  if (retval)
3009  SYMBOL_EXPAND_WARN(retval);
3010 
3011  return retval;
3012 }
3013 
3014 /* Various flags. */
3016  return symbol->issynthetic;
3017 }
3019  return symbol->isexternal;
3020 }
3022  if (!symbol->isdeclaration || symbol->decldefined)
3023  return 1;
3024  return 0;
3025 }
3027  return symbol->isdeclaration;
3028 }
3030  return symbol->decldefined;
3031 }
3033  return symbol->isprototyped;
3034 }
3036  return symbol->isparam;
3037 }
3039  return symbol->ismember;
3040 }
3042  return symbol->isenumval;
3043 }
3045  return symbol->isinlineinstance;
3046 }
3048  return symbol->has_addr;
3049 }
3051  return symbol->has_unspec_params;
3052 }
3054  return symbol->isinlined;
3055 }
3057  return symbol->isdeclinline;
3058 }
3060  return symbol->size_is_bits;
3061 }
3063  return symbol->size_is_bytes;
3064 }
3065 uint32_t symbol_get_bytesize(struct symbol *symbol) {
3066  if (symbol->size_is_bytes)
3067  return symbol->size.bytes;
3068  else if (symbol->size_is_bits) {
3069  if (symbol->size.bits % 8)
3070  /* Overestimate. */
3071  return symbol->size.bits / 8 + 1;
3072  else
3073  return symbol->size.bits / 8;
3074  }
3075 
3076  return 0;
3077 }
3078 
3079 uint32_t symbol_get_bitsize(struct symbol *symbol) {
3080  if (symbol->size_is_bytes)
3081  return symbol->size.bytes * 8;
3082 
3083  return symbol->size.bits;
3084 }
3086  if (!symbol->size_is_bits)
3087  return 0;
3088  return symbol->size.offset;
3089 }
3091  if (!symbol->size_is_bits)
3092  return 0;
3093  return symbol->size.ctbytes;
3094 }
3095 /* @addr */
3097  return symbol->addr;
3098 }
3099 /*
3100  * Utility functions.
3101  */
3103  return SYMBOL_TYPE_FLAG_MATCHES(symbol,flags);
3104 }
3105 
3107  struct scope *scope;
3108 
3109  scope = symbol->scope;
3110  while (scope) {
3111  if (scope->symbol)
3112  return scope->symbol;
3113  scope = scope->parent;
3114  }
3115 
3116  return NULL;
3117 }
3118 
3120  if (SYMBOL_IS_ROOT(symbol))
3121  return symbol;
3122  while ((symbol = symbol_find_parent(symbol)))
3123  if (SYMBOL_IS_ROOT(symbol))
3124  return symbol;
3125  return NULL;
3126 }
3127 
3129  symbol_type_flag_t flags) {
3130  GSList *retval = NULL;
3131  GSList *gsltmp;
3132  struct symbol *s;
3133 
3134  /*
3135  * Only search through the ordered members list.
3136  */
3137  v_g_slist_foreach(SYMBOLX_MEMBERS(symbol),gsltmp,s) {
3138  if (SYMBOL_TYPE_FLAG_MATCHES(s,flags)) {
3139  retval = g_slist_append(retval,s);
3140  }
3141  }
3142 
3143  return retval;
3144 }
3145 
3147  symbol_type_flag_t flags) {
3148  struct scope *scope;
3149 
3150  /*
3151  * NB: we only search the scope's primary symdict -- not its
3152  * duplicates/anonymous symbols.
3153  */
3154  scope = SYMBOLX_SCOPE(symbol);
3155  if (!scope || !scope->symdict)
3156  return NULL;
3157 
3158  return symdict_match_syms(scope->symdict,NULL,flags);
3159 }
3160 
3162  struct symbol *root;
3163 
3164  if (SYMBOL_IS_FULL(symbol) || SYMBOL_IS_ELF(symbol))
3165  return 0;
3166 
3167  if (SYMBOL_IS_ROOT(symbol)) {
3168  SYMBOL_RX_ROOT(symbol,sr);
3169  if (!sr || !sr->debugfile
3170  || !sr->debugfile->ops || !sr->debugfile->ops->symbol_root_expand) {
3171  errno = ENOTSUP;
3172  return -1;
3173  }
3174  return sr->debugfile->ops->symbol_root_expand(sr->debugfile,symbol);
3175  }
3176 
3177  root = symbol_find_root(symbol);
3178  if (!root) {
3179  verror("could not find root for symbol(%s:0x%"PRIxSMOFFSET")!\n",
3180  symbol_get_name(symbol),symbol->ref);
3181  return -1;
3182  }
3183 
3184  SYMBOL_RX_ROOT(root,sr);
3185  if (!sr || !sr->debugfile
3186  || !sr->debugfile->ops || !sr->debugfile->ops->symbol_expand) {
3187  errno = ENOTSUP;
3188  return -1;
3189  }
3190 
3191  return sr->debugfile->ops->symbol_expand(sr->debugfile,root,symbol);
3192 }
3193 
3194 void symbol_set_srcline(struct symbol *s,int sl) {
3195  if (sl > ((1 << SRCLINE_BITS) - 1)) {
3196  vwarn("symbol %s at srcline %d: line too large (max %d)!\n",
3197  symbol_get_name((s)),(sl),(1 << SRCLINE_BITS) - 1);
3198  s->srcline = 0xffff;
3199  }
3200  else {
3201  s->srcline = sl;
3202  }
3203 }
3204 
3205 /*
3206  * Setting sizes is a bit complicated.
3207  *
3208  * If a type or variable has both a byte_size and a bit_size (gcc does
3209  * this for bitfields -- in its DWARF output, byte_size is the size of
3210  * the type containing the bitfield; bit_size is the actual size of the
3211  * bitfield), and byte_size is moved into ctbytes (size of containing
3212  * integral type).
3213  *
3214  * We handle these situations automatically. So if the debuginfo
3215  * parser sees a bytesize first, we set it as a byte size. Then if it
3216  * sees bitfield info, we convert the size to a bit size and move the
3217  * bytes into the ctbytes field.
3218  */
3219 void symbol_set_bytesize(struct symbol *s,uint32_t b) {
3220  if (s->size_is_bits) {
3221  if (b > ((1UL << SIZE_CTBYTES_SIZE) - 1))
3222  vwarn("ctbytes %"PRIu32" too big for field size!\n",b);
3223  s->size.ctbytes = b;
3224  }
3225  else {
3226  s->size_is_bytes = 1;
3227  s->size_is_bits = 0;
3228  s->size.bytes = b;
3229  }
3230 }
3231 
3232 void symbol_set_bitsize(struct symbol *s,uint32_t b) {
3233  if (s->size_is_bytes) {
3234  uint32_t tmpbytes = s->size.bytes;
3235  if (tmpbytes > ((1 << SIZE_CTBYTES_SIZE) - 1))
3236  vwarn("ctbytes %"PRIu32" too big for field size!\n",tmpbytes);
3237  s->size.bytes = 0;
3238  s->size_is_bytes = 0;
3239  s->size.ctbytes = (uint32_t)tmpbytes;
3240  }
3241  s->size_is_bits = 1;
3242  if (b > ((1 << SIZE_BITS_SIZE) - 1))
3243  vwarn("bits %"PRIu32" too big for field size!\n",b);
3244  s->size.bits = b;
3245 }
3246 
3247 void symbol_set_bitoffset(struct symbol *s,uint32_t bo) {
3248  if (s->size_is_bytes) {
3249  uint32_t tmpbytes = (uint32_t)s->size.bytes;
3250  if (tmpbytes > ((1 << SIZE_CTBYTES_SIZE) - 1))
3251  vwarn("ctbytes %"PRIu32" too big for field size!\n",tmpbytes);
3252  s->size.bytes = 0;
3253  s->size_is_bytes = 0;
3254  s->size.ctbytes = (uint32_t)tmpbytes;
3255  }
3256  s->size_is_bits = 1;
3257  if (bo > ((1 << SIZE_OFFSET_SIZE) - 1))
3258  vwarn("offset %"PRIu32" too big for field size!\n",bo);
3259  s->size.offset = bo;
3260 }
3261 
3262 void symbol_set_bitsize_all(struct symbol *s,uint32_t b,uint32_t bo,uint32_t ctb) {
3263  if (b > ((1 << SIZE_BITS_SIZE) - 1))
3264  vwarn("bits %"PRIu32" too big for field size!\n",b);
3265  if (bo > ((1 << SIZE_OFFSET_SIZE) - 1))
3266  vwarn("offset %"PRIu32" too big for field size!\n",bo);
3267  if (ctb > ((1 << SIZE_CTBYTES_SIZE) - 1))
3268  vwarn("ctbytes %"PRIu32" too big for field size!\n",ctb);
3269  s->size_is_bytes = 0;
3270  s->size_is_bits = 1;
3271  s->size.bits = b;
3272  s->size.offset = bo;
3273  s->size.ctbytes = ctb;
3274 }
3275 
3276 void symbol_set_addr(struct symbol *s,ADDR a) {
3277  if (s->has_addr && s->addr < (a)) {
3278  vwarn("symbol(%s:0x%"PRIxSMOFFSET") has existing addr 0x%"PRIxADDR
3279  " lower than new addr 0x%"PRIxADDR"; not updating!\n",
3280  symbol_get_name(s),s->ref,s->addr,a);
3281  }
3282  else {
3283  s->addr = a;
3284  s->has_addr = 1;
3285  }
3286 }
3287 
3288 int symbol_set_root_priv(struct symbol *symbol,void *priv) {
3289  SYMBOL_WX_ROOT(symbol,sr,-1);
3290  sr->priv = priv;
3291  return 0;
3292 }
3293 
3294 int symbol_set_root_compdir(struct symbol *symbol,char *compdirname,int copy) {
3295  SYMBOL_WX_ROOT(symbol,sr,-1);
3296  if (sr->compdirname && !sr->compdirname_nofree)
3297  free(sr->compdirname);
3298  if (compdirname && copy)
3299  sr->compdirname = strdup(compdirname);
3300  else
3301  sr->compdirname = compdirname;
3302  sr->compdirname_nofree = !copy;
3303  return 0;
3304 }
3305 
3306 int symbol_set_root_producer(struct symbol *symbol,char *producer,int copy) {
3307  SYMBOL_WX_ROOT(symbol,sr,-1);
3308  if (sr->producer && !sr->producer_nofree)
3309  free(sr->producer);
3310  if (producer && copy)
3311  sr->producer = strdup(producer);
3312  else
3313  sr->producer = producer;
3314  sr->producer_nofree = !copy;
3315  return 0;
3316 }
3317 
3318 int symbol_set_root_language(struct symbol *symbol,char *language,int copy,
3319  short int lang_code) {
3320  SYMBOL_WX_ROOT(symbol,sr,-1);
3321  if (sr->language && !sr->language_nofree)
3322  free(sr->language);
3323  if (language && copy)
3324  sr->language = strdup(language);
3325  else
3326  sr->language = language;
3327  sr->language_nofree = !copy;
3328  sr->lang_code = lang_code;
3329  return 0;
3330 }
3331 
3333  if (!SYMBOL_IST_BASE(symbol))
3334  return -1;
3335 
3336  SYMBOLX_ENCODING_V(symbol) = num;
3337  return 0;
3338 }
3339 
3340 int symbol_set_entry_pc(struct symbol *symbol,ADDR entry_pc) {
3341  if (SYMBOL_IS_FUNC(symbol)) {
3342  SYMBOL_WX_FUNC(symbol,sf,-1);
3343  sf->entry_pc = entry_pc;
3344  sf->has_entry_pc = 1;
3345  }
3346  else if (SYMBOL_IS_ROOT(symbol)) {
3347  SYMBOL_WX_ROOT(symbol,sr,-1);
3348  sr->entry_pc = entry_pc;
3349  sr->has_entry_pc = 1;
3350  }
3351  else
3352  goto errout;
3353 
3354  if (entry_pc < symbol->addr) {
3355  symbol->addr = entry_pc;
3356  symbol->has_addr = 1;
3357  }
3358 
3359  return 0;
3360 
3361  errout:
3362  return -1;
3363 }
3364 
3365 int symbol_set_location(struct symbol *symbol,struct location *loc) {
3366  SYMBOL_WX_VAR(symbol,sv,-1);
3367 
3368  if (sv->loc) {
3370  "replacing existing location for symbol(%s:0x%"PRIxADDR")!\n",
3371  symbol_get_name(symbol),symbol->ref);
3372  location_free(sv->loc);
3373  }
3374  sv->loc = loc;
3375 
3376  /*
3377  * NB: we also try to update symbol->addr!
3378  */
3379  if (LOCATION_IS_ADDR(sv->loc)) {
3380  if (!symbol->has_addr || LOCATION_ADDR(sv->loc) < symbol->addr) {
3381  symbol->addr = LOCATION_ADDR(sv->loc);
3382  symbol->has_addr = 1;
3383  }
3384  }
3385 
3386  return 0;
3387 }
3388 
3390  symbol->isinlined = isinlined;
3391  symbol->isdeclinline = isdeclinline;
3392  return 0;
3393 }
3394 
3396  SMOFFSET ref,struct symbol *origin) {
3397  SYMBOL_WX_INLINE(symbol,sii,-1);
3398 
3399  symbol->isinlineinstance = 1;
3400 
3401  sii->origin_ref = ref;
3402  sii->origin = origin;
3403 
3404  return 0;
3405 }
3406 
3407 static int symbol_set_inline_instances(struct symbol *symbol,GSList *instances) {
3408  GSList *gsltmp;
3409  struct symbol *instance;
3410  SYMBOL_WX_INLINE(symbol,sii,-1);
3411 
3412  v_g_slist_foreach(instances,gsltmp,instance)
3413  RHOLD(instance,symbol);
3414  sii->inline_instances = g_slist_concat(sii->inline_instances,instances);
3415 
3416  return 0;
3417 }
3418 
3419 /* NB: for now, don't check if the instance is already on our list. */
3420 int symbol_add_inline_instance(struct symbol *symbol,struct symbol *instance) {
3421  SYMBOL_WX_INLINE(symbol,sii,-1);
3422 
3423  sii->inline_instances = g_slist_append(sii->inline_instances,instance);
3424  RHOLD(instance,symbol);
3425 
3426  return 0;
3427 }
3428 
3429 int symbol_set_constval(struct symbol *symbol,void *value,int len,int copy) {
3430  SYMBOL_WX_VAR(symbol,sv,-1);
3431 
3432  if (sv->constval && !symbol->constval_nofree)
3433  free(sv->constval);
3434 
3435  if (!copy) {
3436  sv->constval = value;
3437  symbol->constval_nofree = 1;
3438  }
3439  else {
3440  sv->constval = malloc(len);
3441  memcpy(sv->constval,value,len);
3442  symbol->constval_nofree = 0;
3443  }
3444 
3445  return 0;
3446 }
3447 
3448 int symbol_add_subrange(struct symbol *symbol,int subrange) {
3449  if (!SYMBOL_IST_ARRAY(symbol))
3450  return -1;
3451 
3452  SYMBOLX_SUBRANGES(symbol) = g_slist_append(SYMBOLX_SUBRANGES(symbol),
3453  (gpointer)(uintptr_t)subrange);
3454  return 0;
3455 }
3456 
3457 #if 0
3458 int symbol_change_scope(struct symbol *symbol,struct scope *scope) {
3459 
3460  if (symbol->scope == scope)
3461  return 0;
3462 
3463  /* If it's a member, don't insert OR remove it! */
3464  if (!symbol->ismember) {
3465  /* Remove it from what it might be currently on, but don't free it! */
3466  symtab_steal_symbol(symbol->symtab,symbol);
3467 
3468  /* Add it to the new thing. */
3469  symbol->symtab = NULL;
3470  symtab_insert_symbol(symtab,symbol);
3471  }
3472 
3473  /* Change our immediate children if necessary. For instance
3474  * symbols, we only recurse on their types if we were told to. In
3475  * general, we are saved from crazy recursion loops (i.e., on nested
3476  * struct types) because we check to see if we already changed the
3477  * symtab.
3478  if (typerecurse && symbol->datatype)
3479  symbol_change_scope(symbol->datatype,symtab,typerecurse);
3480  */
3481 
3482  if (!SYMBOL_IS_FULL(symbol))
3483  return 0;
3484 
3485  if (SYMBOL_IS_TYPE(symbol)) {
3486  if (SYMBOL_IST_STUN(symbol)) {
3487  list_for_each_entry(tmpi,&symbol->s.ti->d.su.members,d.v.member)
3488  symbol_change_symtab(tmpi->d.v.member_symbol,symtab);
3489  }
3490  else if (SYMBOL_IST_ENUM(symbol)) {
3491  list_for_each_entry(tmpi,&symbol->s.ti->d.e.members,d.v.member)
3492  symbol_change_symtab(tmpi->d.v.member_symbol,symtab);
3493  }
3494  }
3495  else if (SYMBOL_IS_FUNC(symbol)) {
3496  /* We don't need to recurse on this symtab; any children already
3497  * point to d.f.symtab.
3498  */
3499  if (SYMTAB_HAS_PARENT(symbol->s.ii->d.f.symtab))
3500  list_del(&symbol->s.ii->d.f.symtab->member);
3501  symbol->s.ii->d.f.symtab->hierarchy->parent = symtab;
3502  symtab->hierarchy->subtabs = g_slist_append(symtab->hierarchy->subtabs,
3503  symbol->s.ii->d.f.symtab);
3504 
3505  /* We also don't need to do it for any of our args or variables;
3506  * they are on this function's symtab, which we just reparented.
3507  */
3508  }
3509  /* Nothing to do for labels. */
3510 
3511  return 0;
3512 }
3513 #endif
3514 
3515 static inline int __check_type_in_list(struct symbol *type,
3516  struct array_list *list) {
3517  if (!list)
3518  return 0;
3519 
3520  if (array_list_find(list,type) > -1)
3521  return 1;
3522 
3523  return 0;
3524 }
3525 
3526 static int __symbol_type_equiv(struct symbol *t1,struct symbol *t2,
3527  struct array_list **t1ss,
3528  struct array_list **t2ss,
3529  GHashTable *eqcache,
3530  GHashTable *updated_datatype_refs) {
3531  GSList *m1_mlist;
3532  GSList *m2_mlist;
3533  struct symbol *m1;
3534  struct symbol *m2;
3535  struct symbol *t1d;
3536  struct symbol *t2d;
3537  int retval = 0;
3538  int rc1 = 0,rc2 = 0;
3539  int t1created = 0;
3540  int t2created = 0;
3541  GSList *gsltmp1,*gsltmp2;
3542  char *sn1,*sn2;
3543 
3544  if (t1 == t2)
3545  return 0;
3546  if (eqcache && g_hash_table_lookup(eqcache,t1) == t2)
3547  return 0;
3548 
3549  /* Check if we've already been examining this type (for nested
3550  * structs/unions); if we have, just return equiv so that the
3551  * recursion will return! Equivalence is decided further up the
3552  * stack.
3553  */
3554  if (t1ss && *t1ss)
3555  rc1 = __check_type_in_list(t1,*t1ss);
3556  if (t2ss && *t2ss)
3557  rc2 = __check_type_in_list(t2,*t2ss);
3558  if ((rc1 || rc2) && rc1 == rc2) {
3559  vdebug(8,LA_DEBUG,LF_SYMBOL,"t1 = %p t2 = %p -> 0\n",t1,t2);
3560  return 0;
3561  }
3562  else if (rc1 || rc2) {
3563  vdebug(8,LA_DEBUG,LF_SYMBOL,"t1 = %p t2 = %p -> 1\n",t1,t2);
3564  return 1;
3565  }
3566 
3567  vdebug(8,LA_DEBUG,LF_SYMBOL,"t1 = %p t2 = %p -> ?\n",t1,t2);
3568 
3569  if (t1->datatype_code != t2->datatype_code)
3570  return 1;
3571 
3572  if (t1->loadtag != t2->loadtag)
3573  return 1;
3574 
3575  sn1 = symbol_get_name(t1);
3576  sn2 = symbol_get_name(t2);
3577  if ((!sn1 || !sn2) && sn1 != sn2)
3578  return 1;
3579  else if (!((sn1 == NULL && sn2 == NULL)
3580  || strcmp(sn1,sn2) == 0))
3581  return 1;
3582 
3583  /* Cheat bad -- the t1->size union is a uint32_t! */
3584  if (*(uint32_t *)&t1->size != *(uint32_t *)&t2->size
3585  || t1->size_is_bytes != t2->size_is_bytes
3586  || t1->size_is_bits != t2->size_is_bits)
3587  return 1;
3588 
3589  if (!SYMBOL_HAS_EXTRA(t1))
3590  goto datatype_check;
3591 
3592  /*
3593  * Check details that are in symbol->extra.* .
3594  */
3595  switch (t1->datatype_code) {
3596  case DATATYPE_VOID:
3597  break;
3598  case DATATYPE_ARRAY:
3599  m1_mlist = SYMBOLX_SUBRANGES(t1);
3600  m2_mlist = SYMBOLX_SUBRANGES(t2);
3601  /* The list values are really int, but just compare the pointers. */
3602  v_g_slist_foreach_dual(m1_mlist,m2_mlist,gsltmp1,gsltmp2,m1,m2) {
3603  if (m1 != m2)
3604  return 1;
3605  }
3606  if (gsltmp1 || gsltmp2)
3607  return 1;
3608  break;
3609  case DATATYPE_FUNC:
3610  if (t1->has_unspec_params != t2->has_unspec_params)
3611  return 1;
3612  /* NB: fall through to check members! */
3613  case DATATYPE_STRUCT:
3614  case DATATYPE_UNION:
3615  m1_mlist = SYMBOLX_MEMBERS(t1);
3616  m2_mlist = SYMBOLX_MEMBERS(t2);
3617 
3618  if (m1_mlist == NULL && m2_mlist == NULL)
3619  break;
3620  else if (!m1_mlist || !m2_mlist)
3621  return 1;
3622 
3623  /*
3624  * Before we check member types, push ourselves as "already
3625  * being checked". Then, if a recursive call to this function
3626  * sees these symbols on their respective lists again, it just
3627  * returns 0 (equivalent) and we finish the checking further up
3628  * the recursion stack.
3629  *
3630  * NB: we don't really need to do this for functions, so we don't.
3631  */
3632  if (t1->datatype_code != DATATYPE_FUNC) {
3633  if (!*t1ss) {
3634  *t1ss = array_list_create(4);
3635  t1created = 1;
3636  }
3637  if (!*t2ss) {
3638  *t2ss = array_list_create(4);
3639  t2created = 1;
3640  }
3641  array_list_append(*t1ss,t1);
3642  array_list_append(*t2ss,t2);
3643  }
3644 
3645  /* Then check all the names/types of the members! */
3646  while (m1_mlist && m2_mlist) {
3647  m1 = m1_mlist->data;
3648  m2 = m2_mlist->data;
3649 
3650  m1_mlist = m1_mlist->next;
3651  m2_mlist = m2_mlist->next;
3652 
3653  //vwarn("i = %d %p %p %p %p %p %p\n",i,ti1,ti2,mi1,mi2,m1,m2);
3654  if ((m1 == NULL && m2 == NULL)
3655  || (symbol_get_name(m1) == NULL && symbol_get_name(m2) == NULL))
3656  /* name can be NULL for function params, of course */
3657  ;
3658  else if ((m1 == NULL && m2 != NULL)
3659  || (m1 != NULL && m2 == NULL)
3660  || (symbol_get_name(m1) == NULL && symbol_get_name(m2) != NULL)
3661  || (symbol_get_name(m1) != NULL && symbol_get_name(m2) == NULL)
3662  || strcmp(symbol_get_name(m1),symbol_get_name(m2))) {
3663  retval = 1;
3664  break;
3665  }
3666 
3667  t1d = m1->datatype;
3668  t2d = m2->datatype;
3669 
3670  if (updated_datatype_refs) {
3671  t1d = (struct symbol *) \
3672  g_hash_table_lookup(updated_datatype_refs,
3673  (gpointer)(uintptr_t)m1->datatype_ref);
3674  if (!t1d)
3675  t1d = m1->datatype;
3676  t2d = (struct symbol *) \
3677  g_hash_table_lookup(updated_datatype_refs,
3678  (gpointer)(uintptr_t)m2->datatype_ref);
3679  if (!t2d)
3680  t2d = m2->datatype;
3681  }
3682 
3683  if (t1d == t2d)
3684  continue;
3685 
3686  if ((rc1 = __symbol_type_equiv(t1d,t2d,t1ss,t2ss,eqcache,
3687  updated_datatype_refs))) {
3688  retval = rc1;
3689  break;
3690  }
3691  }
3692 
3693  if (t1->datatype_code != DATATYPE_FUNC) {
3694  array_list_remove(*t1ss);
3695  array_list_remove(*t2ss);
3696  }
3697 
3698  if (t1->datatype_code != DATATYPE_FUNC) {
3699  if (t1created) {
3700  array_list_free(*t1ss);
3701  *t1ss = NULL;
3702  }
3703  if (t2created) {
3704  array_list_free(*t2ss);
3705  *t2ss = NULL;
3706  }
3707  }
3708 
3709  if (retval)
3710  return retval;
3711 
3712  /* If we have an uneven number members, they can't be equivalent. */
3713  if (m1_mlist != NULL || m2_mlist != NULL)
3714  return 1;
3715 
3716  break;
3717  case DATATYPE_ENUM:
3718  ;
3719  m1_mlist = SYMBOLX_MEMBERS(t1);
3720  m2_mlist = SYMBOLX_MEMBERS(t2);
3721 
3722  /*
3723  * Life is good if the names are equiv.
3724  */
3725  if (m1_mlist == NULL && m2_mlist == NULL)
3726  break;
3727  else if (!m1_mlist || !m2_mlist)
3728  return 1;
3729 
3730  while (m1_mlist && m2_mlist) {
3731  m1 = m1_mlist->data;
3732  m2 = m2_mlist->data;
3733 
3734  m1_mlist = m1_mlist->next;
3735  m2_mlist = m2_mlist->next;
3736 
3737  if ((m1 == NULL && m2 != NULL)
3738  || (m1 != NULL && m2 == NULL)
3739  || (symbol_get_name(m1) == NULL && symbol_get_name(m2) != NULL)
3740  || (symbol_get_name(m1) != NULL && symbol_get_name(m2) == NULL)
3741  || strcmp(symbol_get_name(m1),symbol_get_name(m2))) {
3742  retval = 1;
3743  break;
3744  }
3745  }
3746  /* If we have an uneven number members, they can't be equivalent. */
3747  if (!retval && (m1_mlist != NULL || m2_mlist != NULL))
3748  return 1;
3749 
3750  break;
3751  case DATATYPE_PTR:
3752  case DATATYPE_REF:
3753  case DATATYPE_TYPEDEF:
3754  case DATATYPE_CONST:
3755  case DATATYPE_VOL:
3756  break;
3757  case DATATYPE_BASE:
3758  if (SYMBOLX_ENCODING_V(t1) != SYMBOLX_ENCODING_V(t2))
3759  return 1;
3760  break;
3761  default:
3762  return -1;
3763  }
3764 
3765  datatype_check:
3766  /*
3767  * For types that use the datatype field to point to another type,
3768  * check that type's equiv.
3769  */
3770  if (SYMBOL_IST_ARRAY(t1) || SYMBOL_IST_FUNC(t1) || SYMBOL_IST_PTR(t1)
3771  || SYMBOL_IST_TYPEDEF(t1) || SYMBOL_IST_CONST(t1) || SYMBOL_IST_VOL(t1)) {
3772  if (!t1->datatype || !t2->datatype)
3773  return 1;
3774 
3775  t1d = t1->datatype;
3776  t2d = t2->datatype;
3777  if (updated_datatype_refs) {
3778  t1d = (struct symbol *)g_hash_table_lookup(updated_datatype_refs,
3779  (gpointer)(uintptr_t)t1->datatype_ref);
3780  if (!t1d)
3781  t1d = t1->datatype;
3782  t2d = (struct symbol *)g_hash_table_lookup(updated_datatype_refs,
3783  (gpointer)(uintptr_t)t2->datatype_ref);
3784  if (!t2d)
3785  t2d = t2->datatype;
3786  }
3787  if (t1d == t2d)
3788  return 0;
3789  retval = __symbol_type_equiv(t1d,t2d,t1ss,t2ss,eqcache,updated_datatype_refs);
3790  return retval;
3791  }
3792 
3793  /*
3794  * If we got here, everything's good!
3795  */
3796  if (eqcache)
3797  g_hash_table_insert(eqcache,t1,t2);
3798  return 0;
3799 }
3800 
3801 int symbol_type_equal(struct symbol *t1,struct symbol *t2,
3802  GHashTable *eqcache,GHashTable *updated_datatype_refs) {
3803  struct array_list *t1ss = NULL;
3804  struct array_list *t2ss = NULL;
3805  int retval;
3806 
3807  if (!SYMBOL_IS_TYPE(t1) || !SYMBOL_IS_TYPE(t2))
3808  return -1;
3809 
3810  retval = __symbol_type_equiv(t1,t2,&t1ss,&t2ss,eqcache,updated_datatype_refs);
3811 
3812  return retval;
3813 }
3814 
3815 struct symbol *__symbol_get_one_member__int(struct symbol *symbol,char *member,
3816  struct array_list **chainptr) {
3817  struct symbol *retval = NULL;
3818  struct symbol **anonstack = NULL;
3819  int *parentstack = NULL;
3820  struct symbol **tmpstack = NULL;
3821  int *tmpparentstack = NULL;
3822  int stacklen = 0;
3823  int stackalen = 0;
3824  int i = 0;
3825  /* Set type to symbol to seed the while loop in the SYMBOL_IST_STUN
3826  * case.
3827  */
3828  struct symbol *type;
3829  int j, k;
3830  struct lsymbol *lsymbol;
3831  struct symbol *tsymbol;
3832  GSList *gsltmp;
3833 
3834  struct dump_info udn = {
3835  .stream = stderr,
3836  .prefix = "",
3837  .detail = 0,
3838  .meta = 0,
3839  };
3840  vdebug(4,LA_DEBUG,LF_DLOOKUP,"symbol: ");
3842  symbol_dump(symbol,&udn);
3843  vdebugc(4,LA_DEBUG,LF_DLOOKUP,"\n");
3844 
3845  type = symbol;
3846 
3847  /* This doesn't look safe, but it is! If it's a type, we skip
3848  * const/vol or typedefs, before testing. If it's not one of those
3849  * types, this function is an identity function, so we just operate
3850  * on @symbol.
3851  */
3852  if (SYMBOL_IS_TYPE(symbol)) {
3853  tsymbol = symbol_type_skip_qualifiers(symbol);
3854  if (tsymbol != symbol) {
3855  vdebug(4,LA_DEBUG,LF_DLOOKUP,"skipped type symbol %s, now: ",
3856  symbol_get_name(symbol));
3858  symbol_dump(tsymbol,&udn);
3859 
3860  symbol = tsymbol;
3861  type = symbol;
3862  }
3863  }
3864 
3865  /* Make sure the datatype is fully loaded before we search it. */
3866  SYMBOL_EXPAND_WARN(type);
3867 
3868  if (!SYMBOL_HAS_EXTRA(symbol))
3869  return NULL;
3870 
3871  if (SYMBOL_IST_CONTAINER(symbol)) {
3872  /*
3873  * First, check our internal symbol table.
3874  */
3875  if (symbol_read_owned_scope(symbol)) {
3877  member,NULL,SYMBOL_TYPE_FLAG_NONE);
3878  if (lsymbol) {
3879  symbol = lsymbol->symbol;
3880  /* Don't force free; somebody might have a reference */
3881  lsymbol_free(lsymbol,0);
3882  return symbol;
3883  }
3884  }
3885 
3886  /*
3887  * Check all our members. It's too bad that we cannot just
3888  * lookup in the symbol's scope, but that only looks up named
3889  * symbols. If we come across an unnamed struct/class/union
3890  * member, push it onto our anon stack and come back to it.
3891  * This avoids non-tail recursion.
3892  *
3893  * Also, we push variables, not types, as we go through the
3894  * list. We also keep a parent index list; each time we push an
3895  * anonymous S/U member variable, we push the anonstack index of
3896  * its parent member variable. Then we can build a symbol_chain
3897  * if the caller needs it.
3898  *
3899  * We need a symbol chain for summing up member offsets for
3900  * nested structs. Note, however, that this chain only consists
3901  * of parent variables that were unnamed!! That is the case
3902  * because this function only returns one member. It is the
3903  * caller's job to build up the complete symbol chain consisting
3904  * of more than one nested variable/function.
3905  */
3906  while (1) {
3907  v_g_slist_foreach(SYMBOLX_MEMBERS(type),gsltmp,retval) {
3908  vdebug(5,LA_DEBUG,LF_SYMBOL,"checking symbol: ");
3910  symbol_dump(retval,&udn);
3911  vdebug(5,LA_DEBUG,LF_SYMBOL,"\n");
3912 
3913  if (!retval->name && SYMBOL_IST_STUNC(retval->datatype)) {
3914  /* push this one for later examination. */
3915  if (stacklen == stackalen) {
3916  stackalen += 4;
3917  tmpstack = (struct symbol **) \
3918  realloc(anonstack,sizeof(struct symbol *)*stackalen);
3919  if (!tmpstack) {
3920  verror("realloc anonstack: %s\n",strerror(errno));
3921  goto errout;
3922  }
3923  anonstack = tmpstack;
3924 
3925  tmpparentstack = (int *) \
3926  realloc(parentstack,sizeof(int)*stackalen);
3927  if (!tmpparentstack) {
3928  verror("realloc parentstack: %s\n",
3929  strerror(errno));
3930  goto errout;
3931  }
3932  parentstack = tmpparentstack;
3933  }
3934  anonstack[stacklen] = retval;
3935  /* the parent is always the anonstack idx we're
3936  * working on. Since we want the parent, we need i - 1.
3937  */
3938  parentstack[stacklen] = i - 1;
3939  ++stacklen;
3940  }
3941  else if (retval->name && strcmp(retval->name,member) == 0) {
3942  //free(anonstack);
3943  goto out;
3944  }
3945  }
3946  if (stackalen > 8)
3947  vwarnopt(4,LA_DEBUG,LF_DLOOKUP,"big stackalen=%d, stack=%d\n",
3948  stackalen,stacklen);
3949  else
3950  vdebug(4,LA_DEBUG,LF_SYMBOL,"stackalen=%d, stack=%d\n",
3951  stackalen,stacklen);
3952  /* If we're out of stuff on our stack, bail. */
3953  if (i == stacklen) {
3954  free(anonstack);
3955  free(parentstack);
3956  anonstack = NULL;
3957  parentstack = NULL;
3958  break;
3959  }
3960  /* Otherwise process the next thing on the stack. */
3961  else {
3962  type = anonstack[i++]->datatype;
3963 
3964  /* Make sure the datatype is fully loaded before we search it. */
3965  SYMBOL_EXPAND_WARN(type);
3966  }
3967  }
3968  }
3969  else if (SYMBOL_IS_FUNC(symbol)) {
3970  /* Just check our internal symbol table; the args are there too. */
3971  if (symbol_read_owned_scope(symbol)) {
3973  member,NULL,SYMBOL_TYPE_FLAG_NONE);
3974  if (lsymbol) {
3975  symbol = lsymbol->symbol;
3976  /* Don't force free; somebody might have a reference */
3977  lsymbol_free(lsymbol,0);
3978  return symbol;
3979  }
3980  }
3981 
3982  return NULL;
3983  }
3984  else if (SYMBOL_IS_VAR(symbol)) {
3985  /* This doesn't look safe, but it is! If it's a type, we skip
3986  * const/vol or typedefs, before testing. If it's not one of those
3987  * types, this function is an identity function, so we just operate
3988  * on @symbol.
3989  */
3990  tsymbol = symbol_type_skip_qualifiers(symbol->datatype);
3991  if (tsymbol != symbol->datatype) {
3992  vdebug(4,LA_DEBUG,LF_DLOOKUP,"skipped type symbol for %s, now: ",
3993  symbol_get_name(symbol->datatype));
3995  symbol_dump(tsymbol,&udn);
3996  }
3997 
3998  /* Make sure the datatype is fully loaded before we search it. */
3999  SYMBOL_EXPAND_WARN(tsymbol);
4000 
4001  if (SYMBOL_IST_STUN(tsymbol)) {
4003  "returning result of searching S/U type symbol: ");
4005  symbol_dump(tsymbol,&udn);
4006 
4007  return __symbol_get_one_member__int(tsymbol,member,chainptr);
4008  }
4009  else if (SYMBOL_IST_PTR(tsymbol)) {
4010  /*
4011  * We keep looking inside the pointed-to type, autoexpanding it
4012  * if necessary.
4013  */
4015  member,chainptr);
4016  }
4017  else
4018  goto errout;
4019  }
4020 
4021  errout:
4022  if (anonstack)
4023  free(anonstack);
4024  if (parentstack)
4025  free(parentstack);
4026  return NULL;
4027 
4028  out:
4029  vdebug(3,LA_DEBUG,LF_SYMBOL | LF_DLOOKUP,"returning symbol: ");
4031  symbol_dump(retval,&udn);
4032  /*
4033  * If type points to something other than the top-level symbol, that
4034  * means we explored anon structs, and we must return an anon symbol
4035  * chain that includes the anon variables between @symbol and @retval.
4036  */
4037  if (chainptr && type != symbol) {
4038  int count;
4039  /* Always includes the anon struct we found, and any anon struct
4040  * parents.
4041  */
4042  /* First count up how many anon parents we have in this chain;
4043  * then malloc it; then fill it up in reverse order.
4044  */
4045  count = 1;
4046  for (j = i - 1; parentstack[j] != -1; j = parentstack[j])
4047  ++count;
4048  *chainptr = array_list_create(count);
4049  for (j = i - 1,k = count; k > 0; --k, j = parentstack[j]) {
4050  array_list_item_set(*chainptr,k-1,anonstack[j]);
4051  }
4052  }
4053 
4054  if (anonstack)
4055  free(anonstack);
4056  if (parentstack)
4057  free(parentstack);
4058 
4059  return retval;
4060 }
4061 
4062 
4063 int symbol_contains_addr(struct symbol *symbol,ADDR obj_addr) {
4064  struct scope *scope;
4065 
4066  scope = symbol_read_owned_scope(symbol);
4067  if (!scope)
4068  return 0;
4069 
4070  return scope_contains_addr(scope,obj_addr);
4071 }
4072 
4073 /*
4074  * Given an IP (as an object-relative address), check and see if this
4075  * symbol is currently visible (in scope). To do this we, check if the
4076  * IP is in the symtab's range; or if it is in any child symtab's range
4077  * where no symbol in that symtab overrides the primary symbol name!
4078  */
4079 /*
4080 int symbol_visible_at_ip(struct symbol *symbol,ADDR ip) {
4081  struct symtab *symtab = symbol->symtab;
4082  struct range *range;
4083  int retval = 0;
4084  int i;
4085  gpointer data = NULL;
4086 
4087  if (SYMBOL_IS_TYPE(symbol)) {
4088  return 0;
4089  }
4090 
4091  // XXX: global check and return 1 if so?
4092 
4093  while (1) {
4094  data = g_hash_table_lookup(symtab->tab,symbol->name);
4095  range = &symtab->range;
4096  if (RANGE_IS_PC(range)) {
4097  if (range->r.a.lowpc <= ip && ip < range->r.a.highpc
4098  && (symtab == symbol->symtab || !data)) {
4099  retval = 1;
4100  break;
4101  }
4102  }
4103  else if (RANGE_IS_LIST(range)) {
4104  for (i = 0; i < range->r.rlist.len; ++i) {
4105  if (range->r.rlist.list[i]->start <= ip
4106  && ip < range->r.rlist.list[i]->end
4107  && (symtab == symbol->symtab || !data)) {
4108  retval = 1;
4109  break;
4110  }
4111  }
4112  if (retval)
4113  break;
4114  }
4115  else
4116  break;
4117  }
4118 
4119  return retval;
4120 }
4121 */
4122 
4123 struct symbol *symbol_get_one_member__int(struct symbol *symbol,char *member) {
4124  return __symbol_get_one_member__int(symbol,member,NULL);
4125 }
4126 
4127 struct symbol *symbol_get_one_member(struct symbol *symbol,char *member) {
4128  struct symbol *retval = __symbol_get_one_member__int(symbol,member,NULL);
4129 
4130  if (retval)
4131  RHOLD(retval,retval);
4132 
4133  return retval;
4134 }
4135 
4136 struct symbol *symbol_get_member(struct symbol *symbol,char *memberlist,
4137  const char *delim) {
4138  char *saveptr = NULL;
4139  struct symbol *retval = NULL;
4140  char *member;
4141  char *mlist = strdup(memberlist);
4142 
4143  retval = symbol;
4144 
4145  if (!delim)
4146  delim = DWDEBUG_DEF_DELIM;
4147 
4148  while ((member = strtok_r(!saveptr ? mlist : NULL,delim,&saveptr))) {
4149  retval = __symbol_get_one_member__int(retval,member,NULL);
4150  if (!retval)
4151  break;
4152  }
4153 
4154  free(mlist);
4155 
4156  if (retval)
4157  RHOLD(retval,retval);
4158 
4159  return retval;
4160 }
4161 
4162 struct symbol *symbol_get_inline_origin(struct symbol *symbol) {
4163  struct symbol *origin;
4164  struct symbol_inline *ii;
4165 
4166  ii = SYMBOLX_INLINE(symbol);
4167  if (!ii || !ii->origin)
4168  return NULL;
4169 
4170  origin = ii->origin;
4171 
4172  /*
4173  * There may be a chain of abstract origins, so we have to follow them!
4174  */
4175  while (1) {
4176  ii = SYMBOLX_INLINE(origin);
4177  /* If it is not abstract, then stop looking. */
4178  if (!ii || !ii->origin)
4179  break;
4180 
4181  /* Otherwise, if its origin's origin is abstract, keep going. */
4182  origin = ii->origin;
4183  }
4184 
4185  return origin;
4186 }
4187 
4188 /*
4189  * Skips const and volatile types, for now. Ok, skip typedefs too!
4190  */
4191 struct symbol *symbol_type_skip_qualifiers(struct symbol *type) {
4192  if (!SYMBOL_IS_TYPE(type))
4193  return NULL;
4194 
4195  while (type && type->type == SYMBOL_TYPE_TYPE
4196  && (SYMBOL_IST_VOL(type)
4197  || SYMBOL_IST_CONST(type)
4198  || SYMBOL_IST_TYPEDEF(type))) {
4199  type = type->datatype;
4200  }
4201 
4202  if (type) {
4203  SYMBOL_EXPAND_WARN(type);
4204  }
4205 
4206  return type;
4207 }
4208 
4209 struct symbol *symbol_type_skip_ptrs(struct symbol *type) {
4210  if (!SYMBOL_IS_TYPE(type))
4211  return NULL;
4212 
4213  while (type->type == SYMBOL_TYPE_TYPE && SYMBOL_IST_PTR(type)) {
4214  type = type->datatype;
4215  }
4216 
4217  if (type) {
4218  SYMBOL_EXPAND_WARN(type);
4219  }
4220 
4221  return type;
4222 }
4223 
4224 int symbol_type_is_char(struct symbol *type) {
4225  if (!SYMBOL_IS_TYPE(type))
4226  return 0;
4227 
4228  type = symbol_type_skip_qualifiers(type);
4229 
4230  if (SYMBOL_IST_BASE(type)
4231  && symbol_get_bytesize(type) == 1
4234  return 1;
4235 
4236  return 0;
4237 }
4238 
4239 unsigned int symbol_type_array_bytesize(struct symbol *type) {
4240  int size;
4241  GSList *gsltmp;
4242  void *elm;
4243 
4244  if (!SYMBOL_IS_TYPE(type))
4245  return 0;
4246 
4247  type = symbol_type_skip_qualifiers(type);
4248  if (!SYMBOL_IST_ARRAY(type))
4249  return 0;
4250  if (!SYMBOL_HAS_EXTRA(type))
4251  return 0;
4252 
4254 
4255  v_g_slist_foreach(SYMBOLX_SUBRANGES(type),gsltmp,elm) {
4256  vdebug(5,LA_DEBUG,LF_SYMBOL,"subrange length is %d\n",
4257  ((int)(uintptr_t)elm) + 1);
4258  size = size * (((int)(uintptr_t)elm) + 1);
4259  }
4260 
4261  vdebug(5,LA_DEBUG,LF_SYMBOL,"full array size is %d for array type %s\n",
4262  size,symbol_get_name(type));
4263 
4264  return size;
4265 }
4266 
4267 unsigned int symbol_type_full_bytesize(struct symbol *type) {
4268  if (!SYMBOL_IS_TYPE(type))
4269  return 0;
4270 
4271  type = symbol_type_skip_qualifiers(type);
4272 
4273  if (SYMBOL_IST_ARRAY(type))
4274  return symbol_type_array_bytesize(type);
4275  return symbol_get_bytesize(type);
4276 }
4277 
4278 #if 0
4279 int symbol_get_location_offset(struct symbol *symbol,OFFSET *offset_saveptr) {
4280  struct location *loc;
4281 
4282  if (!SYMBOL_IS_VAR(symbol))
4283  return -1;
4284 
4285  loc = SYMBOLX_VAR_LOC(symbol);
4286  if (loc && LOCATION_IS_M_OFFSET(loc)) {
4287  if (offset_saveptr)
4288  *offset_saveptr = LOCATION_OFFSET(loc);
4289  return 0;
4290  }
4291  return -1;
4292 }
4293 
4294 int symbol_get_location_addr(struct symbol *symbol,ADDR *addr_saveptr) {
4295  ADDR addr;
4296  struct location *loc;
4297 
4298  if (symbol->has_addr) {
4299  addr = symbol->addr;
4300  }
4301  else if (SYMBOL_IS_VAR(symbol)) {
4302  loc = SYMBOLX_VAR_LOC(symbol);
4303  if (!loc)
4304  return -1;
4305  addr = LOCATION_ADDR(loc);
4306  }
4307  else {
4308  return -1;
4309  }
4310 
4311  if (addr_saveptr)
4312  *addr_saveptr = addr;
4313 
4314  return 0;
4315 }
4316 #endif
4317 
4318 REFCNT symbol_release(struct symbol *symbol) {
4319  REFCNT retval;
4320  char *name = NULL;
4321  if (symbol_get_name(symbol))
4322  name = strdup(symbol_get_name(symbol));
4323  /*
4324  * WE DO NOT FREE symbols on release; our debugfile garbage
4325  * collector has to do this for us according to some policy!
4326  *
4327  * Actually, we only free dynamic symbols automatically on release!
4328  */
4329  if (symbol->issynthetic || symbol->isshared) {
4331  "dynamic/shared symbol %s//%s at %"PRIxSMOFFSET": ",
4332  SYMBOL_TYPE(symbol->type),symbol_get_name(symbol),symbol->ref);
4333  RPUT(symbol,symbol,symbol,retval);
4334  if (retval)
4335  vdebugc(10,LA_DEBUG,LF_SYMBOL," refcnt %d\n",retval);
4336  else
4337  vdebug(10,LA_DEBUG,LF_SYMBOL,"dynamic/shared symbol %s refcnt 0\n",name);
4338  }
4339  else {
4340  vdebug(10,LA_DEBUG,LF_SYMBOL,"symbol %s//%s at %"PRIxSMOFFSET": ",
4341  SYMBOL_TYPE(symbol->type),symbol_get_name(symbol),symbol->ref);
4342  RPUT(symbol,symbol,symbol,retval);
4343  //RPUTNF(symbol,symbol,retval);
4344  //retval = RPUT(symbol,symbol,symbol);
4345  if (retval)
4346  vdebugc(10,LA_DEBUG,LF_SYMBOL," refcnt %d\n",retval);
4347  else
4348  vdebug(10,LA_DEBUG,LF_SYMBOL,"symbol %s refcnt 0\n",name);
4349  }
4350  if (name)
4351  free(name);
4352 
4353  return retval;
4354 }
4355 
4356 void symbol_free_inline(struct symbol *symbol) {
4357  GSList *gsltmp;
4358  struct symbol *iisymbol;
4359  REFCNT trefcnt;
4360 
4361  SYMBOL_RX_INLINE(symbol,sii);
4362 
4363  if (!sii)
4364  return;
4365 
4366  /*
4367  * Also have to free any inline instance list.
4368  */
4369  if (sii->inline_instances) {
4370  v_g_slist_foreach(sii->inline_instances,gsltmp,iisymbol) {
4371  RPUT(iisymbol,symbol,symbol,trefcnt);
4372  }
4373  g_slist_free(sii->inline_instances);
4374  sii->inline_instances = NULL;
4375  }
4376 
4377  /*
4378  * Also have to free any inline instance's origin info that we copied.
4379  */
4380  if (symbol->isinlineinstance && sii->origin) {
4381  /*
4382  * NB NB NB: we cannot have objects referencing each other;
4383  * such objects might not get deleted.
4384  *
4385  * (See comments in common.h about ref usage.)
4386  */
4387  //RPUT(symbol->s.ii->origin,symbol,symbol,trefcnt);
4388 
4389  sii->origin = NULL;
4390 
4391  /*
4392  if (symbol->datatype) {
4393  RPUT(symbol->datatype,symbol,symbol,trefcnt);
4394  symbol->datatype = NULL;
4395  }
4396  */
4397  }
4398 
4399  free(sii);
4400 }
4401 
4402 void symbol_free_extra(struct symbol *symbol) {
4403  REFCNT trefcnt;
4404  GSList *gsltmp;
4405  struct symbol *m;
4406 
4407  if (!SYMBOL_HAS_EXTRA(symbol))
4408  return;
4409 
4410  if (SYMBOL_IS_ROOT(symbol)) {
4411  SYMBOL_RX_ROOT(symbol,sr);
4412  if (sr->compdirname && !sr->compdirname_nofree)
4413  free(sr->compdirname);
4414  if (sr->producer && !sr->producer_nofree)
4415  free(sr->producer);
4416  if (sr->language && !sr->language_nofree)
4417  free(sr->language);
4418  if (sr->scope) {
4419  if (sr->scope->symbol == symbol)
4420  sr->scope->symbol = NULL;
4421  RPUT(sr->scope,scope,symbol,trefcnt);
4422  }
4423 
4424  if (sr->priv) {
4425  if (sr->debugfile
4426  && sr->debugfile->ops
4427  && sr->debugfile->ops->symbol_root_priv_free)
4428  sr->debugfile->ops->symbol_root_priv_free(sr->debugfile,symbol);
4429  else
4430  free(sr->priv);
4431  }
4432  free(sr);
4433  }
4434  /* NB: remember to RPUT on all members, not just on the scopes. */
4435  else if (SYMBOL_IS_FUNC(symbol)) {
4436  SYMBOL_RX_FUNC(symbol,sf);
4437  if (sf->members) {
4438  v_g_slist_foreach(sf->members,gsltmp,m) {
4439  RPUT(m,symbol,symbol,trefcnt);
4440  }
4441  g_slist_free(sf->members);
4442  }
4443  if (sf->scope) {
4444  if (sf->scope->symbol == symbol)
4445  sf->scope->symbol = NULL;
4446  RPUT(sf->scope,scope,symbol,trefcnt);
4447  }
4448  if (sf->fbloc)
4449  location_free(sf->fbloc);
4450  if (sf->ii)
4451  symbol_free_inline(symbol);
4452  free(sf);
4453  }
4454  else if (SYMBOL_IS_VAR(symbol)) {
4455  SYMBOL_RX_VAR(symbol,sv);
4456  if (sv->loc)
4457  location_free(sv->loc);
4458  if (sv->constval && !symbol->constval_nofree)
4459  free(sv->constval);
4460  if (sv->ii)
4461  symbol_free_inline(symbol);
4462  free(sv);
4463  }
4464  else if (SYMBOL_IS_LABEL(symbol)) {
4465  SYMBOL_RX_LABEL(symbol,sl);
4466  if (sl->ii)
4467  symbol_free_inline(symbol);
4468  free(sl);
4469  }
4470  else if (SYMBOL_IS_BLOCK(symbol)) {
4471  SYMBOL_RX_BLOCK(symbol,sb);
4472  if (sb->members) {
4473  v_g_slist_foreach(sb->members,gsltmp,m) {
4474  RPUT(m,symbol,symbol,trefcnt);
4475  }
4476  g_slist_free(sb->members);
4477  }
4478  if (sb->scope) {
4479  if (sb->scope->symbol == symbol)
4480  sb->scope->symbol = NULL;
4481  RPUT(sb->scope,scope,symbol,trefcnt);
4482  }
4483  if (sb->ii)
4484  symbol_free_inline(symbol);
4485  free(sb);
4486  }
4487  else if (SYMBOL_IST_ARRAY(symbol)) {
4488  if (SYMBOLX_SUBRANGES(symbol))
4489  g_slist_free(SYMBOLX_SUBRANGES(symbol));
4490  }
4491  else if (SYMBOL_IST_ENUM(symbol)) {
4492  if (symbol->extra.members) {
4493  v_g_slist_foreach(symbol->extra.members,gsltmp,m) {
4494  RPUT(m,symbol,symbol,trefcnt);
4495  }
4496  g_slist_free(symbol->extra.members);
4497  }
4498  }
4499  else if (SYMBOL_IST_CONTAINER(symbol)) {
4500  SYMBOL_RX_CONTAINER(symbol,sc);
4501  if (sc->members) {
4502  v_g_slist_foreach(sc->members,gsltmp,m) {
4503  RPUT(m,symbol,symbol,trefcnt);
4504  }
4505  g_slist_free(sc->members);
4506  }
4507  if (sc->scope) {
4508  if (sc->scope->symbol == symbol)
4509  sc->scope->symbol = NULL;
4510  RPUT(sc->scope,scope,symbol,trefcnt);
4511  }
4512  free(sc);
4513  }
4514 }
4515 
4516 REFCNT symbol_free(struct symbol *symbol,int force) {
4517  int retval = symbol->refcnt;
4518  REFCNT trefcnt;
4519 
4520  if (symbol->refcnt) {
4521  if (!force) {
4522  verror("cannot free (%d refs) ",symbol->refcnt);
4523  ERRORDUMPSYMBOL_NL(symbol);
4524  return symbol->refcnt;
4525  }
4526  else {
4527  vwarn("forced free (%d refs) ",symbol->refcnt);
4528  ERRORDUMPSYMBOL_NL(symbol);
4529  }
4530  }
4531 
4532  if (symbol->name)
4533  vdebug(5,LA_DEBUG,LF_SYMBOL,"freeing symbol %s//%s at %"PRIxSMOFFSET"\n",
4534  SYMBOL_TYPE(symbol->type),symbol->name,symbol->ref);
4535  else
4536  vdebug(5,LA_DEBUG,LF_SYMBOL,"freeing symbol %s//(null) at %"PRIxSMOFFSET"\n",
4537  SYMBOL_TYPE(symbol->type),symbol->ref);
4538 
4539  /*
4540  * If this symbol refers to a type from some other CU, release on
4541  * that type.
4542  */
4543  if (symbol->usesshareddatatype && symbol->datatype) {
4544  RPUT(symbol->datatype,symbol,symbol,trefcnt);
4545  symbol->usesshareddatatype = 0;
4546  symbol->datatype = NULL;
4547  }
4548  /* If this is a dynamic symbol, we have to recursively release any
4549  * dynamic symbols it points to.
4550  */
4551  else if (symbol->issynthetic && symbol->datatype) {
4552  RPUT(symbol->datatype,symbol,symbol,trefcnt);
4553  symbol->datatype = NULL;
4554  }
4555 
4556  /*
4557  * If we copied definition info from some other symbol, release that
4558  * stuff before we do anything else.
4559  */
4560  if (symbol->decldefined) {
4561  if (symbol->decltypedefined && symbol->datatype) {
4562  symbol->decltypedefined = 0;
4563  RPUT(symbol->datatype,symbol,symbol,trefcnt);
4564  symbol->datatype = NULL;
4565  }
4566 
4567  symbol->decldefined = 0;
4568  /*
4569  * See the comments in struct debugfile::decldefnsused ; thus,
4570  * we just NULL this out. The definition symbol "owns" this
4571  * pointer, and it will be freed at the conclusion of
4572  * debugfile_free.
4573  */
4574  symbol->extra.exists = NULL;
4575  }
4576 
4577  if (SYMBOL_HAS_EXTRA(symbol))
4578  symbol_free_extra(symbol);
4579 
4580  if (symbol->name && !symbol->name_nofree) {
4581  vdebug(5,LA_DEBUG,LF_SYMBOL,"freeing name %s\n",symbol->name);
4582  free(symbol->name);
4583  }
4584  symbol->name = NULL;
4585 
4586  vdebug(5,LA_DEBUG,LF_SYMBOL,"freeing %p\n",symbol);
4587  free(symbol);
4588 
4589  return retval;
4590 }
4591 
4595 struct lsymbol *lsymbol_create(struct symbol *symbol,
4596  struct array_list *chain) {
4597  struct lsymbol *lsymbol = (struct lsymbol *)malloc(sizeof(struct lsymbol));
4598 
4599  memset(lsymbol,0,sizeof(struct lsymbol));
4600  lsymbol->symbol = symbol;
4601  lsymbol->chain = chain;
4602  lsymbol->refcnt = 0;
4603 
4604  if (chain)
4605  lsymbol_hold_int(lsymbol);
4606 
4607  return lsymbol;
4608 }
4609 
4610 void lsymbol_append(struct lsymbol *lsymbol,struct symbol *symbol) {
4611  if (!lsymbol->chain)
4612  lsymbol->chain = array_list_create(1);
4613 
4614  /* Add the symbol to the end of the chain, and ... */
4615  array_list_append(lsymbol->chain,symbol);
4616 
4617  /* Update the "deepest nested symbol" pointer to point to it. */
4618  lsymbol->symbol = symbol;
4619 
4620  RHOLD(symbol,lsymbol);
4621 }
4622 
4623 void lsymbol_prepend(struct lsymbol *lsymbol,struct symbol *symbol) {
4624  if (!lsymbol->chain)
4625  lsymbol->chain = array_list_create(1);
4626 
4627  array_list_prepend(lsymbol->chain,symbol);
4628 
4629  RHOLD(symbol,lsymbol);
4630 }
4631 
4633  struct symbol *member) {
4634  struct array_list *chain;
4635  struct lsymbol *ls;
4636 
4637  chain = array_list_clone(parent->chain,1);
4638  array_list_append(chain,member);
4639  ls = lsymbol_create(member,chain);
4640 
4641  lsymbol_hold_int(ls);
4642 
4643  return ls;
4644 }
4645 
4647  struct symbol *member) {
4648  struct lsymbol *retval;
4649 
4650  retval = lsymbol_create_from_member__int(parent,member);
4651  if (retval)
4652  RHOLD(retval,retval);
4653 
4654  return retval;
4655 }
4656 
4657 struct lsymbol *lsymbol_create_from_symbol__int(struct symbol *symbol) {
4658  struct array_list *chain;
4659  struct lsymbol *ls;
4660  struct symbol *s = symbol;
4661  struct symbol *parent;
4662 
4663  if (!s)
4664  return NULL;
4665 
4666  chain = array_list_create(1);
4667  ls = lsymbol_create(s,chain);
4668 
4669  again:
4670  lsymbol_prepend(ls,s);
4671  if (SYMBOL_IS_TYPE(s)) {
4672  goto out;
4673  }
4674  else if (SYMBOL_IS_VAR(s)
4675  && (symbol->isenumval || symbol->isparam || symbol->ismember)) {
4676  if (symbol->isenumval) {
4677  s = s->datatype;
4678  goto again;
4679  }
4680  else if (s->isparam || s->ismember) {
4681  parent = symbol_find_parent(s);
4682  if (s->isparam && SYMBOL_IS_FUNC(parent)) {
4683  s = parent;
4684  goto again;
4685  }
4686  else if (s->ismember && SYMBOL_IST_STUN(parent)) {
4687  s = parent;
4688  goto again;
4689  }
4690  else {
4691  /* if (!SYMBOL_IS_FULL(s)
4692  * || (s->isparam && SYMBOL_IST_FUNC(parent))
4693  * || (s->ismember)) {
4694  */
4695  goto out;
4696  }
4697  }
4698  goto out;
4699  }
4700  else if (SYMBOL_IS_VAR(s) || SYMBOL_IS_FUNC(s)) {
4701  /* If the symtab the var/function is on is not the root, trace
4702  * up until we find either the root symtab, or a function
4703  * symtab. If we find a function's symtab, we keep going up and
4704  * look for more functions. When we hit the root symtab, we're
4705  * done, of course.
4706  */
4707  parent = symbol_find_parent(s);
4708  if (parent && !SYMBOL_IS_ROOT(parent)) {
4709  s = parent;
4710  goto again;
4711  }
4712  else {
4713  goto out;
4714  }
4715  }
4716  /* Just fall out */
4717 
4718  out:
4719  return ls;
4720 }
4721 
4722 struct lsymbol *lsymbol_create_from_symbol(struct symbol *symbol) {
4723  struct lsymbol *retval;
4724 
4725  retval = lsymbol_create_from_symbol__int(symbol);
4726  if (retval)
4727  RHOLD(retval,retval);
4728 
4729  return retval;
4730 }
4731 
4733  if (lsymbol->symbol)
4734  return symbol_get_name(lsymbol->symbol);
4735  return NULL;
4736 }
4737 
4738 struct symbol *lsymbol_get_symbol(struct lsymbol *lsymbol) {
4739  return lsymbol->symbol;
4740 }
4741 
4743  int i = array_list_len(lsymbol->chain) - 1;
4744  struct symbol *s = lsymbol->symbol;
4745 
4746  for ( ; i >= 0; --i) {
4747  s = (struct symbol *)array_list_item(lsymbol->chain,i);
4748  if (!s->isinlineinstance)
4749  break;
4750  }
4751  if (s->isinlineinstance)
4752  return NULL;
4753 
4754  return s;
4755 }
4756 
4758  int i;
4759  struct symbol *s = NULL;
4760  struct symbol *ps = NULL;
4761  struct lsymbol *ls;
4762  struct array_list *chain;
4763 
4764  if (!lsymbol->symbol->isinlineinstance)
4765  return NULL;
4766 
4767  chain = array_list_create(array_list_len(lsymbol->chain) - 1);
4768 
4769  for (i = 0; i < array_list_len(lsymbol->chain); ++i) {
4770  s = (struct symbol *)array_list_item(lsymbol->chain,i);
4771  if (!s->isinlineinstance)
4772  array_list_append(chain,s);
4773  else
4774  break;
4775  ps = s;
4776  }
4777 
4778  if (i == 0) {
4779  array_list_free(chain);
4780  return NULL;
4781  }
4782 
4783  ls = lsymbol_create(ps,chain);
4784 
4785  return ls;
4786 }
4787 
4789  struct lsymbol *retval;
4790 
4791  retval = lsymbol_create_noninline__int(lsymbol);
4792  if (retval)
4793  RHOLD(retval,retval);
4794 
4795  return retval;
4796 }
4797 
4799  int i;
4800  for (i = 0; i < array_list_len(lsymbol->chain); ++i) {
4801  RHOLD((struct symbol *)array_list_item(lsymbol->chain,i),lsymbol);
4802  }
4803 }
4804 
4806  REFCNT refcnt;
4807  RPUT(lsymbol,lsymbol,lsymbol,refcnt);
4808  return refcnt;
4809 }
4810 
4811 REFCNT lsymbol_free(struct lsymbol *lsymbol,int force) {
4812  int retval = lsymbol->refcnt;
4813  int i;
4814  REFCNT trefcnt;
4815 
4816  if (lsymbol->refcnt) {
4817  if (!force) {
4818  vwarn("cannot free (%d refs) ",lsymbol->refcnt);
4819  ERRORDUMPLSYMBOL_NL(lsymbol);
4820  return lsymbol->refcnt;
4821  }
4822  else {
4823  verror("forced free (%d refs) ",lsymbol->refcnt);
4824  ERRORDUMPLSYMBOL(lsymbol);
4825  }
4826  }
4827 
4828  if (lsymbol->chain) {
4829  for (i = 0; i < array_list_len(lsymbol->chain); ++i) {
4830  RPUT((struct symbol *)array_list_item(lsymbol->chain,i),symbol,
4831  lsymbol,trefcnt);
4832  }
4833  array_list_free(lsymbol->chain);
4834  }
4835  else if (lsymbol->symbol) {
4836  RPUT(lsymbol->symbol,symbol,lsymbol,trefcnt);
4837  }
4838  free(lsymbol);
4839 
4840  return retval;
4841 }
4842 
4848  gpointer value,gpointer userdata) {
4849  struct dump_info *ud = (struct dump_info *)userdata;
4850  struct array_list *list = (struct array_list *)value;
4851  struct symbol *symbol;
4852  int i;
4853 
4854  array_list_foreach(list,i,symbol) {
4855  symbol_dump(symbol,ud);
4856  fprintf(ud->stream,"\n");
4857  }
4858 }
4859 
4860 void g_hash_foreach_dump_symbol(gpointer key __attribute__((unused)),
4861  gpointer value,gpointer userdata) {
4862  struct dump_info *ud = (struct dump_info *)userdata;
4863  symbol_dump((struct symbol *)value,ud);
4864  fprintf(ud->stream,"\n");
4865 }
4866 
4867 #if 0
4868 void g_hash_foreach_dump_duplist(gpointer key,gpointer value,gpointer userdata) {
4869  struct dump_info *ud = (struct dump_info *)userdata;
4870  struct array_list *duplist = (struct array_list *)value;
4871  char *name = (char *)key;
4872  int i;
4873  struct dump_info udn;
4874 
4875  udn.prefix = malloc(strlen(ud->prefix)+2+1);
4876  sprintf(udn.prefix,"%s%s",ud->prefix," ");
4877  udn.stream = ud->stream;
4878  udn.meta = ud->meta;
4879  udn.detail = ud->detail;
4880 
4881  fprintf(ud->stream,"%sduplist(%s):\n",ud->prefix,name);
4882  for (i = 0; i < array_list_len(duplist); ++i) {
4883  symbol_dump((struct symbol *)array_list_item(duplist,i),&udn);
4884  fprintf(ud->stream,"\n");
4885  }
4886  fprintf(ud->stream,"\n");
4887  free(udn.prefix);
4888 }
4889 #endif
4890 
4891 void clrange_scope_name_dumper(Word_t start,Word_t end,
4892  struct dump_info *ud,void *data) {
4893  struct scope *scope = (struct scope *)data;
4894  if (scope && scope->symbol)
4895  fprintf(ud->stream,"%s",symbol_get_name(scope->symbol));
4896  return;
4897 }
4898 
4899 void clrange_symbol_name_dumper(Word_t start,Word_t end,
4900  struct dump_info *ud,void *data) {
4901  struct symbol *symbol = (struct symbol *)data;
4902  if (symbol)
4903  fprintf(ud->stream,"%s",symbol_get_name(symbol));
4904  return;
4905 }
4906 
4907 void debugfile_dump(struct debugfile *debugfile,struct dump_info *ud,
4908  int types,int globals,int symtabs,int elfsymtab,
4909  int doranges) {
4910  char *p = "";
4911  char *np1, *np2;
4912  struct dump_info udn;
4913  int s1,s2,s3,s4;
4914 
4915  if (ud->prefix) {
4916  p = ud->prefix;
4917  np1 = malloc(strlen(p) + 1 + 2);
4918  np2 = malloc(strlen(p) + 1 + 4);
4919  sprintf(np1,"%s%s",p," ");
4920  sprintf(np2,"%s%s",p," ");
4921  }
4922  else {
4923  np1 = " ";
4924  np2 = " ";
4925  }
4926  udn.prefix = np2;
4927  udn.stream = ud->stream;
4928  udn.meta = ud->meta;
4929  udn.detail = ud->detail;
4930 
4931  fprintf(ud->stream,"%sdebugfile(%s):\n",p,debugfile->filename);
4932  fprintf(ud->stream,"%s flags: 0x%x\n",p,
4933  debugfile->flags);
4934  fprintf(ud->stream,"%s refcnt: %d\n",p,debugfile->refcnt);
4935  fprintf(ud->stream,"%s types: (%d)\n",p,g_hash_table_size(debugfile->types));
4936  if (types)
4937  g_hash_table_foreach(debugfile->types,g_hash_foreach_dump_symbol,&udn);
4938  fprintf(ud->stream,"%s shared_types: (%d)\n",
4939  p,g_hash_table_size(debugfile->shared_types));
4940  if (types)
4941  g_hash_table_foreach(debugfile->shared_types,
4943  fprintf(ud->stream,"%s globals: (%d)\n",
4944  p,g_hash_table_size(debugfile->globals));
4945  if (globals)
4946  g_hash_table_foreach(debugfile->globals,g_hash_foreach_dump_symbol,&udn);
4947  fprintf(ud->stream,"%s root srcfiles: (%d)\n",
4948  p,g_hash_table_size(debugfile->srcfiles));
4949  //ud->prefix = np1;
4950  if (symtabs) {
4951  g_hash_table_foreach(debugfile->srcfiles,g_hash_foreach_dump_symbol,&udn);
4952  if (g_hash_table_size(debugfile->srcfiles))
4953  fprintf(ud->stream,"\n");
4954  }
4955  fprintf(ud->stream,"%s multi-use srcfile symtabs: (%d)\n",
4956  p,g_hash_table_size(debugfile->srcfiles_multiuse));
4957  if (symtabs) {
4958  g_hash_table_foreach(debugfile->srcfiles_multiuse,
4960  if (g_hash_table_size(debugfile->srcfiles_multiuse))
4961  fprintf(ud->stream,"\n");
4962  }
4963  if (doranges) {
4964  fprintf(ud->stream,"%s ranges:\n",p);
4965  clrange_dump(debugfile->ranges,&udn,
4967  }
4968  if (debugfile->binfile
4969  && debugfile->binfile->root
4970  && symbol_read_owned_scope(debugfile->binfile->root)) {
4972  &s1,&s2,&s3,&s4);
4973  fprintf(ud->stream,
4974  "%s binfile root: (tab=%d,anon=%d,dup=%d,subscopes=%d)\n",
4975  p,s1,s2,s3,s4);
4976  if (elfsymtab) {
4977  symbol_dump(debugfile->binfile->root,&udn);
4978  fprintf(ud->stream,"\n");
4979  }
4980  if (doranges) {
4981  fprintf(ud->stream,"%s binfile root ranges:\n",p);
4982  clrange_dump(debugfile->binfile->ranges,&udn,
4984  }
4985  }
4986  else
4987  fprintf(ud->stream,
4988  "%s binfile root: (tab=%d,anon=%d,dup=%d)\n",
4989  p,0,0,0);
4990  if (debugfile->binfile_pointing
4991  && debugfile->binfile_pointing->root
4992  && symbol_read_owned_scope(debugfile->binfile->root)) {
4994  &s1,&s2,&s3,&s4);
4995  fprintf(ud->stream,
4996  "%s binfile_pointing root: (tab=%d,anon=%d,dup=%d,subscopes=%d)\n",
4997  p,s1,s2,s3,s4);
4998  if (elfsymtab) {
4999  symbol_dump(debugfile->binfile_pointing->root,&udn);
5000  fprintf(ud->stream,"\n");
5001  }
5002  if (doranges) {
5003  fprintf(ud->stream,"%s binfile_pointing root ranges:\n",p);
5004  clrange_dump(debugfile->binfile_pointing->ranges,&udn,
5006  }
5007  }
5008  else
5009  fprintf(ud->stream,
5010  "%s binfile_pointing root: (tab=%d,anon=%d,dup=%d)\n",
5011  p,0,0,0);
5012 
5013  if (ud->prefix) {
5014  free(np1);
5015  free(np2);
5016  }
5017 }
5018 
5019 void symbol_root_dump(struct symbol *symbol,struct dump_info *ud) {
5020  SYMBOL_RX_ROOT(symbol,sr);
5021 
5022  fprintf(ud->stream,"%s",symbol_get_name(symbol));
5023 
5024  fprintf(ud->stream," (compdirname=%s,producer=%s,language=%s (%d))",
5025  sr->compdirname,sr->producer,sr->language,sr->lang_code);
5026 
5027  if (ud->detail && sr->scope) {
5028  fprintf(ud->stream," {\n");
5029  scope_dump(sr->scope,ud);
5030  fprintf(ud->stream,"%s}\n",ud->prefix);
5031  }
5032  else
5033  fprintf(ud->stream," { }\n");
5034 }
5035 
5036 void symbol_label_dump(struct symbol *symbol,struct dump_info *ud) {
5037  fprintf(ud->stream,"%s @@ 0x%"PRIxADDR,
5038  symbol_get_name(symbol),symbol_get_addr(symbol));
5039 }
5040 
5041 void symbol_block_dump(struct symbol *symbol,struct dump_info *ud) {
5042  struct scope *scope;
5043  struct dump_info udn = {
5044  .stream = ud->stream,
5045  .prefix = "",
5046  .detail = ud->detail,
5047  .meta = ud->meta,
5048  };
5049 
5050  fprintf(ud->stream,"%s (@@ 0x%"PRIxADDR")",
5051  symbol_get_name(symbol),symbol_get_addr(symbol));
5052  if (ud->detail) {
5053  scope = symbol_read_owned_scope(symbol);
5054  if (scope)
5055  scope_dump(scope,&udn);
5056  }
5057 }
5058 
5059 void symbol_var_dump(struct symbol *symbol,struct dump_info *ud) {
5060  GSList *gsltmp;
5061  struct symbol *iisymbol;
5062  struct symbol *datatype;
5063  struct dump_info udn = {
5064  .stream = ud->stream,
5065  .prefix = ud->prefix,
5066  .detail = 0,
5067  .meta = 0,
5068  };
5069  int i;
5070  int sz;
5071 
5072  datatype = symbol_get_datatype_real(symbol);
5073 
5074  if (ud->detail) {
5075  if (datatype) {
5076  symbol_type_dump(datatype,&udn);
5077  }
5078  else if (symbol->datatype_ref)
5079  fprintf(ud->stream,"ref%"PRIxSMOFFSET,symbol->datatype_ref);
5080  }
5081  /* all variables are named, but not all members of structs/unions! */
5082  /* well, inlined params aren't named either. */
5083  SYMBOL_RX_INLINE(symbol,sii);
5084  if (symbol->isinlineinstance && symbol->isparam) {
5085  /* Only print a space if we printed the var's type above! */
5086  if (ud->detail)
5087  fprintf(ud->stream," ");
5088 
5089  if (sii) {
5090  if (sii->origin) {
5091  fprintf(ud->stream,"INLINED_PARAM(");
5092  symbol_var_dump(sii->origin,&udn);
5093  fprintf(ud->stream,")");
5094  }
5095  else
5096  fprintf(ud->stream,"INLINED_ANON_PARAM()");
5097  }
5098  else {
5099  fprintf(ud->stream,"INLINED_PARAM(<UNK>)");
5100  }
5101  }
5102  else if (symbol->isinlineinstance) {
5103  /* Only print a space if we printed the var's type above! */
5104  if (ud->detail)
5105  fprintf(ud->stream," ");
5106 
5107  if (sii) {
5108  if (sii->origin) {
5109  fprintf(ud->stream,"INLINED_INSTANCE(");
5110  symbol_var_dump(sii->origin,&udn);
5111  fprintf(ud->stream,") (%s)",symbol_get_name_orig(symbol));
5112  }
5113  else
5114  fprintf(ud->stream,"INLINED_ANON_INSTANCE(%s)",
5115  symbol_get_name(symbol));
5116  }
5117  else {
5118  fprintf(ud->stream,"INLINED_INSTANCE(%s)",
5119  symbol_get_name_orig(symbol));
5120  }
5121  }
5122  else if (symbol->name) {
5123  /* Only print a space if we printed the var's type above! */
5124  if (ud->detail)
5125  fprintf(ud->stream," ");
5126 
5127  fprintf(ud->stream,"%s",symbol_get_name(symbol));
5128  }
5129 
5130  if (symbol->size_is_bits) {
5131  /* this is a bitfield */
5132  fprintf(ud->stream,":%hd(%hd)(ct %d B)",
5133  symbol_get_bitsize(symbol),symbol_get_bitoffset(symbol),
5134  symbol_get_bitctbytes(symbol));
5135  }
5136  if (symbol->isenumval && SYMBOLX_VAR_CONSTVAL(symbol)) {
5137  // XXX fix type printing -- this *is* a malloc'd constval
5138  fprintf(ud->stream," = %d",*((int *)SYMBOLX_VAR_CONSTVAL(symbol)));
5139  }
5140 
5141  if (ud->meta
5142  && (symbol->srcline || symbol->isexternal || symbol->isdeclaration
5143  || symbol->decldefined || symbol->isdeclinline
5144  || symbol->isinlined || (sii && sii->inline_instances))) {
5145  fprintf(ud->stream," (");
5146  if (!symbol->isparam && !symbol->ismember) {
5147  if (symbol->isexternal)
5148  fputs("external,",ud->stream);
5149  if (symbol->isdeclaration)
5150  fputs("isdecl,",ud->stream);
5151  if (symbol->decldefined)
5152  fputs("decldefined,",ud->stream);
5153  if (symbol->isdeclinline)
5154  fputs("declinline,",ud->stream);
5155  if (symbol->isinlined)
5156  fputs("inlined,",ud->stream);
5157  }
5158  if (symbol->srcline != 0)
5159  fprintf(ud->stream,"line=%d,",symbol->srcline);
5160  if (sii && sii->inline_instances) {
5161  fprintf(ud->stream,"inlineinstances=(");
5162  v_g_slist_foreach(sii->inline_instances,gsltmp,iisymbol) {
5163  if (iisymbol->has_addr)
5164  fprintf(ud->stream,"0x%"PRIxADDR",",
5165  symbol_get_addr(iisymbol));
5166  else
5167  fprintf(ud->stream,"ref%"PRIxSMOFFSET",",
5168  iisymbol->ref);
5169  }
5170  fprintf(ud->stream,")");
5171  }
5172  fprintf(ud->stream,")");
5173  }
5174 
5175  if (ud->detail) {
5176  if (SYMBOLX_VAR_LOC(symbol)
5177  && !(LOCATION_IS_ADDR(SYMBOLX_VAR_LOC(symbol))
5178  && symbol->has_addr
5179  && symbol->addr == LOCATION_ADDR(SYMBOLX_VAR_LOC(symbol)))) {
5180  fprintf(ud->stream," @@ ");
5181  location_dump(SYMBOLX_VAR_LOC(symbol),ud);
5182  }
5183 
5184  if (SYMBOLX_VAR_CONSTVAL(symbol)) {
5185  sz = symbol_type_full_bytesize(datatype);
5186  fprintf(ud->stream," @@ CONST(%d,",sz);
5187  for (i = 0; i < sz; ++i)
5188  fprintf(ud->stream,"%02hhx",
5189  ((char *)SYMBOLX_VAR_CONSTVAL(symbol))[sz - 1 - i]);
5190  fprintf(ud->stream,")");
5191  }
5192 
5193  if (symbol->has_addr)
5194  fprintf(ud->stream," @@ 0x%"PRIxADDR,symbol_get_addr(symbol));
5195 
5196  if (symbol->size_is_bytes)
5197  fprintf(ud->stream," (%d B)",symbol_get_bytesize(symbol));
5198  else if (symbol->size_is_bits)
5199  fprintf(ud->stream," (%d b)",symbol_get_bitsize(symbol));
5200  }
5201 }
5202 
5203 void symbol_function_dump(struct symbol *symbol,struct dump_info *ud) {
5204  struct symbol *datatype;
5205  GSList *members;
5206  GSList *gsltmp;
5207  struct symbol *member;
5208  struct symbol *iisymbol;
5209  int i = 0;
5210  struct dump_info udn = {
5211  .stream = ud->stream,
5212  .prefix = ud->prefix,
5213  .detail = 0,
5214  .meta = 0,
5215  };
5216  struct dump_info udn2 = {
5217  .stream = ud->stream,
5218  .prefix = "",
5219  .detail = ud->detail,
5220  .meta = ud->meta,
5221  };
5222  struct dump_info udn3 = {
5223  .stream = ud->stream,
5224  .prefix = "",
5225  .detail = 0,
5226  .meta = 0,
5227  };
5228 
5229  SYMBOL_RX_INLINE(symbol,sii);
5230  SYMBOL_RX_FUNC(symbol,sf);
5231 
5232  datatype = symbol_get_datatype_real(symbol);
5233 
5234  if (ud->detail) {
5235  if (datatype) {
5236  symbol_type_dump(datatype,&udn);
5237  fprintf(ud->stream," ");
5238  }
5239  else if (symbol->datatype_ref)
5240  fprintf(ud->stream,"ref%"PRIxSMOFFSET" ",symbol->datatype_ref);
5241  }
5242  if (symbol->isinlineinstance) {
5243  if (sii) {
5244  if (sii->origin) {
5245  fprintf(ud->stream,"INLINED_FUNC(");
5246  symbol_var_dump(sii->origin,&udn);
5247  fprintf(ud->stream,") (%s)",symbol_get_name_orig(symbol));
5248  }
5249  else
5250  fprintf(ud->stream,"INLINED_ANON_FUNC() (%s)",
5251  symbol_get_name_orig(symbol));
5252  }
5253  else {
5254  fprintf(ud->stream,"INLINED_FUNC(<UNK>)");
5255  }
5256  }
5257  else
5258  fprintf(ud->stream,"%s",symbol_get_name(symbol));
5259  if (ud->detail) {
5260  fprintf(ud->stream," (");
5261 
5262  members = SYMBOLX_MEMBERS(symbol);
5263  i = 0;
5264  v_g_slist_foreach(members,gsltmp,member) {
5265  if (likely(i > 0))
5266  fprintf(ud->stream,", ");
5267  symbol_var_dump(member,ud);
5268  ++i;
5269  }
5270  if (symbol->has_unspec_params)
5271  fprintf(ud->stream,"...");
5272 
5273  fprintf(ud->stream,")");
5274  }
5275 
5276  if (ud->meta) {
5277  fputs(" (",ud->stream);
5278  if (symbol->isexternal)
5279  fputs("external,",ud->stream);
5280  if (symbol->isexternal)
5281  fputs("prototyped,",ud->stream);
5282  if (symbol->isdeclaration)
5283  fputs("decl,",ud->stream);
5284  if (symbol->decldefined)
5285  fputs("decldefined,",ud->stream);
5286  if (symbol->isdeclinline)
5287  fputs("declinline,",ud->stream);
5288  if (symbol->isinlined)
5289  fputs("inlined,",ud->stream);
5290  if (sf && sf->fbloc) {
5291  fputs("frame_base=",ud->stream);
5292  location_dump(sf->fbloc,&udn2);
5293  fputs(",",ud->stream);
5294  }
5295  if (symbol->srcline != 0)
5296  fprintf(ud->stream,"line=%d,",symbol->srcline);
5297 
5298  if (sii && sii->inline_instances) {
5299  fputs("inlineinstances=(",ud->stream);
5300  v_g_slist_foreach(sii->inline_instances,gsltmp,iisymbol) {
5301  if (iisymbol->has_addr)
5302  fprintf(ud->stream,"0x%"PRIxADDR",",
5303  symbol_get_addr(iisymbol));
5304  else
5305  fprintf(ud->stream,"ref%"PRIxSMOFFSET",",
5306  iisymbol->ref);
5307  }
5308  fputs(")",ud->stream);
5309  }
5310  fputs(")",ud->stream);
5311  }
5312 
5313  if (ud->detail) {
5314  if (symbol->has_addr)
5315  fprintf(ud->stream," @@ 0x%"PRIxADDR,symbol_get_addr(symbol));
5316  if (symbol->size_is_bytes)
5317  fprintf(ud->stream," (%d B)",symbol_get_bytesize(symbol));
5318  else if (symbol->size_is_bits)
5319  fprintf(ud->stream," (%d b)",symbol_get_bitsize(symbol));
5320 
5321  if (sf && sf->scope) {
5322  fputs(" ",ud->stream);
5323  scope_dump(sf->scope,&udn3);
5324  }
5325  }
5326 }
5327 
5328 void symbol_type_dump(struct symbol *symbol,struct dump_info *ud) {
5329  struct symbol *tmp;
5330  GSList *members;
5331  struct symbol *member;
5332  struct symbol *member_datatype;
5333  GSList *gsltmp;
5334  void *elm;
5335  int i = 0;
5336  char *ss;
5337  struct dump_info udn = {
5338  .stream = ud->stream,
5339  .prefix = ud->prefix,
5340  .detail = 0,
5341  .meta = 0,
5342  };
5343 
5344  if (!symbol) {
5345  fprintf(ud->stream,"<UNK>");
5346  return;
5347  }
5348 
5349  switch (symbol->datatype_code) {
5350  case DATATYPE_VOID:
5351  fprintf(ud->stream,"void");
5352  break;
5353  case DATATYPE_ARRAY:
5355  if (SYMBOLX_SUBRANGES(symbol)) {
5356  fprintf(ud->stream," ");
5357  v_g_slist_foreach(SYMBOLX_SUBRANGES(symbol),gsltmp,elm) {
5358  fprintf(ud->stream,"[%d]",((int)(uintptr_t)elm) + 1);
5359  }
5360  }
5361  else {
5362  fprintf(ud->stream,"[<UNK>]");
5363  }
5364  break;
5365  case DATATYPE_CONST:
5366  fprintf(ud->stream,"const ");
5368  break;
5369  case DATATYPE_VOL:
5370  fprintf(ud->stream,"volatile ");
5372  break;
5373  case DATATYPE_STRUCT:
5374  case DATATYPE_UNION:
5375  case DATATYPE_CLASS:
5376  case DATATYPE_NAMESPACE:
5377  ss = "struct";
5378  if (SYMBOL_IST_UNION(symbol))
5379  ss = "union";
5380  else if (SYMBOL_IST_CLASS(symbol))
5381  ss = "class";
5382  else if (SYMBOL_IST_NAMESPACE(symbol))
5383  ss = "namespace";
5384  if (!symbol->name)
5385  fprintf(ud->stream,"%s",ss);
5386  else
5387  fprintf(ud->stream,"%s",symbol->name);
5388  if (ud->meta) {
5389  if (symbol->size_is_bytes)
5390  fprintf(ud->stream," (%d B)",symbol->size.bytes);
5391  else if (symbol->size_is_bits)
5392  fprintf(ud->stream," (%d b)",symbol->size.bits);
5393  if (symbol->srcline != 0)
5394  fprintf(ud->stream," (line=%d)",symbol->srcline);
5395  }
5396  if (ud->detail && SYMBOL_HAS_EXTRA(symbol)) {
5397  fprintf(ud->stream," { ");
5398 
5399  members = SYMBOLX_MEMBERS(symbol);
5400  i = 0;
5401  v_g_slist_foreach(members,gsltmp,member) {
5402  if (likely(i > 0))
5403  fprintf(ud->stream,"; ");
5404 
5405  /* NOTE: C structs/unions can have members of the same
5406  * type as the parent struct -- so don't recurse if this
5407  * is true! -- OR if it's a pointer chain back to the struct.
5408  */
5409  member_datatype = symbol_get_datatype_real(member);
5410  if (member_datatype == symbol) {
5411  symbol_var_dump(member,&udn);
5412  }
5413  else if (member_datatype
5414  && SYMBOL_IST_STUN(member_datatype)
5415  && !member_datatype->name) {
5416  symbol_type_dump(member_datatype,ud);
5417 
5418  if (ud->detail && SYMBOLX_VAR_LOC(member)) {
5419  fprintf(ud->stream," @@ ");
5420  location_dump(SYMBOLX_VAR_LOC(member),ud);
5421  }
5422 
5423  if (SYMBOLX_VAR_CONSTVAL(member))
5424  fprintf(ud->stream," @@ CONST(%p)",
5425  SYMBOLX_VAR_CONSTVAL(member));
5426  }
5427  else
5428  symbol_var_dump(member,ud);
5429 
5430  ++i;
5431  }
5432  fprintf(ud->stream," }");
5433  }
5434  break;
5435  case DATATYPE_ENUM:
5436  if (!symbol_get_name(symbol))
5437  fprintf(ud->stream,"enum");
5438  else
5439  fprintf(ud->stream,"%s",symbol_get_name(symbol));
5440  if (ud->meta) {
5441  if (symbol->size_is_bytes)
5442  fprintf(ud->stream," (%d B)",symbol_get_bytesize(symbol));
5443  else if (symbol->size_is_bits)
5444  fprintf(ud->stream," (%d b)",symbol_get_bitsize(symbol));
5445  if (symbol->srcline != 0)
5446  fprintf(ud->stream," (line=%d)",symbol->srcline);
5447  }
5448  if (ud->detail && SYMBOL_HAS_EXTRA(symbol)) {
5449  fprintf(ud->stream," { ");
5450 
5451  members = SYMBOLX_MEMBERS(symbol);
5452  i = 0;
5453  v_g_slist_foreach(members,gsltmp,member) {
5454  if (likely(i > 0))
5455  fprintf(ud->stream,", ");
5456  symbol_var_dump(member,&udn);
5457  ++i;
5458  }
5459  fprintf(ud->stream," }");
5460  }
5461  break;
5462  case DATATYPE_PTR:
5463  /* NOTE: C structs/unions can have members of the same
5464  * type as the parent struct -- so don't recurse if this
5465  * is true! -- OR if it's a pointer chain back to the struct.
5466  * So for the pointer chain, allow the detail flag set to 1 as
5467  * long as the next type is a pointer. Otherwise, halt the
5468  * recursion of detail since for pointers we never want detail
5469  * of the pointer-to type, just the name --- AND since we might
5470  * be pointing back to a type that we're already printing, like
5471  * a struct member var that is a pointer to the struct type
5472  * itself.
5473  *
5474  * Basically, if the pointed-to type will not recurse in this
5475  * function, it's safe to print details for it; otherwise, it's
5476  * not... I think!
5477  */
5478  tmp = symbol_get_datatype_real(symbol);
5479  if (tmp) {
5480  if (SYMBOL_IST_PTR(tmp) || SYMBOL_IST_VOID(tmp) || SYMBOL_IST_BASE(tmp))
5481  symbol_type_dump(tmp,ud);
5482  else
5483  symbol_type_dump(tmp,&udn);
5484  fprintf(ud->stream,"*");
5485  }
5486  else
5487  fprintf(ud->stream,"ref%"PRIxSMOFFSET" *",
5488  symbol->datatype_ref);
5489  break;
5490  case DATATYPE_REF:
5491  /*
5492  * Same as DATATYPE_PTR case above, basically. Just & instead of * .
5493  */
5494  tmp = symbol_get_datatype_real(symbol);
5495  if (tmp) {
5496  if (SYMBOL_IST_PTR(tmp) || SYMBOL_IST_VOID(tmp) || SYMBOL_IST_BASE(tmp))
5497  symbol_type_dump(tmp,ud);
5498  else
5499  symbol_type_dump(tmp,&udn);
5500  fprintf(ud->stream,"&");
5501  }
5502  else
5503  fprintf(ud->stream,"ref%"PRIxSMOFFSET" &",
5504  symbol->datatype_ref);
5505  break;
5506  case DATATYPE_FUNC:
5507  if (ud->detail)
5509 
5510  if (!symbol->name)
5511  fprintf(ud->stream,"()");
5512  else
5513  fprintf(ud->stream,"(%s)",symbol_get_name(symbol));
5514 
5515  if (ud->meta)
5516  fprintf(ud->stream," (prototyped=%d,external=%d) ",
5517  symbol->isprototyped,symbol->isexternal);
5518  if (symbol->srcline != 0)
5519  fprintf(ud->stream,"(line=%d) ",symbol->srcline);
5520 
5521  if (ud->detail && SYMBOL_HAS_EXTRA(symbol)) {
5522  fprintf(ud->stream,"(");
5523 
5524  members = SYMBOLX_MEMBERS(symbol);
5525  i = 0;
5526  v_g_slist_foreach(members,gsltmp,member) {
5527  if (likely(i > 0))
5528  fprintf(ud->stream,", ");
5529  symbol_var_dump(member,ud);
5530  ++i;
5531  }
5532  if (symbol->has_unspec_params)
5533  fprintf(ud->stream,"...");
5534 
5535  fprintf(ud->stream,")");
5536  }
5537  break;
5538  case DATATYPE_TYPEDEF:
5539  if (!ud->detail)
5540  fprintf(ud->stream,"%s",symbol_get_name(symbol));
5541  else if (symbol_get_datatype_real(symbol)) {
5542  fprintf(ud->stream,"typedef ");
5544  fprintf(ud->stream," %s",symbol_get_name_orig(symbol));
5545  }
5546  else
5547  fprintf(ud->stream,"typedef ref%"PRIxSMOFFSET" %s",
5548  symbol->datatype_ref,symbol_get_name(symbol));
5549  if (ud->meta) {
5550  if (symbol->srcline != 0)
5551  fprintf(ud->stream," (line=%d)",symbol->srcline);
5552  }
5553  break;
5554  case DATATYPE_BASE:
5555  if (!ud->meta)
5556  fprintf(ud->stream,"%s",symbol->name);
5557  else {
5558  if (symbol->size_is_bytes)
5559  fprintf(ud->stream," (%d B)",symbol_get_bytesize(symbol));
5560  else if (symbol->size_is_bits)
5561  fprintf(ud->stream," (%d b)",symbol_get_bitsize(symbol));
5562  if (symbol->srcline != 0)
5563  fprintf(ud->stream," (line=%d)",symbol->srcline);
5564  fprintf(ud->stream," (encoding=%d)",SYMBOLX_ENCODING_V(symbol));
5565  }
5566  break;
5567  default:
5568  vwarn("unknown datatype_code %d!\n",symbol->datatype_code);
5569  }
5570 }
5571 
5572 void symbol_dump(struct symbol *symbol,struct dump_info *ud) {
5573  char *p = "";
5574  char *np;
5575  struct dump_info udn;
5576 
5577  if (ud->prefix) {
5578  p = ud->prefix;
5579  np = malloc(strlen(p) + 1 + 2);
5580  sprintf(np,"%s%s",p," ");
5581  }
5582  else {
5583  np = " ";
5584  }
5585  udn.prefix = np;
5586  udn.stream = ud->stream;
5587  udn.meta = ud->meta;
5588  udn.detail = ud->detail;
5589 
5590  if (symbol->type == SYMBOL_TYPE_TYPE) {
5591  fprintf(ud->stream,"%stype: ",p);
5592  symbol_type_dump(symbol,&udn);
5593  }
5594  else if (symbol->type == SYMBOL_TYPE_ROOT) {
5595  fprintf(ud->stream,"%sroot: ",p);
5596  symbol_root_dump(symbol,&udn);
5597  }
5598  else if (symbol->type == SYMBOL_TYPE_VAR) {
5599  fprintf(ud->stream,"%svar: ",p);
5600  symbol_var_dump(symbol,&udn);
5601  }
5602  else if (symbol->type == SYMBOL_TYPE_FUNC) {
5603  fprintf(ud->stream,"%sfunc: ",p);
5604  symbol_function_dump(symbol,&udn);
5605  }
5606  else if (symbol->type == SYMBOL_TYPE_LABEL) {
5607  fprintf(ud->stream,"%slabel: ",p);
5608  symbol_label_dump(symbol,&udn);
5609  }
5610  else if (symbol->type == SYMBOL_TYPE_BLOCK) {
5611  fprintf(ud->stream,"%sblock: ",p);
5612  symbol_block_dump(symbol,&udn);
5613  }
5614  else {
5615  fprintf(ud->stream,"unknown symbol type %d!\n",symbol->type);
5616  }
5617 
5618  if (ud->prefix)
5619  free(np);
5620 }
5621 
5622 void lsymbol_dump(struct lsymbol *lsymbol,struct dump_info *ud) {
5623  int i = 0;
5624  int len;
5625  struct dump_info udn = {
5626  .stream = ud->stream,
5627  .detail = ud->detail,
5628  .meta = ud->meta,
5629  };
5630  char *prefixbuf = NULL;
5631 
5632  fprintf(ud->stream,"%slsymbol:\n",ud->prefix);
5633 
5634  if (lsymbol->chain && array_list_len(lsymbol->chain)) {
5635  prefixbuf = malloc(strlen(ud->prefix) + (array_list_len(lsymbol->chain) + 1) * 2 + 1);
5636  sprintf(prefixbuf,"%s ",ud->prefix);
5637  len = strlen(prefixbuf);
5638 
5639  udn.prefix = prefixbuf;
5640 
5641  while (1) {
5642  symbol_dump((struct symbol *)array_list_item(lsymbol->chain,i),&udn);
5643  if (++i == array_list_len(lsymbol->chain))
5644  break;
5645  fprintf(ud->stream,"\n");
5646  prefixbuf[len++] = ' ';
5647  prefixbuf[len++] = ' ';
5648  prefixbuf[len] = '\0';
5649  }
5650  }
5651  else if (lsymbol->symbol) {
5652  prefixbuf = malloc(strlen(ud->prefix) + 2 + 1);
5653  sprintf(prefixbuf,"%s ",ud->prefix);
5654  udn.prefix = prefixbuf;
5655  symbol_dump(lsymbol->symbol,&udn);
5656  }
5657 
5658  if (prefixbuf)
5659  free(prefixbuf);
5660 }
5661 
5662 inline char *SYMBOL_TYPE(int n) {
5663  switch (n) {
5664  case SYMBOL_TYPE_NONE: return "none";
5665  case SYMBOL_TYPE_ROOT: return "root";
5666  case SYMBOL_TYPE_TYPE: return "type";
5667  case SYMBOL_TYPE_VAR: return "var";
5668  case SYMBOL_TYPE_FUNC: return "func";
5669  case SYMBOL_TYPE_LABEL: return "label";
5670  case SYMBOL_TYPE_BLOCK: return "block";
5671  default: return NULL;
5672  }
5673 }
5674 
5675 inline char *SYMBOL_SOURCE(int n) {
5676  switch (n) {
5677  case SYMBOL_SOURCE_DWARF: return "dwarf";
5678  case SYMBOL_SOURCE_ELF: return "elf";
5679  case SYMBOL_SOURCE_PHP: return "php";
5680  default: return NULL;
5681  }
5682 }
5683 
5684 inline char *DATATYPE(int n) {
5685  switch (n) {
5686  case DATATYPE_VOID: return "void";
5687  case DATATYPE_ARRAY: return "array";
5688  case DATATYPE_STRUCT: return "struct";
5689  case DATATYPE_ENUM: return "enum";
5690  case DATATYPE_PTR: return "ptr";
5691  case DATATYPE_REF: return "ref";
5692  case DATATYPE_FUNC: return "function";
5693  case DATATYPE_TYPEDEF: return "typedef";
5694  case DATATYPE_UNION: return "union";
5695  case DATATYPE_BASE: return "base";
5696  case DATATYPE_CONST: return "const";
5697  case DATATYPE_VOL: return "volatile";
5698  case DATATYPE_NAMESPACE: return "namespace";
5699  case DATATYPE_CLASS: return "class";
5700  case DATATYPE_TEMPLATE: return "template";
5701  case DATATYPE_DYNAMIC: return "<dynamic>";
5702  default: return NULL;
5703  }
5704 }
#define SYMBOL_IST_NAMESPACE(sym)
int symbol_contains_addr(struct symbol *symbol, ADDR obj_addr)
Definition: debug.c:4063
int debugfile_add_type(struct debugfile *debugfile, struct symbol *symbol)
Definition: debug.c:2300
int debugfile_insert_root(struct debugfile *debugfile, struct symbol *symbol)
Definition: debug.c:1891
char * SYMBOL_SOURCE(int n)
Definition: debug.c:5675
#define LOCATION_ADDR(loc)
Definition: dwdebug_priv.h:622
char * symbol_get_name_inline(struct symbol *symbol)
Definition: debug.c:2600
unsigned int srcline
Definition: dwdebug_priv.h:824
int symbol_insert_symbol(struct symbol *parent, struct symbol *child)
Definition: debug.c:2758
#define RF_ACCEPT
Definition: rfilter.h:29
int symbol_has_unspecified_parameters(struct symbol *symbol)
Definition: debug.c:3050
uint32_t symbol_get_bitoffset(struct symbol *symbol)
Definition: debug.c:3085
OFFSET symbol_offsetof(struct symbol *symbol, const char *name, const char *delim)
Definition: debug.c:314
#define vwarnopt(level, area, flags, format,...)
Definition: log.h:37
#define SYMBOL_EXPAND_WARN(symbol)
struct symbol * symbol_find_parent(struct symbol *symbol)
Definition: debug.c:3106
#define LOCATION_IS_ADDR(loc)
Definition: dwdebug_priv.h:611
OFFSET lsymbol_offsetof(struct lsymbol *lsymbol, const char *name, const char *delim)
Definition: debug.c:364
encoding_t
Definition: dwdebug.h:266
GHashTable * types
Definition: dwdebug.h:913
#define SYMBOLX_SUBRANGES(sym)
struct lsymbol * debugfile_lookup_sym__int(struct debugfile *debugfile, char *name, const char *delim, struct rfilter *srcfile_filter, symbol_type_flag_t flags)
Definition: debug.c:677
int debugfile_declaration_copy_definition(struct debugfile *debugfile, struct symbol *declaration, struct symbol *definition)
Definition: debug.c:1994
void symbol_free_inline(struct symbol *symbol)
Definition: debug.c:4356
struct lsymbol * lsymbol_lookup_sym__int(struct lsymbol *lsymbol, const char *name, const char *delim)
Definition: debug.c:275
unsigned int has_addr
Definition: dwdebug_priv.h:839
struct scope * symbol_write_owned_scope(struct symbol *symbol)
Definition: debug.c:2689
ADDR end
Definition: dwdebug_priv.h:438
struct debugfile * debugfile_from_file(char *filename, char *root_prefix, struct array_list *debugfile_load_opts_list)
Definition: debug.c:1584
unsigned int decltypedefined
Definition: dwdebug_priv.h:839
GHashTable * cuoffsets
Definition: dwdebug.h:899
GHashTable * decldefnsused
Definition: dwdebug.h:956
struct symbol * debugfile_find_type(struct debugfile *debugfile, char *typename)
Definition: debug.c:2288
char * filename
Definition: binfile.h:243
#define unlikely(expr)
Definition: debugpred.h:101
unsigned int orig_name_offset
Definition: dwdebug_priv.h:821
int symbol_set_root_language(struct symbol *symbol, char *language, int copy, short int lang_code)
Definition: debug.c:3318
void symbol_set_bytesize(struct symbol *s, uint32_t b)
Definition: debug.c:3219
#define SYMBOL_IST_VOL(sym)
void symbol_set_bitoffset(struct symbol *s, uint32_t bo)
Definition: debug.c:3247
REFCNT lsymbol_release(struct lsymbol *lsymbol)
Definition: debug.c:4805
GSList * symbol_get_ordered_members(struct symbol *symbol, symbol_type_flag_t flags)
Definition: debug.c:3128
struct lsymbol * debugfile_lookup_addr__int(struct debugfile *debugfile, ADDR addr)
Definition: debug.c:503
struct symbol * origin
void debugfile_save_declaration(struct debugfile *debugfile, struct symbol *symbol)
Definition: debug.c:2081
char * linetab
Definition: dwdebug.h:859
#define SYMBOL_IS_ELF(sym)
struct lsymbol * lsymbol_lookup_sym(struct lsymbol *lsymbol, const char *name, const char *delim)
Definition: debug.c:299
#define SYMBOL_RX_ROOT(sym, rvar)
union symbol::@7 size
int symbol_set_constval(struct symbol *symbol, void *value, int len, int copy)
Definition: debug.c:3429
struct array_list * debugfile_lookup_addrs_line(struct debugfile *debugfile, char *filename, int line)
Definition: debug.c:387
void location_dump(struct location *location, struct dump_info *ud)
Definition: location.c:392
struct symbol * symbol
Definition: dwdebug.h:1010
struct lsymbol * lsymbol_create_from_symbol(struct symbol *symbol)
Definition: debug.c:4722
load_type_t
Definition: dwdebug.h:166
void binfile_init(void)
Definition: binfile.c:103
void clrange_symbol_name_dumper(Word_t start, Word_t end, struct dump_info *ud, void *data)
Definition: debug.c:4899
GSList * members
Definition: dwdebug_priv.h:976
char * DATATYPE(int n)
Definition: debug.c:5684
#define SYMBOL_RX_FUNC(sym, rvar)
clrange_t ranges
Definition: binfile.h:279
struct symbol * symbol_create(symbol_type_t symtype, symbol_source_t source, char *name, int name_copy, SMOFFSET offset, load_type_t loadtype, struct scope *scope)
Definition: debug.c:2550
struct scope * symbol_read_owned_scope(struct symbol *symbol)
Definition: debug.c:2674
struct symbol * symbol_get_one_member__int(struct symbol *symbol, char *member)
Definition: debug.c:4123
unsigned int guessed_size
Definition: dwdebug_priv.h:839
#define SYMBOL_RX_VAR(sym, rvar)
struct lsymbol * lsymbol_create_from_symbol__int(struct symbol *symbol)
Definition: debug.c:4657
GHashTable * srcfiles
Definition: dwdebug.h:883
GHashTable * shared_types
Definition: dwdebug.h:918
struct symbol * lsymbol_get_noninline_parent_symbol(struct lsymbol *lsymbol)
Definition: debug.c:4742
void * p
#define SYMBOL_WX_VAR(sym, wvar, reterr)
static uint64_t unsigned int i
struct array_list * clmatch_find(clmatch_t *clf, Word_t index)
Definition: clfit.c:882
load_type_t loadtag
Definition: dwdebug_priv.h:830
GHashTable * srcaddrlines
Definition: dwdebug.h:980
int scope_insert_symbol(struct scope *scope, struct symbol *symbol)
Definition: scope.c:57
#define SYMBOLX_MEMBERS(sym)
GSList * symdict_match_syms(struct symdict *symdict, struct rfilter *symbol_filter, symbol_type_flag_t flags)
Definition: symdict.c:481
char * version
Definition: binfile.h:259
struct array_list __attribute__
int symbol_get_srcline(struct symbol *symbol)
Definition: debug.c:2937
unsigned int isexternal
Definition: dwdebug_priv.h:839
struct symdict * symdict
Definition: dwdebug_priv.h:466
struct symbol * symbol_find_root(struct symbol *symbol)
Definition: debug.c:3119
#define v_g_slist_foreach(gslhead, gslcur, elm)
Definition: glib_wrapper.h:60
SMOFFSET ref
Definition: dwdebug_priv.h:868
#define v_g_list_foreach(glhead, glcur, elm)
Definition: glib_wrapper.h:34
struct debugfile_load_opts * opts
Definition: dwdebug.h:803
int debugfile_type_flags_t
Definition: dwdebug.h:782
unsigned int size_is_bytes
Definition: dwdebug_priv.h:839
struct symbol * __symbol_get_one_member__int(struct symbol *symbol, char *member, struct array_list **chainptr)
Definition: debug.c:3815
#define SYMBOL_IST_ENUM(sym)
void debugfile_handle_declaration(struct debugfile *debugfile, struct symbol *symbol)
Definition: debug.c:2100
ADDR addr
Definition: dwdebug_priv.h:916
unsigned int isshared
Definition: dwdebug_priv.h:839
struct symbol_block * block
Definition: dwdebug_priv.h:981
#define SYMBOL_IS_FULL(sym)
char * debugfile_search_path(char *filename, char *root_prefix, char *debug_postfix, const char *DFPATH[], char *buf, int buflen)
Definition: debug.c:1510
#define likely(expr)
Definition: debugpred.h:102
#define SYMBOL_IS_INSTANCE(sym)
int symbol_is_enumerator(struct symbol *symbol)
Definition: debug.c:3041
int mallopt(int param, int value)
Definition: debugserver.c:265
#define SIZE_OFFSET_SIZE
Definition: dwdebug_priv.h:904
int32_t SMOFFSET
Definition: common.h:100
REFCNT symbol_free(struct symbol *symbol, int force)
Definition: debug.c:4516
symbol_source_t
Definition: dwdebug.h:159
ADDR symbol_get_addr(struct symbol *symbol)
Definition: debug.c:3096
struct debugfile * debugfile_from_binfile(struct binfile *binfile, struct array_list *debugfile_load_opts_list)
Definition: debug.c:1805
#define assert(x)
Definition: dlmalloc.c:1456
uint32_t symbol_get_bytesize(struct symbol *symbol)
Definition: debug.c:3065
struct lsymbol * lsymbol_create_from_member__int(struct lsymbol *parent, struct symbol *member)
Definition: debug.c:4632
ADDR start
Definition: dwdebug_priv.h:437
void symbol_set_srcline(struct symbol *s, int sl)
Definition: debug.c:3194
void symbol_type_dump(struct symbol *symbol, struct dump_info *ud)
Definition: debug.c:5328
int symbol_type_equal(struct symbol *t1, struct symbol *t2, GHashTable *eqcache, GHashTable *updated_datatype_refs)
Definition: debug.c:3801
int32_t s4
char * debugfile_get_name(struct debugfile *debugfile)
Definition: debug.c:1286
int32_t OFFSET
Definition: common.h:65
int symbol_is_decldefined(struct symbol *symbol)
Definition: debug.c:3029
SMOFFSET datatype_ref
Definition: dwdebug_priv.h:882
void dwdebug_evict(struct debugfile *debugfile)
Definition: debug.c:115
int debugfile_update_root(struct debugfile *debugfile, struct symbol *symbol)
Definition: debug.c:1826
void debugfile_resolve_declarations(struct debugfile *debugfile)
Definition: debug.c:2250
int symbol_is_inlineinstance(struct symbol *symbol)
Definition: debug.c:3044
#define verror(format,...)
Definition: log.h:30
int id
Definition: dwdebug.h:823
int symbol_is_parameter(struct symbol *symbol)
Definition: debug.c:3035
debugfile_load_flags_t flags
Definition: dwdebug.h:761
#define verrorc(format,...)
Definition: log.h:32
#define SYMBOL_IST_CONST(sym)
char * rangetab
Definition: dwdebug.h:852
struct lsymbol * lsymbol_clone(struct lsymbol *lsymbol, struct symbol *newchild)
Definition: debug.c:369
char * symbol_get_srcfile(struct symbol *symbol)
Definition: debug.c:2941
#define SYMBOLX_ROOT(sym)
struct symbol * symbol_get_datatype(struct symbol *symbol)
Definition: debug.c:2989
struct debugfile_ops dwarf_debugfile_ops
#define SYMBOL_IS_CONTAINER(sym)
#define SYMBOLX_VAR_LOC(sym)
#define SYMBOL_IST_UNION(sym)
#define SYMBOL_WX_BLOCK(sym, wvar, reterr)
#define SYMBOL_IS_OWN_DATATYPE(sym)
GHashTable * globals
Definition: dwdebug.h:929
symbol_type_t type
Definition: dwdebug_priv.h:833
#define SYMBOL_RX_BLOCK(sym, rvar)
int symbol_is_inlined(struct symbol *symbol)
Definition: debug.c:3053
char * dbg_strtab
Definition: dwdebug.h:838
struct lsymbol * debugfile_lookup_addr(struct debugfile *debugfile, ADDR addr)
Definition: debug.c:667
int symbol_set_root_compdir(struct symbol *symbol, char *compdirname, int copy)
Definition: debug.c:3294
uint32_t ctbytes
Definition: dwdebug_priv.h:906
struct lsymbol * symbol_lookup_sym(struct symbol *symbol, const char *name, const char *delim)
Definition: debug.c:264
GSList * scope_match_syms(struct scope *scope, struct rfilter *symbol_filter, symbol_type_flag_t flags)
Definition: scope.c:811
int symbol_is_member(struct symbol *symbol)
Definition: debug.c:3038
struct scope * scope
debugfile_load_flags_t
Definition: dwdebug.h:99
struct binfile * binfile_open_debuginfo__int(struct binfile *binfile, struct binfile_instance *bfinst, const char *DFPATH[])
Definition: binfile.c:297
symbol_type_t
Definition: dwdebug.h:148
void dwdebug_init(void)
Definition: debug.c:83
#define vwarn(format,...)
Definition: log.h:33
#define ADDRMAX
Definition: common.h:74
void lsymbol_dump(struct lsymbol *lsymbol, struct dump_info *ud)
Definition: debug.c:5622
int symbol_type_is_char(struct symbol *type)
Definition: debug.c:4224
void free(void *ptr)
Definition: debugserver.c:207
char * root_prefix
Definition: binfile.h:376
struct symbol_type_container * container
Definition: dwdebug_priv.h:977
struct range * range
Definition: dwdebug_priv.h:471
struct symbol * scope_get_sym(struct scope *scope, const char *name, symbol_type_flag_t flags)
Definition: scope.c:771
#define LOCATION_IS_M_OFFSET(loc)
Definition: dwdebug_priv.h:615
struct lsymbol * lsymbol_create_from_member(struct lsymbol *parent, struct symbol *member)
Definition: debug.c:4646
#define SYMBOL_IS_LABEL(sym)
struct scope * scope
void clrange_free(clrange_t clf)
Definition: clfit.c:572
#define LOCATION_OFFSET(loc)
Definition: dwdebug_priv.h:624
Definition: log.h:124
Definition: log.h:69
int symbol_has_ext_name(struct symbol *symbol)
Definition: debug.c:2667
void g_hash_foreach_dump_symbol(gpointer key __attribute__((unused)), gpointer value, gpointer userdata)
Definition: debug.c:4860
unsigned int constval_nofree
Definition: dwdebug_priv.h:839
int(* load)(struct debugfile *debugfile)
Definition: dwdebug_priv.h:130
char * prefix
Definition: output.h:25
char * lsymbol_get_name(struct lsymbol *lsymbol)
Definition: debug.c:4732
int symbol_set_encoding(struct symbol *symbol, encoding_t num)
Definition: debug.c:3332
int symbol_is_declaration(struct symbol *symbol)
Definition: debug.c:3026
#define list_for_each_entry(pos, head, member)
Definition: list.h:335
#define array_list_foreach(alist, lpc, placeholder)
Definition: alist.h:371
int symbol_has_addr(struct symbol *symbol)
Definition: debug.c:3047
char * symbol_get_name_orig(struct symbol *symbol)
Definition: debug.c:2612
struct symbol * root
Definition: binfile.h:272
unsigned int symbol_type_array_bytesize(struct symbol *type)
Definition: debug.c:4239
void clmatchone_free(clmatchone_t clf)
Definition: clfit.c:994
int(* fini)(struct debugfile *debugfile)
Definition: dwdebug_priv.h:182
void dwdebug_fini(void)
Definition: debug.c:143
struct scope * symbol_containing_scope(struct symbol *symbol)
Definition: debug.c:2671
void clmatch_free(clmatch_t clf)
Definition: clfit.c:897
REFCNT refcnt
Definition: dwdebug.h:792
int symbol_set_location(struct symbol *symbol, struct location *loc)
Definition: debug.c:3365
unsigned int isparam
Definition: dwdebug_priv.h:839
#define SYMBOL_RX_INLINE(sym, rvar)
void location_free(struct location *location)
Definition: location.c:359
struct debugfile_ops * ops
Definition: dwdebug.h:799
datatype_code_t datatype_code
Definition: dwdebug_priv.h:827
#define SYMBOL_WX_CONTAINER(sym, wvar, reterr)
REFCNT debugfile_free(struct debugfile *debugfile, int force)
Definition: debug.c:2384
struct binfile * binfile_open__int(char *filename, char *root_prefix, struct binfile_instance *bfinst)
Definition: binfile.c:254
#define SYMBOL_IST_BASE(sym)
int symbol_is_prototyped(struct symbol *symbol)
Definition: debug.c:3032
void symbol_var_dump(struct symbol *symbol, struct dump_info *ud)
Definition: debug.c:5059
debugfile_type_t
Definition: dwdebug.h:770
struct symbol * symbol_get_datatype_real(struct symbol *symbol)
Definition: debug.c:2970
struct range * next
Definition: dwdebug_priv.h:439
unsigned int isprototyped
Definition: dwdebug_priv.h:839
int scope_hold_symbol(struct scope *scope, struct symbol *symbol)
Definition: scope.c:73
#define SYMBOL_TYPE_FLAG_MATCHES(sym, flags)
int(* init)(struct debugfile *debugfile)
Definition: dwdebug_priv.h:129
void malloc_stats(void)
Definition: debugserver.c:280
unsigned int isenumval
Definition: dwdebug_priv.h:839
uint32_t offset
Definition: dwdebug_priv.h:906
struct dt_argp_state opts
Definition: dumptarget.c:111
struct debugfile_load_opts * debugfile_load_opts_parse(char *optstr)
Definition: debug.c:1194
#define SYMBOL_RX_LABEL(sym, rvar)
#define SYMBOL_IST_ARRAY(sym)
int symbol_type_flags_match(struct symbol *symbol, symbol_type_flag_t flags)
Definition: debug.c:3102
GHashTable * srclines
Definition: dwdebug.h:979
symbol_type_t symbol_get_type(struct symbol *symbol)
Definition: debug.c:2962
struct symbol * lsymbol_get_symbol(struct lsymbol *lsymbol)
Definition: debug.c:4738
Pvoid_t clmatch_t
Definition: clfit.h:129
uint8_t has_debuginfo
Definition: binfile.h:202
void symbol_set_bitsize(struct symbol *s, uint32_t b)
Definition: debug.c:3232
#define SYMBOLX_ENCODING_V(sym)
#define SYMBOL_IST_PTR(sym)
#define SYMBOL_IST_FUNC(sym)
#define SYMBOL_IS_BLOCK(sym)
char * name
Definition: dwdebug_priv.h:788
int symbol_add_inline_instance(struct symbol *symbol, struct symbol *instance)
Definition: debug.c:3420
int symbol_is_external(struct symbol *symbol)
Definition: debug.c:3018
void symbol_dump(struct symbol *symbol, struct dump_info *ud)
Definition: debug.c:5572
#define DWDEBUG_DEF_DELIM
Definition: dwdebug.h:50
#define ERRORDUMPSYMBOL_NL(s)
Definition: dwdebug_priv.h:54
void clrange_dump(clrange_t *clf, struct dump_info *ud, clrange_dumper_t dumper)
Definition: clfit.c:599
#define PRIxSMOFFSET
Definition: common.h:102
void clrange_scope_name_dumper(Word_t start, Word_t end, struct dump_info *ud, void *data)
Definition: debug.c:4891
unsigned int name_nofree
Definition: dwdebug_priv.h:839
#define SYMBOL_IST_STRUCT(sym)
#define M_TRIM_THRESHOLD
Definition: dlmalloc.c:725
int debugfile_add_global(struct debugfile *debugfile, struct symbol *symbol)
Definition: debug.c:2262
struct debugfile * debugfile_create_basic(debugfile_type_t dtype, debugfile_type_flags_t dtflags, char *filename, struct debugfile_load_opts *opts)
Definition: debug.c:1298
int len
Definition: dumptarget.c:52
#define SYMBOL_IST_STUNC(sym)
#define RHOLD(x, hx)
Definition: common.h:622
#define RF_REJECT
Definition: rfilter.h:30
void symbol_set_addr(struct symbol *s, ADDR a)
Definition: debug.c:3276
int scope_remove_symbol(struct scope *scope, struct symbol *symbol)
Definition: scope.c:132
void symbol_label_dump(struct symbol *symbol, struct dump_info *ud)
Definition: debug.c:5036
REFCNT refcnt
Definition: dwdebug_priv.h:863
#define SYMBOL_IST_STUN(sym)
unsigned int has_unspec_params
Definition: dwdebug_priv.h:839
int symbol_set_root_producer(struct symbol *symbol, char *producer, int copy)
Definition: debug.c:3306
char * debugfile_get_version(struct debugfile *debugfile)
Definition: debug.c:1290
unsigned int issynthetic
Definition: dwdebug_priv.h:839
struct lsymbol * scope_lookup_sym__int(struct scope *scope, const char *name, const char *delim, symbol_type_flag_t flags)
Definition: scope.c:573
#define SYMBOL_WX_INLINE(sym, wvar, reterr)
int symbol_set_inline_origin(struct symbol *symbol, SMOFFSET ref, struct symbol *origin)
Definition: debug.c:3395
Definition: rfilter.h:44
REFCNT symbol_release(struct symbol *symbol)
Definition: debug.c:4318
void debugfile_init_internal(struct debugfile *debugfile)
Definition: debug.c:1401
uint32_t bits
Definition: dwdebug_priv.h:906
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
struct debugfile * debugfile_create(debugfile_type_t dtype, debugfile_type_flags_t dtflags, struct binfile *binfile, struct debugfile_load_opts *opts, struct binfile *binfile_pointing)
Definition: debug.c:1336
struct scope * parent
Definition: dwdebug_priv.h:476
struct scope * scope
int debugfile_remove_root(struct debugfile *debugfile, struct symbol *symbol)
Definition: debug.c:1933
void * realloc(void *ptr, size_t size)
Definition: debugserver.c:221
FILE * stream
Definition: output.h:26
unsigned int isdeclaration
Definition: dwdebug_priv.h:839
void symbol_block_dump(struct symbol *symbol, struct dump_info *ud)
Definition: debug.c:5041
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
REFCNT lsymbol_free(struct lsymbol *lsymbol, int force)
Definition: debug.c:4811
int debugfile_load_opts_checklist(struct array_list *opts_list, char *name, struct debugfile_load_opts **match_saveptr)
Definition: debug.c:1244
unsigned int isdeclinline
Definition: dwdebug_priv.h:839
struct symbol * symbol_type_skip_qualifiers(struct symbol *type)
Definition: debug.c:4191
union symbol::@8 extra
int16_t s2
void debugfile_resolve_one_declaration(struct debugfile *debugfile, char *name)
Definition: debug.c:2241
void lsymbol_prepend(struct lsymbol *lsymbol, struct symbol *symbol)
Definition: debug.c:4623
#define vdebugc(devel, areas, flags, format,...)
Definition: log.h:303
#define SYMBOL_IS_TYPE(sym)
#define SYMBOL_RX_CONTAINER(sym, rvar)
struct rfilter * debugfile_filter
Definition: dwdebug.h:758
#define SYMBOLX_SCOPE(sym)
struct debugfile * debugfile_from_instance(struct binfile_instance *bfinst, struct array_list *debugfile_load_opts_list)
Definition: debug.c:1726
char * loctab
Definition: dwdebug.h:845
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
GHashTable * srcfiles_multiuse
Definition: dwdebug.h:891
struct scope * symbol_link_owned_scope(struct symbol *symbol, struct scope *new_parent)
Definition: debug.c:2726
#define SRCLINE_BITS
Definition: dwdebug.h:185
struct binfile * binfile
Definition: dwdebug.h:808
char * frametab
Definition: dwdebug.h:865
uint32_t symbol_get_bitsize(struct symbol *symbol)
Definition: debug.c:3079
struct lsymbol * debugfile_lookup_sym_line__int(struct debugfile *debugfile, char *filename, int line, SMOFFSET *offset, ADDR *addr)
Definition: debug.c:463
struct symbol * debugfile_lookup_root_name(struct debugfile *debugfile, char *name)
Definition: debug.c:1978
#define SYMBOL_HAS_EXTRA(sym)
struct symbol * debugfile_lookup_root(struct debugfile *debugfile, SMOFFSET offset)
Definition: debug.c:1972
#define SYMBOL_WX_FUNC(sym, wvar, reterr)
unsigned int symbol_type_full_bytesize(struct symbol *type)
Definition: debug.c:4267
GSList * debugfile_match_syms(struct debugfile *debugfile, struct rfilter *symbol_filter, symbol_type_flag_t flags, struct rfilter *srcfile_filter)
Definition: debug.c:1034
struct symbol * symbol_get_sym(struct symbol *symbol, const char *name, symbol_type_flag_t flags)
Definition: debug.c:177
symbol_source_t symbol_get_source(struct symbol *symbol)
Definition: debug.c:2966
struct symbol * symbol_type_skip_ptrs(struct symbol *type)
Definition: debug.c:4209
Definition: log.h:125
struct binfile * binfile_pointing
Definition: dwdebug.h:830
int scope_get_sizes(struct scope *scope, int *named, int *duplicated, int *anon, int *numscopes)
Definition: scope.c:263
struct debugfile_load_opts default_debugfile_load_opts
Definition: debug.c:57
int debugfile_lookup_line_addr(struct debugfile *debugfile, char *filename, ADDR addr)
Definition: debug.c:411
void symbol_set_name(struct symbol *symbol, char *name, int copy)
Definition: debug.c:2615
struct lsymbol * lsymbol_create_noninline__int(struct lsymbol *lsymbol)
Definition: debug.c:4757
struct scope * scope
Definition: dwdebug_priv.h:806
void * exists
Definition: dwdebug_priv.h:971
REFCNT refcnt
Definition: dwdebug.h:1002
uint32_t ADDR
Definition: common.h:64
clrange_t ranges
Definition: dwdebug.h:977
#define SYMBOLX_VAR_CONSTVAL(sym)
GSList * symbol_get_members(struct symbol *symbol, symbol_type_flag_t flags)
Definition: debug.c:3146
struct symbol * symbol_get_inline_origin(struct symbol *symbol)
Definition: debug.c:4162
struct lsymbol * lsymbol_create(struct symbol *symbol, struct array_list *chain)
Definition: debug.c:4595
struct scope * scope_lookup_addr(struct scope *scope, ADDR pc)
Definition: scope.c:528
struct array_list * debugfile_get_loaded_debugfiles(void)
Definition: debug.c:1810
struct rfilter * srcfile_filter
Definition: dwdebug.h:759
int symbol_set_root_priv(struct symbol *symbol, void *priv)
Definition: debug.c:3288
#define SIZE_BITS_SIZE
Definition: dwdebug_priv.h:903
struct rfilter * symbol_filter
Definition: dwdebug.h:760
int scope_insert_scope(struct scope *parent, struct scope *child)
Definition: scope.c:88
int symbol_change_parent(struct symbol *parent, struct symbol *child, struct symbol *newparent)
Definition: debug.c:2884
char * filename
Definition: dwdebug.h:817
int symbol_expand(struct symbol *symbol)
Definition: debug.c:3161
symbol_source_t source
Definition: dwdebug_priv.h:836
struct symbol * symbol_get_member(struct symbol *symbol, char *memberlist, const char *delim)
Definition: debug.c:4136
int debugfile_lookup_filename_line_addr(struct debugfile *debugfile, ADDR addr, char **filename, int *line)
Definition: debug.c:437
#define array_list_foreach_continue(alist, lpc, placeholder)
Definition: alist.h:376
struct scope * scope
uint32_t REFCNT
Definition: common.h:124
uint32_t bytes
Definition: dwdebug_priv.h:901
#define PRIxADDR
Definition: common.h:67
#define SYMBOL_IS_ROOT(sym)
int detail
Definition: output.h:28
void scope_dump(struct scope *scope, struct dump_info *ud)
Definition: scope.c:409
char * SYMBOL_TYPE(int n)
Definition: debug.c:5662
GHashTable * addresses
Definition: dwdebug.h:965
int symbol_set_inline_info(struct symbol *symbol, int isinlined, int isdeclinline)
Definition: debug.c:3389
#define SYMBOL_IST_VOID(sym)
char * root_prefix
Definition: binfile.h:321
GHashTable * pubnames
Definition: dwdebug.h:975
unsigned int isinlined
Definition: dwdebug_priv.h:839
void g_hash_foreach_dump_symbol_list(gpointer key __attribute__((unused)), gpointer value, gpointer userdata)
Definition: debug.c:4847
void lsymbol_append(struct lsymbol *lsymbol, struct symbol *symbol)
Definition: debug.c:4610
#define array_list_foreach_delete(alist, lpc)
Definition: alist.h:389
struct symbol_function * function
Definition: dwdebug_priv.h:978
int symbol_is_synthetic(struct symbol *symbol)
Definition: debug.c:3015
debugfile_type_flags_t flags
Definition: dwdebug.h:789
char * symbol_get_name(struct symbol *symbol)
Definition: debug.c:2587
void dwdebug_evict_all(void)
Definition: debug.c:130
#define RPUT(x, objtype, hx, rc)
Definition: common.h:624
int accept
Definition: rfilter.h:46
void debugfile_load_opts_free(struct debugfile_load_opts *opts)
Definition: debug.c:1275
#define SYMBOL_IST_CONTAINER(sym)
struct symbol_root * root
Definition: dwdebug_priv.h:973
#define SYMBOL_HAS_MEMBERS(sym)
void * malloc(size_t size)
Definition: debugserver.c:214
void symbol_free_extra(struct symbol *symbol)
Definition: debug.c:4402
void symbol_build_extname(struct symbol *symbol)
Definition: debug.c:2628
#define ERRORDUMPSYMBOL(s)
Definition: dwdebug_priv.h:50
void * clrange_find(clrange_t *clf, Word_t index)
Definition: clfit.c:312
int symbol_add_subrange(struct symbol *symbol, int subrange)
Definition: debug.c:3448
struct array_list * chain
Definition: dwdebug.h:1016
int symbol_is_bitsize(struct symbol *symbol)
Definition: debug.c:3059
symbol_type_flag_t
Definition: dwdebug.h:190
unsigned int isinlineinstance
Definition: dwdebug_priv.h:839
int scope_contains_addr(struct scope *scope, ADDR addr)
Definition: scope.c:504
#define v_g_slist_foreach_dual(gslhead1, gslhead2, gslcur1, gslcur2, elm1, elm2)
Definition: glib_wrapper.h:66
void debugfile_dump(struct debugfile *debugfile, struct dump_info *ud, int types, int globals, int symtabs, int elfsymtab, int doranges)
Definition: debug.c:4907
int(* symbol_replace)(struct debugfile *debugfile, struct symbol *old, struct symbol *new)
Definition: dwdebug_priv.h:131
#define SIZE_CTBYTES_SIZE
Definition: dwdebug_priv.h:905
void symbol_root_dump(struct symbol *symbol, struct dump_info *ud)
Definition: debug.c:5019
unsigned int decldefined
Definition: dwdebug_priv.h:839
char * symbol_get_compdirname(struct symbol *symbol)
Definition: debug.c:2949
#define SYMBOL_WX_ROOT(sym, wvar, reterr)
#define ERRORDUMPLSYMBOL_NL(s)
Definition: dwdebug_priv.h:112
void symbol_set_bitsize_all(struct symbol *s, uint32_t b, uint32_t bo, uint32_t ctb)
Definition: debug.c:3262
debugfile_load_flags_t debugfile_load_flags_parse(char *flagstr, char *delim)
Definition: debug.c:1148
int meta
Definition: output.h:27
struct lsymbol * debugfile_lookup_sym_line(struct debugfile *debugfile, char *filename, int line, SMOFFSET *offset, ADDR *addr)
Definition: debug.c:491
struct lsymbol * symbol_lookup_sym__int(struct symbol *symbol, const char *name, const char *delim)
Definition: debug.c:195
int symbol_set_entry_pc(struct symbol *symbol, ADDR entry_pc)
Definition: debug.c:3340
void symbol_function_dump(struct symbol *symbol, struct dump_info *ud)
Definition: debug.c:5203
int symbol_is_definition(struct symbol *symbol)
Definition: debug.c:3021
int vdebug_is_on(int level, log_areas_t areas, log_flags_t flags)
Definition: log.c:335
#define SYMBOL_IST_TYPEDEF(sym)
#define SYMBOL_IS_FUNC(sym)
uint32_t symbol_get_bitctbytes(struct symbol *symbol)
Definition: debug.c:3090
struct lsymbol * lsymbol_create_noninline(struct lsymbol *lsymbol)
Definition: debug.c:4788
int symbol_is_bytesize(struct symbol *symbol)
Definition: debug.c:3062
unsigned int usesshareddatatype
Definition: dwdebug_priv.h:839
unsigned int size_is_bits
Definition: dwdebug_priv.h:839
GHashTable * decllists
Definition: dwdebug.h:937
int debugfile_lookup_addr_alt__int(struct debugfile *debugfile, ADDR addr, struct lsymbol **primary, struct lsymbol **alt)
Definition: debug.c:580
#define ERRORDUMPLSYMBOL(s)
Definition: dwdebug_priv.h:107
struct symbol * symbol_get_one_member(struct symbol *symbol, char *member)
Definition: debug.c:4127
struct symbol * datatype
Definition: dwdebug_priv.h:925
debugfile_type_t type
Definition: dwdebug.h:788
unsigned int ismember
Definition: dwdebug_priv.h:839
#define SYMBOL_IS_VAR(sym)
int symbol_is_declinline(struct symbol *symbol)
Definition: debug.c:3056
char * filename
Definition: binfile.h:368
char * compdirname
Definition: dwdebug_priv.h:993
clrange_t clrange_create(void)
Definition: clfit.c:27
#define SYMBOL_IST_CLASS(sym)
void lsymbol_hold_int(struct lsymbol *lsymbol)
Definition: debug.c:4798
struct scope * scope_create(struct symbol *owner, SMOFFSET ref)
Definition: scope.c:37
#define SYMBOLX_INLINE(sym)
int debugfile_replace_type(struct debugfile *debugfile, struct symbol *symbol)
Definition: debug.c:2334
int symbol_remove_symbol(struct symbol *parent, struct symbol *child)
Definition: debug.c:2845
struct symbol * symbol
Definition: dwdebug_priv.h:463