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
srcfilename(addr)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
findline(addr,exact)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
srcline(addr)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
linelookup(addr)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
objaddr(line,name)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
newfunc(f,addr)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
whatblock(addr)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
cmpfunc(f1,f2)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
ordfunctab()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
clrfunctab()361 public clrfunctab()
362 {
363 nfuncs = 0;
364 }
365
dumpfunctab()366 public dumpfunctab()
367 {
368 int i;
369
370 for (i = 0; i < nfuncs; i++) {
371 psym(functab[i].func);
372 }
373 }
374