|
|
1.1 root 1: /*
2: * Copyright (c) 1983 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)mappings.c 5.5 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: /*
25: * Source-to-object and vice versa mappings.
26: */
27:
28: #include "defs.h"
29: #include "mappings.h"
30: #include "symbols.h"
31: #include "source.h"
32: #include "object.h"
33: #include "machine.h"
34:
35: #ifndef public
36: #include "machine.h"
37: #include "source.h"
38: #include "symbols.h"
39:
40: typedef struct {
41: Address addr;
42: String filename;
43: Lineno lineindex; /* index to first linetab entry */
44: } Filetab;
45:
46: typedef struct {
47: Lineno line;
48: Address addr;
49: } Linetab;
50:
51: Filetab *filetab;
52: Linetab *linetab;
53:
54: #define NOADDR ((Address) -1) /* no address for line or procedure */
55:
56: #endif
57:
58: /*
59: * Get the source file name associated with a given address.
60: */
61:
62: public String srcfilename(addr)
63: Address addr;
64: {
65: register Address i, j, k;
66: Address a;
67: Filetab *ftp;
68: String s;
69:
70: s = nil;
71: if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) {
72: i = 0;
73: j = nlhdr.nfiles - 1;
74: while (i < j) {
75: k = (i + j) / 2;
76: ftp = &filetab[k];
77: a = ftp->addr;
78: if (a == addr) {
79: s = ftp->filename;
80: break;
81: } else if (addr > a) {
82: i = k + 1;
83: } else {
84: j = k - 1;
85: }
86: }
87: if (s == nil) {
88: if (addr >= filetab[i].addr) {
89: s = filetab[i].filename;
90: } else {
91: s = filetab[i-1].filename;
92: }
93: }
94: }
95: return s;
96: }
97:
98: /*
99: * Find the line associated with the given address.
100: * If the second parameter is true, then the address must match
101: * a source line exactly. Otherwise the nearest source line
102: * below the given address is returned.
103: *
104: * Return the index of the line table entry or -1 if none suitable.
105: */
106:
107: private integer findline (addr, exact)
108: Address addr;
109: Boolean exact;
110: {
111: register Address i, j, k;
112: register Lineno r;
113: register Address a;
114:
115: if (nlhdr.nlines == 0 or addr < linetab[0].addr) {
116: r = -1;
117: } else {
118: i = 0;
119: j = nlhdr.nlines - 1;
120: if (addr == linetab[i].addr) {
121: r = i;
122: } else if (addr == linetab[j].addr) {
123: r = j;
124: } else if (addr > linetab[j].addr) {
125: r = exact ? -1 : j;
126: } else {
127: do {
128: k = (i + j) div 2;
129: a = linetab[k].addr;
130: if (a == addr) break;
131: if (addr > a) {
132: i = k + 1;
133: } else {
134: j = k - 1;
135: }
136: } while (i <= j);
137: if (a == addr) {
138: r = k;
139: } else if (exact) {
140: r = -1;
141: } else if (addr > linetab[i].addr) {
142: r = i;
143: } else {
144: r = i - 1;
145: }
146: }
147: }
148: return r;
149: }
150:
151: /*
152: * Lookup the source line number nearest (from below) to an address.
153: *
154: * It is possible (unfortunately) that the compiler will generate
155: * code before line number for a procedure. Therefore we check
156: * to see that the found line is in the same procedure as the given address.
157: * If it isn't, then we walk forward until the first suitable line is found.
158: */
159:
160: public Lineno srcline (addr)
161: Address addr;
162: {
163: Lineno i, r;
164: Symbol f1, f2;
165: Address a;
166:
167: i = findline(addr, false);
168: if (i == -1) {
169: f1 = whatblock(addr);
170: if (f1 == nil or nosource(f1)) {
171: r = 0;
172: } else {
173: a = codeloc(f1);
174: for (;;) {
175: r = linelookup(a);
176: if (r != 0 or a >= CODESTART + objsize) {
177: break;
178: }
179: ++a;
180: }
181: }
182: } else {
183: r = linetab[i].line;
184: if (linetab[i].addr != addr) {
185: f1 = whatblock(addr);
186: if (nosource(f1)) {
187: r = 0;
188: } else {
189: f2 = whatblock(linetab[i].addr + 1);
190: if (f1 != f2) {
191: do {
192: ++i;
193: } while (linetab[i].addr < addr and i < nlhdr.nlines);
194: r = linetab[i].line;
195: }
196: }
197: }
198: }
199: return r;
200: }
201:
202: /*
203: * Look for a line exactly corresponding to the given address.
204: */
205:
206: public Lineno linelookup(addr)
207: Address addr;
208: {
209: integer i;
210: Lineno r;
211:
212: i = findline(addr, true);
213: if (i == -1) {
214: r = 0;
215: } else {
216: r = linetab[i].line;
217: }
218: return r;
219: }
220:
221: /*
222: * Lookup the object address of a given line from the named file.
223: *
224: * Potentially all files in the file table need to be checked
225: * until the line is found since a particular file name may appear
226: * more than once in the file table (caused by includes).
227: */
228:
229: public Address objaddr(line, name)
230: Lineno line;
231: String name;
232: {
233: register Filetab *ftp;
234: register Lineno i, j;
235: Boolean foundfile;
236:
237: if (nlhdr.nlines == 0) {
238: return NOADDR;
239: }
240: if (name == nil) {
241: name = cursource;
242: }
243: foundfile = false;
244: for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
245: if (streq(ftp->filename, name)) {
246: foundfile = true;
247: i = ftp->lineindex;
248: if (ftp == &filetab[nlhdr.nfiles-1]) {
249: j = nlhdr.nlines;
250: } else {
251: j = (ftp + 1)->lineindex;
252: }
253: while (i < j) {
254: if (linetab[i].line == line) {
255: return linetab[i].addr;
256: }
257: i++;
258: }
259: }
260: }
261: if (not foundfile) {
262: error("source file \"%s\" not compiled with -g", name);
263: }
264: return NOADDR;
265: }
266:
267: /*
268: * Table for going from object addresses to the functions in which they belong.
269: */
270:
271: #define NFUNCS 500 /* initial size of function table */
272:
273: typedef struct {
274: Symbol func;
275: Address addr;
276: } AddrOfFunc;
277:
278: private AddrOfFunc *functab;
279: private int nfuncs = 0;
280: private int functablesize = 0;
281:
282: /*
283: * Insert a new function into the table.
284: */
285:
286: public newfunc(f, addr)
287: Symbol f;
288: Address addr;
289: {
290: register AddrOfFunc *af;
291: register int i;
292: AddrOfFunc *newfunctab;
293:
294: if (nfuncs >= functablesize) {
295: if (functablesize == 0) {
296: functab = newarr(AddrOfFunc, NFUNCS);
297: functablesize = NFUNCS;
298: } else {
299: functablesize *= 2;
300: newfunctab = newarr(AddrOfFunc, functablesize);
301: bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc));
302: dispose(functab);
303: functab = newfunctab;
304: }
305: }
306: af = &functab[nfuncs];
307: af->func = f;
308: af->addr = addr;
309: ++nfuncs;
310: }
311:
312: /*
313: * Return the function that begins at the given address.
314: */
315:
316: public Symbol whatblock(addr)
317: Address addr;
318: {
319: register int i, j, k;
320: Address a;
321:
322: i = 0;
323: j = nfuncs - 1;
324: if (addr < functab[i].addr) {
325: return program;
326: } else if (addr == functab[i].addr) {
327: return functab[i].func;
328: } else if (addr >= functab[j].addr) {
329: return functab[j].func;
330: }
331: while (i <= j) {
332: k = (i + j) / 2;
333: a = functab[k].addr;
334: if (a == addr) {
335: return functab[k].func;
336: } else if (addr > a) {
337: i = k+1;
338: } else {
339: j = k-1;
340: }
341: }
342: if (addr > functab[i].addr) {
343: return functab[i].func;
344: } else {
345: return functab[i-1].func;
346: }
347: /* NOTREACHED */
348: }
349:
350: /*
351: * Order the functab.
352: */
353:
354: private int cmpfunc(f1, f2)
355: AddrOfFunc *f1, *f2;
356: {
357: register Address a1, a2;
358:
359: a1 = (*f1).addr;
360: a2 = (*f2).addr;
361: return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) );
362: }
363:
364: public ordfunctab()
365: {
366: qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc);
367: }
368:
369: /*
370: * Clear out the functab, used when re-reading the object information.
371: */
372:
373: public clrfunctab()
374: {
375: nfuncs = 0;
376: }
377:
378: public dumpfunctab()
379: {
380: int i;
381:
382: for (i = 0; i < nfuncs; i++) {
383: psym(functab[i].func);
384: }
385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.