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