19671Slinton /* Copyright (c) 1982 Regents of the University of California */ 29671Slinton 3*18224Slinton static char sccsid[] = "@(#)mappings.c 1.6 (Berkeley) 03/01/85"; 49671Slinton 5*18224Slinton static char rcsid[] = "$Header: mappings.c,v 1.4 84/12/26 10:40:25 linton Exp $"; 6*18224Slinton 79671Slinton /* 89671Slinton * Source-to-object and vice versa mappings. 99671Slinton */ 109671Slinton 119671Slinton #include "defs.h" 129671Slinton #include "mappings.h" 139671Slinton #include "symbols.h" 149671Slinton #include "source.h" 159671Slinton #include "object.h" 169671Slinton #include "machine.h" 179671Slinton 189671Slinton #ifndef public 199671Slinton #include "machine.h" 209671Slinton #include "source.h" 219671Slinton #include "symbols.h" 229671Slinton 239671Slinton typedef struct { 249671Slinton Address addr; 259671Slinton String filename; 269671Slinton Lineno lineindex; /* index to first linetab entry */ 279671Slinton } Filetab; 289671Slinton 299671Slinton typedef struct { 309671Slinton Lineno line; 319671Slinton Address addr; 329671Slinton } Linetab; 339671Slinton 349671Slinton Filetab *filetab; 359671Slinton Linetab *linetab; 369671Slinton 379671Slinton #define NOADDR ((Address) -1) /* no address for line or procedure */ 389671Slinton 399671Slinton #endif 409671Slinton 419671Slinton /* 429671Slinton * Get the source file name associated with a given address. 439671Slinton */ 449671Slinton 459671Slinton public String srcfilename(addr) 469671Slinton Address addr; 479671Slinton { 489671Slinton register Address i, j, k; 499671Slinton Address a; 509671Slinton Filetab *ftp; 519671Slinton String s; 529671Slinton 539671Slinton s = nil; 549671Slinton if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) { 559671Slinton i = 0; 569671Slinton j = nlhdr.nfiles - 1; 579671Slinton while (i < j) { 589671Slinton k = (i + j) / 2; 599671Slinton ftp = &filetab[k]; 609671Slinton a = ftp->addr; 619671Slinton if (a == addr) { 629671Slinton s = ftp->filename; 639671Slinton break; 649671Slinton } else if (addr > a) { 659671Slinton i = k + 1; 669671Slinton } else { 679671Slinton j = k - 1; 689671Slinton } 699671Slinton } 709671Slinton if (s == nil) { 719671Slinton if (addr >= filetab[i].addr) { 729671Slinton s = filetab[i].filename; 739671Slinton } else { 749671Slinton s = filetab[i-1].filename; 759671Slinton } 769671Slinton } 779671Slinton } 789671Slinton return s; 799671Slinton } 809671Slinton 819671Slinton /* 829671Slinton * Find the line associated with the given address. 839671Slinton * If the second parameter is true, then the address must match 849671Slinton * a source line exactly. Otherwise the nearest source line 85*18224Slinton * below the given address is returned. 86*18224Slinton * 87*18224Slinton * Return the index of the line table entry or -1 if none suitable. 889671Slinton */ 899671Slinton 90*18224Slinton private integer findline (addr, exact) 919671Slinton Address addr; 929671Slinton Boolean exact; 939671Slinton { 949671Slinton register Address i, j, k; 959671Slinton register Lineno r; 969671Slinton register Address a; 979671Slinton 989671Slinton if (nlhdr.nlines == 0 or addr < linetab[0].addr) { 99*18224Slinton r = -1; 1009671Slinton } else { 1019671Slinton i = 0; 1029671Slinton j = nlhdr.nlines - 1; 1039671Slinton if (addr == linetab[i].addr) { 104*18224Slinton r = i; 1059671Slinton } else if (addr == linetab[j].addr) { 106*18224Slinton r = j; 1079671Slinton } else if (addr > linetab[j].addr) { 108*18224Slinton r = exact ? -1 : j; 1099671Slinton } else { 1109671Slinton do { 1119671Slinton k = (i + j) div 2; 1129671Slinton a = linetab[k].addr; 1139671Slinton if (a == addr) break; 1149671Slinton if (addr > a) { 1159671Slinton i = k + 1; 1169671Slinton } else { 1179671Slinton j = k - 1; 1189671Slinton } 1199671Slinton } while (i <= j); 1209671Slinton if (a == addr) { 121*18224Slinton r = k; 1229671Slinton } else if (exact) { 123*18224Slinton r = -1; 1249671Slinton } else if (addr > linetab[i].addr) { 125*18224Slinton r = i; 1269671Slinton } else { 127*18224Slinton r = i - 1; 1289671Slinton } 1299671Slinton } 1309671Slinton } 1319671Slinton return r; 1329671Slinton } 1339671Slinton 1349671Slinton /* 135*18224Slinton * Lookup the source line number nearest (from below) to an address. 136*18224Slinton * 137*18224Slinton * It is possible (unfortunately) that the compiler will generate 138*18224Slinton * code before line number for a procedure. Therefore we check 139*18224Slinton * to see that the found line is in the same procedure as the given address. 140*18224Slinton * If it isn't, then we walk forward until the first suitable line is found. 1419671Slinton */ 1429671Slinton 1439671Slinton public Lineno srcline(addr) 1449671Slinton Address addr; 1459671Slinton { 146*18224Slinton integer i; 147*18224Slinton Lineno r; 148*18224Slinton Symbol f1, f2; 149*18224Slinton 150*18224Slinton i = findline(addr, false); 151*18224Slinton if (i == -1) { 152*18224Slinton r = 0; 153*18224Slinton } else { 154*18224Slinton r = linetab[i].line; 155*18224Slinton if (linetab[i].addr != addr) { 156*18224Slinton f1 = whatblock(addr); 157*18224Slinton if (nosource(f1)) { 158*18224Slinton r = 0; 159*18224Slinton } else { 160*18224Slinton f2 = whatblock(linetab[i].addr + 1); 161*18224Slinton if (f1 != f2) { 162*18224Slinton do { 163*18224Slinton ++i; 164*18224Slinton } while (linetab[i].addr < addr and i < nlhdr.nlines); 165*18224Slinton r = linetab[i].line; 166*18224Slinton } 167*18224Slinton } 168*18224Slinton } 169*18224Slinton } 170*18224Slinton return r; 1719671Slinton } 1729671Slinton 1739671Slinton /* 1749671Slinton * Look for a line exactly corresponding to the given address. 1759671Slinton */ 1769671Slinton 1779671Slinton public Lineno linelookup(addr) 1789671Slinton Address addr; 1799671Slinton { 180*18224Slinton integer i; 181*18224Slinton Lineno r; 182*18224Slinton 183*18224Slinton i = findline(addr, true); 184*18224Slinton if (i == -1) { 185*18224Slinton r = 0; 186*18224Slinton } else { 187*18224Slinton r = linetab[i].line; 188*18224Slinton } 189*18224Slinton return r; 1909671Slinton } 1919671Slinton 1929671Slinton /* 1939671Slinton * Lookup the object address of a given line from the named file. 1949671Slinton * 1959671Slinton * Potentially all files in the file table need to be checked 1969671Slinton * until the line is found since a particular file name may appear 1979671Slinton * more than once in the file table (caused by includes). 1989671Slinton */ 1999671Slinton 2009671Slinton public Address objaddr(line, name) 2019671Slinton Lineno line; 2029671Slinton String name; 2039671Slinton { 2049671Slinton register Filetab *ftp; 2059671Slinton register Lineno i, j; 2069671Slinton Boolean foundfile; 2079671Slinton 2089671Slinton if (nlhdr.nlines == 0) { 2099671Slinton return NOADDR; 2109671Slinton } 2119671Slinton if (name == nil) { 2129671Slinton name = cursource; 2139671Slinton } 2149671Slinton foundfile = false; 2159671Slinton for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) { 2169671Slinton if (streq(ftp->filename, name)) { 2179671Slinton foundfile = true; 2189671Slinton i = ftp->lineindex; 2199671Slinton if (ftp == &filetab[nlhdr.nfiles-1]) { 2209671Slinton j = nlhdr.nlines; 2219671Slinton } else { 2229671Slinton j = (ftp + 1)->lineindex; 2239671Slinton } 2249671Slinton while (i < j) { 2259671Slinton if (linetab[i].line == line) { 2269671Slinton return linetab[i].addr; 2279671Slinton } 2289671Slinton i++; 2299671Slinton } 2309671Slinton } 2319671Slinton } 2329671Slinton if (not foundfile) { 233*18224Slinton error("source file \"%s\" not compiled with -g", name); 2349671Slinton } 2359671Slinton return NOADDR; 2369671Slinton } 2379671Slinton 2389671Slinton /* 2399671Slinton * Table for going from object addresses to the functions in which they belong. 2409671Slinton */ 2419671Slinton 242*18224Slinton #define NFUNCS 500 /* initial size of function table */ 2439671Slinton 24414439Slinton typedef struct { 24514439Slinton Symbol func; 24614439Slinton Address addr; 24714439Slinton } AddrOfFunc; 24814439Slinton 249*18224Slinton private AddrOfFunc *functab; 250*18224Slinton private int nfuncs = 0; 251*18224Slinton private int functablesize = 0; 2529671Slinton 2539671Slinton /* 2549671Slinton * Insert a new function into the table. 2559671Slinton */ 2569671Slinton 25714439Slinton public newfunc(f, addr) 2589671Slinton Symbol f; 25914439Slinton Address addr; 2609671Slinton { 26114439Slinton register AddrOfFunc *af; 262*18224Slinton register int i; 263*18224Slinton AddrOfFunc *newfunctab; 26414439Slinton 265*18224Slinton if (nfuncs >= functablesize) { 266*18224Slinton if (functablesize == 0) { 267*18224Slinton functab = newarr(AddrOfFunc, NFUNCS); 268*18224Slinton functablesize = NFUNCS; 269*18224Slinton } else { 270*18224Slinton functablesize *= 2; 271*18224Slinton newfunctab = newarr(AddrOfFunc, functablesize); 272*18224Slinton bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc)); 273*18224Slinton dispose(functab); 274*18224Slinton functab = newfunctab; 275*18224Slinton } 2769671Slinton } 27714439Slinton af = &functab[nfuncs]; 27814439Slinton af->func = f; 27914439Slinton af->addr = addr; 2809671Slinton ++nfuncs; 2819671Slinton } 2829671Slinton 2839671Slinton /* 2849671Slinton * Return the function that begins at the given address. 2859671Slinton */ 2869671Slinton 2879671Slinton public Symbol whatblock(addr) 2889671Slinton Address addr; 2899671Slinton { 2909671Slinton register int i, j, k; 2919671Slinton Address a; 2929671Slinton 2939671Slinton i = 0; 2949671Slinton j = nfuncs - 1; 29514439Slinton if (addr < functab[i].addr) { 2969671Slinton return program; 29714439Slinton } else if (addr == functab[i].addr) { 29814439Slinton return functab[i].func; 29914439Slinton } else if (addr >= functab[j].addr) { 30014439Slinton return functab[j].func; 3019671Slinton } 3029671Slinton while (i <= j) { 3039671Slinton k = (i + j) / 2; 30414439Slinton a = functab[k].addr; 3059671Slinton if (a == addr) { 30614439Slinton return functab[k].func; 3079671Slinton } else if (addr > a) { 3089671Slinton i = k+1; 3099671Slinton } else { 3109671Slinton j = k-1; 3119671Slinton } 3129671Slinton } 31314439Slinton if (addr > functab[i].addr) { 31414439Slinton return functab[i].func; 3159671Slinton } else { 31614439Slinton return functab[i-1].func; 3179671Slinton } 3189671Slinton /* NOTREACHED */ 3199671Slinton } 3209671Slinton 3219671Slinton /* 3229671Slinton * Order the functab. 3239671Slinton */ 3249671Slinton 3259671Slinton private int cmpfunc(f1, f2) 32614439Slinton AddrOfFunc *f1, *f2; 3279671Slinton { 3289671Slinton register Address a1, a2; 3299671Slinton 33014439Slinton a1 = (*f1).addr; 33114439Slinton a2 = (*f2).addr; 3329671Slinton return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) ); 3339671Slinton } 3349671Slinton 3359671Slinton public ordfunctab() 3369671Slinton { 33714439Slinton qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc); 3389671Slinton } 3399671Slinton 3409671Slinton /* 3419671Slinton * Clear out the functab, used when re-reading the object information. 3429671Slinton */ 3439671Slinton 3449671Slinton public clrfunctab() 3459671Slinton { 3469671Slinton nfuncs = 0; 3479671Slinton } 34812541Scsvaf 34912541Scsvaf public dumpfunctab() 35012541Scsvaf { 35114439Slinton int i; 35212541Scsvaf 35314439Slinton for (i = 0; i < nfuncs; i++) { 35414439Slinton psym(functab[i].func); 35514439Slinton } 35612541Scsvaf } 357