|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)object.c 5.2 (Berkeley) 1/12/88"; ! 9: #endif not lint ! 10: ! 11: static char rcsid[] = "$Header: object.c,v 1.5 87/03/26 20:24:58 donn Exp $"; ! 12: ! 13: /* ! 14: * Object code interface, mainly for extraction of symbolic information. ! 15: */ ! 16: ! 17: #include "defs.h" ! 18: #include "object.h" ! 19: #include "stabstring.h" ! 20: #include "main.h" ! 21: #include "symbols.h" ! 22: #include "names.h" ! 23: #include "languages.h" ! 24: #include "mappings.h" ! 25: #include "lists.h" ! 26: #include <a.out.h> ! 27: #include <stab.h> ! 28: #include <ctype.h> ! 29: ! 30: #ifndef public ! 31: ! 32: struct { ! 33: unsigned int stringsize; /* size of the dumped string table */ ! 34: unsigned int nsyms; /* number of symbols */ ! 35: unsigned int nfiles; /* number of files */ ! 36: unsigned int nlines; /* number of lines */ ! 37: } nlhdr; ! 38: ! 39: #include "languages.h" ! 40: #include "symbols.h" ! 41: ! 42: #endif ! 43: ! 44: #ifndef N_MOD2 ! 45: # define N_MOD2 0x50 ! 46: #endif ! 47: ! 48: public String objname = "a.out"; ! 49: public integer objsize; ! 50: ! 51: public Language curlang; ! 52: public Symbol curmodule; ! 53: public Symbol curparam; ! 54: public Symbol curcomm; ! 55: public Symbol commchain; ! 56: ! 57: private char *stringtab; ! 58: private struct nlist *curnp; ! 59: private Boolean warned; ! 60: private Boolean strip_ = false; ! 61: ! 62: private Filetab *filep; ! 63: private Linetab *linep, *prevlinep; ! 64: ! 65: public String curfilename () ! 66: { ! 67: return ((filep-1)->filename); ! 68: } ! 69: ! 70: /* ! 71: * Blocks are figured out on the fly while reading the symbol table. ! 72: */ ! 73: ! 74: #define MAXBLKDEPTH 25 ! 75: ! 76: public Symbol curblock; ! 77: ! 78: private Symbol blkstack[MAXBLKDEPTH]; ! 79: private integer curlevel; ! 80: private integer bnum, nesting; ! 81: private Address addrstk[MAXBLKDEPTH]; ! 82: ! 83: public pushBlock (b) ! 84: Symbol b; ! 85: { ! 86: if (curlevel >= MAXBLKDEPTH) { ! 87: fatal("nesting depth too large (%d)", curlevel); ! 88: } ! 89: blkstack[curlevel] = curblock; ! 90: ++curlevel; ! 91: curblock = b; ! 92: if (traceblocks) { ! 93: printf("entering block %s\n", symname(b)); ! 94: } ! 95: } ! 96: ! 97: /* ! 98: * Change the current block with saving the previous one, ! 99: * since it is assumed that the symbol for the current one is to be deleted. ! 100: */ ! 101: ! 102: public changeBlock (b) ! 103: Symbol b; ! 104: { ! 105: curblock = b; ! 106: } ! 107: ! 108: public enterblock (b) ! 109: Symbol b; ! 110: { ! 111: if (curblock == nil) { ! 112: b->level = 1; ! 113: } else { ! 114: b->level = curblock->level + 1; ! 115: } ! 116: b->block = curblock; ! 117: pushBlock(b); ! 118: } ! 119: ! 120: public exitblock () ! 121: { ! 122: if (curblock->class == FUNC or curblock->class == PROC) { ! 123: if (prevlinep != linep) { ! 124: curblock->symvalue.funcv.src = true; ! 125: } ! 126: } ! 127: if (curlevel <= 0) { ! 128: panic("nesting depth underflow (%d)", curlevel); ! 129: } ! 130: --curlevel; ! 131: if (traceblocks) { ! 132: printf("exiting block %s\n", symname(curblock)); ! 133: } ! 134: curblock = blkstack[curlevel]; ! 135: } ! 136: ! 137: /* ! 138: * Enter a source line or file name reference into the appropriate table. ! 139: * Expanded inline to reduce procedure calls. ! 140: * ! 141: * private enterline (linenumber, address) ! 142: * Lineno linenumber; ! 143: * Address address; ! 144: * ... ! 145: */ ! 146: ! 147: #define enterline(linenumber, address) \ ! 148: { \ ! 149: register Linetab *lp; \ ! 150: \ ! 151: lp = linep - 1; \ ! 152: if (linenumber != lp->line) { \ ! 153: if (address != lp->addr) { \ ! 154: ++lp; \ ! 155: } \ ! 156: lp->line = linenumber; \ ! 157: lp->addr = address; \ ! 158: linep = lp + 1; \ ! 159: } \ ! 160: } ! 161: ! 162: /* ! 163: * Read in the namelist from the obj file. ! 164: * ! 165: * Reads and seeks are used instead of fread's and fseek's ! 166: * for efficiency sake; there's a lot of data being read here. ! 167: */ ! 168: ! 169: public readobj (file) ! 170: String file; ! 171: { ! 172: Fileid f; ! 173: struct exec hdr; ! 174: struct nlist nlist; ! 175: ! 176: f = open(file, 0); ! 177: if (f < 0) { ! 178: fatal("can't open %s", file); ! 179: } ! 180: read(f, &hdr, sizeof(hdr)); ! 181: if (N_BADMAG(hdr)) { ! 182: objsize = 0; ! 183: nlhdr.nsyms = 0; ! 184: nlhdr.nfiles = 0; ! 185: nlhdr.nlines = 0; ! 186: } else { ! 187: objsize = hdr.a_text; ! 188: nlhdr.nsyms = hdr.a_syms / sizeof(nlist); ! 189: nlhdr.nfiles = nlhdr.nsyms; ! 190: nlhdr.nlines = nlhdr.nsyms; ! 191: } ! 192: if (nlhdr.nsyms > 0) { ! 193: lseek(f, (long) N_STROFF(hdr), 0); ! 194: read(f, &(nlhdr.stringsize), sizeof(nlhdr.stringsize)); ! 195: nlhdr.stringsize -= 4; ! 196: stringtab = newarr(char, nlhdr.stringsize); ! 197: read(f, stringtab, nlhdr.stringsize); ! 198: allocmaps(nlhdr.nfiles, nlhdr.nlines); ! 199: lseek(f, (long) N_SYMOFF(hdr), 0); ! 200: readsyms(f); ! 201: ordfunctab(); ! 202: setnlines(); ! 203: setnfiles(); ! 204: } else { ! 205: initsyms(); ! 206: } ! 207: close(f); ! 208: } ! 209: ! 210: /* ! 211: * Found the beginning of the externals in the object file ! 212: * (signified by the "-lg" or find an external), close the ! 213: * block for the last procedure. ! 214: */ ! 215: ! 216: private foundglobals () ! 217: { ! 218: if (curblock->class != PROG) { ! 219: exitblock(); ! 220: if (curblock->class != PROG) { ! 221: exitblock(); ! 222: } ! 223: } ! 224: enterline(0, (linep-1)->addr + 1); ! 225: } ! 226: ! 227: /* ! 228: * Read in symbols from object file. ! 229: */ ! 230: ! 231: private readsyms (f) ! 232: Fileid f; ! 233: { ! 234: struct nlist *namelist; ! 235: register struct nlist *np, *ub; ! 236: register String name; ! 237: boolean afterlg, foundstab; ! 238: integer index; ! 239: char *lastchar; ! 240: ! 241: initsyms(); ! 242: namelist = newarr(struct nlist, nlhdr.nsyms); ! 243: read(f, namelist, nlhdr.nsyms * sizeof(struct nlist)); ! 244: afterlg = false; ! 245: foundstab = false; ! 246: ub = &namelist[nlhdr.nsyms]; ! 247: curnp = &namelist[0]; ! 248: np = curnp; ! 249: while (np < ub) { ! 250: index = np->n_un.n_strx; ! 251: if (index != 0) { ! 252: name = &stringtab[index - 4]; ! 253: /* ! 254: * If the program contains any .f files a trailing _ is stripped ! 255: * from the name on the assumption it was added by the compiler. ! 256: * This only affects names that follow the sdb N_SO entry with ! 257: * the .f name. ! 258: */ ! 259: if (strip_ and name[0] != '\0' ) { ! 260: lastchar = &name[strlen(name) - 1]; ! 261: if (*lastchar == '_') { ! 262: *lastchar = '\0'; ! 263: } ! 264: } ! 265: } else { ! 266: name = nil; ! 267: } ! 268: ! 269: /* ! 270: * Assumptions: ! 271: * not an N_STAB ==> name != nil ! 272: * name[0] == '-' ==> name == "-lg" ! 273: * name[0] != '_' ==> filename or invisible ! 274: * ! 275: * The "-lg" signals the beginning of global loader symbols. ! 276: * ! 277: */ ! 278: if ((np->n_type&N_STAB) != 0) { ! 279: foundstab = true; ! 280: enter_nl(name, np); ! 281: } else if (name[0] == '-') { ! 282: afterlg = true; ! 283: foundglobals(); ! 284: } else if (afterlg) { ! 285: check_global(name, np); ! 286: } else if ((np->n_type&N_EXT) == N_EXT) { ! 287: afterlg = true; ! 288: foundglobals(); ! 289: check_global(name, np); ! 290: } else if (name[0] == '_') { ! 291: check_local(&name[1], np); ! 292: } else if ((np->n_type&N_TEXT) == N_TEXT) { ! 293: check_filename(name); ! 294: } ! 295: ++curnp; ! 296: np = curnp; ! 297: } ! 298: if (not foundstab) { ! 299: warning("no source compiled with -g"); ! 300: } ! 301: dispose(namelist); ! 302: } ! 303: ! 304: /* ! 305: * Get a continuation entry from the name list. ! 306: * Return the beginning of the name. ! 307: */ ! 308: ! 309: public String getcont () ! 310: { ! 311: register integer index; ! 312: register String name; ! 313: ! 314: ++curnp; ! 315: index = curnp->n_un.n_strx; ! 316: if (index == 0) { ! 317: name = ""; ! 318: } else { ! 319: name = &stringtab[index - 4]; ! 320: } ! 321: return name; ! 322: } ! 323: ! 324: /* ! 325: * Initialize symbol information. ! 326: */ ! 327: ! 328: private initsyms () ! 329: { ! 330: curblock = nil; ! 331: curlevel = 0; ! 332: nesting = 0; ! 333: program = insert(identname("", true)); ! 334: program->class = PROG; ! 335: program->language = primlang; ! 336: program->symvalue.funcv.beginaddr = CODESTART; ! 337: program->symvalue.funcv.inline = false; ! 338: newfunc(program, codeloc(program)); ! 339: findbeginning(program); ! 340: enterblock(program); ! 341: curmodule = program; ! 342: } ! 343: ! 344: /* ! 345: * Free all the object file information that's being stored. ! 346: */ ! 347: ! 348: public objfree () ! 349: { ! 350: symbol_free(); ! 351: /* keywords_free(); */ ! 352: /* names_free(); */ ! 353: /* dispose(stringtab); */ ! 354: clrfunctab(); ! 355: } ! 356: ! 357: /* ! 358: * Enter a namelist entry. ! 359: */ ! 360: ! 361: private enter_nl (name, np) ! 362: String name; ! 363: register struct nlist *np; ! 364: { ! 365: register Symbol s; ! 366: register Name n; ! 367: ! 368: s = nil; ! 369: switch (np->n_type) { ! 370: /* ! 371: * Build a symbol for the FORTRAN common area. All GSYMS that follow ! 372: * will be chained in a list with the head kept in common.offset, and ! 373: * the tail in common.chain. ! 374: */ ! 375: case N_BCOMM: ! 376: if (curcomm) { ! 377: curcomm->symvalue.common.chain = commchain; ! 378: } ! 379: n = identname(name, true); ! 380: curcomm = lookup(n); ! 381: if (curcomm == nil) { ! 382: curcomm = insert(n); ! 383: curcomm->class = COMMON; ! 384: curcomm->block = curblock; ! 385: curcomm->level = program->level; ! 386: curcomm->symvalue.common.chain = nil; ! 387: } ! 388: commchain = curcomm->symvalue.common.chain; ! 389: break; ! 390: ! 391: case N_ECOMM: ! 392: if (curcomm) { ! 393: curcomm->symvalue.common.chain = commchain; ! 394: curcomm = nil; ! 395: } ! 396: break; ! 397: ! 398: case N_LBRAC: ! 399: ++nesting; ! 400: addrstk[nesting] = (linep - 1)->addr; ! 401: break; ! 402: ! 403: case N_RBRAC: ! 404: --nesting; ! 405: if (addrstk[nesting] == NOADDR) { ! 406: exitblock(); ! 407: newfunc(curblock, (linep - 1)->addr); ! 408: addrstk[nesting] = (linep - 1)->addr; ! 409: } ! 410: break; ! 411: ! 412: case N_SLINE: ! 413: enterline((Lineno) np->n_desc, (Address) np->n_value); ! 414: break; ! 415: ! 416: /* ! 417: * Source files. ! 418: */ ! 419: case N_SO: ! 420: n = identname(name, true); ! 421: enterSourceModule(n, (Address) np->n_value); ! 422: break; ! 423: ! 424: /* ! 425: * Textually included files. ! 426: */ ! 427: case N_SOL: ! 428: enterfile(name, (Address) np->n_value); ! 429: break; ! 430: ! 431: /* ! 432: * These symbols are assumed to have non-nil names. ! 433: */ ! 434: case N_GSYM: ! 435: case N_FUN: ! 436: case N_STSYM: ! 437: case N_LCSYM: ! 438: case N_RSYM: ! 439: case N_PSYM: ! 440: case N_LSYM: ! 441: case N_SSYM: ! 442: case N_LENG: ! 443: if (index(name, ':') == nil) { ! 444: if (not warned) { ! 445: warned = true; ! 446: printf("warning: old style symbol information "); ! 447: printf("found in \"%s\"\n", curfilename()); ! 448: } ! 449: } else { ! 450: entersym(name, np); ! 451: } ! 452: break; ! 453: ! 454: case N_PC: ! 455: case N_MOD2: ! 456: break; ! 457: ! 458: default: ! 459: printf("warning: stab entry unrecognized: "); ! 460: if (name != nil) { ! 461: printf("name %s,", name); ! 462: } ! 463: printf("ntype %2x, desc %x, value %x'\n", ! 464: np->n_type, np->n_desc, np->n_value); ! 465: break; ! 466: } ! 467: } ! 468: ! 469: /* ! 470: * Try to find the symbol that is referred to by the given name. Since it's ! 471: * an external, we need to follow a level or two of indirection. ! 472: */ ! 473: ! 474: private Symbol findsym (n, var_isextref) ! 475: Name n; ! 476: boolean *var_isextref; ! 477: { ! 478: register Symbol r, s; ! 479: ! 480: *var_isextref = false; ! 481: find(s, n) where ! 482: ( ! 483: s->level == program->level and ( ! 484: s->class == EXTREF or s->class == VAR or ! 485: s->class == PROC or s->class == FUNC ! 486: ) ! 487: ) or ( ! 488: s->block == program and s->class == MODULE ! 489: ) ! 490: endfind(s); ! 491: if (s == nil) { ! 492: r = nil; ! 493: } else if (s->class == EXTREF) { ! 494: *var_isextref = true; ! 495: r = s->symvalue.extref; ! 496: delete(s); ! 497: ! 498: /* ! 499: * Now check for another level of indirection that could come from ! 500: * a forward reference in procedure nesting information. In this case ! 501: * the symbol has already been deleted. ! 502: */ ! 503: if (r != nil and r->class == EXTREF) { ! 504: r = r->symvalue.extref; ! 505: } ! 506: /* ! 507: } else if (s->class == MODULE) { ! 508: s->class = FUNC; ! 509: s->level = program->level; ! 510: r = s; ! 511: */ ! 512: } else { ! 513: r = s; ! 514: } ! 515: return r; ! 516: } ! 517: ! 518: /* ! 519: * Create a symbol for a text symbol with no source information. ! 520: * We treat it as an assembly language function. ! 521: */ ! 522: ! 523: private Symbol deffunc (n) ! 524: Name n; ! 525: { ! 526: Symbol f; ! 527: ! 528: f = insert(n); ! 529: f->language = findlanguage(".s"); ! 530: f->class = FUNC; ! 531: f->type = t_int; ! 532: f->block = curblock; ! 533: f->level = program->level; ! 534: f->symvalue.funcv.src = false; ! 535: f->symvalue.funcv.inline = false; ! 536: if (f->chain != nil) { ! 537: panic("chain not nil in deffunc"); ! 538: } ! 539: return f; ! 540: } ! 541: ! 542: /* ! 543: * Create a symbol for a data or bss symbol with no source information. ! 544: * We treat it as an assembly language variable. ! 545: */ ! 546: ! 547: private Symbol defvar (n) ! 548: Name n; ! 549: { ! 550: Symbol v; ! 551: ! 552: v = insert(n); ! 553: v->language = findlanguage(".s"); ! 554: v->storage = EXT; ! 555: v->class = VAR; ! 556: v->type = t_int; ! 557: v->level = program->level; ! 558: v->block = curblock; ! 559: return v; ! 560: } ! 561: ! 562: /* ! 563: * Update a symbol entry with a text address. ! 564: */ ! 565: ! 566: private updateTextSym (s, name, addr) ! 567: Symbol s; ! 568: char *name; ! 569: Address addr; ! 570: { ! 571: if (s->class == VAR) { ! 572: s->symvalue.offset = addr; ! 573: } else { ! 574: s->symvalue.funcv.beginaddr = addr; ! 575: if (name[0] == '_') { ! 576: newfunc(s, codeloc(s)); ! 577: findbeginning(s); ! 578: } ! 579: } ! 580: } ! 581: ! 582: /* ! 583: * Avoid seeing Pascal labels as text symbols. ! 584: */ ! 585: ! 586: private boolean PascalLabel (n) ! 587: Name n; ! 588: { ! 589: boolean b; ! 590: register char *p; ! 591: ! 592: b = false; ! 593: if (curlang == findlanguage(".p")) { ! 594: p = ident(n); ! 595: while (*p != '\0') { ! 596: if (*p == '_' and *(p+1) == '$') { ! 597: b = true; ! 598: break; ! 599: } ! 600: ++p; ! 601: } ! 602: } ! 603: return b; ! 604: } ! 605: ! 606: /* ! 607: * Check to see if a global _name is already in the symbol table, ! 608: * if not then insert it. ! 609: */ ! 610: ! 611: private check_global (name, np) ! 612: String name; ! 613: register struct nlist *np; ! 614: { ! 615: register Name n; ! 616: register Symbol t, u; ! 617: char buf[4096]; ! 618: boolean isextref; ! 619: integer count; ! 620: ! 621: if (not streq(name, "_end")) { ! 622: if (name[0] == '_') { ! 623: n = identname(&name[1], true); ! 624: } else { ! 625: n = identname(name, true); ! 626: if (lookup(n) != nil) { ! 627: sprintf(buf, "$%s", name); ! 628: n = identname(buf, false); ! 629: } ! 630: } ! 631: if ((np->n_type&N_TYPE) == N_TEXT) { ! 632: count = 0; ! 633: t = findsym(n, &isextref); ! 634: while (isextref) { ! 635: ++count; ! 636: updateTextSym(t, name, np->n_value); ! 637: t = findsym(n, &isextref); ! 638: } ! 639: if (count == 0) { ! 640: if (t == nil) { ! 641: if (not PascalLabel(n)) { ! 642: t = deffunc(n); ! 643: updateTextSym(t, name, np->n_value); ! 644: if (tracesyms) { ! 645: printdecl(t); ! 646: } ! 647: } ! 648: } else { ! 649: if (t->class == MODULE) { ! 650: u = t; ! 651: t = deffunc(n); ! 652: t->block = u; ! 653: if (tracesyms) { ! 654: printdecl(t); ! 655: } ! 656: } ! 657: updateTextSym(t, name, np->n_value); ! 658: } ! 659: } ! 660: } else if ((np->n_type&N_TYPE) == N_BSS or (np->n_type&N_TYPE) == N_DATA) { ! 661: find(t, n) where ! 662: t->class == COMMON ! 663: endfind(t); ! 664: if (t != nil) { ! 665: u = (Symbol) t->symvalue.common.offset; ! 666: while (u != nil) { ! 667: u->symvalue.offset = u->symvalue.common.offset+np->n_value; ! 668: u = u->symvalue.common.chain; ! 669: } ! 670: } else { ! 671: check_var(np, n); ! 672: } ! 673: } else { ! 674: check_var(np, n); ! 675: } ! 676: } ! 677: } ! 678: ! 679: /* ! 680: * Check to see if a namelist entry refers to a variable. ! 681: * If not, create a variable for the entry. In any case, ! 682: * set the offset of the variable according to the value field ! 683: * in the entry. ! 684: * ! 685: * If the external name has been referred to by several other symbols, ! 686: * we must update each of them. ! 687: */ ! 688: ! 689: private check_var (np, n) ! 690: struct nlist *np; ! 691: register Name n; ! 692: { ! 693: register Symbol t, u, next; ! 694: Symbol conflict; ! 695: ! 696: t = lookup(n); ! 697: if (t == nil) { ! 698: t = defvar(n); ! 699: t->symvalue.offset = np->n_value; ! 700: if (tracesyms) { ! 701: printdecl(t); ! 702: } ! 703: } else { ! 704: conflict = nil; ! 705: do { ! 706: next = t->next_sym; ! 707: if (t->name == n) { ! 708: if (t->class == MODULE and t->block == program) { ! 709: conflict = t; ! 710: } else if (t->class == EXTREF and t->level == program->level) { ! 711: u = t->symvalue.extref; ! 712: while (u != nil and u->class == EXTREF) { ! 713: u = u->symvalue.extref; ! 714: } ! 715: u->symvalue.offset = np->n_value; ! 716: delete(t); ! 717: } else if (t->level == program->level and ! 718: (t->class == VAR or t->class == PROC or t->class == FUNC) ! 719: ) { ! 720: conflict = nil; ! 721: t->symvalue.offset = np->n_value; ! 722: } ! 723: } ! 724: t = next; ! 725: } while (t != nil); ! 726: if (conflict != nil) { ! 727: u = defvar(n); ! 728: u->block = conflict; ! 729: u->symvalue.offset = np->n_value; ! 730: } ! 731: } ! 732: } ! 733: ! 734: /* ! 735: * Check to see if a local _name is known in the current scope. ! 736: * If not then enter it. ! 737: */ ! 738: ! 739: private check_local (name, np) ! 740: String name; ! 741: register struct nlist *np; ! 742: { ! 743: register Name n; ! 744: register Symbol t, cur; ! 745: ! 746: n = identname(name, true); ! 747: cur = ((np->n_type&N_TYPE) == N_TEXT) ? curmodule : curblock; ! 748: find(t, n) where t->block == cur endfind(t); ! 749: if (t == nil) { ! 750: t = insert(n); ! 751: t->language = findlanguage(".s"); ! 752: t->type = t_int; ! 753: t->block = cur; ! 754: t->storage = EXT; ! 755: t->level = cur->level; ! 756: if ((np->n_type&N_TYPE) == N_TEXT) { ! 757: t->class = FUNC; ! 758: t->symvalue.funcv.src = false; ! 759: t->symvalue.funcv.inline = false; ! 760: t->symvalue.funcv.beginaddr = np->n_value; ! 761: newfunc(t, codeloc(t)); ! 762: findbeginning(t); ! 763: } else { ! 764: t->class = VAR; ! 765: t->symvalue.offset = np->n_value; ! 766: } ! 767: } ! 768: } ! 769: ! 770: /* ! 771: * Check to see if a symbol corresponds to a object file name. ! 772: * For some reason these are listed as in the text segment. ! 773: */ ! 774: ! 775: private check_filename (name) ! 776: String name; ! 777: { ! 778: register String mname; ! 779: register integer i; ! 780: Name n; ! 781: Symbol s; ! 782: ! 783: mname = strdup(name); ! 784: i = strlen(mname) - 2; ! 785: if (i >= 0 and mname[i] == '.' and mname[i+1] == 'o') { ! 786: mname[i] = '\0'; ! 787: --i; ! 788: while (mname[i] != '/' and i >= 0) { ! 789: --i; ! 790: } ! 791: n = identname(&mname[i+1], true); ! 792: find(s, n) where s->block == program and s->class == MODULE endfind(s); ! 793: if (s == nil) { ! 794: s = insert(n); ! 795: s->language = findlanguage(".s"); ! 796: s->class = MODULE; ! 797: s->symvalue.funcv.beginaddr = 0; ! 798: findbeginning(s); ! 799: } ! 800: if (curblock->class != PROG) { ! 801: exitblock(); ! 802: if (curblock->class != PROG) { ! 803: exitblock(); ! 804: } ! 805: } ! 806: enterblock(s); ! 807: curmodule = s; ! 808: } ! 809: } ! 810: ! 811: /* ! 812: * Check to see if a symbol is about to be defined within an unnamed block. ! 813: * If this happens, we create a procedure for the unnamed block, make it ! 814: * "inline" so that tracebacks don't associate an activation record with it, ! 815: * and enter it into the function table so that it will be detected ! 816: * by "whatblock". ! 817: */ ! 818: ! 819: public chkUnnamedBlock () ! 820: { ! 821: register Symbol s; ! 822: static int bnum = 0; ! 823: char buf[100]; ! 824: Address startaddr; ! 825: ! 826: if (nesting > 0 and addrstk[nesting] != NOADDR) { ! 827: startaddr = (linep - 1)->addr; ! 828: ++bnum; ! 829: sprintf(buf, "$b%d", bnum); ! 830: s = insert(identname(buf, false)); ! 831: s->language = curlang; ! 832: s->class = PROC; ! 833: s->symvalue.funcv.src = false; ! 834: s->symvalue.funcv.inline = true; ! 835: s->symvalue.funcv.beginaddr = startaddr; ! 836: enterblock(s); ! 837: newfunc(s, startaddr); ! 838: addrstk[nesting] = NOADDR; ! 839: } ! 840: } ! 841: ! 842: /* ! 843: * Compilation unit. C associates scope with filenames ! 844: * so we treat them as "modules". The filename without ! 845: * the suffix is used for the module name. ! 846: * ! 847: * Because there is no explicit "end-of-block" mark in ! 848: * the object file, we must exit blocks for the current ! 849: * procedure and module. ! 850: */ ! 851: ! 852: private enterSourceModule (n, addr) ! 853: Name n; ! 854: Address addr; ! 855: { ! 856: register Symbol s; ! 857: Name nn; ! 858: String mname, suffix; ! 859: ! 860: mname = strdup(ident(n)); ! 861: if (rindex(mname, '/') != nil) { ! 862: mname = rindex(mname, '/') + 1; ! 863: } ! 864: suffix = rindex(mname, '.'); ! 865: if (suffix > mname && *(suffix-1) == '.') { ! 866: /* special hack for C++ */ ! 867: --suffix; ! 868: } ! 869: curlang = findlanguage(suffix); ! 870: if (curlang == findlanguage(".f")) { ! 871: strip_ = true; ! 872: } ! 873: if (suffix != nil) { ! 874: *suffix = '\0'; ! 875: } ! 876: if (not (*language_op(curlang, L_HASMODULES))()) { ! 877: if (curblock->class != PROG) { ! 878: exitblock(); ! 879: if (curblock->class != PROG) { ! 880: exitblock(); ! 881: } ! 882: } ! 883: nn = identname(mname, true); ! 884: if (curmodule == nil or curmodule->name != nn) { ! 885: s = insert(nn); ! 886: s->class = MODULE; ! 887: s->symvalue.funcv.beginaddr = 0; ! 888: findbeginning(s); ! 889: } else { ! 890: s = curmodule; ! 891: } ! 892: s->language = curlang; ! 893: enterblock(s); ! 894: curmodule = s; ! 895: } ! 896: if (program->language == nil) { ! 897: program->language = curlang; ! 898: } ! 899: warned = false; ! 900: enterfile(ident(n), addr); ! 901: initTypeTable(); ! 902: } ! 903: ! 904: /* ! 905: * Allocate file and line tables and initialize indices. ! 906: */ ! 907: ! 908: private allocmaps (nf, nl) ! 909: integer nf, nl; ! 910: { ! 911: if (filetab != nil) { ! 912: dispose(filetab); ! 913: } ! 914: if (linetab != nil) { ! 915: dispose(linetab); ! 916: } ! 917: filetab = newarr(Filetab, nf); ! 918: linetab = newarr(Linetab, nl); ! 919: filep = filetab; ! 920: linep = linetab; ! 921: } ! 922: ! 923: /* ! 924: * Add a file to the file table. ! 925: * ! 926: * If the new address is the same as the previous file address ! 927: * this routine used to not enter the file, but this caused some ! 928: * problems so it has been removed. It's not clear that this in ! 929: * turn may not also cause a problem. ! 930: */ ! 931: ! 932: private enterfile (filename, addr) ! 933: String filename; ! 934: Address addr; ! 935: { ! 936: filep->addr = addr; ! 937: filep->filename = filename; ! 938: filep->lineindex = linep - linetab; ! 939: ++filep; ! 940: } ! 941: ! 942: /* ! 943: * Since we only estimated the number of lines (and it was a poor ! 944: * estimation) and since we need to know the exact number of lines ! 945: * to do a binary search, we set it when we're done. ! 946: */ ! 947: ! 948: private setnlines () ! 949: { ! 950: nlhdr.nlines = linep - linetab; ! 951: } ! 952: ! 953: /* ! 954: * Similarly for nfiles ... ! 955: */ ! 956: ! 957: private setnfiles () ! 958: { ! 959: nlhdr.nfiles = filep - filetab; ! 960: setsource(filetab[0].filename); ! 961: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.