xref: /csrg-svn/old/dbx/mappings.c (revision 18224)
19671Slinton /* Copyright (c) 1982 Regents of the University of California */
29671Slinton 
3*18224Slinton static	char sccsid[] = "@(#)mappings.c	1.6 (Berkeley) 03/01/85";
49671Slinton 
5*18224Slinton static char rcsid[] = "$Header: mappings.c,v 1.4 84/12/26 10:40:25 linton Exp $";
6*18224Slinton 
79671Slinton /*
89671Slinton  * Source-to-object and vice versa mappings.
99671Slinton  */
109671Slinton 
119671Slinton #include "defs.h"
129671Slinton #include "mappings.h"
139671Slinton #include "symbols.h"
149671Slinton #include "source.h"
159671Slinton #include "object.h"
169671Slinton #include "machine.h"
179671Slinton 
189671Slinton #ifndef public
199671Slinton #include "machine.h"
209671Slinton #include "source.h"
219671Slinton #include "symbols.h"
229671Slinton 
239671Slinton typedef struct {
249671Slinton     Address addr;
259671Slinton     String filename;
269671Slinton     Lineno lineindex;		/* index to first linetab entry */
279671Slinton } Filetab;
289671Slinton 
299671Slinton typedef struct {
309671Slinton     Lineno line;
319671Slinton     Address addr;
329671Slinton } Linetab;
339671Slinton 
349671Slinton Filetab *filetab;
359671Slinton Linetab *linetab;
369671Slinton 
379671Slinton #define NOADDR ((Address) -1)	/* no address for line or procedure */
389671Slinton 
399671Slinton #endif
409671Slinton 
419671Slinton /*
429671Slinton  * Get the source file name associated with a given address.
439671Slinton  */
449671Slinton 
459671Slinton public String srcfilename(addr)
469671Slinton Address addr;
479671Slinton {
489671Slinton     register Address i, j, k;
499671Slinton     Address a;
509671Slinton     Filetab *ftp;
519671Slinton     String s;
529671Slinton 
539671Slinton     s = nil;
549671Slinton     if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) {
559671Slinton 	i = 0;
569671Slinton 	j = nlhdr.nfiles - 1;
579671Slinton 	while (i < j) {
589671Slinton 	    k = (i + j) / 2;
599671Slinton 	    ftp = &filetab[k];
609671Slinton 	    a = ftp->addr;
619671Slinton 	    if (a == addr) {
629671Slinton 		s = ftp->filename;
639671Slinton 		break;
649671Slinton 	    } else if (addr > a) {
659671Slinton 		i = k + 1;
669671Slinton 	    } else {
679671Slinton 		j = k - 1;
689671Slinton 	    }
699671Slinton 	}
709671Slinton 	if (s == nil) {
719671Slinton 	    if (addr >= filetab[i].addr) {
729671Slinton 		s = filetab[i].filename;
739671Slinton 	    } else {
749671Slinton 		s = filetab[i-1].filename;
759671Slinton 	    }
769671Slinton 	}
779671Slinton     }
789671Slinton     return s;
799671Slinton }
809671Slinton 
819671Slinton /*
829671Slinton  * Find the line associated with the given address.
839671Slinton  * If the second parameter is true, then the address must match
849671Slinton  * a source line exactly.  Otherwise the nearest source line
85*18224Slinton  * below the given address is returned.
86*18224Slinton  *
87*18224Slinton  * Return the index of the line table entry or -1 if none suitable.
889671Slinton  */
899671Slinton 
90*18224Slinton private integer findline (addr, exact)
919671Slinton Address addr;
929671Slinton Boolean exact;
939671Slinton {
949671Slinton     register Address i, j, k;
959671Slinton     register Lineno r;
969671Slinton     register Address a;
979671Slinton 
989671Slinton     if (nlhdr.nlines == 0 or addr < linetab[0].addr) {
99*18224Slinton 	r = -1;
1009671Slinton     } else {
1019671Slinton 	i = 0;
1029671Slinton 	j = nlhdr.nlines - 1;
1039671Slinton 	if (addr == linetab[i].addr) {
104*18224Slinton 	    r = i;
1059671Slinton 	} else if (addr == linetab[j].addr) {
106*18224Slinton 	    r = j;
1079671Slinton 	} else if (addr > linetab[j].addr) {
108*18224Slinton 	    r = exact ? -1 : j;
1099671Slinton 	} else {
1109671Slinton 	    do {
1119671Slinton 		k = (i + j) div 2;
1129671Slinton 		a = linetab[k].addr;
1139671Slinton 	    if (a == addr) break;
1149671Slinton 		if (addr > a) {
1159671Slinton 		    i = k + 1;
1169671Slinton 		} else {
1179671Slinton 		    j = k - 1;
1189671Slinton 		}
1199671Slinton 	    } while (i <= j);
1209671Slinton 	    if (a == addr) {
121*18224Slinton 		r = k;
1229671Slinton 	    } else if (exact) {
123*18224Slinton 		r = -1;
1249671Slinton 	    } else if (addr > linetab[i].addr) {
125*18224Slinton 		r = i;
1269671Slinton 	    } else {
127*18224Slinton 		r = i - 1;
1289671Slinton 	    }
1299671Slinton 	}
1309671Slinton     }
1319671Slinton     return r;
1329671Slinton }
1339671Slinton 
1349671Slinton /*
135*18224Slinton  * Lookup the source line number nearest (from below) to an address.
136*18224Slinton  *
137*18224Slinton  * It is possible (unfortunately) that the compiler will generate
138*18224Slinton  * code before line number for a procedure.  Therefore we check
139*18224Slinton  * to see that the found line is in the same procedure as the given address.
140*18224Slinton  * If it isn't, then we walk forward until the first suitable line is found.
1419671Slinton  */
1429671Slinton 
1439671Slinton public Lineno srcline(addr)
1449671Slinton Address addr;
1459671Slinton {
146*18224Slinton     integer i;
147*18224Slinton     Lineno r;
148*18224Slinton     Symbol f1, f2;
149*18224Slinton 
150*18224Slinton     i = findline(addr, false);
151*18224Slinton     if (i == -1) {
152*18224Slinton 	r = 0;
153*18224Slinton     } else {
154*18224Slinton 	r = linetab[i].line;
155*18224Slinton 	if (linetab[i].addr != addr) {
156*18224Slinton 	    f1 = whatblock(addr);
157*18224Slinton 	    if (nosource(f1)) {
158*18224Slinton 		r = 0;
159*18224Slinton 	    } else {
160*18224Slinton 		f2 = whatblock(linetab[i].addr + 1);
161*18224Slinton 		if (f1 != f2) {
162*18224Slinton 		    do {
163*18224Slinton 			++i;
164*18224Slinton 		    } while (linetab[i].addr < addr and i < nlhdr.nlines);
165*18224Slinton 		    r = linetab[i].line;
166*18224Slinton 		}
167*18224Slinton 	    }
168*18224Slinton 	}
169*18224Slinton     }
170*18224Slinton     return r;
1719671Slinton }
1729671Slinton 
1739671Slinton /*
1749671Slinton  * Look for a line exactly corresponding to the given address.
1759671Slinton  */
1769671Slinton 
1779671Slinton public Lineno linelookup(addr)
1789671Slinton Address addr;
1799671Slinton {
180*18224Slinton     integer i;
181*18224Slinton     Lineno r;
182*18224Slinton 
183*18224Slinton     i = findline(addr, true);
184*18224Slinton     if (i == -1) {
185*18224Slinton 	r = 0;
186*18224Slinton     } else {
187*18224Slinton 	r = linetab[i].line;
188*18224Slinton     }
189*18224Slinton     return r;
1909671Slinton }
1919671Slinton 
1929671Slinton /*
1939671Slinton  * Lookup the object address of a given line from the named file.
1949671Slinton  *
1959671Slinton  * Potentially all files in the file table need to be checked
1969671Slinton  * until the line is found since a particular file name may appear
1979671Slinton  * more than once in the file table (caused by includes).
1989671Slinton  */
1999671Slinton 
2009671Slinton public Address objaddr(line, name)
2019671Slinton Lineno line;
2029671Slinton String name;
2039671Slinton {
2049671Slinton     register Filetab *ftp;
2059671Slinton     register Lineno i, j;
2069671Slinton     Boolean foundfile;
2079671Slinton 
2089671Slinton     if (nlhdr.nlines == 0) {
2099671Slinton 	return NOADDR;
2109671Slinton     }
2119671Slinton     if (name == nil) {
2129671Slinton 	name = cursource;
2139671Slinton     }
2149671Slinton     foundfile = false;
2159671Slinton     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
2169671Slinton 	if (streq(ftp->filename, name)) {
2179671Slinton 	    foundfile = true;
2189671Slinton 	    i = ftp->lineindex;
2199671Slinton 	    if (ftp == &filetab[nlhdr.nfiles-1]) {
2209671Slinton 		j = nlhdr.nlines;
2219671Slinton 	    } else {
2229671Slinton 		j = (ftp + 1)->lineindex;
2239671Slinton 	    }
2249671Slinton 	    while (i < j) {
2259671Slinton 		if (linetab[i].line == line) {
2269671Slinton 		    return linetab[i].addr;
2279671Slinton 		}
2289671Slinton 		i++;
2299671Slinton 	    }
2309671Slinton 	}
2319671Slinton     }
2329671Slinton     if (not foundfile) {
233*18224Slinton 	error("source file \"%s\" not compiled with -g", name);
2349671Slinton     }
2359671Slinton     return NOADDR;
2369671Slinton }
2379671Slinton 
2389671Slinton /*
2399671Slinton  * Table for going from object addresses to the functions in which they belong.
2409671Slinton  */
2419671Slinton 
242*18224Slinton #define NFUNCS 500	/* initial size of function table */
2439671Slinton 
24414439Slinton typedef struct {
24514439Slinton     Symbol func;
24614439Slinton     Address addr;
24714439Slinton } AddrOfFunc;
24814439Slinton 
249*18224Slinton private AddrOfFunc *functab;
250*18224Slinton private int nfuncs = 0;
251*18224Slinton private int functablesize = 0;
2529671Slinton 
2539671Slinton /*
2549671Slinton  * Insert a new function into the table.
2559671Slinton  */
2569671Slinton 
25714439Slinton public newfunc(f, addr)
2589671Slinton Symbol f;
25914439Slinton Address addr;
2609671Slinton {
26114439Slinton     register AddrOfFunc *af;
262*18224Slinton     register int i;
263*18224Slinton     AddrOfFunc *newfunctab;
26414439Slinton 
265*18224Slinton     if (nfuncs >= functablesize) {
266*18224Slinton 	if (functablesize == 0) {
267*18224Slinton 	    functab = newarr(AddrOfFunc, NFUNCS);
268*18224Slinton 	    functablesize = NFUNCS;
269*18224Slinton 	} else {
270*18224Slinton 	    functablesize *= 2;
271*18224Slinton 	    newfunctab = newarr(AddrOfFunc, functablesize);
272*18224Slinton 	    bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc));
273*18224Slinton 	    dispose(functab);
274*18224Slinton 	    functab = newfunctab;
275*18224Slinton 	}
2769671Slinton     }
27714439Slinton     af = &functab[nfuncs];
27814439Slinton     af->func = f;
27914439Slinton     af->addr = addr;
2809671Slinton     ++nfuncs;
2819671Slinton }
2829671Slinton 
2839671Slinton /*
2849671Slinton  * Return the function that begins at the given address.
2859671Slinton  */
2869671Slinton 
2879671Slinton public Symbol whatblock(addr)
2889671Slinton Address addr;
2899671Slinton {
2909671Slinton     register int i, j, k;
2919671Slinton     Address a;
2929671Slinton 
2939671Slinton     i = 0;
2949671Slinton     j = nfuncs - 1;
29514439Slinton     if (addr < functab[i].addr) {
2969671Slinton 	return program;
29714439Slinton     } else if (addr == functab[i].addr) {
29814439Slinton 	return functab[i].func;
29914439Slinton     } else if (addr >= functab[j].addr) {
30014439Slinton 	return functab[j].func;
3019671Slinton     }
3029671Slinton     while (i <= j) {
3039671Slinton 	k = (i + j) / 2;
30414439Slinton 	a = functab[k].addr;
3059671Slinton 	if (a == addr) {
30614439Slinton 	    return functab[k].func;
3079671Slinton 	} else if (addr > a) {
3089671Slinton 	    i = k+1;
3099671Slinton 	} else {
3109671Slinton 	    j = k-1;
3119671Slinton 	}
3129671Slinton     }
31314439Slinton     if (addr > functab[i].addr) {
31414439Slinton 	return functab[i].func;
3159671Slinton     } else {
31614439Slinton 	return functab[i-1].func;
3179671Slinton     }
3189671Slinton     /* NOTREACHED */
3199671Slinton }
3209671Slinton 
3219671Slinton /*
3229671Slinton  * Order the functab.
3239671Slinton  */
3249671Slinton 
3259671Slinton private int cmpfunc(f1, f2)
32614439Slinton AddrOfFunc *f1, *f2;
3279671Slinton {
3289671Slinton     register Address a1, a2;
3299671Slinton 
33014439Slinton     a1 = (*f1).addr;
33114439Slinton     a2 = (*f2).addr;
3329671Slinton     return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) );
3339671Slinton }
3349671Slinton 
3359671Slinton public ordfunctab()
3369671Slinton {
33714439Slinton     qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc);
3389671Slinton }
3399671Slinton 
3409671Slinton /*
3419671Slinton  * Clear out the functab, used when re-reading the object information.
3429671Slinton  */
3439671Slinton 
3449671Slinton public clrfunctab()
3459671Slinton {
3469671Slinton     nfuncs = 0;
3479671Slinton }
34812541Scsvaf 
34912541Scsvaf public dumpfunctab()
35012541Scsvaf {
35114439Slinton     int i;
35212541Scsvaf 
35314439Slinton     for (i = 0; i < nfuncs; i++) {
35414439Slinton 	psym(functab[i].func);
35514439Slinton     }
35612541Scsvaf }
357