|
1 /* |
|
2 Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. |
|
3 Portions Copyright (C) 2007 David Anderson. All Rights Reserved. |
|
4 Portions Copyright 2007 Sun Microsystems, Inc. All rights reserved. |
|
5 |
|
6 |
|
7 This program is free software; you can redistribute it and/or modify it |
|
8 under the terms of version 2 of the GNU General Public License as |
|
9 published by the Free Software Foundation. |
|
10 |
|
11 This program is distributed in the hope that it would be useful, but |
|
12 WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
14 |
|
15 Further, this software is distributed without any warranty that it is |
|
16 free of the rightful claim of any third person regarding infringement |
|
17 or the like. Any license provided herein, whether implied or |
|
18 otherwise, applies only to this software file. Patent licenses, if |
|
19 any, provided herein do not apply to combinations of this program with |
|
20 other software, or any other product whatsoever. |
|
21 |
|
22 You should have received a copy of the GNU General Public License along |
|
23 with this program; if not, write the Free Software Foundation, Inc., 51 |
|
24 Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. |
|
25 |
|
26 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, |
|
27 Mountain View, CA 94043, or: |
|
28 |
|
29 http://www.sgi.com |
|
30 |
|
31 For further information regarding this notice, see: |
|
32 |
|
33 http://oss.sgi.com/projects/GenInfo/NoticeExplan |
|
34 |
|
35 |
|
36 $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwarfdump.c,v 1.48 2006/04/18 18:05:57 davea Exp $ */ |
|
37 |
|
38 /* The address of the Free Software Foundation is |
|
39 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
|
40 Boston, MA 02110-1301, USA. |
|
41 SGI has moved from the Crittenden Lane address. |
|
42 */ |
|
43 |
|
44 |
|
45 |
|
46 #include "globals.h" |
|
47 |
|
48 /* for 'open' */ |
|
49 #include <sys/types.h> |
|
50 #include <sys/stat.h> |
|
51 #include <fcntl.h> |
|
52 #ifdef HAVE_GETOPT_H |
|
53 #include <getopt.h> |
|
54 #endif |
|
55 |
|
56 #include "makename.h" |
|
57 #include "dwconf.h" |
|
58 extern char *optarg; |
|
59 |
|
60 #define OKAY 0 |
|
61 #define FAILED 1 |
|
62 #define BYTES_PER_INSTRUCTION 4 |
|
63 |
|
64 static string process_args(int argc, char *argv[]); |
|
65 static void print_infos(Dwarf_Debug dbg); |
|
66 static void print_usage_message(void); |
|
67 |
|
68 static string program_name; |
|
69 int check_error = 0; |
|
70 |
|
71 /* defined in print_sections.c, die for the current compile unit, |
|
72 used in get_fde_proc_name() */ |
|
73 extern Dwarf_Die current_cu_die_for_print_frames; |
|
74 |
|
75 |
|
76 boolean info_flag = FALSE; |
|
77 boolean use_old_dwarf_loclist = FALSE; /* This so both dwarf_loclist() |
|
78 and dwarf_loclist_n() can be |
|
79 tested. Defaults to new |
|
80 dwarf_loclist_n() */ |
|
81 |
|
82 static boolean line_flag = FALSE; |
|
83 static boolean abbrev_flag = FALSE; |
|
84 static boolean frame_flag = FALSE; /* .debug_frame section. */ |
|
85 static boolean eh_frame_flag = FALSE; /* GNU .eh_frame section. */ |
|
86 static boolean pubnames_flag = FALSE; |
|
87 static boolean macinfo_flag = FALSE; |
|
88 static boolean loc_flag = FALSE; |
|
89 static boolean aranges_flag = FALSE; |
|
90 static boolean string_flag = FALSE; |
|
91 static boolean reloc_flag = FALSE; |
|
92 static boolean static_func_flag = FALSE; |
|
93 static boolean static_var_flag = FALSE; |
|
94 static boolean type_flag = FALSE; |
|
95 static boolean weakname_flag = FALSE; |
|
96 |
|
97 int verbose = 0; |
|
98 boolean dense = FALSE; |
|
99 boolean ellipsis = FALSE; |
|
100 boolean dst_format = FALSE; |
|
101 boolean show_global_offsets = FALSE; |
|
102 |
|
103 boolean check_abbrev_code = FALSE; |
|
104 boolean check_pubname_attr = FALSE; |
|
105 boolean check_reloc_offset = FALSE; |
|
106 boolean check_attr_tag = FALSE; |
|
107 boolean check_tag_tree = FALSE; |
|
108 boolean check_type_offset = FALSE; |
|
109 boolean generic_1000_regs = FALSE; |
|
110 |
|
111 static boolean dwarf_check = FALSE; |
|
112 |
|
113 /* These configure items are for the |
|
114 frame data. |
|
115 */ |
|
116 static char *config_file_path = 0; |
|
117 static char *config_file_abi = 0; |
|
118 static char *config_file_defaults[] = { |
|
119 "./dwarfdump.conf", |
|
120 /* Note: HOME location uses .dwarfdump. */ |
|
121 "HOME/.dwarfdump.conf", |
|
122 #ifdef CONFPREFIX |
|
123 /* See Makefile.in "libdir" and CFLAGS */ |
|
124 /* We need 2 levels of macro to get the name turned into |
|
125 the string we want. */ |
|
126 #define STR2(s) # s |
|
127 #define STR(s) STR2(s) |
|
128 STR(CONFPREFIX) |
|
129 "/dwarfdump.conf", |
|
130 #else |
|
131 "/usr/lib/dwarfdump.conf", |
|
132 #endif |
|
133 0 |
|
134 }; |
|
135 static struct dwconf_s config_file_data; |
|
136 |
|
137 char cu_name[BUFSIZ]; |
|
138 boolean cu_name_flag = FALSE; |
|
139 Dwarf_Unsigned cu_offset = 0; |
|
140 |
|
141 Dwarf_Check_Result abbrev_code_result; |
|
142 Dwarf_Check_Result pubname_attr_result; |
|
143 Dwarf_Check_Result reloc_offset_result; |
|
144 Dwarf_Check_Result attr_tag_result; |
|
145 Dwarf_Check_Result tag_tree_result; |
|
146 Dwarf_Check_Result type_offset_result; |
|
147 |
|
148 Dwarf_Error err; |
|
149 |
|
150 #define PRINT_CHECK_RESULT(str,result) {\ |
|
151 fprintf(stderr, "%-24s%8d%8d\n", str, result.checks, result.errors); \ |
|
152 } |
|
153 |
|
154 static int process_one_file(Elf * elf, string file_name, int archive, |
|
155 struct dwconf_s *conf); |
|
156 static int |
|
157 open_a_file(string name) |
|
158 { |
|
159 int f = 0; |
|
160 |
|
161 #ifdef __CYGWIN__ |
|
162 f = open(name, O_RDONLY | O_BINARY); |
|
163 #else |
|
164 f = open(name, O_RDONLY); |
|
165 #endif |
|
166 return f; |
|
167 |
|
168 } |
|
169 |
|
170 /* |
|
171 * Iterate through dwarf and print all info. |
|
172 */ |
|
173 int |
|
174 main(int argc, char *argv[]) |
|
175 { |
|
176 string file_name; |
|
177 int f; |
|
178 Elf_Cmd cmd; |
|
179 Elf *arf, *elf; |
|
180 int archive = 0; |
|
181 |
|
182 (void) elf_version(EV_NONE); |
|
183 if (elf_version(EV_CURRENT) == EV_NONE) { |
|
184 (void) fprintf(stderr, "dwarfdump: libelf.a out of date.\n"); |
|
185 exit(1); |
|
186 } |
|
187 |
|
188 file_name = process_args(argc, argv); |
|
189 f = open_a_file(file_name); |
|
190 if (f == -1) { |
|
191 fprintf(stderr, "%s ERROR: can't open %s\n", program_name, |
|
192 file_name); |
|
193 return (FAILED); |
|
194 } |
|
195 |
|
196 cmd = ELF_C_READ; |
|
197 arf = elf_begin(f, cmd, (Elf *) 0); |
|
198 if (elf_kind(arf) == ELF_K_AR) { |
|
199 archive = 1; |
|
200 } |
|
201 while ((elf = elf_begin(f, cmd, arf)) != 0) { |
|
202 Elf32_Ehdr *eh32; |
|
203 |
|
204 #ifdef HAVE_ELF64_GETEHDR |
|
205 Elf64_Ehdr *eh64; |
|
206 #endif /* HAVE_ELF64_GETEHDR */ |
|
207 eh32 = elf32_getehdr(elf); |
|
208 if (!eh32) { |
|
209 #ifdef HAVE_ELF64_GETEHDR |
|
210 /* not a 32-bit obj */ |
|
211 eh64 = elf64_getehdr(elf); |
|
212 if (!eh64) { |
|
213 /* not a 64-bit obj either! */ |
|
214 /* dwarfdump is quiet when not an object */ |
|
215 } else { |
|
216 process_one_file(elf, file_name, archive, |
|
217 &config_file_data); |
|
218 } |
|
219 #endif /* HAVE_ELF64_GETEHDR */ |
|
220 } else { |
|
221 process_one_file(elf, file_name, archive, |
|
222 &config_file_data); |
|
223 } |
|
224 cmd = elf_next(elf); |
|
225 elf_end(elf); |
|
226 } |
|
227 elf_end(arf); |
|
228 /* Trivial malloc space cleanup. */ |
|
229 clean_up_die_esb(); |
|
230 clean_up_syms_malloc_data(); |
|
231 |
|
232 if (check_error) |
|
233 return FAILED; |
|
234 else |
|
235 return OKAY; |
|
236 } |
|
237 |
|
238 /* |
|
239 Given a file which we know is an elf file, process |
|
240 the dwarf data. |
|
241 |
|
242 */ |
|
243 static int |
|
244 process_one_file(Elf * elf, string file_name, int archive, |
|
245 struct dwconf_s *config_file_data) |
|
246 { |
|
247 Dwarf_Debug dbg; |
|
248 int dres; |
|
249 |
|
250 dres = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err); |
|
251 if (dres == DW_DLV_NO_ENTRY) { |
|
252 printf("No DWARF information present in %s\n", file_name); |
|
253 return 0; |
|
254 } |
|
255 if (dres != DW_DLV_OK) { |
|
256 print_error(dbg, "dwarf_elf_init", dres, err); |
|
257 } |
|
258 |
|
259 if (archive) { |
|
260 Elf_Arhdr *mem_header = elf_getarhdr(elf); |
|
261 |
|
262 printf("\narchive member \t%s\n", |
|
263 mem_header ? mem_header->ar_name : ""); |
|
264 } |
|
265 dwarf_set_frame_rule_inital_value(dbg, |
|
266 config_file_data-> |
|
267 cf_initial_rule_value); |
|
268 dwarf_set_frame_rule_table_size(dbg, |
|
269 config_file_data-> |
|
270 cf_table_entry_count); |
|
271 |
|
272 if (info_flag || line_flag || cu_name_flag) |
|
273 print_infos(dbg); |
|
274 if (pubnames_flag) |
|
275 print_pubnames(dbg); |
|
276 if (macinfo_flag) |
|
277 print_macinfo(dbg); |
|
278 if (loc_flag) |
|
279 print_locs(dbg); |
|
280 if (abbrev_flag) |
|
281 print_abbrevs(dbg); |
|
282 if (string_flag) |
|
283 print_strings(dbg); |
|
284 if (aranges_flag) |
|
285 print_aranges(dbg); |
|
286 if (frame_flag || eh_frame_flag) { |
|
287 current_cu_die_for_print_frames = 0; |
|
288 print_frames(dbg, frame_flag, eh_frame_flag, config_file_data); |
|
289 } |
|
290 if (static_func_flag) |
|
291 print_static_funcs(dbg); |
|
292 if (static_var_flag) |
|
293 print_static_vars(dbg); |
|
294 /* DWARF_PUBTYPES is the standard typenames dwarf section. |
|
295 SGI_TYPENAME is the same concept but is SGI specific ( it was |
|
296 defined 10 years before dwarf pubtypes). */ |
|
297 |
|
298 if (type_flag) { |
|
299 print_types(dbg, DWARF_PUBTYPES); |
|
300 print_types(dbg, SGI_TYPENAME); |
|
301 } |
|
302 if (weakname_flag) |
|
303 print_weaknames(dbg); |
|
304 if (reloc_flag) |
|
305 print_relocinfo(dbg); |
|
306 if (dwarf_check) { |
|
307 fprintf(stderr, "DWARF CHECK RESULT\n"); |
|
308 fprintf(stderr, "<item> <checks><errors>\n"); |
|
309 } |
|
310 if (check_pubname_attr) |
|
311 PRINT_CHECK_RESULT("pubname_attr", pubname_attr_result) |
|
312 if (check_attr_tag) |
|
313 PRINT_CHECK_RESULT("attr_tag", attr_tag_result) |
|
314 if (check_tag_tree) |
|
315 PRINT_CHECK_RESULT("tag_tree", tag_tree_result) |
|
316 if (check_type_offset) |
|
317 PRINT_CHECK_RESULT("type_offset", |
|
318 type_offset_result) |
|
319 |
|
320 dres = dwarf_finish(dbg, &err); |
|
321 if (dres != DW_DLV_OK) { |
|
322 print_error(dbg, "dwarf_finish", dres, err); |
|
323 } |
|
324 return 0; |
|
325 |
|
326 } |
|
327 |
|
328 static void do_all() |
|
329 { |
|
330 info_flag = line_flag = frame_flag = abbrev_flag = TRUE; |
|
331 pubnames_flag = aranges_flag = macinfo_flag = TRUE; |
|
332 loc_flag = string_flag = TRUE; |
|
333 reloc_flag = TRUE; |
|
334 static_func_flag = static_var_flag = TRUE; |
|
335 type_flag = weakname_flag = TRUE; |
|
336 } |
|
337 |
|
338 /* process arguments and return object filename */ |
|
339 static string |
|
340 process_args(int argc, char *argv[]) |
|
341 { |
|
342 extern int optind; |
|
343 int c = 0; |
|
344 boolean usage_error = FALSE; |
|
345 int oarg = 0; |
|
346 |
|
347 program_name = argv[0]; |
|
348 |
|
349 /* j q unused */ |
|
350 if (argv[1] != NULL && argv[1][0] != '-') { |
|
351 do_all(); |
|
352 } |
|
353 |
|
354 while ((c = |
|
355 getopt(argc, argv, |
|
356 "abcdefFgGhik:lmoprRst:u:vVwx:yz")) != EOF) { |
|
357 switch (c) { |
|
358 case 'x': /* Select abi/path to use */ |
|
359 { |
|
360 char *path = 0; |
|
361 char *abi = 0; |
|
362 |
|
363 /* -x name=<path> meaning name dwarfdump.conf file -x |
|
364 abi=<abi> meaning select abi from dwarfdump.conf |
|
365 file. Must always select abi to use dwarfdump.conf */ |
|
366 if (strncmp(optarg, "name=", 5) == 0) { |
|
367 path = makename(&optarg[5]); |
|
368 if (strlen(path) < 1) |
|
369 goto badopt; |
|
370 config_file_path = path; |
|
371 } else if (strncmp(optarg, "abi=", 4) == 0) { |
|
372 abi = makename(&optarg[4]); |
|
373 if (strlen(abi) < 1) |
|
374 goto badopt; |
|
375 config_file_abi = abi; |
|
376 break; |
|
377 } else { |
|
378 badopt: |
|
379 fprintf(stderr, "-x name=<path-to-conf> \n"); |
|
380 fprintf(stderr, " and \n"); |
|
381 fprintf(stderr, "-x abi=<abi-in-conf> \n"); |
|
382 fprintf(stderr, "are legal, not -x %s\n", optarg); |
|
383 usage_error = TRUE; |
|
384 break; |
|
385 } |
|
386 } |
|
387 break; |
|
388 case 'g': |
|
389 use_old_dwarf_loclist = TRUE; |
|
390 /* FALL THROUGH. */ |
|
391 case 'i': |
|
392 info_flag = TRUE; |
|
393 break; |
|
394 case 'l': |
|
395 line_flag = TRUE; |
|
396 break; |
|
397 case 'f': |
|
398 frame_flag = TRUE; |
|
399 break; |
|
400 case 'F': |
|
401 eh_frame_flag = TRUE; |
|
402 break; |
|
403 case 'b': |
|
404 abbrev_flag = TRUE; |
|
405 break; |
|
406 case 'p': |
|
407 pubnames_flag = TRUE; |
|
408 break; |
|
409 case 'r': |
|
410 aranges_flag = TRUE; |
|
411 break; |
|
412 case 'R': |
|
413 generic_1000_regs = TRUE; |
|
414 info_flag = TRUE; |
|
415 break; |
|
416 case 'm': |
|
417 macinfo_flag = TRUE; |
|
418 break; |
|
419 case 'c': |
|
420 loc_flag = TRUE; |
|
421 break; |
|
422 case 's': |
|
423 string_flag = TRUE; |
|
424 break; |
|
425 case 'a': |
|
426 do_all(); |
|
427 break; |
|
428 case 'v': |
|
429 verbose++; |
|
430 break; |
|
431 case 'V': |
|
432 { |
|
433 printf("%s\n","Version 4May2007"); |
|
434 } |
|
435 break; |
|
436 case 'd': |
|
437 dense = TRUE; |
|
438 break; |
|
439 case 'e': |
|
440 ellipsis = TRUE; |
|
441 break; |
|
442 case 'o': |
|
443 reloc_flag = TRUE; |
|
444 break; |
|
445 case 'k': |
|
446 dwarf_check = TRUE; |
|
447 oarg = optarg[0]; |
|
448 switch (oarg) { |
|
449 case 'a': |
|
450 check_pubname_attr = TRUE; |
|
451 check_attr_tag = TRUE; |
|
452 check_tag_tree = check_type_offset = TRUE; |
|
453 pubnames_flag = info_flag = TRUE; |
|
454 break; |
|
455 case 'e': |
|
456 check_pubname_attr = TRUE; |
|
457 pubnames_flag = TRUE; |
|
458 break; |
|
459 case 'r': |
|
460 check_attr_tag = TRUE; |
|
461 info_flag = TRUE; |
|
462 break; |
|
463 case 't': |
|
464 check_tag_tree = TRUE; |
|
465 info_flag = TRUE; |
|
466 break; |
|
467 case 'y': |
|
468 check_type_offset = TRUE; |
|
469 info_flag = TRUE; |
|
470 break; |
|
471 default: |
|
472 usage_error = TRUE; |
|
473 break; |
|
474 } |
|
475 break; |
|
476 case 'u': /* compile unit */ |
|
477 cu_name_flag = TRUE; |
|
478 strcpy(cu_name, optarg); |
|
479 break; |
|
480 case 't': |
|
481 oarg = optarg[0]; |
|
482 switch (oarg) { |
|
483 case 'a': |
|
484 /* all */ |
|
485 static_func_flag = static_var_flag = TRUE; |
|
486 break; |
|
487 case 'f': |
|
488 /* .debug_static_func */ |
|
489 static_func_flag = TRUE; |
|
490 break; |
|
491 case 'v': |
|
492 /* .debug_static_var */ |
|
493 static_var_flag = TRUE; |
|
494 break; |
|
495 default: |
|
496 usage_error = TRUE; |
|
497 break; |
|
498 } |
|
499 break; |
|
500 case 'y': /* .debug_types */ |
|
501 type_flag = TRUE; |
|
502 break; |
|
503 case 'w': /* .debug_weaknames */ |
|
504 weakname_flag = TRUE; |
|
505 break; |
|
506 case 'z': |
|
507 fprintf(stderr, "-z is no longer supported:ignored\n"); |
|
508 break; |
|
509 case 'G': |
|
510 show_global_offsets = TRUE; |
|
511 break; |
|
512 default: |
|
513 usage_error = TRUE; |
|
514 break; |
|
515 } |
|
516 } |
|
517 |
|
518 init_conf_file_data(&config_file_data); |
|
519 if (config_file_abi && generic_1000_regs) { |
|
520 printf("Specifying both -R and -x abi= is not allowed. Use one " |
|
521 "or the other. -x abi= ignored.\n"); |
|
522 config_file_abi = FALSE; |
|
523 } |
|
524 if(generic_1000_regs) { |
|
525 init_generic_config_1000_regs(&config_file_data); |
|
526 } |
|
527 if (config_file_abi && (frame_flag || eh_frame_flag)) { |
|
528 int res = find_conf_file_and_read_config(config_file_path, |
|
529 config_file_abi, |
|
530 config_file_defaults, |
|
531 &config_file_data); |
|
532 |
|
533 if (res > 0) { |
|
534 printf |
|
535 ("Frame not configured due to error(s). Giving up.\n"); |
|
536 eh_frame_flag = FALSE; |
|
537 frame_flag = FALSE; |
|
538 } |
|
539 } |
|
540 if (usage_error || (optind != (argc - 1))) { |
|
541 print_usage_message(); |
|
542 exit(FAILED); |
|
543 } |
|
544 return argv[optind]; |
|
545 } |
|
546 |
|
547 static void |
|
548 print_usage_message(void) |
|
549 { |
|
550 fprintf(stderr, "Usage: %s <options> <object file>\n", |
|
551 program_name); |
|
552 fprintf(stderr, "options:\t-a\tprint all .debug_* sections\n"); |
|
553 fprintf(stderr, "\t\t-b\tprint abbrev section\n"); |
|
554 fprintf(stderr, "\t\t-c\tprint loc section\n"); |
|
555 fprintf(stderr, |
|
556 "\t\t-d\tdense: one line per entry (info section only)\n"); |
|
557 fprintf(stderr, |
|
558 "\t\t-e\tellipsis: short names for tags, attrs etc.\n"); |
|
559 fprintf(stderr, "\t\t-f\tprint dwarf frame section\n"); |
|
560 fprintf(stderr, "\t\t-F\tprint gnu .eh_frame section\n"); |
|
561 fprintf(stderr, "\t\t-g\t(use incomplete loclist support)\n"); |
|
562 fprintf(stderr, "\t\t-G\tshow global die offsets\n"); |
|
563 fprintf(stderr, "\t\t-h\tprint exception tables\n"); |
|
564 fprintf(stderr, "\t\t-i\tprint info section\n"); |
|
565 fprintf(stderr, "\t\t-k[aerty] check dwarf information\n"); |
|
566 fprintf(stderr, "\t\t a\tdo all checks\n"); |
|
567 fprintf(stderr, "\t\t e\texamine attributes of pubnames\n"); |
|
568 fprintf(stderr, "\t\t r\texamine attr-tag relation\n"); |
|
569 fprintf(stderr, "\t\t t\texamine tag trees\n"); |
|
570 fprintf(stderr, "\t\t y\texamine type info\n"); |
|
571 fprintf(stderr, "\t\t-l\tprint line section\n"); |
|
572 fprintf(stderr, "\t\t-m\tprint macinfo section\n"); |
|
573 fprintf(stderr, "\t\t-o\tprint relocation info\n"); |
|
574 fprintf(stderr, "\t\t-p\tprint pubnames section\n"); |
|
575 fprintf(stderr, "\t\t-r\tprint aranges section\n"); |
|
576 fprintf(stderr, "\t\t-R\tPrint frame register names as r33 etc\n"); |
|
577 fprintf(stderr, "\t\t \t and allow up to 1000 registers.\n"); |
|
578 fprintf(stderr, "\t\t \t Print using a 'generic' register set.\n"); |
|
579 fprintf(stderr, "\t\t-s\tprint string section\n"); |
|
580 fprintf(stderr, "\t\t-t[afv] static: \n"); |
|
581 fprintf(stderr, "\t\t a\tprint both sections\n"); |
|
582 fprintf(stderr, "\t\t f\tprint static func section\n"); |
|
583 fprintf(stderr, "\t\t v\tprint static var section\n"); |
|
584 fprintf(stderr, |
|
585 "\t\t-u<file> print sections only for specified file\n"); |
|
586 fprintf(stderr, "\t\t-v\tverbose: show more information\n"); |
|
587 fprintf(stderr, "\t\t-vv verbose: show even more information\n"); |
|
588 fprintf(stderr, "\t\t-V print version information\n"); |
|
589 fprintf(stderr, "\t\t-x name=<path>\tname dwarfdump.conf\n"); |
|
590 fprintf(stderr, "\t\t-x abi=<abi>\tname abi in dwarfdump.conf\n"); |
|
591 fprintf(stderr, "\t\t-w\tprint weakname section\n"); |
|
592 fprintf(stderr, "\t\t-y\tprint type section\n"); |
|
593 |
|
594 } |
|
595 |
|
596 /* process each compilation unit in .debug_info */ |
|
597 static void |
|
598 print_infos(Dwarf_Debug dbg) |
|
599 { |
|
600 Dwarf_Unsigned cu_header_length = 0; |
|
601 Dwarf_Unsigned abbrev_offset = 0; |
|
602 Dwarf_Half version_stamp = 0; |
|
603 Dwarf_Half address_size = 0; |
|
604 Dwarf_Die cu_die = 0; |
|
605 Dwarf_Unsigned next_cu_offset = 0; |
|
606 int nres = DW_DLV_OK; |
|
607 |
|
608 if (info_flag) |
|
609 printf("\n.debug_info\n"); |
|
610 |
|
611 /* Loop until it fails. */ |
|
612 while ((nres = |
|
613 dwarf_next_cu_header(dbg, &cu_header_length, &version_stamp, |
|
614 &abbrev_offset, &address_size, |
|
615 &next_cu_offset, &err)) |
|
616 == DW_DLV_OK) { |
|
617 int sres; |
|
618 |
|
619 if (cu_name_flag) { |
|
620 int tres; |
|
621 Dwarf_Half tag; |
|
622 Dwarf_Attribute attrib; |
|
623 Dwarf_Half theform; |
|
624 int fres; |
|
625 int ares; |
|
626 |
|
627 sres = dwarf_siblingof(dbg, NULL, &cu_die, &err); |
|
628 if (sres != DW_DLV_OK) { |
|
629 print_error(dbg, "siblingof cu header", sres, err); |
|
630 } |
|
631 tres = dwarf_tag(cu_die, &tag, &err); |
|
632 if (tres != DW_DLV_OK) { |
|
633 print_error(dbg, "tag of cu die", tres, err); |
|
634 } |
|
635 ares = dwarf_attr(cu_die, DW_AT_name, &attrib, &err); |
|
636 if (ares != DW_DLV_OK) { |
|
637 print_error(dbg, "dwarf DW_AT_name ", ares, err); |
|
638 } |
|
639 fres = dwarf_whatform(attrib, &theform, &err); |
|
640 if (fres != DW_DLV_OK) { |
|
641 print_error(dbg, "dwarf_whatform problem ", fres, err); |
|
642 } else if (theform == DW_FORM_string |
|
643 || theform == DW_FORM_strp) { |
|
644 string temps; |
|
645 int strres; |
|
646 string p; |
|
647 |
|
648 strres = dwarf_formstring(attrib, &temps, &err); |
|
649 p = temps; |
|
650 if (strres != DW_DLV_OK) { |
|
651 print_error(dbg, |
|
652 "formstring failed unexpectedly", |
|
653 strres, err); |
|
654 } |
|
655 if (cu_name[0] != '/') { |
|
656 p = strrchr(temps, '/'); |
|
657 if (p == NULL) { |
|
658 p = temps; |
|
659 } else { |
|
660 p++; |
|
661 } |
|
662 } |
|
663 if (strcmp(cu_name, p)) { |
|
664 continue; |
|
665 } |
|
666 } else { |
|
667 print_error(dbg, |
|
668 "dwarf_whatform unexpected value", |
|
669 fres, err); |
|
670 } |
|
671 dwarf_dealloc(dbg, attrib, DW_DLA_ATTR); |
|
672 dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); |
|
673 } |
|
674 if (verbose) { |
|
675 if (dense) { |
|
676 printf("<%s>", "cu_header"); |
|
677 printf(" %s<%llu>", "cu_header_length", |
|
678 cu_header_length); |
|
679 printf(" %s<%d>", "version_stamp", version_stamp); |
|
680 printf(" %s<%llu>", "abbrev_offset", abbrev_offset); |
|
681 printf(" %s<%d>\n", "address_size", address_size); |
|
682 |
|
683 } else { |
|
684 printf("\nCU_HEADER:\n"); |
|
685 printf("\t\t%-28s%llu\n", "cu_header_length", |
|
686 cu_header_length); |
|
687 printf("\t\t%-28s%d\n", "version_stamp", version_stamp); |
|
688 printf("\t\t%-28s%llu\n", "abbrev_offset", |
|
689 abbrev_offset); |
|
690 printf("\t\t%-28s%d", "address_size", address_size); |
|
691 } |
|
692 } |
|
693 |
|
694 /* process a single compilation unit in .debug_info. */ |
|
695 sres = dwarf_siblingof(dbg, NULL, &cu_die, &err); |
|
696 if (sres == DW_DLV_OK) { |
|
697 if (info_flag || cu_name_flag) { |
|
698 Dwarf_Signed cnt = 0; |
|
699 char **srcfiles = 0; |
|
700 int srcf = dwarf_srcfiles(cu_die, |
|
701 &srcfiles, &cnt, &err); |
|
702 |
|
703 if (srcf != DW_DLV_OK) { |
|
704 srcfiles = 0; |
|
705 cnt = 0; |
|
706 } |
|
707 |
|
708 print_die_and_children(dbg, cu_die, srcfiles, cnt); |
|
709 if (srcf == DW_DLV_OK) { |
|
710 int si; |
|
711 |
|
712 for (si = 0; si < cnt; ++si) { |
|
713 dwarf_dealloc(dbg, srcfiles[si], DW_DLA_STRING); |
|
714 } |
|
715 dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST); |
|
716 } |
|
717 } |
|
718 if (line_flag) |
|
719 print_line_numbers_this_cu(dbg, cu_die); |
|
720 dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); |
|
721 } else if (sres == DW_DLV_NO_ENTRY) { |
|
722 /* do nothing I guess. */ |
|
723 } else { |
|
724 print_error(dbg, "Regetting cu_die", sres, err); |
|
725 } |
|
726 cu_offset = next_cu_offset; |
|
727 } |
|
728 if (nres == DW_DLV_ERROR) { |
|
729 string errmsg = dwarf_errmsg(err); |
|
730 Dwarf_Unsigned myerr = dwarf_errno(err); |
|
731 |
|
732 fprintf(stderr, "%s ERROR: %s: %s (%lu)\n", |
|
733 program_name, "attempting to print .debug_info", |
|
734 errmsg, (unsigned long) myerr); |
|
735 fprintf(stderr, "attempting to continue.\n"); |
|
736 } |
|
737 } |
|
738 |
|
739 /* ARGSUSED */ |
|
740 void |
|
741 print_error(Dwarf_Debug dbg, string msg, int dwarf_code, |
|
742 Dwarf_Error err) |
|
743 { |
|
744 fflush(stdout); |
|
745 fflush(stderr); |
|
746 if (dwarf_code == DW_DLV_ERROR) { |
|
747 string errmsg = dwarf_errmsg(err); |
|
748 Dwarf_Unsigned myerr = dwarf_errno(err); |
|
749 |
|
750 fprintf(stderr, "%s ERROR: %s: %s (%lu)\n", |
|
751 program_name, msg, errmsg, (unsigned long) myerr); |
|
752 } else if (dwarf_code == DW_DLV_NO_ENTRY) { |
|
753 fprintf(stderr, "%s NO ENTRY: %s: \n", program_name, msg); |
|
754 } else if (dwarf_code == DW_DLV_OK) { |
|
755 fprintf(stderr, "%s: %s \n", program_name, msg); |
|
756 } else { |
|
757 fprintf(stderr, "%s InternalError: %s: code %d\n", |
|
758 program_name, msg, dwarf_code); |
|
759 } |
|
760 fflush(stderr); |
|
761 exit(FAILED); |
|
762 |
|
763 } |