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