1/* Coff file dumper. 2 Copyright (C) 1994-2017 Free Software Foundation, Inc. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or (at 9 your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 22/* Written by Steve Chamberlain <sac@cygnus.com> 23 24 This module reads a type tree generated by coffgrok and prints 25 it out so we can test the grokker. */ 26 27#include "sysdep.h" 28#include "bfd.h" 29#include "bfd_stdint.h" 30#include "libiberty.h" 31#include "bucomm.h" 32 33#include "coffgrok.h" 34#include "getopt.h" 35 36static int atnl; 37 38static void tab (int); 39static void nl (void); 40static void dump_coff_lines (struct coff_line *); 41static void dump_coff_type (struct coff_type *); 42static void dump_coff_where (struct coff_where *); 43static void dump_coff_visible (struct coff_visible *); 44static void dump_coff_scope (struct coff_scope *); 45static void dump_coff_sfile (struct coff_sfile *); 46static void dump_coff_section (struct coff_section *); 47static void show_usage (FILE *, int); 48extern int main (int, char **); 49 50static void 51tab (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 93static void 94nl (void) 95{ 96 atnl = 1; 97} 98 99static void 100dump_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 125static void 126dump_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 244static void 245dump_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 break; 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 284static void 285dump_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 330static void 331dump_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 363static void 364dump_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 400static void 401dump_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 418static void 419dump_coff_section (struct coff_section *ptr) 420{ 421 unsigned int i; 422 423 tab (1); 424 printf (_("section %s %d %d address %x size %x number %d nrelocs %u"), 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 struct coff_reloc * r = ptr->relocs + i; 432 tab (0); 433 printf ("(%x %s %x)", 434 r->offset, 435 /* PR 17512: file: 0a38fb7c. */ 436 r->symbol == NULL ? _("<no sym>") : r->symbol->name, 437 r->addend); 438 nl (); 439 } 440 441 tab (-1); 442} 443 444static void 445coff_dump (struct coff_ofile *ptr) 446{ 447 int i; 448 449 printf ("Coff dump"); 450 nl (); 451 printf (_("#sources %d"), ptr->nsources); 452 nl (); 453 dump_coff_sfile (ptr->source_head); 454 455 for (i = 0; i < ptr->nsections; i++) 456 dump_coff_section (ptr->sections + i); 457} 458 459char * program_name; 460 461static void 462show_usage (FILE *file, int status) 463{ 464 fprintf (file, _("Usage: %s [option(s)] in-file\n"), program_name); 465 fprintf (file, _(" Print a human readable interpretation of a COFF object file\n")); 466 fprintf (file, _(" The options are:\n\ 467 @<file> Read options from <file>\n\ 468 -h --help Display this information\n\ 469 -v --version Display the program's version\n\ 470\n")); 471 472 if (REPORT_BUGS_TO[0] && status == 0) 473 fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO); 474 475 exit (status); 476} 477 478int 479main (int ac, char **av) 480{ 481 bfd *abfd; 482 struct coff_ofile *tree; 483 char **matching; 484 char *input_file = NULL; 485 int opt; 486 static struct option long_options[] = 487 { 488 { "help", no_argument, 0, 'h' }, 489 { "version", no_argument, 0, 'V' }, 490 { NULL, no_argument, 0, 0 } 491 }; 492 493#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 494 setlocale (LC_MESSAGES, ""); 495#endif 496#if defined (HAVE_SETLOCALE) 497 setlocale (LC_CTYPE, ""); 498#endif 499 bindtextdomain (PACKAGE, LOCALEDIR); 500 textdomain (PACKAGE); 501 502 program_name = av[0]; 503 xmalloc_set_program_name (program_name); 504 bfd_set_error_program_name (program_name); 505 506 expandargv (&ac, &av); 507 508 while ((opt = getopt_long (ac, av, "HhVv", long_options, 509 (int *) NULL)) 510 != EOF) 511 { 512 switch (opt) 513 { 514 case 'H': 515 case 'h': 516 show_usage (stdout, 0); 517 break; 518 case 'v': 519 case 'V': 520 print_version ("coffdump"); 521 exit (0); 522 case 0: 523 break; 524 default: 525 show_usage (stderr, 1); 526 break; 527 } 528 } 529 530 if (optind < ac) 531 { 532 input_file = av[optind]; 533 } 534 535 if (!input_file) 536 fatal (_("no input file specified")); 537 538 abfd = bfd_openr (input_file, 0); 539 540 if (!abfd) 541 bfd_fatal (input_file); 542 543 if (! bfd_check_format_matches (abfd, bfd_object, &matching)) 544 { 545 bfd_nonfatal (input_file); 546 547 if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 548 { 549 list_matching_formats (matching); 550 free (matching); 551 } 552 exit (1); 553 } 554 555 tree = coff_grok (abfd); 556 if (tree) 557 { 558 coff_dump (tree); 559 printf ("\n"); 560 } 561 562 return 0; 563} 564