xref: /original-bsd/old/dbx/mappings.c (revision c0e889e7)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)mappings.c 1.2 12/15/82";
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 private Symbol functab[MAXNFUNCS];
204 private int nfuncs;
205 
206 /*
207  * Insert a new function into the table.
208  * The table is ordered by object address.
209  */
210 
211 public newfunc(f)
212 Symbol f;
213 {
214     if (nfuncs >= MAXNFUNCS) {
215 	panic("too many procedures/functions");
216     }
217     functab[nfuncs] = f;
218     ++nfuncs;
219 }
220 
221 /*
222  * Return the function that begins at the given address.
223  */
224 
225 public Symbol whatblock(addr)
226 Address addr;
227 {
228     register int i, j, k;
229     Address a;
230 
231     i = 0;
232     j = nfuncs - 1;
233     if (addr < codeloc(functab[i])) {
234 	return program;
235     } else if (addr == codeloc(functab[i])) {
236 	return functab[i];
237     } else if (addr >= codeloc(functab[j])) {
238 	return functab[j];
239     }
240     while (i <= j) {
241 	k = (i + j) / 2;
242 	a = codeloc(functab[k]);
243 	if (a == addr) {
244 	    return functab[k];
245 	} else if (addr > a) {
246 	    i = k+1;
247 	} else {
248 	    j = k-1;
249 	}
250     }
251     if (addr > codeloc(functab[i])) {
252 	return functab[i];
253     } else {
254 	return functab[i-1];
255     }
256     /* NOTREACHED */
257 }
258 
259 /*
260  * Order the functab.
261  */
262 
263 private int cmpfunc(f1, f2)
264 Symbol *f1, *f2;
265 {
266     register Address a1, a2;
267 
268     a1 = codeloc(*f1);
269     a2 = codeloc(*f2);
270     return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) );
271 }
272 
273 public ordfunctab()
274 {
275     qsort(functab, nfuncs, sizeof(Symbol), cmpfunc);
276 }
277 
278 /*
279  * Clear out the functab, used when re-reading the object information.
280  */
281 
282 public clrfunctab()
283 {
284     nfuncs = 0;
285 }
286