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 DF |
7 | #ifndef lint |
8 | static char sccsid[] = "@(#)mappings.c 5.1 (Berkeley) %G%"; | |
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 | ||
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 | ||
149 | public Lineno srcline(addr) | |
150 | Address addr; | |
151 | { | |
0022c355 ML |
152 | integer i; |
153 | Lineno r; | |
154 | Symbol f1, f2; | |
155 | ||
156 | i = findline(addr, false); | |
157 | if (i == -1) { | |
158 | r = 0; | |
159 | } else { | |
160 | r = linetab[i].line; | |
161 | if (linetab[i].addr != addr) { | |
162 | f1 = whatblock(addr); | |
163 | if (nosource(f1)) { | |
164 | r = 0; | |
165 | } else { | |
166 | f2 = whatblock(linetab[i].addr + 1); | |
167 | if (f1 != f2) { | |
168 | do { | |
169 | ++i; | |
170 | } while (linetab[i].addr < addr and i < nlhdr.nlines); | |
171 | r = linetab[i].line; | |
172 | } | |
173 | } | |
174 | } | |
175 | } | |
176 | return r; | |
abf043f1 ML |
177 | } |
178 | ||
179 | /* | |
180 | * Look for a line exactly corresponding to the given address. | |
181 | */ | |
182 | ||
183 | public Lineno linelookup(addr) | |
184 | Address addr; | |
185 | { | |
0022c355 ML |
186 | integer i; |
187 | Lineno r; | |
188 | ||
189 | i = findline(addr, true); | |
190 | if (i == -1) { | |
191 | r = 0; | |
192 | } else { | |
193 | r = linetab[i].line; | |
194 | } | |
195 | return r; | |
abf043f1 ML |
196 | } |
197 | ||
198 | /* | |
199 | * Lookup the object address of a given line from the named file. | |
200 | * | |
201 | * Potentially all files in the file table need to be checked | |
202 | * until the line is found since a particular file name may appear | |
203 | * more than once in the file table (caused by includes). | |
204 | */ | |
205 | ||
206 | public Address objaddr(line, name) | |
207 | Lineno line; | |
208 | String name; | |
209 | { | |
210 | register Filetab *ftp; | |
211 | register Lineno i, j; | |
212 | Boolean foundfile; | |
213 | ||
214 | if (nlhdr.nlines == 0) { | |
215 | return NOADDR; | |
216 | } | |
217 | if (name == nil) { | |
218 | name = cursource; | |
219 | } | |
220 | foundfile = false; | |
221 | for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) { | |
222 | if (streq(ftp->filename, name)) { | |
223 | foundfile = true; | |
224 | i = ftp->lineindex; | |
225 | if (ftp == &filetab[nlhdr.nfiles-1]) { | |
226 | j = nlhdr.nlines; | |
227 | } else { | |
228 | j = (ftp + 1)->lineindex; | |
229 | } | |
230 | while (i < j) { | |
231 | if (linetab[i].line == line) { | |
232 | return linetab[i].addr; | |
233 | } | |
234 | i++; | |
235 | } | |
236 | } | |
237 | } | |
238 | if (not foundfile) { | |
0022c355 | 239 | error("source file \"%s\" not compiled with -g", name); |
abf043f1 ML |
240 | } |
241 | return NOADDR; | |
242 | } | |
243 | ||
244 | /* | |
245 | * Table for going from object addresses to the functions in which they belong. | |
246 | */ | |
247 | ||
0022c355 | 248 | #define NFUNCS 500 /* initial size of function table */ |
abf043f1 | 249 | |
d4345abe ML |
250 | typedef struct { |
251 | Symbol func; | |
252 | Address addr; | |
253 | } AddrOfFunc; | |
254 | ||
0022c355 ML |
255 | private AddrOfFunc *functab; |
256 | private int nfuncs = 0; | |
257 | private int functablesize = 0; | |
abf043f1 ML |
258 | |
259 | /* | |
260 | * Insert a new function into the table. | |
abf043f1 ML |
261 | */ |
262 | ||
d4345abe | 263 | public newfunc(f, addr) |
abf043f1 | 264 | Symbol f; |
d4345abe | 265 | Address addr; |
abf043f1 | 266 | { |
d4345abe | 267 | register AddrOfFunc *af; |
0022c355 ML |
268 | register int i; |
269 | AddrOfFunc *newfunctab; | |
d4345abe | 270 | |
0022c355 ML |
271 | if (nfuncs >= functablesize) { |
272 | if (functablesize == 0) { | |
273 | functab = newarr(AddrOfFunc, NFUNCS); | |
274 | functablesize = NFUNCS; | |
275 | } else { | |
276 | functablesize *= 2; | |
277 | newfunctab = newarr(AddrOfFunc, functablesize); | |
278 | bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc)); | |
279 | dispose(functab); | |
280 | functab = newfunctab; | |
281 | } | |
abf043f1 | 282 | } |
d4345abe ML |
283 | af = &functab[nfuncs]; |
284 | af->func = f; | |
285 | af->addr = addr; | |
abf043f1 ML |
286 | ++nfuncs; |
287 | } | |
288 | ||
289 | /* | |
290 | * Return the function that begins at the given address. | |
291 | */ | |
292 | ||
293 | public Symbol whatblock(addr) | |
294 | Address addr; | |
295 | { | |
296 | register int i, j, k; | |
297 | Address a; | |
298 | ||
299 | i = 0; | |
300 | j = nfuncs - 1; | |
d4345abe | 301 | if (addr < functab[i].addr) { |
abf043f1 | 302 | return program; |
d4345abe ML |
303 | } else if (addr == functab[i].addr) { |
304 | return functab[i].func; | |
305 | } else if (addr >= functab[j].addr) { | |
306 | return functab[j].func; | |
abf043f1 ML |
307 | } |
308 | while (i <= j) { | |
309 | k = (i + j) / 2; | |
d4345abe | 310 | a = functab[k].addr; |
abf043f1 | 311 | if (a == addr) { |
d4345abe | 312 | return functab[k].func; |
abf043f1 ML |
313 | } else if (addr > a) { |
314 | i = k+1; | |
315 | } else { | |
316 | j = k-1; | |
317 | } | |
318 | } | |
d4345abe ML |
319 | if (addr > functab[i].addr) { |
320 | return functab[i].func; | |
abf043f1 | 321 | } else { |
d4345abe | 322 | return functab[i-1].func; |
abf043f1 ML |
323 | } |
324 | /* NOTREACHED */ | |
325 | } | |
326 | ||
327 | /* | |
328 | * Order the functab. | |
329 | */ | |
330 | ||
331 | private int cmpfunc(f1, f2) | |
d4345abe | 332 | AddrOfFunc *f1, *f2; |
abf043f1 ML |
333 | { |
334 | register Address a1, a2; | |
335 | ||
d4345abe ML |
336 | a1 = (*f1).addr; |
337 | a2 = (*f2).addr; | |
abf043f1 ML |
338 | return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) ); |
339 | } | |
340 | ||
341 | public ordfunctab() | |
342 | { | |
d4345abe | 343 | qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc); |
abf043f1 ML |
344 | } |
345 | ||
346 | /* | |
347 | * Clear out the functab, used when re-reading the object information. | |
348 | */ | |
349 | ||
350 | public clrfunctab() | |
351 | { | |
352 | nfuncs = 0; | |
353 | } | |
e3de3d54 AF |
354 | |
355 | public dumpfunctab() | |
356 | { | |
d4345abe ML |
357 | int i; |
358 | ||
359 | for (i = 0; i < nfuncs; i++) { | |
360 | psym(functab[i].func); | |
361 | } | |
e3de3d54 | 362 | } |