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