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