date and time created 83/03/09 16:23:11 by ralph
[unix-history] / usr / src / old / dbx / mappings.c
CommitLineData
abf043f1
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
550fe947 3static char sccsid[] = "@(#)mappings.c 1.2 %G%";
abf043f1
ML
4
5/*
6 * Source-to-object and vice versa mappings.
7 */
8
9#include "defs.h"
10#include "mappings.h"
11#include "symbols.h"
12#include "source.h"
13#include "object.h"
14#include "machine.h"
15
16#ifndef public
17#include "machine.h"
18#include "source.h"
19#include "symbols.h"
20
21typedef struct {
22 Address addr;
23 String filename;
24 Lineno lineindex; /* index to first linetab entry */
25} Filetab;
26
27typedef struct {
28 Lineno line;
29 Address addr;
30} Linetab;
31
32Filetab *filetab;
33Linetab *linetab;
34
35#define NOADDR ((Address) -1) /* no address for line or procedure */
36
37#endif
38
39/*
40 * Get the source file name associated with a given address.
41 */
42
43public String srcfilename(addr)
44Address addr;
45{
46 register Address i, j, k;
47 Address a;
48 Filetab *ftp;
49 String s;
50
51 s = nil;
52 if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) {
53 i = 0;
54 j = nlhdr.nfiles - 1;
55 while (i < j) {
56 k = (i + j) / 2;
57 ftp = &filetab[k];
58 a = ftp->addr;
59 if (a == addr) {
60 s = ftp->filename;
61 break;
62 } else if (addr > a) {
63 i = k + 1;
64 } else {
65 j = k - 1;
66 }
67 }
68 if (s == nil) {
69 if (addr >= filetab[i].addr) {
70 s = filetab[i].filename;
71 } else {
72 s = filetab[i-1].filename;
73 }
74 }
75 }
76 return s;
77}
78
79/*
80 * Find the line associated with the given address.
81 * If the second parameter is true, then the address must match
82 * a source line exactly. Otherwise the nearest source line
83 * below the given address is returned. In any case, if no suitable
84 * line exists, 0 is returned.
85 */
86
87private Lineno findline(addr, exact)
88Address addr;
89Boolean exact;
90{
91 register Address i, j, k;
92 register Lineno r;
93 register Address a;
94
95 if (nlhdr.nlines == 0 or addr < linetab[0].addr) {
96 r = 0;
97 } else {
98 i = 0;
99 j = nlhdr.nlines - 1;
100 if (addr == linetab[i].addr) {
101 r = linetab[i].line;
102 } else if (addr == linetab[j].addr) {
103 r = linetab[j].line;
104 } else if (addr > linetab[j].addr) {
105 r = exact ? 0 : linetab[j].line;
106 } else {
107 do {
108 k = (i + j) div 2;
109 a = linetab[k].addr;
110 if (a == addr) break;
111 if (addr > a) {
112 i = k + 1;
113 } else {
114 j = k - 1;
115 }
116 } while (i <= j);
117 if (a == addr) {
118 r = linetab[k].line;
119 } else if (exact) {
120 r = 0;
121 } else if (addr > linetab[i].addr) {
122 r = linetab[i].line;
123 } else {
124 r = linetab[i-1].line;
125 }
126 }
127 }
128 return r;
129}
130
131/*
132 * Lookup the source line number nearest from below to an address.
133 */
134
135public Lineno srcline(addr)
136Address addr;
137{
138 return findline(addr, false);
139}
140
141/*
142 * Look for a line exactly corresponding to the given address.
143 */
144
145public Lineno linelookup(addr)
146Address addr;
147{
148 return findline(addr, true);
149}
150
151/*
152 * Lookup the object address of a given line from the named file.
153 *
154 * Potentially all files in the file table need to be checked
155 * until the line is found since a particular file name may appear
156 * more than once in the file table (caused by includes).
157 */
158
159public Address objaddr(line, name)
160Lineno line;
161String name;
162{
163 register Filetab *ftp;
164 register Lineno i, j;
165 Boolean foundfile;
166
167 if (nlhdr.nlines == 0) {
168 return NOADDR;
169 }
170 if (name == nil) {
171 name = cursource;
172 }
173 foundfile = false;
174 for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
175 if (streq(ftp->filename, name)) {
176 foundfile = true;
177 i = ftp->lineindex;
178 if (ftp == &filetab[nlhdr.nfiles-1]) {
179 j = nlhdr.nlines;
180 } else {
181 j = (ftp + 1)->lineindex;
182 }
183 while (i < j) {
184 if (linetab[i].line == line) {
185 return linetab[i].addr;
186 }
187 i++;
188 }
189 }
190 }
191 if (not foundfile) {
192 error("unknown source file \"%s\"", name);
193 }
194 return NOADDR;
195}
196
197/*
198 * Table for going from object addresses to the functions in which they belong.
199 */
200
201#define MAXNFUNCS 1001 /* maximum number of functions allowed */
202
203private Symbol functab[MAXNFUNCS];
204private int nfuncs;
205
206/*
207 * Insert a new function into the table.
208 * The table is ordered by object address.
209 */
210
211public newfunc(f)
212Symbol f;
213{
214 if (nfuncs >= MAXNFUNCS) {
215 panic("too many procedures/functions");
216 }
217 functab[nfuncs] = f;
218 ++nfuncs;
219}
220
221/*
222 * Return the function that begins at the given address.
223 */
224
225public Symbol whatblock(addr)
226Address addr;
227{
228 register int i, j, k;
229 Address a;
230
231 i = 0;
232 j = nfuncs - 1;
233 if (addr < codeloc(functab[i])) {
234 return program;
235 } else if (addr == codeloc(functab[i])) {
236 return functab[i];
237 } else if (addr >= codeloc(functab[j])) {
238 return functab[j];
239 }
240 while (i <= j) {
241 k = (i + j) / 2;
242 a = codeloc(functab[k]);
243 if (a == addr) {
244 return functab[k];
245 } else if (addr > a) {
246 i = k+1;
247 } else {
248 j = k-1;
249 }
250 }
251 if (addr > codeloc(functab[i])) {
252 return functab[i];
253 } else {
254 return functab[i-1];
255 }
256 /* NOTREACHED */
257}
258
259/*
260 * Order the functab.
261 */
262
263private int cmpfunc(f1, f2)
264Symbol *f1, *f2;
265{
266 register Address a1, a2;
267
268 a1 = codeloc(*f1);
269 a2 = codeloc(*f2);
270 return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) );
271}
272
273public ordfunctab()
274{
275 qsort(functab, nfuncs, sizeof(Symbol), cmpfunc);
276}
277
278/*
279 * Clear out the functab, used when re-reading the object information.
280 */
281
282public clrfunctab()
283{
284 nfuncs = 0;
285}