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