xref: /csrg-svn/old/dbx/mappings.c (revision 18224)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static	char sccsid[] = "@(#)mappings.c	1.6 (Berkeley) 03/01/85";
4 
5 static char rcsid[] = "$Header: mappings.c,v 1.4 84/12/26 10:40:25 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.
86  *
87  * Return the index of the line table entry or -1 if none suitable.
88  */
89 
90 private integer findline (addr, exact)
91 Address addr;
92 Boolean exact;
93 {
94     register Address i, j, k;
95     register Lineno r;
96     register Address a;
97 
98     if (nlhdr.nlines == 0 or addr < linetab[0].addr) {
99 	r = -1;
100     } else {
101 	i = 0;
102 	j = nlhdr.nlines - 1;
103 	if (addr == linetab[i].addr) {
104 	    r = i;
105 	} else if (addr == linetab[j].addr) {
106 	    r = j;
107 	} else if (addr > linetab[j].addr) {
108 	    r = exact ? -1 : j;
109 	} else {
110 	    do {
111 		k = (i + j) div 2;
112 		a = linetab[k].addr;
113 	    if (a == addr) break;
114 		if (addr > a) {
115 		    i = k + 1;
116 		} else {
117 		    j = k - 1;
118 		}
119 	    } while (i <= j);
120 	    if (a == addr) {
121 		r = k;
122 	    } else if (exact) {
123 		r = -1;
124 	    } else if (addr > linetab[i].addr) {
125 		r = i;
126 	    } else {
127 		r = i - 1;
128 	    }
129 	}
130     }
131     return r;
132 }
133 
134 /*
135  * Lookup the source line number nearest (from below) to an address.
136  *
137  * It is possible (unfortunately) that the compiler will generate
138  * code before line number for a procedure.  Therefore we check
139  * to see that the found line is in the same procedure as the given address.
140  * If it isn't, then we walk forward until the first suitable line is found.
141  */
142 
143 public Lineno srcline(addr)
144 Address addr;
145 {
146     integer i;
147     Lineno r;
148     Symbol f1, f2;
149 
150     i = findline(addr, false);
151     if (i == -1) {
152 	r = 0;
153     } else {
154 	r = linetab[i].line;
155 	if (linetab[i].addr != addr) {
156 	    f1 = whatblock(addr);
157 	    if (nosource(f1)) {
158 		r = 0;
159 	    } else {
160 		f2 = whatblock(linetab[i].addr + 1);
161 		if (f1 != f2) {
162 		    do {
163 			++i;
164 		    } while (linetab[i].addr < addr and i < nlhdr.nlines);
165 		    r = linetab[i].line;
166 		}
167 	    }
168 	}
169     }
170     return r;
171 }
172 
173 /*
174  * Look for a line exactly corresponding to the given address.
175  */
176 
177 public Lineno linelookup(addr)
178 Address addr;
179 {
180     integer i;
181     Lineno r;
182 
183     i = findline(addr, true);
184     if (i == -1) {
185 	r = 0;
186     } else {
187 	r = linetab[i].line;
188     }
189     return r;
190 }
191 
192 /*
193  * Lookup the object address of a given line from the named file.
194  *
195  * Potentially all files in the file table need to be checked
196  * until the line is found since a particular file name may appear
197  * more than once in the file table (caused by includes).
198  */
199 
200 public Address objaddr(line, name)
201 Lineno line;
202 String name;
203 {
204     register Filetab *ftp;
205     register Lineno i, j;
206     Boolean foundfile;
207 
208     if (nlhdr.nlines == 0) {
209 	return NOADDR;
210     }
211     if (name == nil) {
212 	name = cursource;
213     }
214     foundfile = false;
215     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
216 	if (streq(ftp->filename, name)) {
217 	    foundfile = true;
218 	    i = ftp->lineindex;
219 	    if (ftp == &filetab[nlhdr.nfiles-1]) {
220 		j = nlhdr.nlines;
221 	    } else {
222 		j = (ftp + 1)->lineindex;
223 	    }
224 	    while (i < j) {
225 		if (linetab[i].line == line) {
226 		    return linetab[i].addr;
227 		}
228 		i++;
229 	    }
230 	}
231     }
232     if (not foundfile) {
233 	error("source file \"%s\" not compiled with -g", name);
234     }
235     return NOADDR;
236 }
237 
238 /*
239  * Table for going from object addresses to the functions in which they belong.
240  */
241 
242 #define NFUNCS 500	/* initial size of function table */
243 
244 typedef struct {
245     Symbol func;
246     Address addr;
247 } AddrOfFunc;
248 
249 private AddrOfFunc *functab;
250 private int nfuncs = 0;
251 private int functablesize = 0;
252 
253 /*
254  * Insert a new function into the table.
255  */
256 
257 public newfunc(f, addr)
258 Symbol f;
259 Address addr;
260 {
261     register AddrOfFunc *af;
262     register int i;
263     AddrOfFunc *newfunctab;
264 
265     if (nfuncs >= functablesize) {
266 	if (functablesize == 0) {
267 	    functab = newarr(AddrOfFunc, NFUNCS);
268 	    functablesize = NFUNCS;
269 	} else {
270 	    functablesize *= 2;
271 	    newfunctab = newarr(AddrOfFunc, functablesize);
272 	    bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc));
273 	    dispose(functab);
274 	    functab = newfunctab;
275 	}
276     }
277     af = &functab[nfuncs];
278     af->func = f;
279     af->addr = addr;
280     ++nfuncs;
281 }
282 
283 /*
284  * Return the function that begins at the given address.
285  */
286 
287 public Symbol whatblock(addr)
288 Address addr;
289 {
290     register int i, j, k;
291     Address a;
292 
293     i = 0;
294     j = nfuncs - 1;
295     if (addr < functab[i].addr) {
296 	return program;
297     } else if (addr == functab[i].addr) {
298 	return functab[i].func;
299     } else if (addr >= functab[j].addr) {
300 	return functab[j].func;
301     }
302     while (i <= j) {
303 	k = (i + j) / 2;
304 	a = functab[k].addr;
305 	if (a == addr) {
306 	    return functab[k].func;
307 	} else if (addr > a) {
308 	    i = k+1;
309 	} else {
310 	    j = k-1;
311 	}
312     }
313     if (addr > functab[i].addr) {
314 	return functab[i].func;
315     } else {
316 	return functab[i-1].func;
317     }
318     /* NOTREACHED */
319 }
320 
321 /*
322  * Order the functab.
323  */
324 
325 private int cmpfunc(f1, f2)
326 AddrOfFunc *f1, *f2;
327 {
328     register Address a1, a2;
329 
330     a1 = (*f1).addr;
331     a2 = (*f2).addr;
332     return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) );
333 }
334 
335 public ordfunctab()
336 {
337     qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc);
338 }
339 
340 /*
341  * Clear out the functab, used when re-reading the object information.
342  */
343 
344 public clrfunctab()
345 {
346     nfuncs = 0;
347 }
348 
349 public dumpfunctab()
350 {
351     int i;
352 
353     for (i = 0; i < nfuncs; i++) {
354 	psym(functab[i].func);
355     }
356 }
357