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