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