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