Commit | Line | Data |
---|---|---|
2a24676e | 1 | /* |
8a90f3aa KB |
2 | * Copyright (c) 1983 The Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
6ecf3d85 | 5 | * %sccs.include.redist.c% |
2a24676e | 6 | */ |
abf043f1 | 7 | |
2a24676e | 8 | #ifndef lint |
6ecf3d85 | 9 | static char sccsid[] = "@(#)mappings.c 5.5 (Berkeley) %G%"; |
8a90f3aa | 10 | #endif /* not lint */ |
abf043f1 ML |
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 | ||
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 | |
0022c355 ML |
90 | * below the given address is returned. |
91 | * | |
92 | * Return the index of the line table entry or -1 if none suitable. | |
abf043f1 ML |
93 | */ |
94 | ||
0022c355 | 95 | private integer findline (addr, exact) |
abf043f1 ML |
96 | Address addr; |
97 | Boolean exact; | |
98 | { | |
99 | register Address i, j, k; | |
100 | register Lineno r; | |
101 | register Address a; | |
102 | ||
9606e7b9 | 103 | if (nlhdr.nlines == 0 or addr < linetab[0].addr) { |
0022c355 | 104 | r = -1; |
abf043f1 ML |
105 | } else { |
106 | i = 0; | |
107 | j = nlhdr.nlines - 1; | |
108 | if (addr == linetab[i].addr) { | |
0022c355 | 109 | r = i; |
abf043f1 | 110 | } else if (addr == linetab[j].addr) { |
0022c355 | 111 | r = j; |
abf043f1 | 112 | } else if (addr > linetab[j].addr) { |
0022c355 | 113 | r = exact ? -1 : j; |
abf043f1 ML |
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) { | |
0022c355 | 126 | r = k; |
abf043f1 | 127 | } else if (exact) { |
0022c355 | 128 | r = -1; |
abf043f1 | 129 | } else if (addr > linetab[i].addr) { |
0022c355 | 130 | r = i; |
abf043f1 | 131 | } else { |
0022c355 | 132 | r = i - 1; |
abf043f1 ML |
133 | } |
134 | } | |
135 | } | |
136 | return r; | |
137 | } | |
138 | ||
139 | /* | |
0022c355 ML |
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. | |
abf043f1 ML |
146 | */ |
147 | ||
9606e7b9 | 148 | public Lineno srcline (addr) |
abf043f1 ML |
149 | Address addr; |
150 | { | |
9606e7b9 | 151 | Lineno i, r; |
0022c355 | 152 | Symbol f1, f2; |
9606e7b9 | 153 | Address a; |
0022c355 ML |
154 | |
155 | i = findline(addr, false); | |
156 | if (i == -1) { | |
9606e7b9 DS |
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 | } | |
0022c355 ML |
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; | |
abf043f1 ML |
188 | } |
189 | ||
190 | /* | |
191 | * Look for a line exactly corresponding to the given address. | |
192 | */ | |
193 | ||
194 | public Lineno linelookup(addr) | |
195 | Address addr; | |
196 | { | |
0022c355 ML |
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; | |
abf043f1 ML |
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 | ||
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) { | |
0022c355 | 250 | error("source file \"%s\" not compiled with -g", name); |
abf043f1 ML |
251 | } |
252 | return NOADDR; | |
253 | } | |
254 | ||
255 | /* | |
256 | * Table for going from object addresses to the functions in which they belong. | |
257 | */ | |
258 | ||
0022c355 | 259 | #define NFUNCS 500 /* initial size of function table */ |
abf043f1 | 260 | |
d4345abe ML |
261 | typedef struct { |
262 | Symbol func; | |
263 | Address addr; | |
264 | } AddrOfFunc; | |
265 | ||
0022c355 ML |
266 | private AddrOfFunc *functab; |
267 | private int nfuncs = 0; | |
268 | private int functablesize = 0; | |
abf043f1 ML |
269 | |
270 | /* | |
271 | * Insert a new function into the table. | |
abf043f1 ML |
272 | */ |
273 | ||
d4345abe | 274 | public newfunc(f, addr) |
abf043f1 | 275 | Symbol f; |
d4345abe | 276 | Address addr; |
abf043f1 | 277 | { |
d4345abe | 278 | register AddrOfFunc *af; |
0022c355 ML |
279 | register int i; |
280 | AddrOfFunc *newfunctab; | |
d4345abe | 281 | |
0022c355 ML |
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 | } | |
abf043f1 | 293 | } |
d4345abe ML |
294 | af = &functab[nfuncs]; |
295 | af->func = f; | |
296 | af->addr = addr; | |
abf043f1 ML |
297 | ++nfuncs; |
298 | } | |
299 | ||
300 | /* | |
301 | * Return the function that begins at the given address. | |
302 | */ | |
303 | ||
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; | |
d4345abe | 312 | if (addr < functab[i].addr) { |
abf043f1 | 313 | return program; |
d4345abe ML |
314 | } else if (addr == functab[i].addr) { |
315 | return functab[i].func; | |
316 | } else if (addr >= functab[j].addr) { | |
317 | return functab[j].func; | |
abf043f1 ML |
318 | } |
319 | while (i <= j) { | |
320 | k = (i + j) / 2; | |
d4345abe | 321 | a = functab[k].addr; |
abf043f1 | 322 | if (a == addr) { |
d4345abe | 323 | return functab[k].func; |
abf043f1 ML |
324 | } else if (addr > a) { |
325 | i = k+1; | |
326 | } else { | |
327 | j = k-1; | |
328 | } | |
329 | } | |
d4345abe ML |
330 | if (addr > functab[i].addr) { |
331 | return functab[i].func; | |
abf043f1 | 332 | } else { |
d4345abe | 333 | return functab[i-1].func; |
abf043f1 ML |
334 | } |
335 | /* NOTREACHED */ | |
336 | } | |
337 | ||
338 | /* | |
339 | * Order the functab. | |
340 | */ | |
341 | ||
342 | private int cmpfunc(f1, f2) | |
d4345abe | 343 | AddrOfFunc *f1, *f2; |
abf043f1 ML |
344 | { |
345 | register Address a1, a2; | |
346 | ||
d4345abe ML |
347 | a1 = (*f1).addr; |
348 | a2 = (*f2).addr; | |
abf043f1 ML |
349 | return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) ); |
350 | } | |
351 | ||
352 | public ordfunctab() | |
353 | { | |
d4345abe | 354 | qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc); |
abf043f1 ML |
355 | } |
356 | ||
357 | /* | |
358 | * Clear out the functab, used when re-reading the object information. | |
359 | */ | |
360 | ||
361 | public clrfunctab() | |
362 | { | |
363 | nfuncs = 0; | |
364 | } | |
e3de3d54 AF |
365 | |
366 | public dumpfunctab() | |
367 | { | |
d4345abe ML |
368 | int i; |
369 | ||
370 | for (i = 0; i < nfuncs; i++) { | |
371 | psym(functab[i].func); | |
372 | } | |
e3de3d54 | 373 | } |