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.1 (Berkeley) 05/31/85"; 9 #endif not lint 10 11 static char rcsid[] = "$Header: mappings.c,v 1.4 84/12/26 10:40:25 linton 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 integer i; 153 Lineno r; 154 Symbol f1, f2; 155 156 i = findline(addr, false); 157 if (i == -1) { 158 r = 0; 159 } else { 160 r = linetab[i].line; 161 if (linetab[i].addr != addr) { 162 f1 = whatblock(addr); 163 if (nosource(f1)) { 164 r = 0; 165 } else { 166 f2 = whatblock(linetab[i].addr + 1); 167 if (f1 != f2) { 168 do { 169 ++i; 170 } while (linetab[i].addr < addr and i < nlhdr.nlines); 171 r = linetab[i].line; 172 } 173 } 174 } 175 } 176 return r; 177 } 178 179 /* 180 * Look for a line exactly corresponding to the given address. 181 */ 182 183 public Lineno linelookup(addr) 184 Address addr; 185 { 186 integer i; 187 Lineno r; 188 189 i = findline(addr, true); 190 if (i == -1) { 191 r = 0; 192 } else { 193 r = linetab[i].line; 194 } 195 return r; 196 } 197 198 /* 199 * Lookup the object address of a given line from the named file. 200 * 201 * Potentially all files in the file table need to be checked 202 * until the line is found since a particular file name may appear 203 * more than once in the file table (caused by includes). 204 */ 205 206 public Address objaddr(line, name) 207 Lineno line; 208 String name; 209 { 210 register Filetab *ftp; 211 register Lineno i, j; 212 Boolean foundfile; 213 214 if (nlhdr.nlines == 0) { 215 return NOADDR; 216 } 217 if (name == nil) { 218 name = cursource; 219 } 220 foundfile = false; 221 for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) { 222 if (streq(ftp->filename, name)) { 223 foundfile = true; 224 i = ftp->lineindex; 225 if (ftp == &filetab[nlhdr.nfiles-1]) { 226 j = nlhdr.nlines; 227 } else { 228 j = (ftp + 1)->lineindex; 229 } 230 while (i < j) { 231 if (linetab[i].line == line) { 232 return linetab[i].addr; 233 } 234 i++; 235 } 236 } 237 } 238 if (not foundfile) { 239 error("source file \"%s\" not compiled with -g", name); 240 } 241 return NOADDR; 242 } 243 244 /* 245 * Table for going from object addresses to the functions in which they belong. 246 */ 247 248 #define NFUNCS 500 /* initial size of function table */ 249 250 typedef struct { 251 Symbol func; 252 Address addr; 253 } AddrOfFunc; 254 255 private AddrOfFunc *functab; 256 private int nfuncs = 0; 257 private int functablesize = 0; 258 259 /* 260 * Insert a new function into the table. 261 */ 262 263 public newfunc(f, addr) 264 Symbol f; 265 Address addr; 266 { 267 register AddrOfFunc *af; 268 register int i; 269 AddrOfFunc *newfunctab; 270 271 if (nfuncs >= functablesize) { 272 if (functablesize == 0) { 273 functab = newarr(AddrOfFunc, NFUNCS); 274 functablesize = NFUNCS; 275 } else { 276 functablesize *= 2; 277 newfunctab = newarr(AddrOfFunc, functablesize); 278 bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc)); 279 dispose(functab); 280 functab = newfunctab; 281 } 282 } 283 af = &functab[nfuncs]; 284 af->func = f; 285 af->addr = addr; 286 ++nfuncs; 287 } 288 289 /* 290 * Return the function that begins at the given address. 291 */ 292 293 public Symbol whatblock(addr) 294 Address addr; 295 { 296 register int i, j, k; 297 Address a; 298 299 i = 0; 300 j = nfuncs - 1; 301 if (addr < functab[i].addr) { 302 return program; 303 } else if (addr == functab[i].addr) { 304 return functab[i].func; 305 } else if (addr >= functab[j].addr) { 306 return functab[j].func; 307 } 308 while (i <= j) { 309 k = (i + j) / 2; 310 a = functab[k].addr; 311 if (a == addr) { 312 return functab[k].func; 313 } else if (addr > a) { 314 i = k+1; 315 } else { 316 j = k-1; 317 } 318 } 319 if (addr > functab[i].addr) { 320 return functab[i].func; 321 } else { 322 return functab[i-1].func; 323 } 324 /* NOTREACHED */ 325 } 326 327 /* 328 * Order the functab. 329 */ 330 331 private int cmpfunc(f1, f2) 332 AddrOfFunc *f1, *f2; 333 { 334 register Address a1, a2; 335 336 a1 = (*f1).addr; 337 a2 = (*f2).addr; 338 return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) ); 339 } 340 341 public ordfunctab() 342 { 343 qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc); 344 } 345 346 /* 347 * Clear out the functab, used when re-reading the object information. 348 */ 349 350 public clrfunctab() 351 { 352 nfuncs = 0; 353 } 354 355 public dumpfunctab() 356 { 357 int i; 358 359 for (i = 0; i < nfuncs; i++) { 360 psym(functab[i].func); 361 } 362 } 363