1*9671Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*9671Slinton 3*9671Slinton static char sccsid[] = "@(#)@(#)mappings.c 1.1 12/15/82"; 4*9671Slinton 5*9671Slinton /* 6*9671Slinton * Source-to-object and vice versa mappings. 7*9671Slinton */ 8*9671Slinton 9*9671Slinton #include "defs.h" 10*9671Slinton #include "mappings.h" 11*9671Slinton #include "symbols.h" 12*9671Slinton #include "source.h" 13*9671Slinton #include "object.h" 14*9671Slinton #include "machine.h" 15*9671Slinton 16*9671Slinton #ifndef public 17*9671Slinton #include "machine.h" 18*9671Slinton #include "source.h" 19*9671Slinton #include "symbols.h" 20*9671Slinton 21*9671Slinton typedef struct { 22*9671Slinton Address addr; 23*9671Slinton String filename; 24*9671Slinton Lineno lineindex; /* index to first linetab entry */ 25*9671Slinton } Filetab; 26*9671Slinton 27*9671Slinton typedef struct { 28*9671Slinton Lineno line; 29*9671Slinton Address addr; 30*9671Slinton } Linetab; 31*9671Slinton 32*9671Slinton Filetab *filetab; 33*9671Slinton Linetab *linetab; 34*9671Slinton 35*9671Slinton #define NOADDR ((Address) -1) /* no address for line or procedure */ 36*9671Slinton 37*9671Slinton #endif 38*9671Slinton 39*9671Slinton /* 40*9671Slinton * Get the source file name associated with a given address. 41*9671Slinton */ 42*9671Slinton 43*9671Slinton public String srcfilename(addr) 44*9671Slinton Address addr; 45*9671Slinton { 46*9671Slinton register Address i, j, k; 47*9671Slinton Address a; 48*9671Slinton Filetab *ftp; 49*9671Slinton String s; 50*9671Slinton 51*9671Slinton s = nil; 52*9671Slinton if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) { 53*9671Slinton i = 0; 54*9671Slinton j = nlhdr.nfiles - 1; 55*9671Slinton while (i < j) { 56*9671Slinton k = (i + j) / 2; 57*9671Slinton ftp = &filetab[k]; 58*9671Slinton a = ftp->addr; 59*9671Slinton if (a == addr) { 60*9671Slinton s = ftp->filename; 61*9671Slinton break; 62*9671Slinton } else if (addr > a) { 63*9671Slinton i = k + 1; 64*9671Slinton } else { 65*9671Slinton j = k - 1; 66*9671Slinton } 67*9671Slinton } 68*9671Slinton if (s == nil) { 69*9671Slinton if (addr >= filetab[i].addr) { 70*9671Slinton s = filetab[i].filename; 71*9671Slinton } else { 72*9671Slinton s = filetab[i-1].filename; 73*9671Slinton } 74*9671Slinton } 75*9671Slinton } 76*9671Slinton return s; 77*9671Slinton } 78*9671Slinton 79*9671Slinton /* 80*9671Slinton * Find the line associated with the given address. 81*9671Slinton * If the second parameter is true, then the address must match 82*9671Slinton * a source line exactly. Otherwise the nearest source line 83*9671Slinton * below the given address is returned. In any case, if no suitable 84*9671Slinton * line exists, 0 is returned. 85*9671Slinton */ 86*9671Slinton 87*9671Slinton private Lineno findline(addr, exact) 88*9671Slinton Address addr; 89*9671Slinton Boolean exact; 90*9671Slinton { 91*9671Slinton register Address i, j, k; 92*9671Slinton register Lineno r; 93*9671Slinton register Address a; 94*9671Slinton 95*9671Slinton if (nlhdr.nlines == 0 or addr < linetab[0].addr) { 96*9671Slinton r = 0; 97*9671Slinton } else { 98*9671Slinton i = 0; 99*9671Slinton j = nlhdr.nlines - 1; 100*9671Slinton if (addr == linetab[i].addr) { 101*9671Slinton r = linetab[i].line; 102*9671Slinton } else if (addr == linetab[j].addr) { 103*9671Slinton r = linetab[j].line; 104*9671Slinton } else if (addr > linetab[j].addr) { 105*9671Slinton r = exact ? 0 : linetab[j].line; 106*9671Slinton } else { 107*9671Slinton do { 108*9671Slinton k = (i + j) div 2; 109*9671Slinton a = linetab[k].addr; 110*9671Slinton if (a == addr) break; 111*9671Slinton if (addr > a) { 112*9671Slinton i = k + 1; 113*9671Slinton } else { 114*9671Slinton j = k - 1; 115*9671Slinton } 116*9671Slinton } while (i <= j); 117*9671Slinton if (a == addr) { 118*9671Slinton r = linetab[k].line; 119*9671Slinton } else if (exact) { 120*9671Slinton r = 0; 121*9671Slinton } else if (addr > linetab[i].addr) { 122*9671Slinton r = linetab[i].line; 123*9671Slinton } else { 124*9671Slinton r = linetab[i-1].line; 125*9671Slinton } 126*9671Slinton } 127*9671Slinton } 128*9671Slinton return r; 129*9671Slinton } 130*9671Slinton 131*9671Slinton /* 132*9671Slinton * Lookup the source line number nearest from below to an address. 133*9671Slinton */ 134*9671Slinton 135*9671Slinton public Lineno srcline(addr) 136*9671Slinton Address addr; 137*9671Slinton { 138*9671Slinton return findline(addr, false); 139*9671Slinton } 140*9671Slinton 141*9671Slinton /* 142*9671Slinton * Look for a line exactly corresponding to the given address. 143*9671Slinton */ 144*9671Slinton 145*9671Slinton public Lineno linelookup(addr) 146*9671Slinton Address addr; 147*9671Slinton { 148*9671Slinton return findline(addr, true); 149*9671Slinton } 150*9671Slinton 151*9671Slinton /* 152*9671Slinton * Lookup the object address of a given line from the named file. 153*9671Slinton * 154*9671Slinton * Potentially all files in the file table need to be checked 155*9671Slinton * until the line is found since a particular file name may appear 156*9671Slinton * more than once in the file table (caused by includes). 157*9671Slinton */ 158*9671Slinton 159*9671Slinton public Address objaddr(line, name) 160*9671Slinton Lineno line; 161*9671Slinton String name; 162*9671Slinton { 163*9671Slinton register Filetab *ftp; 164*9671Slinton register Lineno i, j; 165*9671Slinton Boolean foundfile; 166*9671Slinton 167*9671Slinton if (nlhdr.nlines == 0) { 168*9671Slinton return NOADDR; 169*9671Slinton } 170*9671Slinton if (name == nil) { 171*9671Slinton name = cursource; 172*9671Slinton } 173*9671Slinton foundfile = false; 174*9671Slinton for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) { 175*9671Slinton if (streq(ftp->filename, name)) { 176*9671Slinton foundfile = true; 177*9671Slinton i = ftp->lineindex; 178*9671Slinton if (ftp == &filetab[nlhdr.nfiles-1]) { 179*9671Slinton j = nlhdr.nlines; 180*9671Slinton } else { 181*9671Slinton j = (ftp + 1)->lineindex; 182*9671Slinton } 183*9671Slinton while (i < j) { 184*9671Slinton if (linetab[i].line == line) { 185*9671Slinton return linetab[i].addr; 186*9671Slinton } 187*9671Slinton i++; 188*9671Slinton } 189*9671Slinton } 190*9671Slinton } 191*9671Slinton if (not foundfile) { 192*9671Slinton error("unknown source file \"%s\"", name); 193*9671Slinton } 194*9671Slinton return NOADDR; 195*9671Slinton } 196*9671Slinton 197*9671Slinton /* 198*9671Slinton * Table for going from object addresses to the functions in which they belong. 199*9671Slinton */ 200*9671Slinton 201*9671Slinton #define MAXNFUNCS 1001 /* maximum number of functions allowed */ 202*9671Slinton 203*9671Slinton private Symbol functab[MAXNFUNCS]; 204*9671Slinton private int nfuncs; 205*9671Slinton 206*9671Slinton /* 207*9671Slinton * Insert a new function into the table. 208*9671Slinton * The table is ordered by object address. 209*9671Slinton */ 210*9671Slinton 211*9671Slinton public newfunc(f) 212*9671Slinton Symbol f; 213*9671Slinton { 214*9671Slinton if (nfuncs >= MAXNFUNCS) { 215*9671Slinton panic("too many procedures/functions"); 216*9671Slinton } 217*9671Slinton functab[nfuncs] = f; 218*9671Slinton ++nfuncs; 219*9671Slinton } 220*9671Slinton 221*9671Slinton /* 222*9671Slinton * Return the function that begins at the given address. 223*9671Slinton */ 224*9671Slinton 225*9671Slinton public Symbol whatblock(addr) 226*9671Slinton Address addr; 227*9671Slinton { 228*9671Slinton register int i, j, k; 229*9671Slinton Address a; 230*9671Slinton 231*9671Slinton i = 0; 232*9671Slinton j = nfuncs - 1; 233*9671Slinton if (addr < codeloc(functab[i])) { 234*9671Slinton return program; 235*9671Slinton } else if (addr == codeloc(functab[i])) { 236*9671Slinton return functab[i]; 237*9671Slinton } else if (addr >= codeloc(functab[j])) { 238*9671Slinton return functab[j]; 239*9671Slinton } 240*9671Slinton while (i <= j) { 241*9671Slinton k = (i + j) / 2; 242*9671Slinton a = codeloc(functab[k]); 243*9671Slinton if (a == addr) { 244*9671Slinton return functab[k]; 245*9671Slinton } else if (addr > a) { 246*9671Slinton i = k+1; 247*9671Slinton } else { 248*9671Slinton j = k-1; 249*9671Slinton } 250*9671Slinton } 251*9671Slinton if (addr > codeloc(functab[i])) { 252*9671Slinton return functab[i]; 253*9671Slinton } else { 254*9671Slinton return functab[i-1]; 255*9671Slinton } 256*9671Slinton /* NOTREACHED */ 257*9671Slinton } 258*9671Slinton 259*9671Slinton /* 260*9671Slinton * Order the functab. 261*9671Slinton */ 262*9671Slinton 263*9671Slinton private int cmpfunc(f1, f2) 264*9671Slinton Symbol *f1, *f2; 265*9671Slinton { 266*9671Slinton register Address a1, a2; 267*9671Slinton 268*9671Slinton a1 = codeloc(*f1); 269*9671Slinton a2 = codeloc(*f2); 270*9671Slinton return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) ); 271*9671Slinton } 272*9671Slinton 273*9671Slinton public ordfunctab() 274*9671Slinton { 275*9671Slinton qsort(functab, nfuncs, sizeof(Symbol), cmpfunc); 276*9671Slinton } 277*9671Slinton 278*9671Slinton /* 279*9671Slinton * Clear out the functab, used when re-reading the object information. 280*9671Slinton */ 281*9671Slinton 282*9671Slinton public clrfunctab() 283*9671Slinton { 284*9671Slinton nfuncs = 0; 285*9671Slinton } 286