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