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