Commit | Line | Data |
---|---|---|
2a24676e DF |
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 | */ | |
abf043f1 | 6 | |
2a24676e | 7 | #ifndef lint |
9606e7b9 | 8 | static char sccsid[] = "@(#)mappings.c 5.3 (Berkeley) %G%"; |
2a24676e | 9 | #endif not lint |
0022c355 | 10 | |
9606e7b9 | 11 | static char rcsid[] = "$Header: mappings.c,v 1.3 87/03/26 19:41:55 donn Exp $"; |
abf043f1 ML |
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 | |
0022c355 ML |
91 | * below the given address is returned. |
92 | * | |
93 | * Return the index of the line table entry or -1 if none suitable. | |
abf043f1 ML |
94 | */ |
95 | ||
0022c355 | 96 | private integer findline (addr, exact) |
abf043f1 ML |
97 | Address addr; |
98 | Boolean exact; | |
99 | { | |
100 | register Address i, j, k; | |
101 | register Lineno r; | |
102 | register Address a; | |
103 | ||
9606e7b9 | 104 | if (nlhdr.nlines == 0 or addr < linetab[0].addr) { |
0022c355 | 105 | r = -1; |
abf043f1 ML |
106 | } else { |
107 | i = 0; | |
108 | j = nlhdr.nlines - 1; | |
109 | if (addr == linetab[i].addr) { | |
0022c355 | 110 | r = i; |
abf043f1 | 111 | } else if (addr == linetab[j].addr) { |
0022c355 | 112 | r = j; |
abf043f1 | 113 | } else if (addr > linetab[j].addr) { |
0022c355 | 114 | r = exact ? -1 : j; |
abf043f1 ML |
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) { | |
0022c355 | 127 | r = k; |
abf043f1 | 128 | } else if (exact) { |
0022c355 | 129 | r = -1; |
abf043f1 | 130 | } else if (addr > linetab[i].addr) { |
0022c355 | 131 | r = i; |
abf043f1 | 132 | } else { |
0022c355 | 133 | r = i - 1; |
abf043f1 ML |
134 | } |
135 | } | |
136 | } | |
137 | return r; | |
138 | } | |
139 | ||
140 | /* | |
0022c355 ML |
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. | |
abf043f1 ML |
147 | */ |
148 | ||
9606e7b9 | 149 | public Lineno srcline (addr) |
abf043f1 ML |
150 | Address addr; |
151 | { | |
9606e7b9 | 152 | Lineno i, r; |
0022c355 | 153 | Symbol f1, f2; |
9606e7b9 | 154 | Address a; |
0022c355 ML |
155 | |
156 | i = findline(addr, false); | |
157 | if (i == -1) { | |
9606e7b9 DS |
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 | } | |
0022c355 ML |
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; | |
abf043f1 ML |
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 | { | |
0022c355 ML |
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; | |
abf043f1 ML |
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) { | |
0022c355 | 251 | error("source file \"%s\" not compiled with -g", name); |
abf043f1 ML |
252 | } |
253 | return NOADDR; | |
254 | } | |
255 | ||
256 | /* | |
257 | * Table for going from object addresses to the functions in which they belong. | |
258 | */ | |
259 | ||
0022c355 | 260 | #define NFUNCS 500 /* initial size of function table */ |
abf043f1 | 261 | |
d4345abe ML |
262 | typedef struct { |
263 | Symbol func; | |
264 | Address addr; | |
265 | } AddrOfFunc; | |
266 | ||
0022c355 ML |
267 | private AddrOfFunc *functab; |
268 | private int nfuncs = 0; | |
269 | private int functablesize = 0; | |
abf043f1 ML |
270 | |
271 | /* | |
272 | * Insert a new function into the table. | |
abf043f1 ML |
273 | */ |
274 | ||
d4345abe | 275 | public newfunc(f, addr) |
abf043f1 | 276 | Symbol f; |
d4345abe | 277 | Address addr; |
abf043f1 | 278 | { |
d4345abe | 279 | register AddrOfFunc *af; |
0022c355 ML |
280 | register int i; |
281 | AddrOfFunc *newfunctab; | |
d4345abe | 282 | |
0022c355 ML |
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 | } | |
abf043f1 | 294 | } |
d4345abe ML |
295 | af = &functab[nfuncs]; |
296 | af->func = f; | |
297 | af->addr = addr; | |
abf043f1 ML |
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; | |
d4345abe | 313 | if (addr < functab[i].addr) { |
abf043f1 | 314 | return program; |
d4345abe ML |
315 | } else if (addr == functab[i].addr) { |
316 | return functab[i].func; | |
317 | } else if (addr >= functab[j].addr) { | |
318 | return functab[j].func; | |
abf043f1 ML |
319 | } |
320 | while (i <= j) { | |
321 | k = (i + j) / 2; | |
d4345abe | 322 | a = functab[k].addr; |
abf043f1 | 323 | if (a == addr) { |
d4345abe | 324 | return functab[k].func; |
abf043f1 ML |
325 | } else if (addr > a) { |
326 | i = k+1; | |
327 | } else { | |
328 | j = k-1; | |
329 | } | |
330 | } | |
d4345abe ML |
331 | if (addr > functab[i].addr) { |
332 | return functab[i].func; | |
abf043f1 | 333 | } else { |
d4345abe | 334 | return functab[i-1].func; |
abf043f1 ML |
335 | } |
336 | /* NOTREACHED */ | |
337 | } | |
338 | ||
339 | /* | |
340 | * Order the functab. | |
341 | */ | |
342 | ||
343 | private int cmpfunc(f1, f2) | |
d4345abe | 344 | AddrOfFunc *f1, *f2; |
abf043f1 ML |
345 | { |
346 | register Address a1, a2; | |
347 | ||
d4345abe ML |
348 | a1 = (*f1).addr; |
349 | a2 = (*f2).addr; | |
abf043f1 ML |
350 | return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) ); |
351 | } | |
352 | ||
353 | public ordfunctab() | |
354 | { | |
d4345abe | 355 | qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc); |
abf043f1 ML |
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 | } | |
e3de3d54 AF |
366 | |
367 | public dumpfunctab() | |
368 | { | |
d4345abe ML |
369 | int i; |
370 | ||
371 | for (i = 0; i < nfuncs; i++) { | |
372 | psym(functab[i].func); | |
373 | } | |
e3de3d54 | 374 | } |