date and time created 88/03/30 15:58:41 by bostic
[unix-history] / usr / src / old / dbx / mappings.c
CommitLineData
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 8static char sccsid[] = "@(#)mappings.c 5.3 (Berkeley) %G%";
2a24676e 9#endif not lint
0022c355 10
9606e7b9 11static 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
29typedef struct {
30 Address addr;
31 String filename;
32 Lineno lineindex; /* index to first linetab entry */
33} Filetab;
34
35typedef struct {
36 Lineno line;
37 Address addr;
38} Linetab;
39
40Filetab *filetab;
41Linetab *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
51public String srcfilename(addr)
52Address 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 96private integer findline (addr, exact)
abf043f1
ML
97Address addr;
98Boolean 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 149public Lineno srcline (addr)
abf043f1
ML
150Address 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
195public Lineno linelookup(addr)
196Address 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
218public Address objaddr(line, name)
219Lineno line;
220String 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
262typedef struct {
263 Symbol func;
264 Address addr;
265} AddrOfFunc;
266
0022c355
ML
267private AddrOfFunc *functab;
268private int nfuncs = 0;
269private int functablesize = 0;
abf043f1
ML
270
271/*
272 * Insert a new function into the table.
abf043f1
ML
273 */
274
d4345abe 275public newfunc(f, addr)
abf043f1 276Symbol f;
d4345abe 277Address 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
305public Symbol whatblock(addr)
306Address 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
343private int cmpfunc(f1, f2)
d4345abe 344AddrOfFunc *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
353public 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
362public clrfunctab()
363{
364 nfuncs = 0;
365}
e3de3d54
AF
366
367public dumpfunctab()
368{
d4345abe
ML
369 int i;
370
371 for (i = 0; i < nfuncs; i++) {
372 psym(functab[i].func);
373 }
e3de3d54 374}