1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)mappings.c 1.4 8/10/83"; 4 5 static char rcsid[] = "$Header: mappings.c,v 1.3 84/03/27 10:21:54 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. In any case, if no suitable 86 * line exists, 0 is returned. 87 */ 88 89 private Lineno findline(addr, exact) 90 Address addr; 91 Boolean exact; 92 { 93 register Address i, j, k; 94 register Lineno r; 95 register Address a; 96 97 if (nlhdr.nlines == 0 or addr < linetab[0].addr) { 98 r = 0; 99 } else { 100 i = 0; 101 j = nlhdr.nlines - 1; 102 if (addr == linetab[i].addr) { 103 r = linetab[i].line; 104 } else if (addr == linetab[j].addr) { 105 r = linetab[j].line; 106 } else if (addr > linetab[j].addr) { 107 r = exact ? 0 : linetab[j].line; 108 } else { 109 do { 110 k = (i + j) div 2; 111 a = linetab[k].addr; 112 if (a == addr) break; 113 if (addr > a) { 114 i = k + 1; 115 } else { 116 j = k - 1; 117 } 118 } while (i <= j); 119 if (a == addr) { 120 r = linetab[k].line; 121 } else if (exact) { 122 r = 0; 123 } else if (addr > linetab[i].addr) { 124 r = linetab[i].line; 125 } else { 126 r = linetab[i-1].line; 127 } 128 } 129 } 130 return r; 131 } 132 133 /* 134 * Lookup the source line number nearest from below to an address. 135 */ 136 137 public Lineno srcline(addr) 138 Address addr; 139 { 140 return findline(addr, false); 141 } 142 143 /* 144 * Look for a line exactly corresponding to the given address. 145 */ 146 147 public Lineno linelookup(addr) 148 Address addr; 149 { 150 return findline(addr, true); 151 } 152 153 /* 154 * Lookup the object address of a given line from the named file. 155 * 156 * Potentially all files in the file table need to be checked 157 * until the line is found since a particular file name may appear 158 * more than once in the file table (caused by includes). 159 */ 160 161 public Address objaddr(line, name) 162 Lineno line; 163 String name; 164 { 165 register Filetab *ftp; 166 register Lineno i, j; 167 Boolean foundfile; 168 169 if (nlhdr.nlines == 0) { 170 return NOADDR; 171 } 172 if (name == nil) { 173 name = cursource; 174 } 175 foundfile = false; 176 for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) { 177 if (streq(ftp->filename, name)) { 178 foundfile = true; 179 i = ftp->lineindex; 180 if (ftp == &filetab[nlhdr.nfiles-1]) { 181 j = nlhdr.nlines; 182 } else { 183 j = (ftp + 1)->lineindex; 184 } 185 while (i < j) { 186 if (linetab[i].line == line) { 187 return linetab[i].addr; 188 } 189 i++; 190 } 191 } 192 } 193 if (not foundfile) { 194 error("unknown source file \"%s\"", name); 195 } 196 return NOADDR; 197 } 198 199 /* 200 * Table for going from object addresses to the functions in which they belong. 201 */ 202 203 #define MAXNFUNCS 1001 /* maximum number of functions allowed */ 204 205 typedef struct { 206 Symbol func; 207 Address addr; 208 } AddrOfFunc; 209 210 private AddrOfFunc functab[MAXNFUNCS]; 211 private int nfuncs; 212 213 /* 214 * Insert a new function into the table. 215 * The table is ordered by object address. 216 */ 217 218 public newfunc(f, addr) 219 Symbol f; 220 Address addr; 221 { 222 register AddrOfFunc *af; 223 224 if (nfuncs >= MAXNFUNCS) { 225 panic("too many procedures/functions"); 226 } 227 af = &functab[nfuncs]; 228 af->func = f; 229 af->addr = addr; 230 ++nfuncs; 231 } 232 233 /* 234 * Return the function that begins at the given address. 235 */ 236 237 public Symbol whatblock(addr) 238 Address addr; 239 { 240 register int i, j, k; 241 Address a; 242 243 i = 0; 244 j = nfuncs - 1; 245 if (addr < functab[i].addr) { 246 return program; 247 } else if (addr == functab[i].addr) { 248 return functab[i].func; 249 } else if (addr >= functab[j].addr) { 250 return functab[j].func; 251 } 252 while (i <= j) { 253 k = (i + j) / 2; 254 a = functab[k].addr; 255 if (a == addr) { 256 return functab[k].func; 257 } else if (addr > a) { 258 i = k+1; 259 } else { 260 j = k-1; 261 } 262 } 263 if (addr > functab[i].addr) { 264 return functab[i].func; 265 } else { 266 return functab[i-1].func; 267 } 268 /* NOTREACHED */ 269 } 270 271 /* 272 * Order the functab. 273 */ 274 275 private int cmpfunc(f1, f2) 276 AddrOfFunc *f1, *f2; 277 { 278 register Address a1, a2; 279 280 a1 = (*f1).addr; 281 a2 = (*f2).addr; 282 return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) ); 283 } 284 285 public ordfunctab() 286 { 287 qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc); 288 } 289 290 /* 291 * Clear out the functab, used when re-reading the object information. 292 */ 293 294 public clrfunctab() 295 { 296 nfuncs = 0; 297 } 298 299 public dumpfunctab() 300 { 301 int i; 302 303 for (i = 0; i < nfuncs; i++) { 304 psym(functab[i].func); 305 } 306 } 307