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