1 /* Coff file dumper. 2 Copyright 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007, 3 2011 Free Software Foundation, Inc. 4 5 This file is part of GNU Binutils. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or (at 10 your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 23 /* Written by Steve Chamberlain <sac@cygnus.com> 24 25 This module reads a type tree generated by coffgrok and prints 26 it out so we can test the grokker. */ 27 28 #include "sysdep.h" 29 #include "bfd.h" 30 #include "bfd_stdint.h" 31 #include "libiberty.h" 32 #include "bucomm.h" 33 34 #include "coffgrok.h" 35 #include "getopt.h" 36 37 static int atnl; 38 39 static void tab (int); 40 static void nl (void); 41 static void dump_coff_lines (struct coff_line *); 42 static void dump_coff_type (struct coff_type *); 43 static void dump_coff_where (struct coff_where *); 44 static void dump_coff_visible (struct coff_visible *); 45 static void dump_coff_scope (struct coff_scope *); 46 static void dump_coff_sfile (struct coff_sfile *); 47 static void dump_coff_section (struct coff_section *); 48 static void show_usage (FILE *, int); 49 extern int main (int, char **); 50 51 static void 52 tab (int x) 53 { 54 static int indent; 55 int i; 56 57 if (atnl) 58 { 59 if (x < 0) 60 { 61 printf (")"); 62 indent += x; 63 64 return; 65 } 66 else 67 { 68 printf ("\n"); 69 atnl = 0; 70 } 71 } 72 73 if (x == -1) 74 { 75 for (i = 0; i < indent; i++) 76 printf (" "); 77 78 indent += x; 79 printf (")"); 80 return; 81 } 82 83 indent += x; 84 85 for (i = 0; i < indent; i++) 86 printf (" "); 87 88 if (x) 89 { 90 printf ("("); 91 } 92 } 93 94 static void 95 nl (void) 96 { 97 atnl = 1; 98 } 99 100 static void 101 dump_coff_lines (struct coff_line *p) 102 { 103 int i; 104 int online = 0; 105 106 tab (1); 107 printf (_("#lines %d "),p->nlines); 108 109 for (i = 0; i < p->nlines; i++) 110 { 111 printf ("(%d 0x%x)", p->lines[i], p->addresses[i]); 112 113 online++; 114 115 if (online > 6) 116 { 117 nl (); 118 tab (0); 119 online = 0; 120 } 121 } 122 nl (); 123 tab (-1); 124 } 125 126 static void 127 dump_coff_type (struct coff_type *p) 128 { 129 tab (1); 130 printf (_("size %d "), p->size); 131 132 switch (p->type) 133 { 134 case coff_secdef_type: 135 printf (_("section definition at %x size %x\n"), 136 p->u.asecdef.address, 137 p->u.asecdef.size); 138 nl (); 139 break; 140 case coff_pointer_type: 141 printf (_("pointer to")); 142 nl (); 143 dump_coff_type (p->u.pointer.points_to); 144 break; 145 case coff_array_type: 146 printf (_("array [%d] of"), p->u.array.dim); 147 nl (); 148 dump_coff_type (p->u.array.array_of); 149 break; 150 case coff_function_type: 151 printf (_("function returning")); 152 nl (); 153 dump_coff_type (p->u.function.function_returns); 154 dump_coff_lines (p->u.function.lines); 155 printf (_("arguments")); 156 nl (); 157 dump_coff_scope (p->u.function.parameters); 158 tab (0); 159 printf (_("code")); 160 nl (); 161 dump_coff_scope (p->u.function.code); 162 tab(0); 163 break; 164 case coff_structdef_type: 165 printf (_("structure definition")); 166 nl (); 167 dump_coff_scope (p->u.astructdef.elements); 168 break; 169 case coff_structref_type: 170 if (!p->u.aenumref.ref) 171 printf (_("structure ref to UNKNOWN struct")); 172 else 173 printf (_("structure ref to %s"), p->u.aenumref.ref->name); 174 break; 175 case coff_enumref_type: 176 printf (_("enum ref to %s"), p->u.astructref.ref->name); 177 break; 178 case coff_enumdef_type: 179 printf (_("enum definition")); 180 nl (); 181 dump_coff_scope (p->u.aenumdef.elements); 182 break; 183 case coff_basic_type: 184 switch (p->u.basic) 185 { 186 case T_NULL: 187 printf ("NULL"); 188 break; 189 case T_VOID: 190 printf ("VOID"); 191 break; 192 case T_CHAR: 193 printf ("CHAR"); 194 break; 195 case T_SHORT: 196 printf ("SHORT"); 197 break; 198 case T_INT: 199 printf ("INT "); 200 break; 201 case T_LONG: 202 printf ("LONG"); 203 break; 204 case T_FLOAT: 205 printf ("FLOAT"); 206 break; 207 case T_DOUBLE: 208 printf ("DOUBLE"); 209 break; 210 case T_STRUCT: 211 printf ("STRUCT"); 212 break; 213 case T_UNION: 214 printf ("UNION"); 215 break; 216 case T_ENUM: 217 printf ("ENUM"); 218 break; 219 case T_MOE: 220 printf ("MOE "); 221 break; 222 case T_UCHAR: 223 printf ("UCHAR"); 224 break; 225 case T_USHORT: 226 printf ("USHORT"); 227 break; 228 case T_UINT: 229 printf ("UINT"); 230 break; 231 case T_ULONG: 232 printf ("ULONG"); 233 break; 234 case T_LNGDBL: 235 printf ("LNGDBL"); 236 break; 237 default: 238 abort (); 239 } 240 } 241 nl (); 242 tab (-1); 243 } 244 245 static void 246 dump_coff_where (struct coff_where *p) 247 { 248 tab (1); 249 switch (p->where) 250 { 251 case coff_where_stack: 252 printf (_("Stack offset %x"), p->offset); 253 break; 254 case coff_where_memory: 255 printf (_("Memory section %s+%x"), p->section->name, p->offset); 256 break; 257 case coff_where_register: 258 printf (_("Register %d"), p->offset); 259 break; 260 case coff_where_member_of_struct: 261 printf (_("Struct Member offset %x"), p->offset); 262 break; 263 case coff_where_member_of_enum: 264 printf (_("Enum Member offset %x"), p->offset); 265 break; 266 case coff_where_unknown: 267 printf (_("Undefined symbol")); 268 break; 269 case coff_where_strtag: 270 printf ("STRTAG"); 271 case coff_where_entag: 272 printf ("ENTAG"); 273 break; 274 case coff_where_typedef: 275 printf ("TYPEDEF"); 276 break; 277 default: 278 abort (); 279 } 280 nl (); 281 tab (-1); 282 } 283 284 static void 285 dump_coff_visible (struct coff_visible *p) 286 { 287 tab (1); 288 switch (p->type) 289 { 290 case coff_vis_ext_def: 291 printf ("coff_vis_ext_def"); 292 break; 293 case coff_vis_ext_ref: 294 printf ("coff_vis_ext_ref"); 295 break; 296 case coff_vis_int_def: 297 printf ("coff_vis_int_def"); 298 break; 299 case coff_vis_common: 300 printf ("coff_vis_common"); 301 break; 302 case coff_vis_auto: 303 printf ("coff_vis_auto"); 304 break; 305 case coff_vis_autoparam: 306 printf ("coff_vis_autoparam"); 307 break; 308 case coff_vis_regparam: 309 printf ("coff_vis_regparam"); 310 break; 311 case coff_vis_register: 312 printf ("coff_vis_register"); 313 break; 314 case coff_vis_tag: 315 printf ("coff_vis_tag"); 316 break; 317 case coff_vis_member_of_struct: 318 printf ("coff_vis_member_of_struct"); 319 break; 320 case coff_vis_member_of_enum: 321 printf ("coff_vis_member_of_enum"); 322 break; 323 default: 324 abort (); 325 } 326 nl (); 327 tab (-1); 328 } 329 330 static void 331 dump_coff_symbol (struct coff_symbol *p) 332 { 333 tab (1); 334 printf (_("List of symbols")); 335 nl (); 336 337 while (p) 338 { 339 tab (1); 340 tab (1); 341 printf (_("Symbol %s, tag %d, number %d"), p->name, p->tag, p->number); 342 nl (); 343 tab (-1); 344 tab (1); 345 printf (_("Type")); 346 nl (); 347 dump_coff_type (p->type); 348 tab (-1); 349 tab (1); 350 printf (_("Where")); 351 dump_coff_where (p->where); 352 tab (-1); 353 tab (1); 354 printf (_("Visible")); 355 dump_coff_visible (p->visible); 356 tab (-1); 357 p = p->next; 358 tab (-1); 359 } 360 tab (-1); 361 } 362 363 static void 364 dump_coff_scope (struct coff_scope *p) 365 { 366 if (p) 367 { 368 tab (1); 369 printf ("%s %" BFD_VMA_FMT "x ", 370 _("List of blocks "), (bfd_vma) (uintptr_t) p); 371 372 if (p->sec) 373 printf( " %s %x..%x", p->sec->name,p->offset, p->offset + p->size -1); 374 375 nl (); 376 tab (0); 377 printf ("*****************"); 378 nl (); 379 380 while (p) 381 { 382 tab (0); 383 printf (_("vars %d"), p->nvars); 384 nl (); 385 dump_coff_symbol (p->vars_head); 386 printf (_("blocks")); 387 nl (); 388 dump_coff_scope (p->list_head); 389 nl (); 390 p = p->next; 391 } 392 393 tab (0); 394 printf ("*****************"); 395 nl (); 396 tab (-1); 397 } 398 } 399 400 static void 401 dump_coff_sfile (struct coff_sfile *p) 402 { 403 tab (1); 404 printf (_("List of source files")); 405 nl (); 406 407 while (p) 408 { 409 tab (0); 410 printf (_("Source file %s"), p->name); 411 nl (); 412 dump_coff_scope (p->scope); 413 p = p->next; 414 } 415 tab (-1); 416 } 417 418 static void 419 dump_coff_section (struct coff_section *ptr) 420 { 421 int i; 422 423 tab (1); 424 printf (_("section %s %d %d address %x size %x number %d nrelocs %d"), 425 ptr->name, ptr->code, ptr->data, ptr->address,ptr->size, 426 ptr->number, ptr->nrelocs); 427 nl (); 428 429 for (i = 0; i < ptr->nrelocs; i++) 430 { 431 tab (0); 432 printf ("(%x %s %x)", 433 ptr->relocs[i].offset, 434 ptr->relocs[i].symbol->name, 435 ptr->relocs[i].addend); 436 nl (); 437 } 438 439 tab (-1); 440 } 441 442 static void 443 coff_dump (struct coff_ofile *ptr) 444 { 445 int i; 446 447 printf ("Coff dump"); 448 nl (); 449 printf (_("#sources %d"), ptr->nsources); 450 nl (); 451 dump_coff_sfile (ptr->source_head); 452 453 for (i = 0; i < ptr->nsections; i++) 454 dump_coff_section (ptr->sections + i); 455 } 456 457 char * program_name; 458 459 static void 460 show_usage (FILE *file, int status) 461 { 462 fprintf (file, _("Usage: %s [option(s)] in-file\n"), program_name); 463 fprintf (file, _(" Print a human readable interpretation of a COFF object file\n")); 464 fprintf (file, _(" The options are:\n\ 465 @<file> Read options from <file>\n\ 466 -h --help Display this information\n\ 467 -v --version Display the program's version\n\ 468 \n")); 469 470 if (REPORT_BUGS_TO[0] && status == 0) 471 fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO); 472 473 exit (status); 474 } 475 476 int 477 main (int ac, char **av) 478 { 479 bfd *abfd; 480 struct coff_ofile *tree; 481 char **matching; 482 char *input_file = NULL; 483 int opt; 484 static struct option long_options[] = 485 { 486 { "help", no_argument, 0, 'h' }, 487 { "version", no_argument, 0, 'V' }, 488 { NULL, no_argument, 0, 0 } 489 }; 490 491 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 492 setlocale (LC_MESSAGES, ""); 493 #endif 494 #if defined (HAVE_SETLOCALE) 495 setlocale (LC_CTYPE, ""); 496 #endif 497 bindtextdomain (PACKAGE, LOCALEDIR); 498 textdomain (PACKAGE); 499 500 program_name = av[0]; 501 xmalloc_set_program_name (program_name); 502 503 expandargv (&ac, &av); 504 505 while ((opt = getopt_long (ac, av, "HhVv", long_options, 506 (int *) NULL)) 507 != EOF) 508 { 509 switch (opt) 510 { 511 case 'H': 512 case 'h': 513 show_usage (stdout, 0); 514 break; 515 case 'v': 516 case 'V': 517 print_version ("coffdump"); 518 exit (0); 519 case 0: 520 break; 521 default: 522 show_usage (stderr, 1); 523 break; 524 } 525 } 526 527 if (optind < ac) 528 { 529 input_file = av[optind]; 530 } 531 532 if (!input_file) 533 fatal (_("no input file specified")); 534 535 abfd = bfd_openr (input_file, 0); 536 537 if (!abfd) 538 bfd_fatal (input_file); 539 540 if (! bfd_check_format_matches (abfd, bfd_object, &matching)) 541 { 542 bfd_nonfatal (input_file); 543 544 if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 545 { 546 list_matching_formats (matching); 547 free (matching); 548 } 549 exit (1); 550 } 551 552 tree = coff_grok (abfd); 553 554 coff_dump (tree); 555 printf ("\n"); 556 557 return 0; 558 } 559