|
|
1.1 ! root 1: /* Read coff symbol tables and convert to internal format, for GDB. ! 2: Design and support routines derived from dbxread.c, and UMAX COFF ! 3: specific routines written 9/1/87 by David D. Johnson, Brown University. ! 4: Revised 11/27/87 [email protected] ! 5: Copyright (C) 1987, 1988 Free Software Foundation, Inc. ! 6: ! 7: GDB is distributed in the hope that it will be useful, but WITHOUT ANY ! 8: WARRANTY. No author or distributor accepts responsibility to anyone ! 9: for the consequences of using it or for whether it serves any ! 10: particular purpose or works at all, unless he says so in writing. ! 11: Refer to the GDB General Public License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute GDB, ! 14: but only under the conditions described in the GDB General Public ! 15: License. A copy of this license is supposed to have been given to you ! 16: along with GDB so you can know your rights and responsibilities. It ! 17: should be in a file named COPYING. Among other things, the copyright ! 18: notice and this notice must be preserved on all copies. ! 19: ! 20: In other words, go ahead and share GDB, but don't try to stop ! 21: anyone else from sharing it farther. Help stamp out software hoarding! ! 22: */ ! 23: ! 24: #include "defs.h" ! 25: #include "param.h" ! 26: #ifdef COFF_FORMAT ! 27: #include "initialize.h" ! 28: #include "symtab.h" ! 29: ! 30: #include <a.out.h> ! 31: #include <stdio.h> ! 32: #include <obstack.h> ! 33: #include <sys/param.h> ! 34: #include <sys/file.h> ! 35: ! 36: static void add_symbol_to_list (); ! 37: static void read_coff_symtab (); ! 38: static void patch_opaque_types (); ! 39: static struct type *decode_function_type (); ! 40: static struct type *decode_type (); ! 41: static struct type *decode_base_type (); ! 42: static struct type *read_enum_type (); ! 43: static struct type *read_struct_type (); ! 44: static void finish_block (); ! 45: static struct blockvector *make_blockvector (); ! 46: static struct symbol *process_coff_symbol (); ! 47: static int init_stringtab (); ! 48: static void free_stringtab (); ! 49: static char *getfilename (); ! 50: static char *getsymname (); ! 51: static int init_lineno (); ! 52: static void enter_linenos (); ! 53: ! 54: extern void free_all_symtabs (); ! 55: ! 56: START_FILE ! 57: ! 58: /* Name of source file whose symbol data we are now processing. ! 59: This comes from a symbol named ".file". */ ! 60: ! 61: static char *last_source_file; ! 62: ! 63: /* Core address of start and end of text of current source file. ! 64: This comes from a ".text" symbol where x_nlinno > 0. */ ! 65: ! 66: static CORE_ADDR cur_src_start_addr; ! 67: static CORE_ADDR cur_src_end_addr; ! 68: ! 69: /* End of the text segment of the executable file, ! 70: as found in the symbol _etext. */ ! 71: ! 72: static CORE_ADDR end_of_text_addr; ! 73: ! 74: /* The addresses of the symbol table stream and number of symbols ! 75: of the object file we are reading (as copied into core). */ ! 76: ! 77: static FILE *nlist_stream_global; ! 78: static int nlist_nsyms_global; ! 79: ! 80: /* The file and text section headers of the symbol file */ ! 81: ! 82: static FILHDR file_hdr; ! 83: static SCNHDR text_hdr; ! 84: ! 85: /* The index in the symbol table of the last coff symbol that was processed. */ ! 86: ! 87: static int symnum; ! 88: ! 89: /* Vector of types defined so far, indexed by their coff symnum. */ ! 90: ! 91: static struct typevector *type_vector; ! 92: ! 93: /* Number of elements allocated for type_vector currently. */ ! 94: ! 95: static int type_vector_length; ! 96: ! 97: /* Vector of line number information. */ ! 98: ! 99: static struct linetable *line_vector; ! 100: ! 101: /* Index of next entry to go in line_vector_index. */ ! 102: ! 103: static int line_vector_index; ! 104: ! 105: /* Last line number recorded in the line vector. */ ! 106: ! 107: static int prev_line_number; ! 108: ! 109: /* Number of elements allocated for line_vector currently. */ ! 110: ! 111: static int line_vector_length; ! 112: ! 113: /* Chain of typedefs of pointers to empty struct/union types. ! 114: They are chained thru the SYMBOL_VALUE. */ ! 115: ! 116: #define HASHSIZE 127 ! 117: static struct symbol *opaque_type_chain[HASHSIZE]; ! 118: ! 119: /* Record the symbols defined for each context in a list. ! 120: We don't create a struct block for the context until we ! 121: know how long to make it. */ ! 122: ! 123: struct pending ! 124: { ! 125: struct pending *next; ! 126: struct symbol *symbol; ! 127: }; ! 128: ! 129: /* Here are the three lists that symbols are put on. */ ! 130: ! 131: struct pending *file_symbols; /* static at top level, and types */ ! 132: ! 133: struct pending *global_symbols; /* global functions and variables */ ! 134: ! 135: struct pending *local_symbols; /* everything local to lexical context */ ! 136: ! 137: /* List of unclosed lexical contexts ! 138: (that will become blocks, eventually). */ ! 139: ! 140: struct context_stack ! 141: { ! 142: struct context_stack *next; ! 143: struct pending *locals; ! 144: struct pending_block *old_blocks; ! 145: struct symbol *name; ! 146: CORE_ADDR start_addr; ! 147: int depth; ! 148: }; ! 149: ! 150: struct context_stack *context_stack; ! 151: ! 152: /* Nonzero if within a function (so symbols should be local, ! 153: if nothing says specifically). */ ! 154: ! 155: int within_function; ! 156: ! 157: /* List of blocks already made (lexical contexts already closed). ! 158: This is used at the end to make the blockvector. */ ! 159: ! 160: struct pending_block ! 161: { ! 162: struct pending_block *next; ! 163: struct block *block; ! 164: }; ! 165: ! 166: struct pending_block *pending_blocks; ! 167: ! 168: extern CORE_ADDR first_object_file_end; /* From blockframe.c */ ! 169: ! 170: /* File name symbols were loaded from. */ ! 171: ! 172: static char *symfile; ! 173: ! 174: /* Look up a coff type-number index. Return the address of the slot ! 175: where the type for that index is stored. ! 176: The type-number is in INDEX. ! 177: ! 178: This can be used for finding the type associated with that index ! 179: or for associating a new type with the index. */ ! 180: ! 181: static struct type ** ! 182: coff_lookup_type (index) ! 183: register int index; ! 184: { ! 185: if (index >= type_vector_length) ! 186: { ! 187: type_vector_length *= 2; ! 188: type_vector = (struct typevector *) ! 189: xrealloc (type_vector, sizeof (struct typevector) ! 190: + type_vector_length * sizeof (struct type *)); ! 191: bzero (&type_vector->type[type_vector_length / 2], ! 192: type_vector_length * sizeof (struct type *) / 2); ! 193: } ! 194: return &type_vector->type[index]; ! 195: } ! 196: ! 197: /* Make sure there is a type allocated for type number index ! 198: and return the type object. ! 199: This can create an empty (zeroed) type object. */ ! 200: ! 201: static struct type * ! 202: coff_alloc_type (index) ! 203: int index; ! 204: { ! 205: register struct type **type_addr = coff_lookup_type (index); ! 206: register struct type *type = *type_addr; ! 207: ! 208: /* If we are referring to a type not known at all yet, ! 209: allocate an empty type for it. ! 210: We will fill it in later if we find out how. */ ! 211: if (type == 0) ! 212: { ! 213: type = (struct type *) obstack_alloc (symbol_obstack, ! 214: sizeof (struct type)); ! 215: bzero (type, sizeof (struct type)); ! 216: *type_addr = type; ! 217: } ! 218: return type; ! 219: } ! 220: ! 221: /* maintain the lists of symbols and blocks */ ! 222: ! 223: /* Add a symbol to one of the lists of symbols. */ ! 224: static void ! 225: add_symbol_to_list (symbol, listhead) ! 226: struct symbol *symbol; ! 227: struct pending **listhead; ! 228: { ! 229: register struct pending *link ! 230: = (struct pending *) xmalloc (sizeof (struct pending)); ! 231: ! 232: link->next = *listhead; ! 233: link->symbol = symbol; ! 234: *listhead = link; ! 235: } ! 236: ! 237: /* Take one of the lists of symbols and make a block from it. ! 238: Put the block on the list of pending blocks. */ ! 239: ! 240: static void ! 241: finish_block (symbol, listhead, old_blocks, start, end) ! 242: struct symbol *symbol; ! 243: struct pending **listhead; ! 244: struct pending_block *old_blocks; ! 245: CORE_ADDR start, end; ! 246: { ! 247: register struct pending *next, *next1; ! 248: register struct block *block; ! 249: register struct pending_block *pblock; ! 250: struct pending_block *opblock; ! 251: register int i; ! 252: ! 253: /* Count the length of the list of symbols. */ ! 254: ! 255: for (next = *listhead, i = 0; next; next = next->next, i++); ! 256: ! 257: block = (struct block *) ! 258: obstack_alloc (symbol_obstack, sizeof (struct block) + (i - 1) * sizeof (struct symbol *)); ! 259: ! 260: /* Copy the symbols into the block. */ ! 261: ! 262: BLOCK_NSYMS (block) = i; ! 263: for (next = *listhead; next; next = next->next) ! 264: BLOCK_SYM (block, --i) = next->symbol; ! 265: ! 266: BLOCK_START (block) = start; ! 267: BLOCK_END (block) = end; ! 268: BLOCK_SUPERBLOCK (block) = 0; /* Filled in when containing block is made */ ! 269: ! 270: /* Put the block in as the value of the symbol that names it. */ ! 271: ! 272: if (symbol) ! 273: { ! 274: SYMBOL_BLOCK_VALUE (symbol) = block; ! 275: BLOCK_FUNCTION (block) = symbol; ! 276: } ! 277: else ! 278: BLOCK_FUNCTION (block) = 0; ! 279: ! 280: /* Now free the links of the list, and empty the list. */ ! 281: ! 282: for (next = *listhead; next; next = next1) ! 283: { ! 284: next1 = next->next; ! 285: free (next); ! 286: } ! 287: *listhead = 0; ! 288: ! 289: /* Install this block as the superblock ! 290: of all blocks made since the start of this scope ! 291: that don't have superblocks yet. */ ! 292: ! 293: opblock = 0; ! 294: for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next) ! 295: { ! 296: if (BLOCK_SUPERBLOCK (pblock->block) == 0) ! 297: BLOCK_SUPERBLOCK (pblock->block) = block; ! 298: opblock = pblock; ! 299: } ! 300: ! 301: /* Record this block on the list of all blocks in the file. ! 302: Put it after opblock, or at the beginning if opblock is 0. ! 303: This puts the block in the list after all its subblocks. */ ! 304: ! 305: pblock = (struct pending_block *) xmalloc (sizeof (struct pending_block)); ! 306: pblock->block = block; ! 307: if (opblock) ! 308: { ! 309: pblock->next = opblock->next; ! 310: opblock->next = pblock; ! 311: } ! 312: else ! 313: { ! 314: pblock->next = pending_blocks; ! 315: pending_blocks = pblock; ! 316: } ! 317: } ! 318: ! 319: static struct blockvector * ! 320: make_blockvector () ! 321: { ! 322: register struct pending_block *next, *next1; ! 323: register struct blockvector *blockvector; ! 324: register int i; ! 325: ! 326: /* Count the length of the list of blocks. */ ! 327: ! 328: for (next = pending_blocks, i = 0; next; next = next->next, i++); ! 329: ! 330: blockvector = (struct blockvector *) ! 331: obstack_alloc (symbol_obstack, sizeof (struct blockvector) + (i - 1) * sizeof (struct block *)); ! 332: ! 333: /* Copy the blocks into the blockvector. ! 334: This is done in reverse order, which happens to put ! 335: the blocks into the proper order (ascending starting address). ! 336: finish_block has hair to insert each block into the list ! 337: after its subblocks in order to make sure this is true. */ ! 338: ! 339: BLOCKVECTOR_NBLOCKS (blockvector) = i; ! 340: for (next = pending_blocks; next; next = next->next) ! 341: BLOCKVECTOR_BLOCK (blockvector, --i) = next->block; ! 342: ! 343: /* Now free the links of the list, and empty the list. */ ! 344: ! 345: for (next = pending_blocks; next; next = next1) ! 346: { ! 347: next1 = next->next; ! 348: free (next); ! 349: } ! 350: pending_blocks = 0; ! 351: ! 352: return blockvector; ! 353: } ! 354: ! 355: /* Manage the vector of line numbers. */ ! 356: ! 357: static ! 358: record_line (line, pc) ! 359: int line; ! 360: CORE_ADDR pc; ! 361: { ! 362: /* Make sure line vector is big enough. */ ! 363: ! 364: if (line_vector_index + 2 >= line_vector_length) ! 365: { ! 366: line_vector_length *= 2; ! 367: line_vector = (struct linetable *) ! 368: xrealloc (line_vector, sizeof (struct linetable) ! 369: + line_vector_length * sizeof (int)); ! 370: } ! 371: ! 372: /* If this line is not continguous with previous one recorded, ! 373: all lines between subsequent line and current one are same pc. ! 374: Add one item to line vector, and if more than one line skipped, ! 375: record a line-number entry for it. */ ! 376: if (prev_line_number > 0 && line != prev_line_number + 1) ! 377: line_vector->item[line_vector_index++] = pc; ! 378: if (prev_line_number < 0 || line > prev_line_number + 2) ! 379: line_vector->item[line_vector_index++] = - line; ! 380: prev_line_number = line; ! 381: ! 382: /* Record the core address of the line. */ ! 383: line_vector->item[line_vector_index++] = pc; ! 384: } ! 385: ! 386: /* Start a new symtab for a new source file. ! 387: This is called when a COFF ".file" symbol is seen; ! 388: it indicates the start of data for one original source file. */ ! 389: ! 390: static void ! 391: start_symtab () ! 392: { ! 393: file_symbols = 0; ! 394: global_symbols = 0; ! 395: context_stack = 0; ! 396: within_function = 0; ! 397: last_source_file = 0; ! 398: ! 399: /* Initialize the source file information for this file. */ ! 400: ! 401: line_vector_index = 0; ! 402: line_vector_length = 1000; ! 403: prev_line_number = -2; /* Force first line number to be explicit */ ! 404: line_vector = (struct linetable *) ! 405: xmalloc (sizeof (struct linetable) + line_vector_length * sizeof (int)); ! 406: } ! 407: ! 408: /* Save the vital information for use when closing off the current file. ! 409: NAME is the file name the symbols came from, START_ADDR is the first ! 410: text address for the file, and SIZE is the number of bytes of text. */ ! 411: ! 412: static void ! 413: complete_symtab (name, start_addr, size) ! 414: char *name; ! 415: CORE_ADDR start_addr; ! 416: unsigned int size; ! 417: { ! 418: last_source_file = savestring (name, strlen (name)); ! 419: cur_src_start_addr = start_addr; ! 420: cur_src_end_addr = start_addr + size; ! 421: } ! 422: ! 423: /* Finish the symbol definitions for one main source file, ! 424: close off all the lexical contexts for that file ! 425: (creating struct block's for them), then make the ! 426: struct symtab for that file and put it in the list of all such. */ ! 427: ! 428: static void ! 429: end_symtab () ! 430: { ! 431: register struct symtab *symtab; ! 432: register struct context_stack *cstk; ! 433: register struct blockvector *blockvector; ! 434: register struct linetable *lv; ! 435: ! 436: /* Finish the lexical context of the last function in the file. */ ! 437: ! 438: if (context_stack) ! 439: { ! 440: cstk = context_stack; ! 441: /* Make a block for the local symbols within. */ ! 442: finish_block (cstk->name, &local_symbols, cstk->old_blocks, ! 443: cstk->start_addr, cur_src_end_addr); ! 444: free (cstk); ! 445: } ! 446: ! 447: finish_block (0, &file_symbols, 0, cur_src_start_addr, cur_src_end_addr); ! 448: finish_block (0, &global_symbols, 0, cur_src_start_addr, cur_src_end_addr); ! 449: blockvector = make_blockvector (); ! 450: ! 451: /* Now create the symtab object this source file. */ ! 452: ! 453: symtab = (struct symtab *) xmalloc (sizeof (struct symtab)); ! 454: symtab->free_ptr = 0; ! 455: ! 456: /* Fill in its components. */ ! 457: symtab->blockvector = blockvector; ! 458: symtab->free_code = free_linetable; ! 459: symtab->filename = last_source_file; ! 460: lv = line_vector; ! 461: lv->nitems = line_vector_index; ! 462: symtab->linetable = (struct linetable *) ! 463: xrealloc (lv, sizeof (struct linetable) + lv->nitems * sizeof (int)); ! 464: symtab->nlines = 0; ! 465: symtab->line_charpos = 0; ! 466: ! 467: /* Link the new symtab into the list of such. */ ! 468: symtab->next = symtab_list; ! 469: symtab_list = symtab; ! 470: ! 471: line_vector = 0; ! 472: line_vector_length = -1; ! 473: last_source_file = 0; ! 474: } ! 475: ! 476: /* Accumulate the misc functions in bunches of 127. ! 477: At the end, copy them all into one newly allocated structure. */ ! 478: ! 479: #define MISC_BUNCH_SIZE 127 ! 480: ! 481: struct misc_bunch ! 482: { ! 483: struct misc_bunch *next; ! 484: struct misc_function contents[MISC_BUNCH_SIZE]; ! 485: }; ! 486: ! 487: /* Bunch currently being filled up. ! 488: The next field points to chain of filled bunches. */ ! 489: ! 490: static struct misc_bunch *misc_bunch; ! 491: ! 492: /* Number of slots filled in current bunch. */ ! 493: ! 494: static int misc_bunch_index; ! 495: ! 496: /* Total number of misc functions recorded so far. */ ! 497: ! 498: static int misc_count; ! 499: ! 500: static void ! 501: init_misc_functions () ! 502: { ! 503: misc_count = 0; ! 504: misc_bunch = 0; ! 505: misc_bunch_index = MISC_BUNCH_SIZE; ! 506: } ! 507: ! 508: static void ! 509: record_misc_function (name, address) ! 510: char *name; ! 511: CORE_ADDR address; ! 512: { ! 513: register struct misc_bunch *new; ! 514: ! 515: if (misc_bunch_index == MISC_BUNCH_SIZE) ! 516: { ! 517: new = (struct misc_bunch *) xmalloc (sizeof (struct misc_bunch)); ! 518: misc_bunch_index = 0; ! 519: new->next = misc_bunch; ! 520: misc_bunch = new; ! 521: } ! 522: misc_bunch->contents[misc_bunch_index].name = savestring (name, strlen (name)); ! 523: misc_bunch->contents[misc_bunch_index].address = address; ! 524: misc_bunch_index++; ! 525: misc_count++; ! 526: } ! 527: ! 528: static int ! 529: compare_misc_functions (fn1, fn2) ! 530: struct misc_function *fn1, *fn2; ! 531: { ! 532: /* Return a signed result based on unsigned comparisons ! 533: so that we sort into unsigned numeric order. */ ! 534: if (fn1->address < fn2->address) ! 535: return -1; ! 536: if (fn1->address > fn2->address) ! 537: return 1; ! 538: return 0; ! 539: } ! 540: ! 541: static void ! 542: discard_misc_bunches () ! 543: { ! 544: register struct misc_bunch *next; ! 545: ! 546: while (misc_bunch) ! 547: { ! 548: next = misc_bunch->next; ! 549: free (misc_bunch); ! 550: misc_bunch = next; ! 551: } ! 552: } ! 553: ! 554: static void ! 555: condense_misc_bunches () ! 556: { ! 557: register int i, j; ! 558: register struct misc_bunch *bunch; ! 559: #ifdef NAMES_HAVE_UNDERSCORE ! 560: int offset = 1; ! 561: #else ! 562: int offset = 0; ! 563: #endif ! 564: ! 565: misc_function_vector ! 566: = (struct misc_function *) ! 567: xmalloc (misc_count * sizeof (struct misc_function)); ! 568: ! 569: j = 0; ! 570: bunch = misc_bunch; ! 571: while (bunch) ! 572: { ! 573: for (i = 0; i < misc_bunch_index; i++) ! 574: { ! 575: register char *tmp; ! 576: ! 577: misc_function_vector[j] = bunch->contents[i]; ! 578: tmp = misc_function_vector[j].name; ! 579: misc_function_vector[j].name = (tmp[0] == '_' ? tmp + offset : tmp); ! 580: j++; ! 581: } ! 582: bunch = bunch->next; ! 583: misc_bunch_index = MISC_BUNCH_SIZE; ! 584: } ! 585: ! 586: misc_function_count = j; ! 587: ! 588: /* Sort the misc functions by address. */ ! 589: ! 590: qsort (misc_function_vector, j, sizeof (struct misc_function), ! 591: compare_misc_functions); ! 592: } ! 593: ! 594: /* Call sort_syms to sort alphabetically ! 595: the symbols of each block of each symtab. */ ! 596: ! 597: static int ! 598: compare_symbols (s1, s2) ! 599: struct symbol **s1, **s2; ! 600: { ! 601: /* Names that are less should come first. */ ! 602: register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)); ! 603: if (namediff != 0) return namediff; ! 604: /* For symbols of the same name, registers should come first. */ ! 605: return ((SYMBOL_CLASS (*s2) == LOC_REGISTER) ! 606: - (SYMBOL_CLASS (*s1) == LOC_REGISTER)); ! 607: } ! 608: ! 609: static void ! 610: sort_syms () ! 611: { ! 612: register struct symtab *s; ! 613: register int i, nbl; ! 614: register struct blockvector *bv; ! 615: register struct block *b; ! 616: ! 617: for (s = symtab_list; s; s = s->next) ! 618: { ! 619: bv = BLOCKVECTOR (s); ! 620: nbl = BLOCKVECTOR_NBLOCKS (bv); ! 621: for (i = 0; i < nbl; i++) ! 622: { ! 623: b = BLOCKVECTOR_BLOCK (bv, i); ! 624: qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b), ! 625: sizeof (struct symbol *), compare_symbols); ! 626: } ! 627: } ! 628: } ! 629: ! 630: /* This is the symbol-file command. Read the file, analyze its symbols, ! 631: and add a struct symtab to symtab_list. */ ! 632: ! 633: void ! 634: symbol_file_command (name) ! 635: char *name; ! 636: { ! 637: int desc; ! 638: int num_symbols; ! 639: int num_sections; ! 640: int symtab_offset; ! 641: extern void close (); ! 642: register int val; ! 643: struct cleanup *old_chain; ! 644: ! 645: dont_repeat (); ! 646: ! 647: if (name == 0) ! 648: { ! 649: if (symtab_list && !query ("Discard symbol table? ", 0)) ! 650: error ("Not confirmed."); ! 651: free_all_symtabs (); ! 652: return; ! 653: } ! 654: ! 655: if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name)) ! 656: error ("Not confirmed."); ! 657: ! 658: if (symfile) ! 659: free (symfile); ! 660: symfile = 0; ! 661: ! 662: { ! 663: char *absolute_name; ! 664: ! 665: desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name); ! 666: if (desc < 0) ! 667: perror_with_name (name); ! 668: else ! 669: name = absolute_name; ! 670: } ! 671: ! 672: old_chain = make_cleanup (close, desc); ! 673: make_cleanup (free_current_contents, &name); ! 674: ! 675: if ((num_symbols = read_file_hdr (desc, &file_hdr)) < 0) ! 676: error ("File \"%s\" not in executable format.", name); ! 677: ! 678: if (num_symbols == 0) ! 679: { ! 680: free_all_symtabs (); ! 681: printf ("%s does not have a symbol-table.\n", name); ! 682: fflush (stdout); ! 683: return; ! 684: } ! 685: ! 686: printf ("Reading symbol data from %s...", name); ! 687: fflush (stdout); ! 688: ! 689: /* Throw away the old symbol table. */ ! 690: ! 691: free_all_symtabs (); ! 692: ! 693: num_sections = file_hdr.f_nscns; ! 694: symtab_offset = file_hdr.f_symptr; ! 695: ! 696: if (read_section_hdr (desc, _TEXT, &text_hdr, num_sections) < 0) ! 697: error ("\"%s\": can't read text section header", name); ! 698: ! 699: /* Read the line number table, all at once. */ ! 700: ! 701: val = init_lineno (desc, text_hdr.s_lnnoptr, text_hdr.s_nlnno); ! 702: if (val < 0) ! 703: error ("\"%s\": error reading line numbers\n", name); ! 704: ! 705: /* Now read the string table, all at once. */ ! 706: ! 707: val = init_stringtab (desc, symtab_offset + num_symbols * SYMESZ); ! 708: if (val < 0) ! 709: { ! 710: free_all_symtabs (); ! 711: printf ("\"%s\": can't get string table", name); ! 712: fflush (stdout); ! 713: return; ! 714: } ! 715: make_cleanup (free_stringtab, 0); ! 716: ! 717: /* Position to read the symbol table. Do not read it all at once. */ ! 718: val = lseek (desc, (long)symtab_offset, 0); ! 719: if (val < 0) ! 720: perror_with_name (name); ! 721: ! 722: init_misc_functions (); ! 723: make_cleanup (discard_misc_bunches, 0); ! 724: ! 725: /* Now that the executable file is positioned at symbol table, ! 726: process it and define symbols accordingly. */ ! 727: ! 728: read_coff_symtab (desc, num_symbols); ! 729: ! 730: patch_opaque_types (); ! 731: ! 732: /* Sort symbols alphabetically within each block. */ ! 733: ! 734: sort_syms (); ! 735: ! 736: /* Go over the misc functions and install them in vector. */ ! 737: ! 738: condense_misc_bunches (); ! 739: ! 740: /* Don't allow char * to have a typename (else would get caddr_t.) */ ! 741: ! 742: TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; ! 743: ! 744: /* Make a default for file to list. */ ! 745: ! 746: select_source_symtab (symtab_list); ! 747: ! 748: symfile = savestring (name, strlen (name)); ! 749: ! 750: do_cleanups (old_chain); ! 751: ! 752: printf ("done.\n"); ! 753: fflush (stdout); ! 754: } ! 755: ! 756: /* Return name of file symbols were loaded from, or 0 if none.. */ ! 757: ! 758: char * ! 759: get_sym_file () ! 760: { ! 761: return symfile; ! 762: } ! 763: ! 764: /* Simplified internal version of coff symbol table information */ ! 765: ! 766: struct coff_symbol { ! 767: char *c_name; ! 768: int c_symnum; /* symbol number of this entry */ ! 769: int c_nsyms; /* 1 if syment only, 2 if syment + auxent */ ! 770: long c_value; ! 771: int c_sclass; ! 772: int c_secnum; ! 773: unsigned int c_type; ! 774: }; ! 775: ! 776: /* Given pointers to a symbol table in coff style exec file, ! 777: analyze them and create struct symtab's describing the symbols. ! 778: NSYMS is the number of symbols in the symbol table. ! 779: We read them one at a time using read_one_sym (). */ ! 780: ! 781: static void ! 782: read_coff_symtab (desc, nsyms) ! 783: int desc; ! 784: int nsyms; ! 785: { ! 786: FILE *stream = fdopen (desc, "r"); ! 787: register struct context_stack *new; ! 788: struct coff_symbol coff_symbol; ! 789: register struct coff_symbol *cs = &coff_symbol; ! 790: static SYMENT main_sym; ! 791: static AUXENT main_aux; ! 792: ! 793: int num_object_files = 0; ! 794: int next_file_symnum; ! 795: char *filestring; ! 796: int depth; ! 797: int fcn_first_line; ! 798: int fcn_last_line; ! 799: long fcn_line_ptr; ! 800: struct cleanup *old_chain; ! 801: ! 802: old_chain = make_cleanup (free_all_symtabs, 0); ! 803: nlist_stream_global = stream; ! 804: nlist_nsyms_global = nsyms; ! 805: last_source_file = 0; ! 806: bzero (opaque_type_chain, sizeof opaque_type_chain); ! 807: ! 808: type_vector_length = 160; ! 809: type_vector = (struct typevector *) ! 810: xmalloc (sizeof (struct typevector) ! 811: + type_vector_length * sizeof (struct type *)); ! 812: bzero (type_vector->type, type_vector_length * sizeof (struct type *)); ! 813: ! 814: start_symtab (); ! 815: ! 816: symnum = 0; ! 817: while (symnum < nsyms) ! 818: { ! 819: QUIT; /* Make this command interruptable. */ ! 820: read_one_sym (cs, &main_sym, &main_aux); ! 821: ! 822: if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) ! 823: { ! 824: CORE_ADDR last_file_end = cur_src_end_addr; ! 825: ! 826: if (last_source_file) ! 827: end_symtab (); ! 828: ! 829: start_symtab (); ! 830: complete_symtab ("_globals_", 0, first_object_file_end); ! 831: /* done with all files, everything from here on out is globals */ ! 832: } ! 833: ! 834: /* Special case for file with type declarations only, no text. */ ! 835: if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG) ! 836: complete_symtab (filestring, 0, 0); ! 837: ! 838: if (ISFCN (cs->c_type)) ! 839: { ! 840: /* ! 841: * gdb expects all functions to also be in misc_function ! 842: * list -- why not... ! 843: */ ! 844: record_misc_function (cs->c_name, cs->c_value); ! 845: ! 846: fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; ! 847: within_function = 1; ! 848: ! 849: new = (struct context_stack *) ! 850: xmalloc (sizeof (struct context_stack)); ! 851: new->depth = depth = 0; ! 852: new->next = 0; ! 853: context_stack = new; ! 854: new->locals = 0; ! 855: new->old_blocks = pending_blocks; ! 856: new->start_addr = cs->c_value; ! 857: new->name = process_coff_symbol (cs, &main_aux); ! 858: continue; ! 859: } ! 860: ! 861: switch (cs->c_sclass) ! 862: { ! 863: case C_EFCN: ! 864: case C_EXTDEF: ! 865: case C_ULABEL: ! 866: case C_USTATIC: ! 867: case C_LINE: ! 868: case C_ALIAS: ! 869: case C_HIDDEN: ! 870: printf ("Bad n_sclass = %d\n", cs->c_sclass); ! 871: break; ! 872: ! 873: case C_FILE: ! 874: /* ! 875: * c_value field contains symnum of next .file entry in table ! 876: * or symnum of first global after last .file. ! 877: */ ! 878: next_file_symnum = cs->c_value; ! 879: filestring = getfilename (&main_aux); ! 880: /* ! 881: * Complete symbol table for last object file ! 882: * containing debugging information. ! 883: */ ! 884: if (last_source_file) ! 885: { ! 886: end_symtab (); ! 887: start_symtab (); ! 888: } ! 889: num_object_files++; ! 890: break; ! 891: ! 892: case C_EXT: ! 893: if (cs->c_secnum == N_ABS && strcmp (cs->c_name, _ETEXT) == 0) ! 894: { ! 895: end_of_text_addr = cs->c_value; ! 896: } ! 897: if (cs->c_type == T_NULL) ! 898: { ! 899: if (cs->c_secnum <= 1) /* text or abs */ ! 900: { ! 901: record_misc_function (cs->c_name, cs->c_value); ! 902: break; ! 903: } ! 904: else ! 905: cs->c_type = T_INT; ! 906: } ! 907: (void) process_coff_symbol (cs, &main_aux); ! 908: break; ! 909: ! 910: case C_STAT: ! 911: if (cs->c_type == T_NULL && cs->c_secnum > N_UNDEF) ! 912: { ! 913: if (strcmp (cs->c_name, _TEXT) == 0) ! 914: { ! 915: if (num_object_files == 1) ! 916: { ! 917: /* Record end address of first file, crt0.s */ ! 918: first_object_file_end = ! 919: cs->c_value + main_aux.x_scn.x_scnlen; ! 920: } ! 921: /* ! 922: * Fill in missing information for debugged ! 923: * object file only if we have line number info. ! 924: */ ! 925: if (main_aux.x_scn.x_nlinno > 0) ! 926: { ! 927: complete_symtab (filestring, cs->c_value, ! 928: main_aux.x_scn.x_scnlen); ! 929: } ! 930: break; ! 931: } ! 932: else if (strcmp (cs->c_name, _DATA) == 0) ! 933: break; ! 934: else if (strcmp (cs->c_name, _BSS) == 0) ! 935: break; ! 936: ! 937: /* get rid of assembly labels here */ ! 938: /* record_misc_function (cs->c_name, cs->c_value); */ ! 939: break; ! 940: } ! 941: (void) process_coff_symbol (cs, &main_aux); ! 942: break; ! 943: ! 944: case C_FCN: ! 945: if (strcmp (cs->c_name, ".bf") == 0) ! 946: { ! 947: /* value contains address of first non-init type code */ ! 948: /* main_aux.x_sym.x_misc.x_lnsz.x_lnno ! 949: contains line number of '{' } */ ! 950: fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; ! 951: } ! 952: else if (strcmp (cs->c_name, ".ef") == 0) ! 953: { ! 954: /* value contains address of exit/return from function */ ! 955: /* round it up to next multiple of 16 */ ! 956: cs->c_value = (cs->c_value + 15) & -16; ! 957: /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno ! 958: contains number of lines to '}' */ ! 959: fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; ! 960: enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line); ! 961: ! 962: new = context_stack; ! 963: finish_block (new->name, &local_symbols, new->old_blocks, ! 964: new->start_addr, cs->c_value); ! 965: context_stack = 0; ! 966: within_function = 0; ! 967: free (new); ! 968: } ! 969: break; ! 970: ! 971: case C_BLOCK: ! 972: if (strcmp (cs->c_name, ".bb") == 0) ! 973: { ! 974: new = (struct context_stack *) ! 975: xmalloc (sizeof (struct context_stack)); ! 976: depth++; ! 977: new->depth = depth; ! 978: new->next = context_stack; ! 979: context_stack = new; ! 980: new->locals = local_symbols; ! 981: new->old_blocks = pending_blocks; ! 982: new->start_addr = cs->c_value; ! 983: new->name = 0; ! 984: local_symbols = 0; ! 985: } ! 986: else if (strcmp (cs->c_name, ".eb") == 0) ! 987: { ! 988: new = context_stack; ! 989: if (new == 0 || depth != new->depth) ! 990: error ("Invalid symbol data: .bb/.eb symbol mismatch."); ! 991: if (local_symbols && context_stack->next) ! 992: { ! 993: /* Make a block for the local symbols within. */ ! 994: finish_block (0, &local_symbols, new->old_blocks, ! 995: new->start_addr, cs->c_value); ! 996: } ! 997: depth--; ! 998: local_symbols = new->locals; ! 999: context_stack = new->next; ! 1000: free (new); ! 1001: } ! 1002: break; ! 1003: ! 1004: default: ! 1005: (void) process_coff_symbol (cs, &main_aux); ! 1006: break; ! 1007: } ! 1008: } ! 1009: ! 1010: if (last_source_file) ! 1011: end_symtab (); ! 1012: fclose (stream); ! 1013: discard_cleanups (old_chain); ! 1014: } ! 1015: ! 1016: /* Routines for reading headers and symbols from executable. */ ! 1017: ! 1018: /* Read COFF file header, check magic number, ! 1019: and return number of symbols. */ ! 1020: read_file_hdr (chan, file_hdr) ! 1021: int chan; ! 1022: FILHDR *file_hdr; ! 1023: { ! 1024: lseek (chan, 0L, 0); ! 1025: if (myread (chan, (char *)file_hdr, FILHSZ) < 0) ! 1026: return -1; ! 1027: ! 1028: switch (file_hdr->f_magic) ! 1029: { ! 1030: case NS32GMAGIC: ! 1031: case NS32SMAGIC: ! 1032: return file_hdr->f_nsyms; ! 1033: ! 1034: default: ! 1035: return -1; ! 1036: } ! 1037: } ! 1038: ! 1039: read_aout_hdr (chan, aout_hdr, size) ! 1040: int chan; ! 1041: AOUTHDR *aout_hdr; ! 1042: int size; ! 1043: { ! 1044: lseek (chan, (long)FILHSZ, 0); ! 1045: if (size != sizeof (AOUTHDR)) ! 1046: return -1; ! 1047: if (myread (chan, (char *)aout_hdr, size) != size) ! 1048: return -1; ! 1049: return 0; ! 1050: } ! 1051: ! 1052: read_section_hdr (chan, section_name, section_hdr, nsects) ! 1053: register int chan; ! 1054: register char *section_name; ! 1055: SCNHDR *section_hdr; ! 1056: register int nsects; ! 1057: { ! 1058: register int i; ! 1059: ! 1060: if (lseek (chan, FILHSZ + sizeof (AOUTHDR), 0) < 0) ! 1061: return -1; ! 1062: ! 1063: for (i = 0; i < nsects; i++) ! 1064: { ! 1065: if (myread (chan, (char *)section_hdr, SCNHSZ) < 0) ! 1066: return -1; ! 1067: if (strncmp (section_hdr->s_name, section_name, 8) == 0) ! 1068: return 0; ! 1069: } ! 1070: return -1; ! 1071: } ! 1072: ! 1073: read_one_sym (cs, sym, aux) ! 1074: register struct coff_symbol *cs; ! 1075: register SYMENT *sym; ! 1076: register AUXENT *aux; ! 1077: { ! 1078: cs->c_symnum = symnum; ! 1079: fread ((char *)sym, SYMESZ, 1, nlist_stream_global); ! 1080: cs->c_nsyms = (sym->n_numaux & 0xff) + 1; ! 1081: if (cs->c_nsyms == 2) ! 1082: { ! 1083: /* doc for coff says there is either no aux entry or just one */ ! 1084: fread ((char *)aux, AUXESZ, 1, nlist_stream_global); ! 1085: } ! 1086: else if (cs->c_nsyms > 2) ! 1087: error ("more than one aux symbol table entry at symnum=%d\n", symnum); ! 1088: ! 1089: cs->c_name = getsymname (sym); ! 1090: cs->c_value = sym->n_value; ! 1091: cs->c_sclass = (sym->n_sclass & 0xff); ! 1092: cs->c_secnum = sym->n_scnum; ! 1093: cs->c_type = (unsigned) sym->n_type; ! 1094: ! 1095: symnum += cs->c_nsyms; ! 1096: } ! 1097: ! 1098: /* Support for string table handling */ ! 1099: ! 1100: static char *stringtab = NULL; ! 1101: ! 1102: static int ! 1103: init_stringtab (chan, offset) ! 1104: int chan; ! 1105: long offset; ! 1106: { ! 1107: long buffer; ! 1108: int val; ! 1109: ! 1110: if (lseek (chan, offset, 0) < 0) ! 1111: return -1; ! 1112: ! 1113: val = myread (chan, (char *)&buffer, sizeof buffer); ! 1114: if (val != sizeof buffer) ! 1115: return -1; ! 1116: ! 1117: if (stringtab) ! 1118: free (stringtab); ! 1119: stringtab = (char *) xmalloc (buffer); ! 1120: if (stringtab == NULL) ! 1121: return -1; ! 1122: ! 1123: bcopy (&buffer, stringtab, sizeof buffer); ! 1124: ! 1125: val = myread (chan, stringtab + sizeof buffer, buffer - sizeof buffer); ! 1126: if (val != buffer - sizeof buffer || stringtab[buffer - 1] != '\0') ! 1127: return -1; ! 1128: ! 1129: return 0; ! 1130: } ! 1131: ! 1132: static void ! 1133: free_stringtab () ! 1134: { ! 1135: if (stringtab) ! 1136: free (stringtab); ! 1137: stringtab = NULL; ! 1138: } ! 1139: ! 1140: static char * ! 1141: getsymname (symbol_entry) ! 1142: SYMENT *symbol_entry; ! 1143: { ! 1144: static char buffer[SYMNMLEN+1]; ! 1145: char *result; ! 1146: ! 1147: if (symbol_entry->n_zeroes == 0) ! 1148: { ! 1149: result = stringtab + symbol_entry->n_offset; ! 1150: } ! 1151: else ! 1152: { ! 1153: strncpy (buffer, symbol_entry->n_name, SYMNMLEN); ! 1154: buffer[SYMNMLEN] = '\0'; ! 1155: result = buffer; ! 1156: } ! 1157: return result; ! 1158: } ! 1159: ! 1160: static char * ! 1161: getfilename (aux_entry) ! 1162: AUXENT *aux_entry; ! 1163: { ! 1164: static char buffer[BUFSIZ]; ! 1165: register char *temp; ! 1166: char *result; ! 1167: extern char *rindex (); ! 1168: ! 1169: if (aux_entry->x_file.x_foff != 0) ! 1170: strcpy (buffer, stringtab + aux_entry->x_file.x_foff); ! 1171: else ! 1172: { ! 1173: strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN); ! 1174: buffer[FILNMLEN] = '\0'; ! 1175: } ! 1176: result = buffer; ! 1177: if ((temp = rindex (result, '/')) != NULL) ! 1178: result = temp + 1; ! 1179: return (result); ! 1180: } ! 1181: ! 1182: /* Support for line number handling */ ! 1183: static char *linetab = NULL; ! 1184: static long linetab_offset; ! 1185: static int linetab_count; ! 1186: ! 1187: static int ! 1188: init_lineno (chan, offset, count) ! 1189: int chan; ! 1190: long offset; ! 1191: int count; ! 1192: { ! 1193: int val; ! 1194: ! 1195: if (lseek (chan, offset, 0) < 0) ! 1196: return -1; ! 1197: ! 1198: if (linetab) ! 1199: free (linetab); ! 1200: linetab = (char *) xmalloc (count * LINESZ); ! 1201: ! 1202: val = myread (chan, linetab, count * LINESZ); ! 1203: if (val != count * LINESZ) ! 1204: return -1; ! 1205: ! 1206: linetab_offset = offset; ! 1207: linetab_count = count; ! 1208: return 0; ! 1209: } ! 1210: ! 1211: static void ! 1212: enter_linenos (file_offset, first_line, last_line) ! 1213: long file_offset; ! 1214: register int first_line; ! 1215: register int last_line; ! 1216: { ! 1217: register char *rawptr = &linetab[file_offset - linetab_offset]; ! 1218: register struct lineno *lptr; ! 1219: ! 1220: /* skip first line entry for each function */ ! 1221: rawptr += LINESZ; ! 1222: /* line numbers start at one for the first line of the function */ ! 1223: first_line--; ! 1224: ! 1225: for (lptr = (struct lineno *)rawptr; ! 1226: lptr->l_lnno && lptr->l_lnno <= last_line; ! 1227: rawptr += LINESZ, lptr = (struct lineno *)rawptr) ! 1228: { ! 1229: record_line (first_line + lptr->l_lnno, lptr->l_addr.l_paddr); ! 1230: } ! 1231: } ! 1232: ! 1233: static int ! 1234: hashname (name) ! 1235: char *name; ! 1236: { ! 1237: register char *p = name; ! 1238: register int total = p[0]; ! 1239: register int c; ! 1240: ! 1241: c = p[1]; ! 1242: total += c << 2; ! 1243: if (c) ! 1244: { ! 1245: c = p[2]; ! 1246: total += c << 4; ! 1247: if (c) ! 1248: total += p[3] << 6; ! 1249: } ! 1250: ! 1251: return total % HASHSIZE; ! 1252: } ! 1253: ! 1254: static void ! 1255: patch_type (type, real_type) ! 1256: struct type *type; ! 1257: struct type *real_type; ! 1258: { ! 1259: register struct type *target = TYPE_TARGET_TYPE (type); ! 1260: register struct type *real_target = TYPE_TARGET_TYPE (real_type); ! 1261: int field_size = TYPE_NFIELDS (real_target) * sizeof (struct field); ! 1262: ! 1263: TYPE_LENGTH (target) = TYPE_LENGTH (real_target); ! 1264: TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target); ! 1265: TYPE_FIELDS (target) = (struct field *) ! 1266: obstack_alloc (symbol_obstack, field_size); ! 1267: ! 1268: bcopy (TYPE_FIELDS (real_target), TYPE_FIELDS (target), field_size); ! 1269: ! 1270: if (TYPE_NAME (real_target)) ! 1271: { ! 1272: if (TYPE_NAME (target)) ! 1273: free (TYPE_NAME (target)); ! 1274: TYPE_NAME (target) = concat (TYPE_NAME (real_target), "", ""); ! 1275: } ! 1276: } ! 1277: ! 1278: /* Patch up all appropriate typdef symbols in the opaque_type_chains ! 1279: so that they can be used to print out opaque data structures properly */ ! 1280: ! 1281: static void ! 1282: patch_opaque_types () ! 1283: { ! 1284: struct symtab *s; ! 1285: ! 1286: /* Look at each symbol in the per-file block of each symtab. */ ! 1287: for (s = symtab_list; s; s = s->next) ! 1288: { ! 1289: register struct block *b; ! 1290: register int i; ! 1291: ! 1292: /* Go through the per-file symbols only */ ! 1293: b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1); ! 1294: for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--) ! 1295: { ! 1296: register struct symbol *real_sym; ! 1297: ! 1298: /* Find completed typedefs to use to fix opaque ones. ! 1299: Remove syms from the chain when their types are stored, ! 1300: but search the whole chain, as there may be several syms ! 1301: from different files with the same name. */ ! 1302: real_sym = BLOCK_SYM (b, i); ! 1303: if (SYMBOL_CLASS (real_sym) == LOC_TYPEDEF && ! 1304: SYMBOL_NAMESPACE (real_sym) == VAR_NAMESPACE && ! 1305: TYPE_CODE (SYMBOL_TYPE (real_sym)) == TYPE_CODE_PTR && ! 1306: TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (real_sym))) != 0) ! 1307: { ! 1308: register char *name = SYMBOL_NAME (real_sym); ! 1309: register int hash = hashname (name); ! 1310: register struct symbol *sym, *prev; ! 1311: ! 1312: prev = 0; ! 1313: for (sym = opaque_type_chain[hash]; sym;) ! 1314: { ! 1315: if (name[0] == SYMBOL_NAME (sym)[0] && ! 1316: !strcmp (name + 1, SYMBOL_NAME (sym) + 1)) ! 1317: { ! 1318: if (prev) ! 1319: SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); ! 1320: else ! 1321: opaque_type_chain[hash] ! 1322: = (struct symbol *) SYMBOL_VALUE (sym); ! 1323: ! 1324: patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym)); ! 1325: ! 1326: if (prev) ! 1327: sym = (struct symbol *) SYMBOL_VALUE (prev); ! 1328: else ! 1329: sym = opaque_type_chain[hash]; ! 1330: } ! 1331: else ! 1332: { ! 1333: prev = sym; ! 1334: sym = (struct symbol *) SYMBOL_VALUE (sym); ! 1335: } ! 1336: } ! 1337: } ! 1338: } ! 1339: } ! 1340: } ! 1341: ! 1342: static struct symbol * ! 1343: process_coff_symbol (cs, aux) ! 1344: register struct coff_symbol *cs; ! 1345: register AUXENT *aux; ! 1346: { ! 1347: register struct symbol *sym ! 1348: = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); ! 1349: char *name; ! 1350: char *dot; ! 1351: #ifdef NAMES_HAVE_UNDERSCORE ! 1352: int offset = 1; ! 1353: #else ! 1354: int offset = 0; ! 1355: #endif ! 1356: ! 1357: bzero (sym, sizeof (struct symbol)); ! 1358: name = cs->c_name; ! 1359: name = (name[0] == '_' ? name + offset : name); ! 1360: SYMBOL_NAME (sym) = obstack_copy0 (symbol_obstack, name, strlen (name)); ! 1361: ! 1362: /* default assumptions */ ! 1363: SYMBOL_VALUE (sym) = cs->c_value; ! 1364: SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; ! 1365: ! 1366: if (ISFCN (cs->c_type)) ! 1367: { ! 1368: SYMBOL_TYPE (sym) ! 1369: = lookup_function_type (decode_function_type (cs, cs->c_type, aux)); ! 1370: SYMBOL_CLASS (sym) = LOC_BLOCK; ! 1371: if (cs->c_sclass == C_STAT) ! 1372: add_symbol_to_list (sym, &file_symbols); ! 1373: else if (cs->c_sclass == C_EXT) ! 1374: add_symbol_to_list (sym, &global_symbols); ! 1375: } ! 1376: else ! 1377: { ! 1378: SYMBOL_TYPE (sym) = decode_type (cs, cs->c_type, aux); ! 1379: switch (cs->c_sclass) ! 1380: { ! 1381: case C_NULL: ! 1382: break; ! 1383: ! 1384: case C_AUTO: ! 1385: SYMBOL_CLASS (sym) = LOC_LOCAL; ! 1386: add_symbol_to_list (sym, &local_symbols); ! 1387: break; ! 1388: ! 1389: case C_EXT: ! 1390: SYMBOL_CLASS (sym) = LOC_STATIC; ! 1391: add_symbol_to_list (sym, &global_symbols); ! 1392: break; ! 1393: ! 1394: case C_STAT: ! 1395: SYMBOL_CLASS (sym) = LOC_STATIC; ! 1396: if (within_function) { ! 1397: /* Static symbol of local scope */ ! 1398: add_symbol_to_list (sym, &local_symbols); ! 1399: } ! 1400: else { ! 1401: /* Static symbol at top level of file */ ! 1402: add_symbol_to_list (sym, &file_symbols); ! 1403: } ! 1404: break; ! 1405: ! 1406: case C_REG: ! 1407: case C_REGPARM: ! 1408: SYMBOL_CLASS (sym) = LOC_REGISTER; ! 1409: add_symbol_to_list (sym, &local_symbols); ! 1410: break; ! 1411: ! 1412: case C_LABEL: ! 1413: break; ! 1414: ! 1415: case C_ARG: ! 1416: SYMBOL_CLASS (sym) = LOC_ARG; ! 1417: add_symbol_to_list (sym, &local_symbols); ! 1418: /* If PCC says a parameter is a short or a char, ! 1419: it is really an int. */ ! 1420: if (SYMBOL_TYPE (sym) == builtin_type_char ! 1421: || SYMBOL_TYPE (sym) == builtin_type_short) ! 1422: SYMBOL_TYPE (sym) = builtin_type_int; ! 1423: else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char ! 1424: || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) ! 1425: SYMBOL_TYPE (sym) = builtin_type_unsigned_int; ! 1426: break; ! 1427: ! 1428: case C_TPDEF: ! 1429: SYMBOL_CLASS (sym) = LOC_TYPEDEF; ! 1430: SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; ! 1431: ! 1432: /* If type has no name, give it one */ ! 1433: if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 ! 1434: && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) ! 1435: TYPE_NAME (SYMBOL_TYPE (sym)) ! 1436: = concat (SYMBOL_NAME (sym), "", ""); ! 1437: ! 1438: /* Keep track of any type which points to empty structured type, ! 1439: so it can be filled from a definition from another file */ ! 1440: if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR && ! 1441: TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0) ! 1442: { ! 1443: register int i = hashname (SYMBOL_NAME (sym)); ! 1444: ! 1445: SYMBOL_VALUE (sym) = (int) opaque_type_chain[i]; ! 1446: opaque_type_chain[i] = sym; ! 1447: } ! 1448: add_symbol_to_list (sym, &file_symbols); ! 1449: break; ! 1450: ! 1451: case C_STRTAG: ! 1452: case C_UNTAG: ! 1453: case C_ENTAG: ! 1454: SYMBOL_CLASS (sym) = LOC_TYPEDEF; ! 1455: SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; ! 1456: if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 ! 1457: && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) ! 1458: TYPE_NAME (SYMBOL_TYPE (sym)) ! 1459: = concat ("", ! 1460: (cs->c_sclass == C_ENTAG ! 1461: ? "enum " ! 1462: : (cs->c_sclass == C_STRTAG ! 1463: ? "struct " : "union ")), ! 1464: SYMBOL_NAME (sym)); ! 1465: add_symbol_to_list (sym, &file_symbols); ! 1466: break; ! 1467: ! 1468: default: ! 1469: break; ! 1470: } ! 1471: } ! 1472: return sym; ! 1473: } ! 1474: ! 1475: /* Decode a coff type specifier; ! 1476: return the type that is meant. */ ! 1477: ! 1478: static ! 1479: struct type * ! 1480: decode_type (cs, c_type, aux) ! 1481: register struct coff_symbol *cs; ! 1482: unsigned int c_type; ! 1483: register AUXENT *aux; ! 1484: { ! 1485: register struct type *type = 0; ! 1486: register int n; ! 1487: unsigned int new_c_type; ! 1488: ! 1489: if (c_type & ~N_BTMASK) ! 1490: { ! 1491: new_c_type = DECREF (c_type); ! 1492: if (ISPTR (c_type)) ! 1493: { ! 1494: type = decode_type (cs, new_c_type, aux); ! 1495: type = lookup_pointer_type (type); ! 1496: } ! 1497: else if (ISFCN (c_type)) ! 1498: { ! 1499: type = decode_type (cs, new_c_type, aux); ! 1500: type = lookup_function_type (type); ! 1501: } ! 1502: else if (ISARY (c_type)) ! 1503: { ! 1504: int i, n; ! 1505: register unsigned short *dim; ! 1506: struct type *base_type; ! 1507: ! 1508: /* Define an array type. */ ! 1509: /* auxent refers to array, not base type */ ! 1510: if (aux->x_sym.x_tagndx == 0) ! 1511: cs->c_nsyms = 1; ! 1512: ! 1513: /* shift the indices down */ ! 1514: dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0]; ! 1515: i = 1; ! 1516: n = dim[0]; ! 1517: for (i = 0; *dim && i < DIMNUM - 1; i++, dim++) ! 1518: *dim = *(dim + 1); ! 1519: *dim = 0; ! 1520: ! 1521: type = (struct type *) ! 1522: obstack_alloc (symbol_obstack, sizeof (struct type)); ! 1523: bzero (type, sizeof (struct type)); ! 1524: ! 1525: base_type = decode_type (cs, new_c_type, aux); ! 1526: ! 1527: TYPE_CODE (type) = TYPE_CODE_ARRAY; ! 1528: TYPE_TARGET_TYPE (type) = base_type; ! 1529: TYPE_LENGTH (type) = n * TYPE_LENGTH (base_type); ! 1530: } ! 1531: return type; ! 1532: } ! 1533: ! 1534: /* Reference to existing type */ ! 1535: if (cs->c_nsyms > 1 && aux->x_sym.x_tagndx != 0) ! 1536: { ! 1537: type = coff_alloc_type (aux->x_sym.x_tagndx); ! 1538: return type; ! 1539: } ! 1540: ! 1541: return decode_base_type (cs, BTYPE (c_type), aux); ! 1542: } ! 1543: ! 1544: /* Decode a coff type specifier for function definition; ! 1545: return the type that the function returns. */ ! 1546: ! 1547: static ! 1548: struct type * ! 1549: decode_function_type (cs, c_type, aux) ! 1550: register struct coff_symbol *cs; ! 1551: unsigned int c_type; ! 1552: register AUXENT *aux; ! 1553: { ! 1554: if (aux->x_sym.x_tagndx == 0) ! 1555: cs->c_nsyms = 1; /* auxent refers to function, not base type */ ! 1556: ! 1557: return decode_type (cs, DECREF (cs->c_type), aux); ! 1558: } ! 1559: ! 1560: /* basic C types */ ! 1561: ! 1562: static ! 1563: struct type * ! 1564: decode_base_type (cs, c_type, aux) ! 1565: register struct coff_symbol *cs; ! 1566: unsigned int c_type; ! 1567: register AUXENT *aux; ! 1568: { ! 1569: struct type *type; ! 1570: ! 1571: switch (c_type) ! 1572: { ! 1573: case T_NULL: ! 1574: /* shouldn't show up here */ ! 1575: break; ! 1576: ! 1577: case T_ARG: ! 1578: /* shouldn't show up here */ ! 1579: break; ! 1580: ! 1581: case T_CHAR: ! 1582: return builtin_type_char; ! 1583: ! 1584: case T_SHORT: ! 1585: return builtin_type_short; ! 1586: ! 1587: case T_INT: ! 1588: return builtin_type_int; ! 1589: ! 1590: case T_LONG: ! 1591: return builtin_type_long; ! 1592: ! 1593: case T_FLOAT: ! 1594: return builtin_type_float; ! 1595: ! 1596: case T_DOUBLE: ! 1597: return builtin_type_double; ! 1598: ! 1599: case T_STRUCT: ! 1600: if (cs->c_nsyms != 2) ! 1601: { ! 1602: /* anonymous structure type */ ! 1603: type = coff_alloc_type (cs->c_symnum); ! 1604: TYPE_CODE (type) = TYPE_CODE_STRUCT; ! 1605: TYPE_NAME (type) = concat ("struct ", "<opaque>", ""); ! 1606: TYPE_LENGTH (type) = 0; ! 1607: TYPE_FIELDS (type) = 0; ! 1608: TYPE_NFIELDS (type) = 0; ! 1609: } ! 1610: else ! 1611: { ! 1612: type = read_struct_type (cs->c_symnum, ! 1613: aux->x_sym.x_misc.x_lnsz.x_size, ! 1614: aux->x_sym.x_fcnary.x_fcn.x_endndx); ! 1615: } ! 1616: return type; ! 1617: ! 1618: case T_UNION: ! 1619: if (cs->c_nsyms != 2) ! 1620: { ! 1621: /* anonymous union type */ ! 1622: type = coff_alloc_type (cs->c_symnum); ! 1623: TYPE_NAME (type) = concat ("union ", "<opaque>", ""); ! 1624: TYPE_LENGTH (type) = 0; ! 1625: TYPE_FIELDS (type) = 0; ! 1626: TYPE_NFIELDS (type) = 0; ! 1627: } ! 1628: else ! 1629: { ! 1630: type = read_struct_type (cs->c_symnum, ! 1631: aux->x_sym.x_misc.x_lnsz.x_size, ! 1632: aux->x_sym.x_fcnary.x_fcn.x_endndx); ! 1633: } ! 1634: TYPE_CODE (type) = TYPE_CODE_UNION; ! 1635: return type; ! 1636: ! 1637: case T_ENUM: ! 1638: return read_enum_type (cs->c_symnum, ! 1639: aux->x_sym.x_misc.x_lnsz.x_size, ! 1640: aux->x_sym.x_fcnary.x_fcn.x_endndx); ! 1641: ! 1642: case T_MOE: ! 1643: /* shouldn't show up here */ ! 1644: break; ! 1645: ! 1646: case T_UCHAR: ! 1647: return builtin_type_unsigned_char; ! 1648: ! 1649: case T_USHORT: ! 1650: return builtin_type_unsigned_short; ! 1651: ! 1652: case T_UINT: ! 1653: return builtin_type_unsigned_int; ! 1654: ! 1655: case T_ULONG: ! 1656: return builtin_type_unsigned_long; ! 1657: } ! 1658: printf ("unexpected type %d at symnum %d\n", c_type, cs->c_symnum); ! 1659: return builtin_type_void; ! 1660: } ! 1661: ! 1662: /* This page contains subroutines of read_type. */ ! 1663: ! 1664: /* Read the description of a structure (or union type) ! 1665: and return an object describing the type. */ ! 1666: ! 1667: static struct type * ! 1668: read_struct_type (index, length, lastsym) ! 1669: int index; ! 1670: int length; ! 1671: int lastsym; ! 1672: { ! 1673: struct nextfield ! 1674: { ! 1675: struct nextfield *next; ! 1676: struct field field; ! 1677: }; ! 1678: ! 1679: register struct type *type; ! 1680: register struct nextfield *list = 0; ! 1681: struct nextfield *new; ! 1682: int nfields = 0; ! 1683: register int n; ! 1684: char *name; ! 1685: #ifdef NAMES_HAVE_UNDERSCORE ! 1686: int offset = 1; ! 1687: #else ! 1688: int offset = 0; ! 1689: #endif ! 1690: struct coff_symbol member_sym; ! 1691: register struct coff_symbol *ms = &member_sym; ! 1692: SYMENT sub_sym; ! 1693: AUXENT sub_aux; ! 1694: ! 1695: type = coff_alloc_type (index); ! 1696: TYPE_CODE (type) = TYPE_CODE_STRUCT; ! 1697: TYPE_LENGTH (type) = length; ! 1698: ! 1699: while (symnum < lastsym && symnum < nlist_nsyms_global) ! 1700: { ! 1701: read_one_sym (ms, &sub_sym, &sub_aux); ! 1702: name = ms->c_name; ! 1703: name = (name[0] == '_' ? name + offset : name); ! 1704: ! 1705: switch (ms->c_sclass) ! 1706: { ! 1707: case C_MOS: ! 1708: case C_MOU: ! 1709: ! 1710: /* Get space to record the next field's data. */ ! 1711: new = (struct nextfield *) alloca (sizeof (struct nextfield)); ! 1712: new->next = list; ! 1713: list = new; ! 1714: ! 1715: /* Save the data. */ ! 1716: list->field.name = savestring (name, strlen (name)); ! 1717: list->field.type = decode_type (ms, ms->c_type, &sub_aux); ! 1718: list->field.bitpos = 8 * ms->c_value; ! 1719: list->field.bitsize = 0; ! 1720: nfields++; ! 1721: break; ! 1722: ! 1723: case C_FIELD: ! 1724: ! 1725: /* Get space to record the next field's data. */ ! 1726: new = (struct nextfield *) alloca (sizeof (struct nextfield)); ! 1727: new->next = list; ! 1728: list = new; ! 1729: ! 1730: /* Save the data. */ ! 1731: list->field.name = savestring (name, strlen (name)); ! 1732: list->field.type = decode_type (ms, ms->c_type, &sub_aux); ! 1733: list->field.bitpos = ms->c_value; ! 1734: list->field.bitsize = sub_aux.x_sym.x_misc.x_lnsz.x_size; ! 1735: nfields++; ! 1736: break; ! 1737: ! 1738: case C_EOS: ! 1739: break; ! 1740: } ! 1741: } ! 1742: /* Now create the vector of fields, and record how big it is. */ ! 1743: ! 1744: TYPE_NFIELDS (type) = nfields; ! 1745: TYPE_FIELDS (type) = (struct field *) ! 1746: obstack_alloc (symbol_obstack, sizeof (struct field) * nfields); ! 1747: ! 1748: /* Copy the saved-up fields into the field vector. */ ! 1749: ! 1750: for (n = nfields; list; list = list->next) ! 1751: TYPE_FIELD (type, --n) = list->field; ! 1752: ! 1753: return type; ! 1754: } ! 1755: ! 1756: /* Read a definition of an enumeration type, ! 1757: and create and return a suitable type object. ! 1758: Also defines the symbols that represent the values of the type. */ ! 1759: ! 1760: static struct type * ! 1761: read_enum_type (index, length, lastsym) ! 1762: int index; ! 1763: int length; ! 1764: int lastsym; ! 1765: { ! 1766: register struct symbol *sym; ! 1767: register struct type *type; ! 1768: int nsyms = 0; ! 1769: struct pending **symlist; ! 1770: struct coff_symbol member_sym; ! 1771: register struct coff_symbol *ms = &member_sym; ! 1772: SYMENT sub_sym; ! 1773: AUXENT sub_aux; ! 1774: struct pending *osyms, *syms; ! 1775: register int n; ! 1776: char *name; ! 1777: #ifdef NAMES_HAVE_UNDERSCORE ! 1778: int offset = 1; ! 1779: #else ! 1780: int offset = 0; ! 1781: #endif ! 1782: ! 1783: type = coff_alloc_type (index); ! 1784: if (within_function) ! 1785: symlist = &local_symbols; ! 1786: else ! 1787: symlist = &file_symbols; ! 1788: osyms = *symlist; ! 1789: ! 1790: while (symnum < lastsym && symnum < nlist_nsyms_global) ! 1791: { ! 1792: read_one_sym (ms, &sub_sym, &sub_aux); ! 1793: name = ms->c_name; ! 1794: name = (name[0] == '_' ? name + offset : name); ! 1795: ! 1796: switch (ms->c_sclass) ! 1797: { ! 1798: case C_MOE: ! 1799: sym = (struct symbol *) xmalloc (sizeof (struct symbol)); ! 1800: bzero (sym, sizeof (struct symbol)); ! 1801: ! 1802: SYMBOL_NAME (sym) = savestring (name, strlen (name)); ! 1803: SYMBOL_CLASS (sym) = LOC_CONST; ! 1804: SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; ! 1805: SYMBOL_VALUE (sym) = ms->c_value; ! 1806: add_symbol_to_list (sym, symlist); ! 1807: nsyms++; ! 1808: break; ! 1809: ! 1810: case C_EOS: ! 1811: break; ! 1812: } ! 1813: } ! 1814: ! 1815: /* Now fill in the fields of the type-structure. */ ! 1816: ! 1817: TYPE_LENGTH (type) = sizeof (int); ! 1818: TYPE_CODE (type) = TYPE_CODE_ENUM; ! 1819: TYPE_NFIELDS (type) = nsyms; ! 1820: TYPE_FIELDS (type) = (struct field *) ! 1821: obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms); ! 1822: ! 1823: /* Find the symbols for the values and put them into the type. ! 1824: The symbols can be found in the symlist that we put them on ! 1825: to cause them to be defined. osyms contains the old value ! 1826: of that symlist; everything up to there was defined by us. */ ! 1827: ! 1828: for (syms = *symlist, n = nsyms; syms != osyms; syms = syms->next) ! 1829: { ! 1830: SYMBOL_TYPE (syms->symbol) = type; ! 1831: TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (syms->symbol); ! 1832: TYPE_FIELD_VALUE (type, n) = SYMBOL_VALUE (syms->symbol); ! 1833: TYPE_FIELD_BITPOS (type, n) = 0; ! 1834: TYPE_FIELD_BITSIZE (type, n) = 0; ! 1835: } ! 1836: return type; ! 1837: } ! 1838: ! 1839: static ! 1840: initialize () ! 1841: { ! 1842: symfile = 0; ! 1843: ! 1844: add_com ("symbol-file", class_files, symbol_file_command, ! 1845: "Load symbol table (in coff format) from executable file FILE."); ! 1846: } ! 1847: ! 1848: END_FILE ! 1849: ! 1850: #endif /* COFF_FORMAT */ ! 1851:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.