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