|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: static char sccsid[] = "@(#)mappings.c 5.5 (Berkeley) 6/1/90"; ! 22: #endif /* not lint */ ! 23: ! 24: /* ! 25: * Source-to-object and vice versa mappings. ! 26: */ ! 27: ! 28: #include "defs.h" ! 29: #include "mappings.h" ! 30: #include "symbols.h" ! 31: #include "source.h" ! 32: #include "object.h" ! 33: #include "machine.h" ! 34: ! 35: #ifndef public ! 36: #include "machine.h" ! 37: #include "source.h" ! 38: #include "symbols.h" ! 39: ! 40: typedef struct { ! 41: Address addr; ! 42: String filename; ! 43: Lineno lineindex; /* index to first linetab entry */ ! 44: } Filetab; ! 45: ! 46: typedef struct { ! 47: Lineno line; ! 48: Address addr; ! 49: } Linetab; ! 50: ! 51: Filetab *filetab; ! 52: Linetab *linetab; ! 53: ! 54: #define NOADDR ((Address) -1) /* no address for line or procedure */ ! 55: ! 56: #endif ! 57: ! 58: /* ! 59: * Get the source file name associated with a given address. ! 60: */ ! 61: ! 62: public String srcfilename(addr) ! 63: Address addr; ! 64: { ! 65: register Address i, j, k; ! 66: Address a; ! 67: Filetab *ftp; ! 68: String s; ! 69: ! 70: s = nil; ! 71: if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) { ! 72: i = 0; ! 73: j = nlhdr.nfiles - 1; ! 74: while (i < j) { ! 75: k = (i + j) / 2; ! 76: ftp = &filetab[k]; ! 77: a = ftp->addr; ! 78: if (a == addr) { ! 79: s = ftp->filename; ! 80: break; ! 81: } else if (addr > a) { ! 82: i = k + 1; ! 83: } else { ! 84: j = k - 1; ! 85: } ! 86: } ! 87: if (s == nil) { ! 88: if (addr >= filetab[i].addr) { ! 89: s = filetab[i].filename; ! 90: } else { ! 91: s = filetab[i-1].filename; ! 92: } ! 93: } ! 94: } ! 95: return s; ! 96: } ! 97: ! 98: /* ! 99: * Find the line associated with the given address. ! 100: * If the second parameter is true, then the address must match ! 101: * a source line exactly. Otherwise the nearest source line ! 102: * below the given address is returned. ! 103: * ! 104: * Return the index of the line table entry or -1 if none suitable. ! 105: */ ! 106: ! 107: private integer findline (addr, exact) ! 108: Address addr; ! 109: Boolean exact; ! 110: { ! 111: register Address i, j, k; ! 112: register Lineno r; ! 113: register Address a; ! 114: ! 115: if (nlhdr.nlines == 0 or addr < linetab[0].addr) { ! 116: r = -1; ! 117: } else { ! 118: i = 0; ! 119: j = nlhdr.nlines - 1; ! 120: if (addr == linetab[i].addr) { ! 121: r = i; ! 122: } else if (addr == linetab[j].addr) { ! 123: r = j; ! 124: } else if (addr > linetab[j].addr) { ! 125: r = exact ? -1 : j; ! 126: } else { ! 127: do { ! 128: k = (i + j) div 2; ! 129: a = linetab[k].addr; ! 130: if (a == addr) break; ! 131: if (addr > a) { ! 132: i = k + 1; ! 133: } else { ! 134: j = k - 1; ! 135: } ! 136: } while (i <= j); ! 137: if (a == addr) { ! 138: r = k; ! 139: } else if (exact) { ! 140: r = -1; ! 141: } else if (addr > linetab[i].addr) { ! 142: r = i; ! 143: } else { ! 144: r = i - 1; ! 145: } ! 146: } ! 147: } ! 148: return r; ! 149: } ! 150: ! 151: /* ! 152: * Lookup the source line number nearest (from below) to an address. ! 153: * ! 154: * It is possible (unfortunately) that the compiler will generate ! 155: * code before line number for a procedure. Therefore we check ! 156: * to see that the found line is in the same procedure as the given address. ! 157: * If it isn't, then we walk forward until the first suitable line is found. ! 158: */ ! 159: ! 160: public Lineno srcline (addr) ! 161: Address addr; ! 162: { ! 163: Lineno i, r; ! 164: Symbol f1, f2; ! 165: Address a; ! 166: ! 167: i = findline(addr, false); ! 168: if (i == -1) { ! 169: f1 = whatblock(addr); ! 170: if (f1 == nil or nosource(f1)) { ! 171: r = 0; ! 172: } else { ! 173: a = codeloc(f1); ! 174: for (;;) { ! 175: r = linelookup(a); ! 176: if (r != 0 or a >= CODESTART + objsize) { ! 177: break; ! 178: } ! 179: ++a; ! 180: } ! 181: } ! 182: } else { ! 183: r = linetab[i].line; ! 184: if (linetab[i].addr != addr) { ! 185: f1 = whatblock(addr); ! 186: if (nosource(f1)) { ! 187: r = 0; ! 188: } else { ! 189: f2 = whatblock(linetab[i].addr + 1); ! 190: if (f1 != f2) { ! 191: do { ! 192: ++i; ! 193: } while (linetab[i].addr < addr and i < nlhdr.nlines); ! 194: r = linetab[i].line; ! 195: } ! 196: } ! 197: } ! 198: } ! 199: return r; ! 200: } ! 201: ! 202: /* ! 203: * Look for a line exactly corresponding to the given address. ! 204: */ ! 205: ! 206: public Lineno linelookup(addr) ! 207: Address addr; ! 208: { ! 209: integer i; ! 210: Lineno r; ! 211: ! 212: i = findline(addr, true); ! 213: if (i == -1) { ! 214: r = 0; ! 215: } else { ! 216: r = linetab[i].line; ! 217: } ! 218: return r; ! 219: } ! 220: ! 221: /* ! 222: * Lookup the object address of a given line from the named file. ! 223: * ! 224: * Potentially all files in the file table need to be checked ! 225: * until the line is found since a particular file name may appear ! 226: * more than once in the file table (caused by includes). ! 227: */ ! 228: ! 229: public Address objaddr(line, name) ! 230: Lineno line; ! 231: String name; ! 232: { ! 233: register Filetab *ftp; ! 234: register Lineno i, j; ! 235: Boolean foundfile; ! 236: ! 237: if (nlhdr.nlines == 0) { ! 238: return NOADDR; ! 239: } ! 240: if (name == nil) { ! 241: name = cursource; ! 242: } ! 243: foundfile = false; ! 244: for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) { ! 245: if (streq(ftp->filename, name)) { ! 246: foundfile = true; ! 247: i = ftp->lineindex; ! 248: if (ftp == &filetab[nlhdr.nfiles-1]) { ! 249: j = nlhdr.nlines; ! 250: } else { ! 251: j = (ftp + 1)->lineindex; ! 252: } ! 253: while (i < j) { ! 254: if (linetab[i].line == line) { ! 255: return linetab[i].addr; ! 256: } ! 257: i++; ! 258: } ! 259: } ! 260: } ! 261: if (not foundfile) { ! 262: error("source file \"%s\" not compiled with -g", name); ! 263: } ! 264: return NOADDR; ! 265: } ! 266: ! 267: /* ! 268: * Table for going from object addresses to the functions in which they belong. ! 269: */ ! 270: ! 271: #define NFUNCS 500 /* initial size of function table */ ! 272: ! 273: typedef struct { ! 274: Symbol func; ! 275: Address addr; ! 276: } AddrOfFunc; ! 277: ! 278: private AddrOfFunc *functab; ! 279: private int nfuncs = 0; ! 280: private int functablesize = 0; ! 281: ! 282: /* ! 283: * Insert a new function into the table. ! 284: */ ! 285: ! 286: public newfunc(f, addr) ! 287: Symbol f; ! 288: Address addr; ! 289: { ! 290: register AddrOfFunc *af; ! 291: register int i; ! 292: AddrOfFunc *newfunctab; ! 293: ! 294: if (nfuncs >= functablesize) { ! 295: if (functablesize == 0) { ! 296: functab = newarr(AddrOfFunc, NFUNCS); ! 297: functablesize = NFUNCS; ! 298: } else { ! 299: functablesize *= 2; ! 300: newfunctab = newarr(AddrOfFunc, functablesize); ! 301: bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc)); ! 302: dispose(functab); ! 303: functab = newfunctab; ! 304: } ! 305: } ! 306: af = &functab[nfuncs]; ! 307: af->func = f; ! 308: af->addr = addr; ! 309: ++nfuncs; ! 310: } ! 311: ! 312: /* ! 313: * Return the function that begins at the given address. ! 314: */ ! 315: ! 316: public Symbol whatblock(addr) ! 317: Address addr; ! 318: { ! 319: register int i, j, k; ! 320: Address a; ! 321: ! 322: i = 0; ! 323: j = nfuncs - 1; ! 324: if (addr < functab[i].addr) { ! 325: return program; ! 326: } else if (addr == functab[i].addr) { ! 327: return functab[i].func; ! 328: } else if (addr >= functab[j].addr) { ! 329: return functab[j].func; ! 330: } ! 331: while (i <= j) { ! 332: k = (i + j) / 2; ! 333: a = functab[k].addr; ! 334: if (a == addr) { ! 335: return functab[k].func; ! 336: } else if (addr > a) { ! 337: i = k+1; ! 338: } else { ! 339: j = k-1; ! 340: } ! 341: } ! 342: if (addr > functab[i].addr) { ! 343: return functab[i].func; ! 344: } else { ! 345: return functab[i-1].func; ! 346: } ! 347: /* NOTREACHED */ ! 348: } ! 349: ! 350: /* ! 351: * Order the functab. ! 352: */ ! 353: ! 354: private int cmpfunc(f1, f2) ! 355: AddrOfFunc *f1, *f2; ! 356: { ! 357: register Address a1, a2; ! 358: ! 359: a1 = (*f1).addr; ! 360: a2 = (*f2).addr; ! 361: return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) ); ! 362: } ! 363: ! 364: public ordfunctab() ! 365: { ! 366: qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc); ! 367: } ! 368: ! 369: /* ! 370: * Clear out the functab, used when re-reading the object information. ! 371: */ ! 372: ! 373: public clrfunctab() ! 374: { ! 375: nfuncs = 0; ! 376: } ! 377: ! 378: public dumpfunctab() ! 379: { ! 380: int i; ! 381: ! 382: for (i = 0; i < nfuncs; i++) { ! 383: psym(functab[i].func); ! 384: } ! 385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.