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