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
symdict.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, 2012, 2013 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 <stdlib.h>
20 #include <errno.h>
21 #include <glib.h>
22 
23 #include "config.h"
24 #include "common.h"
25 #include "log.h"
26 #include "list.h"
27 #include "alist.h"
28 
29 #include "dwdebug_priv.h"
30 #include "dwdebug.h"
31 
35 struct symdict *symdict_create(void) {
36  struct symdict *symdict;
37 
38  symdict = (struct symdict *)calloc(1,sizeof(*symdict));
39  if (!symdict)
40  return NULL;
41 
42  /*
43  * Don't initialize these until they are actually used, in
44  * symdict_insert_symbol -- try to save memory.
45  *
46  * Don't provide key/value destructors; symbol_free does that!
47  */
48  symdict->tab = NULL;
49  symdict->duptab = NULL;
50  symdict->anontab = NULL;
51 
52  return symdict;
53 }
54 
56  int retval = 0;
57 
58  if (symdict->tab)
59  retval += g_hash_table_size(symdict->tab);
60  if (symdict->duptab)
61  retval += g_hash_table_size(symdict->duptab);
62  if (symdict->anontab)
63  retval += g_hash_table_size(symdict->anontab);
64 
65  return retval;
66 }
67 
69  int retval = 0;
70  GHashTableIter iter;
71  gpointer value;
72  struct array_list *duplist;
73 
74  if (symdict->tab)
75  retval += g_hash_table_size(symdict->tab);
76  if (symdict->duptab) {
77  g_hash_table_iter_init(&iter,symdict->duptab);
78  while (g_hash_table_iter_next(&iter,NULL,&value)) {
79  duplist = (struct array_list *)value;
80  retval += array_list_len(duplist);
81  }
82  }
83  if (symdict->anontab)
84  retval += g_hash_table_size(symdict->anontab);
85 
86  return retval;
87 }
88 
90  int retval = 0;
91  GHashTableIter iter;
92  gpointer value;
93  struct array_list *duplist;
94 
95  if (symdict->tab)
96  retval += g_hash_table_size(symdict->tab);
97  if (symdict->duptab) {
98  g_hash_table_iter_init(&iter,symdict->duptab);
99  while (g_hash_table_iter_next(&iter,NULL,&value)) {
100  duplist = (struct array_list *)value;
101  retval += array_list_len(duplist);
102  }
103  }
104 
105  return retval;
106 }
107 
108 int symdict_get_sizes(struct symdict *symdict,int *named,int *duplicated,int *anon) {
109  GHashTableIter iter;
110  gpointer value;
111  struct array_list *duplist;
112 
113  if (named) {
114  if (symdict->tab)
115  *named = g_hash_table_size(symdict->tab);
116  else
117  *named = 0;
118  }
119  if (duplicated) {
120  if (symdict->duptab) {
121  *duplicated = 0;
122  g_hash_table_iter_init(&iter,symdict->duptab);
123  while (g_hash_table_iter_next(&iter,NULL,&value)) {
124  duplist = (struct array_list *)value;
125  *duplicated += array_list_len(duplist);
126  }
127  }
128  else
129  *duplicated = 0;
130  }
131  if (anon) {
132  if (symdict->anontab)
133  *anon = g_hash_table_size(symdict->anontab);
134  else
135  *anon = 0;
136  }
137 
138  return 0;
139 }
140 
142  char *name = symbol_get_name(symbol);
143  struct symbol *exsym = NULL;
144  struct array_list *exlist = NULL;
145 
146  if (name) {
147  if (unlikely(symdict->duptab)
148  && unlikely((exlist = (struct array_list *) \
149  g_hash_table_lookup(symdict->duptab,name)))) {
150  array_list_append(exlist,symbol);
151 
153  "duplicate symbol(%s:0x%"PRIxSMOFFSET") (%d)\n",
154  symbol_get_name(symbol),symbol->ref,array_list_len(exlist));
155  }
156  else if (symdict->tab
157  && unlikely((exsym = (struct symbol *) \
158  g_hash_table_lookup(symdict->tab,name)))) {
159  exlist = array_list_create(2);
160  array_list_append(exlist,exsym);
161  array_list_append(exlist,symbol);
162  g_hash_table_steal(symdict->tab,name);
163  if (!symdict->duptab)
164  symdict->duptab = g_hash_table_new(g_str_hash,g_str_equal);
165  g_hash_table_insert(symdict->duptab,name,exlist);
166 
168  "duplicate symbol(%s:0x%"PRIxSMOFFSET") (2)\n",
169  symbol_get_name(symbol),symbol->ref);
170  }
171  else {
172  if (!symdict->tab)
173  symdict->tab = g_hash_table_new(g_str_hash,g_str_equal);
174  g_hash_table_insert(symdict->tab,name,symbol);
175  }
176 
177  return 0;
178  }
179  else if (symbol->ref) {
180  if (symdict->anontab
181  && unlikely(g_hash_table_lookup(symdict->anontab,
182  (gpointer)(uintptr_t)symbol->ref))) {
183  verror("tried to insert duplicate anonymous symbol"
184  " at 0x%"PRIxSMOFFSET" -- BUG!\n",symbol->ref);
185  return 1;
186  }
187  if (!symdict->anontab)
188  symdict->anontab = g_hash_table_new(g_direct_hash,g_direct_equal);
189  g_hash_table_insert(symdict->anontab,
190  (gpointer)(uintptr_t)symbol->ref,symbol);
191 
192  return 0;
193  }
194  else {
195  verror("tried to insert non-anonymous symbol with no name/ref"
196  " -- BUG!\n");
197  return 1;
198  }
199 }
200 
202  if (!symbol->ref) {
203  verror("tried to insert anonymous symbol with no ref -- BUG!\n");
204  return 1;
205  }
206 
207  if (symdict->anontab
208  && unlikely(g_hash_table_lookup(symdict->anontab,
209  (gpointer)(uintptr_t)symbol->ref))) {
210  verror("tried to insert duplicate anonymous symbol"
211  " at 0x%"PRIxSMOFFSET" -- BUG!\n",symbol->ref);
212  return 1;
213  }
214  if (!symdict->anontab)
215  symdict->anontab = g_hash_table_new(g_direct_hash,g_direct_equal);
216 
217  g_hash_table_insert(symdict->anontab,
218  (gpointer)(uintptr_t)symbol->ref,symbol);
219 
220  return 0;
221 }
222 
224  char *name = symbol_get_name(symbol);
225  struct symbol *exsym = NULL;
226  struct array_list *exlist = NULL;
227  REFCNT trefcnt;
228 
229  if (name) {
230  if (unlikely(symdict->duptab)
231  && unlikely((exlist = (struct array_list *) \
232  g_hash_table_lookup(symdict->duptab,name)))) {
233  array_list_remove_item(exlist,symbol);
234  if (array_list_len(exlist) == 1) {
235  g_hash_table_remove(symdict->duptab,name);
236  exsym = (struct symbol *)array_list_item(exlist,0);
237  array_list_free(exlist);
238  g_hash_table_insert(symdict->tab,name,exsym);
239  }
240  }
241  else if (symdict->tab && g_hash_table_lookup(symdict->tab,name)) {
242  g_hash_table_remove(symdict->tab,name);
243  }
244  else {
245  verror("symbol(%s:0x%"PRIxSMOFFSET") not on symdict(%p)!\n",
246  name,symbol->ref,symdict);
247  return -1;
248  }
249  }
250  else if (unlikely(symdict->anontab)
251  && g_hash_table_lookup(symdict->anontab,
252  (gpointer)(uintptr_t)symbol->ref)) {
253  g_hash_table_remove(symdict->anontab,(gpointer)(uintptr_t)symbol->ref);
254  }
255  else {
256  verror("anon symbol(%s:0x%"PRIxSMOFFSET") not on symdict(%p)!\n",
257  name,symbol->ref,symdict);
258  return -1;
259  }
260 
261  return 0;
262 }
263 
264 static void _symdict_symbol_dtor(struct symbol *symbol,void *priv) {
265  symbol_free(symbol,1);
266 }
267 
269  _symdict_symbol_dtor;
270 
271 void symdict_free(struct symdict *symdict,symdict_symbol_dtor_t ssd,void *priv) {
272  GHashTableIter iter;
273  gpointer vp;
274  struct symbol *symbol;
275  struct array_list *list;
276  int i;
277 
278  if (!ssd)
280 
281  if (symdict->tab) {
282  g_hash_table_iter_init(&iter,symdict->tab);
283  while (g_hash_table_iter_next(&iter,NULL,&vp)) {
284  symbol = (struct symbol *)vp;
285  ssd(symbol,priv);
286  g_hash_table_iter_remove(&iter);
287  }
288  g_hash_table_destroy(symdict->tab);
289  }
290 
291  if (symdict->duptab) {
292  g_hash_table_iter_init(&iter,symdict->duptab);
293  while (g_hash_table_iter_next(&iter,NULL,&vp)) {
294  list = (struct array_list *)vp;
295  array_list_foreach(list,i,symbol) {
296  ssd(symbol,priv);
297  }
298  array_list_free(list);
299  g_hash_table_iter_remove(&iter);
300  }
301  g_hash_table_destroy(symdict->duptab);
302  }
303 
304  if (symdict->anontab) {
305  g_hash_table_iter_init(&iter,symdict->anontab);
306  while (g_hash_table_iter_next(&iter,NULL,&vp)) {
307  symbol = (struct symbol *)vp;
308  ssd(symbol,priv);
309  g_hash_table_iter_remove(&iter);
310  }
311  g_hash_table_destroy(symdict->anontab);
312  }
313 
314  free(symdict);
315 }
316 
317 void symdict_dump(struct symdict *symdict,struct dump_info *ud) {
318  char *p = "";
319  char *np;
320  struct dump_info udn;
321 
322  if (ud->prefix) {
323  p = ud->prefix;
324  np = malloc(strlen(p) + 1 + 2);
325  sprintf(np,"%s%s",p," ");
326  }
327  else {
328  np = " ";
329  }
330  udn.prefix = np;
331  udn.stream = ud->stream;
332  udn.meta = ud->meta;
333  udn.detail = ud->detail;
334 
335  if (symdict->tab)
336  g_hash_table_foreach(symdict->tab,g_hash_foreach_dump_symbol,&udn);
337  if (symdict->duptab)
338  g_hash_table_foreach(symdict->duptab,g_hash_foreach_dump_symbol_list,&udn);
339 
340  if (ud->prefix) {
341  free(np);
342  }
343 }
344 
348 struct symbol *symdict_get_sym(struct symdict *symdict,const char *name,
349  symbol_type_flag_t flags) {
350  int i;
351  struct symbol *symbol = NULL;
352  struct symbol *svalue;
353  struct array_list *duplist;
354 
355  if (symdict->tab
356  && (svalue = (struct symbol *)g_hash_table_lookup(symdict->tab,name))
357  && SYMBOL_TYPE_FLAG_MATCHES(svalue,flags)) {
358  /* If this is a type symbol, or a symbol with a location,
359  * allow it to match right away; else, save it off if we
360  * haven't already saved off a "first match"; else, save it
361  * off and return it if we don't find anything better!
362  */
363  symbol = svalue;
365  if (SYMBOL_IS_TYPE(svalue))
367  "found type %s\n",symbol_get_name(symbol));
368  else if (!svalue->isdeclaration)
370  "found definition %s\n",symbol_get_name(symbol));
371  else
373  "found non-type, non-definition %s\n",
374  symbol_get_name(symbol));
375  }
376  }
377  /* If it's in the duptab table, figure out which match is best; we
378  * prefer the first non-type definition, unless they're looking for
379  * a type.
380  */
381  else if (symdict->duptab
382  && (duplist = (struct array_list *) \
383  g_hash_table_lookup(symdict->duptab,name))) {
384  for (i = 0; i < array_list_len(duplist); ++i) {
385  svalue = (struct symbol *)array_list_item(duplist,i);
386  if (SYMBOL_TYPE_FLAG_MATCHES(svalue,flags)) {
387  /* If this is a type symbol, or a symbol with a location,
388  * allow it to match right away; else, save it off if we
389  * haven't already saved off a "first match"; else, save it
390  * off and return it if we don't find anything better!
391  */
392  if (symbol_is_definition(svalue)) {
393  symbol = svalue;
395  "found dup definition %s\n",symbol_get_name(symbol));
396  break;
397  }
398  else if (SYMBOL_IS_TYPE(svalue)) {
399  symbol = svalue;
401  "found dup type %s; saving and continuing search\n",
402  symbol_get_name(symbol));
403  //break;
404  }
405  else if (!symbol) {
406  symbol = svalue;
408  "found dup non-type, non-definition %s;"
409  " saving and continuing search\n",
410  symbol_get_name(symbol));
411  }
412  }
413  }
414  }
415 
416  return symbol;
417 }
418 
420  struct rfilter *symbol_filter,
421  symbol_type_flag_t flags,
422  int no_main,int no_dup,int no_anon) {
423  GHashTableIter iter;
424  char *name;
425  struct symbol *symbol;
426  int accept;
427  gpointer key;
428  gpointer value;
429  struct array_list *duplist;
430  int i;
431  GSList *retval = NULL;
432 
433  if (!no_main && symdict->tab) {
434  g_hash_table_iter_init(&iter,symdict->tab);
435  while (g_hash_table_iter_next(&iter,&key,&value)) {
436  name = (char *)key;
437  symbol = (struct symbol *)value;
438  if (SYMBOL_TYPE_FLAG_MATCHES(symbol,flags)) {
439  rfilter_check(symbol_filter,name,&accept,NULL);
440  if (accept == RF_ACCEPT)
441  retval = g_slist_prepend(retval,symbol);
442  }
443  }
444  }
445 
446  if (!no_dup && symdict->duptab) {
447  g_hash_table_iter_init(&iter,symdict->duptab);
448  while (g_hash_table_iter_next(&iter,&key,&value)) {
449  name = (char *)key;
450  duplist = (struct array_list *)value;
451 
452  /* Like the above ->tab search, but this time check the
453  * name first, and then only check the symbol flags if
454  * the name matched.
455  */
456  rfilter_check(symbol_filter,name,&accept,NULL);
457  if (accept == RF_ACCEPT) {
458  for (i = 0; i < array_list_len(duplist); ++i) {
459  symbol = (struct symbol *)array_list_item(duplist,i);
460  if (SYMBOL_TYPE_FLAG_MATCHES(symbol,flags)) {
461  retval = g_slist_prepend(retval,symbol);
462  }
463  }
464  }
465  }
466  }
467 
468  if (!no_anon && !symbol_filter && symdict->anontab) {
469  g_hash_table_iter_init(&iter,symdict->anontab);
470  while (g_hash_table_iter_next(&iter,NULL,&value)) {
471  symbol = (struct symbol *)value;
472  if (SYMBOL_TYPE_FLAG_MATCHES(symbol,flags)) {
473  retval = g_slist_prepend(retval,symbol);
474  }
475  }
476  }
477 
478  return retval;
479 }
480 
481 GSList *symdict_match_syms(struct symdict *symdict,struct rfilter *symbol_filter,
482  symbol_type_flag_t flags) {
483  return symdict_match_syms_by_tab(symdict,symbol_filter,flags,0,0,0);
484 }
int symdict_remove_symbol(struct symdict *symdict, struct symbol *symbol)
Definition: symdict.c:223
#define RF_ACCEPT
Definition: rfilter.h:29
symdict_symbol_dtor_t default_symdict_symbol_dtor
Definition: symdict.c:268
#define unlikely(expr)
Definition: debugpred.h:101
int symdict_get_size(struct symdict *symdict)
Definition: symdict.c:68
GHashTable * anontab
Definition: dwdebug_priv.h:383
void * p
static uint64_t unsigned int i
GHashTable * tab
Definition: dwdebug_priv.h:368
SMOFFSET ref
Definition: dwdebug_priv.h:868
void symdict_free(struct symdict *symdict, symdict_symbol_dtor_t ssd, void *priv)
Definition: symdict.c:271
struct symdict * symdict_create(void)
Definition: symdict.c:35
REFCNT symbol_free(struct symbol *symbol, int force)
Definition: debug.c:4516
int symdict_get_sizes(struct symdict *symdict, int *named, int *duplicated, int *anon)
Definition: symdict.c:108
#define verror(format,...)
Definition: log.h:30
int symdict_insert_symbol_anon(struct symdict *symdict, struct symbol *symbol)
Definition: symdict.c:201
void ** list
Definition: alist.h:34
int symdict_get_size_simple(struct symdict *symdict)
Definition: symdict.c:55
struct symbol * symdict_get_sym(struct symdict *symdict, const char *name, symbol_type_flag_t flags)
Definition: symdict.c:348
void free(void *ptr)
Definition: debugserver.c:207
Definition: log.h:69
void g_hash_foreach_dump_symbol(gpointer key __attribute__((unused)), gpointer value, gpointer userdata)
Definition: debug.c:4860
char * prefix
Definition: output.h:25
int symdict_insert_symbol(struct symdict *symdict, struct symbol *symbol)
Definition: symdict.c:141
#define array_list_foreach(alist, lpc, placeholder)
Definition: alist.h:371
#define SYMBOL_TYPE_FLAG_MATCHES(sym, flags)
char * name
Definition: dwdebug_priv.h:788
#define PRIxSMOFFSET
Definition: common.h:102
void(* symdict_symbol_dtor_t)(struct symbol *symbol, void *priv)
Definition: dwdebug_priv.h:419
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
FILE * stream
Definition: output.h:26
unsigned int isdeclaration
Definition: dwdebug_priv.h:839
#define SYMBOL_IS_TYPE(sym)
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
Definition: log.h:129
GSList * symdict_match_syms_by_tab(struct symdict *symdict, struct rfilter *symbol_filter, symbol_type_flag_t flags, int no_main, int no_dup, int no_anon)
Definition: symdict.c:419
Definition: log.h:125
int symdict_get_size_named(struct symdict *symdict)
Definition: symdict.c:89
GHashTable * duptab
Definition: dwdebug_priv.h:375
GSList * symdict_match_syms(struct symdict *symdict, struct rfilter *symbol_filter, symbol_type_flag_t flags)
Definition: symdict.c:481
uint32_t REFCNT
Definition: common.h:124
int detail
Definition: output.h:28
void g_hash_foreach_dump_symbol_list(gpointer key __attribute__((unused)), gpointer value, gpointer userdata)
Definition: debug.c:4847
char * symbol_get_name(struct symbol *symbol)
Definition: debug.c:2587
void * malloc(size_t size)
Definition: debugserver.c:214
symbol_type_flag_t
Definition: dwdebug.h:190
void symdict_dump(struct symdict *symdict, struct dump_info *ud)
Definition: symdict.c:317
int meta
Definition: output.h:27
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