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
dumpdebuginfo.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 <stdlib.h>
21 #include <getopt.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <regex.h>
26 #include <ctype.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 
31 #include "common.h"
32 #include "log.h"
33 #include "binfile.h"
34 #include "dwdebug.h"
35 
36 extern struct binfile_ops elf_binfile_ops;
37 
38 extern char *optarg;
39 extern int optind, opterr, optopt;
40 
41 int main(int argc,char **argv) {
42  char ch;
43  char *filename;
44  struct debugfile *debugfile;
45  int detail = 0;
46  int meta = 0;
47  int i;
48  char *optargc;
49  int dotypes = 1;
50  int doglobals = 1;
51  int dosymtabs = 1;
52  int doelfsymtab = 1;
53  int doreverse = 0;
54  int doranges = 1;
55  char *endptr = NULL;
56  struct lsymbol *s;
57  struct lsymbol *s2;
58  struct symbol *is;
59  struct symbol *ps;
60  struct array_list *opts_list = NULL;
61  struct debugfile_load_opts *opts;
62  struct binfile_instance *bfi = NULL;
63  struct binfile_instance_elf *bfelfi = NULL;
64  char *saveptr = NULL;
65  char *mapi;
66  int sec;
67  ADDR addr;
68  ADDR base = 0;
69  int infer = 0;
70  int quiet = 0;
71  int nofree = 0;
72 
73  dwdebug_init();
74 
75  while ((ch = getopt(argc, argv, "d::w::gDMl:F:TGSErI:i:RNq")) != -1) {
76  switch(ch) {
77  case 'd':
78  if (optarg) {
79  if (*optarg == 'd') {
80  optarg = &optarg[1];
82  while (*optarg == 'd') {
84  optarg = &optarg[1];
85  }
86  }
87  else
89  }
90  else
92  break;
93  case 'w':
94  if (optarg) {
95  if (*optarg == 'w') {
96  optarg = &optarg[1];
98  while (*optarg == 'w') {
100  optarg = &optarg[1];
101  }
102  }
103  else
104  vmi_set_warn_level(atoi(optarg));
105  }
106  else
108  break;
109  case 'D':
110  ++detail;
111  break;
112  case 'M':
113  ++meta;
114  break;
115  case 'l':
116  if (vmi_add_log_area_flaglist(optarg,NULL)) {
117  fprintf(stderr,"ERROR: bad debug flag in '%s'!\n",optarg);
118  exit(-1);
119  }
120  break;
121  case 'F':
122  optargc = strdup(optarg);
123 
124  opts = debugfile_load_opts_parse(optargc);
125 
126  if (!opts) {
127  verror("bad debugfile_load_opts '%s'!\n",optarg);
128  goto dlo_err;
129  }
130  else {
131  if (!opts_list)
132  opts_list = array_list_create(4);
133 
134  array_list_append(opts_list,opts);
135  }
136  free(optargc);
137  break;
138  dlo_err:
139  fprintf(stderr,"ERROR: bad debugfile_load_opts '%s'!\n",optargc);
140  free(optargc);
141  if (opts_list) {
142  array_list_foreach(opts_list,i,opts) {
144  }
145  array_list_free(opts_list);
146  }
147  exit(-1);
148  case 'T':
149  dotypes = 0;
150  break;
151  case 'G':
152  doglobals = 0;
153  break;
154  case 'S':
155  dosymtabs = 0;
156  break;
157  case 'E':
158  doelfsymtab = 0;
159  break;
160  case 'r':
161  doreverse = 1;
162  break;
163  case 'i':
164  infer = 1;
165  base = (ADDR)strtoul(optarg,NULL,0);
166  break;
167  case 'I':
168  bfi = calloc(1,sizeof(*bfi));
169  bfi->ops = &elf_binfile_ops;
170  bfi->priv = bfelfi = calloc(1,sizeof(*bfelfi));
171 
172  bfelfi->num_sections = 0;
173  bfelfi->section_tab = NULL;
174 
175  while ((mapi = strtok_r(!saveptr ? optarg : NULL,",",&saveptr))) {
176  if (sscanf(mapi,"%u:%lx",&sec,&addr) == 2) {
177  if ((sec + 1) > bfelfi->num_sections) {
178  bfelfi->num_sections = sec + 1;
179  bfelfi->section_tab = realloc(bfelfi->section_tab,
180  (sec + 1)*sizeof(ADDR));
181  }
182  bfelfi->section_tab[sec] = addr;
183  }
184  }
185 
186  break;
187  case 'R':
188  doranges = 0;
189  break;
190  case 'N':
191  nofree = 1;
192  break;
193  case 'q':
194  quiet = 1;
195  break;
196  default:
197  fprintf(stderr,"ERROR: unknown option %c!\n",ch);
198  exit(-1);
199  }
200  }
201 
202  argc -= optind;
203  argv += optind;
204 
205  if (argc >= 1)
206  filename = argv[0];
207  else {
208  fprintf(stderr,"ERROR: you must supply an ELF filename!\n");
209  exit(-1);
210  }
211 
212  if (infer) {
213  bfi = binfile_infer_instance(filename,NULL,base,NULL);
214  debugfile = debugfile_from_instance(bfi,opts_list);
215  }
216  else if (bfi) {
217  bfi->filename = filename;
218  debugfile = debugfile_from_instance(bfi,opts_list);
219  }
220  else
221  debugfile = debugfile_from_file(filename,NULL,opts_list);
222  if (!debugfile) {
223  fprintf(stderr,"ERROR: could not create debugfile from %s!\n",
224  filename);
225  exit(-1);
226  }
227 
228  struct dump_info ud = {
229  .stream = stdout,
230  .prefix = "",
231  .meta = meta,
232  .detail = detail,
233  };
234 
235  if (argc < 2 && !quiet)
236  debugfile_dump(debugfile,&ud,dotypes,doglobals,dosymtabs,doelfsymtab,
237  doranges);
238  else {
239  for (i = 1; i < argc; ++i) {
240  ADDR addr = (ADDR)strtoull(argv[i],&endptr,0);
241  char *cptr = NULL;
242 
243  if ((cptr = rindex(argv[i],':'))) {
244  *cptr = '\0';
245  ++cptr;
246  if (isdigit(*cptr))
247  s = debugfile_lookup_sym_line(debugfile,argv[i],
248  atoi(cptr),NULL,NULL);
249  else if (*cptr == 'F' || *cptr == 'f') {
250  GSList *list = NULL;
251  GSList *list2;
252  struct rfilter *rfilter = rfilter_create_parse(argv[i]);
253  if (!rfilter) {
254  fprintf(stderr,
255  "Could not create symbol rfilter from '%s'!\n",
256  argv[i]);
257  continue;
258  }
259 
261  if (*cptr == 'F')
263  list = debugfile_match_syms(debugfile,rfilter,flags,NULL);
264  if (!list) {
265  fprintf(stderr,
266  "Did not find any symbols for rfilter '%s'!\n",
267  argv[i]);
268  continue;
269  }
270 
271  list2 = list;
272  while (list2) {
273  symbol_dump((struct symbol *)list2->data,&ud);
274  fprintf(ud.stream,"\n");
275  list2 = g_slist_next(list2);
276  }
277 
278  rfilter_free(rfilter);
279  g_slist_free(list);
280  continue;
281  }
282  else {
283  fprintf(stderr,
284  "Unknown suffix char '%c' in arg '%s', skipping!\n",
285  *cptr,argv[i]);
286  continue;
287  }
288  }
289  else if (endptr != argv[i]) {
290  s = debugfile_lookup_addr(debugfile,addr);
291  }
292  else {
293  s = debugfile_lookup_sym(debugfile,argv[i],".",
294  NULL,SYMBOL_TYPE_NONE);
295  }
296 
297  if (!s) {
298  fprintf(stderr,"Could not lookup %s!\n",argv[i]);
299  }
300  else {
301  fprintf(stdout,"forward lookup %s: ",argv[i]);
302  lsymbol_dump(s,&ud);
303  fprintf(stdout,"\n");
304  is = s->symbol;
306  fprintf(stdout,"first noninline parent %s: \n",argv[i]);
307  ud.prefix = " ";
309  if (ps) {
310  symbol_dump(ps,&ud);
311  fprintf(stdout,"\n");
312  }
313  else
314  fprintf(stdout,"NO PARENT! (fake inline of itself?)\n");
315  }
316  /* We release this one because we got it through a
317  * lookup function, so a ref was taken to it on our
318  * behalf.
319  */
320  lsymbol_release(s);
321 
322  if (doreverse) {
324  fprintf(stdout,"reverse lookup %s: ",argv[i]);
325  ud.prefix = "";
326  lsymbol_dump(s2,&ud);
327  /* We free this one instead of releasing because we
328  * created it instead of looked it up, so a ref to it was
329  * not taken on our behalf.
330  */
331  lsymbol_release(s2);
332  fprintf(stdout,"\n");
333  }
334  }
335  }
336  }
337 
338  if (!nofree) {
339  dwdebug_fini();
340 
341 #ifdef REF_DEBUG
343 #endif
344  }
345 
346  if (opts_list) {
347  array_list_foreach(opts_list,i,opts) {
349  }
350  array_list_free(opts_list);
351  }
352 
353  return 0;
354 }
char * optarg
int optind
struct debugfile * debugfile_from_file(char *filename, char *root_prefix, struct array_list *debugfile_load_opts_list)
Definition: debug.c:1584
struct binfile_instance * binfile_infer_instance(char *filename, char *root_prefix, ADDR base, GHashTable *config)
Definition: binfile.c:242
REFCNT lsymbol_release(struct lsymbol *lsymbol)
Definition: debug.c:4805
struct symbol * symbol
Definition: dwdebug.h:1010
struct lsymbol * lsymbol_create_from_symbol(struct symbol *symbol)
Definition: debug.c:4722
struct symbol * lsymbol_get_noninline_parent_symbol(struct lsymbol *lsymbol)
Definition: debug.c:4742
static uint64_t unsigned int i
void vmi_inc_log_level(void)
Definition: log.c:38
int vmi_add_log_area_flaglist(char *flaglist, char *separator)
Definition: log.c:103
int symbol_is_inlineinstance(struct symbol *symbol)
Definition: debug.c:3044
#define verror(format,...)
Definition: log.h:30
struct lsymbol * debugfile_lookup_addr(struct debugfile *debugfile, ADDR addr)
Definition: debug.c:667
void vmi_set_log_level(int level)
Definition: log.c:34
void dwdebug_init(void)
Definition: debug.c:83
void lsymbol_dump(struct lsymbol *lsymbol, struct dump_info *ud)
Definition: debug.c:5622
void free(void *ptr)
Definition: debugserver.c:207
char * prefix
Definition: output.h:25
#define array_list_foreach(alist, lpc, placeholder)
Definition: alist.h:371
void dwdebug_fini(void)
Definition: debug.c:143
int optopt
struct array_list list
Definition: rfilter.h:41
struct dt_argp_state opts
Definition: dumptarget.c:111
struct debugfile_load_opts * debugfile_load_opts_parse(char *optstr)
Definition: debug.c:1194
int main(int argc, char **argv)
Definition: dumpdebuginfo.c:41
int opterr
void symbol_dump(struct symbol *symbol, struct dump_info *ud)
Definition: debug.c:5572
void vmi_set_warn_level(int level)
Definition: log.c:42
struct binfile_ops elf_binfile_ops
Definition: binfile_elf.c:67
void vmi_inc_warn_level(void)
Definition: log.c:46
void * realloc(void *ptr, size_t size)
Definition: debugserver.c:221
FILE * stream
Definition: output.h:26
struct lsymbol * debugfile_lookup_sym(struct debugfile *debugfile, char *name, const char *delim, struct rfilter *srcfile_filter, symbol_type_flag_t flags)
Definition: debug.c:1021
int16_t s2
struct debugfile * debugfile_from_instance(struct binfile_instance *bfinst, struct array_list *debugfile_load_opts_list)
Definition: debug.c:1726
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
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 binfile_ops * ops
Definition: binfile.h:381
#define REF_DEBUG_REPORT_FINISH()
Definition: common.h:653
uint32_t ADDR
Definition: common.h:64
int detail
Definition: output.h:28
void debugfile_load_opts_free(struct debugfile_load_opts *opts)
Definition: debug.c:1275
symbol_type_flag_t
Definition: dwdebug.h:190
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 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
unsigned int num_sections
Definition: binfile.h:386
char * filename
Definition: binfile.h:368