xref: /csrg-svn/old/dbx/mappings.c (revision 42683)
121611Sdist /*
238105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic  * All rights reserved.
438105Sbostic  *
5*42683Sbostic  * %sccs.include.redist.c%
621611Sdist  */
79671Slinton 
821611Sdist #ifndef lint
9*42683Sbostic static char sccsid[] = "@(#)mappings.c	5.5 (Berkeley) 06/01/90";
1038105Sbostic #endif /* not lint */
119671Slinton 
129671Slinton /*
139671Slinton  * Source-to-object and vice versa mappings.
149671Slinton  */
159671Slinton 
169671Slinton #include "defs.h"
179671Slinton #include "mappings.h"
189671Slinton #include "symbols.h"
199671Slinton #include "source.h"
209671Slinton #include "object.h"
219671Slinton #include "machine.h"
229671Slinton 
239671Slinton #ifndef public
249671Slinton #include "machine.h"
259671Slinton #include "source.h"
269671Slinton #include "symbols.h"
279671Slinton 
289671Slinton typedef struct {
299671Slinton     Address addr;
309671Slinton     String filename;
319671Slinton     Lineno lineindex;		/* index to first linetab entry */
329671Slinton } Filetab;
339671Slinton 
349671Slinton typedef struct {
359671Slinton     Lineno line;
369671Slinton     Address addr;
379671Slinton } Linetab;
389671Slinton 
399671Slinton Filetab *filetab;
409671Slinton Linetab *linetab;
419671Slinton 
429671Slinton #define NOADDR ((Address) -1)	/* no address for line or procedure */
439671Slinton 
449671Slinton #endif
459671Slinton 
469671Slinton /*
479671Slinton  * Get the source file name associated with a given address.
489671Slinton  */
499671Slinton 
srcfilename(addr)509671Slinton public String srcfilename(addr)
519671Slinton Address addr;
529671Slinton {
539671Slinton     register Address i, j, k;
549671Slinton     Address a;
559671Slinton     Filetab *ftp;
569671Slinton     String s;
579671Slinton 
589671Slinton     s = nil;
599671Slinton     if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) {
609671Slinton 	i = 0;
619671Slinton 	j = nlhdr.nfiles - 1;
629671Slinton 	while (i < j) {
639671Slinton 	    k = (i + j) / 2;
649671Slinton 	    ftp = &filetab[k];
659671Slinton 	    a = ftp->addr;
669671Slinton 	    if (a == addr) {
679671Slinton 		s = ftp->filename;
689671Slinton 		break;
699671Slinton 	    } else if (addr > a) {
709671Slinton 		i = k + 1;
719671Slinton 	    } else {
729671Slinton 		j = k - 1;
739671Slinton 	    }
749671Slinton 	}
759671Slinton 	if (s == nil) {
769671Slinton 	    if (addr >= filetab[i].addr) {
779671Slinton 		s = filetab[i].filename;
789671Slinton 	    } else {
799671Slinton 		s = filetab[i-1].filename;
809671Slinton 	    }
819671Slinton 	}
829671Slinton     }
839671Slinton     return s;
849671Slinton }
859671Slinton 
869671Slinton /*
879671Slinton  * Find the line associated with the given address.
889671Slinton  * If the second parameter is true, then the address must match
899671Slinton  * a source line exactly.  Otherwise the nearest source line
9018224Slinton  * below the given address is returned.
9118224Slinton  *
9218224Slinton  * Return the index of the line table entry or -1 if none suitable.
939671Slinton  */
949671Slinton 
findline(addr,exact)9518224Slinton private integer findline (addr, exact)
969671Slinton Address addr;
979671Slinton Boolean exact;
989671Slinton {
999671Slinton     register Address i, j, k;
1009671Slinton     register Lineno r;
1019671Slinton     register Address a;
1029671Slinton 
10333324Sdonn     if (nlhdr.nlines == 0 or addr < linetab[0].addr) {
10418224Slinton 	r = -1;
1059671Slinton     } else {
1069671Slinton 	i = 0;
1079671Slinton 	j = nlhdr.nlines - 1;
1089671Slinton 	if (addr == linetab[i].addr) {
10918224Slinton 	    r = i;
1109671Slinton 	} else if (addr == linetab[j].addr) {
11118224Slinton 	    r = j;
1129671Slinton 	} else if (addr > linetab[j].addr) {
11318224Slinton 	    r = exact ? -1 : j;
1149671Slinton 	} else {
1159671Slinton 	    do {
1169671Slinton 		k = (i + j) div 2;
1179671Slinton 		a = linetab[k].addr;
1189671Slinton 	    if (a == addr) break;
1199671Slinton 		if (addr > a) {
1209671Slinton 		    i = k + 1;
1219671Slinton 		} else {
1229671Slinton 		    j = k - 1;
1239671Slinton 		}
1249671Slinton 	    } while (i <= j);
1259671Slinton 	    if (a == addr) {
12618224Slinton 		r = k;
1279671Slinton 	    } else if (exact) {
12818224Slinton 		r = -1;
1299671Slinton 	    } else if (addr > linetab[i].addr) {
13018224Slinton 		r = i;
1319671Slinton 	    } else {
13218224Slinton 		r = i - 1;
1339671Slinton 	    }
1349671Slinton 	}
1359671Slinton     }
1369671Slinton     return r;
1379671Slinton }
1389671Slinton 
1399671Slinton /*
14018224Slinton  * Lookup the source line number nearest (from below) to an address.
14118224Slinton  *
14218224Slinton  * It is possible (unfortunately) that the compiler will generate
14318224Slinton  * code before line number for a procedure.  Therefore we check
14418224Slinton  * to see that the found line is in the same procedure as the given address.
14518224Slinton  * If it isn't, then we walk forward until the first suitable line is found.
1469671Slinton  */
1479671Slinton 
srcline(addr)14833324Sdonn public Lineno srcline (addr)
1499671Slinton Address addr;
1509671Slinton {
15133324Sdonn     Lineno i, r;
15218224Slinton     Symbol f1, f2;
15333324Sdonn     Address a;
15418224Slinton 
15518224Slinton     i = findline(addr, false);
15618224Slinton     if (i == -1) {
15733324Sdonn 	f1 = whatblock(addr);
15833324Sdonn 	if (f1 == nil or nosource(f1)) {
15933324Sdonn 	    r = 0;
16033324Sdonn 	} else {
16133324Sdonn 	    a = codeloc(f1);
16233324Sdonn 	    for (;;) {
16333324Sdonn 		r = linelookup(a);
16433324Sdonn 		if (r != 0 or a >= CODESTART + objsize) {
16533324Sdonn 		    break;
16633324Sdonn 		}
16733324Sdonn 		++a;
16833324Sdonn 	    }
16933324Sdonn 	}
17018224Slinton     } else {
17118224Slinton 	r = linetab[i].line;
17218224Slinton 	if (linetab[i].addr != addr) {
17318224Slinton 	    f1 = whatblock(addr);
17418224Slinton 	    if (nosource(f1)) {
17518224Slinton 		r = 0;
17618224Slinton 	    } else {
17718224Slinton 		f2 = whatblock(linetab[i].addr + 1);
17818224Slinton 		if (f1 != f2) {
17918224Slinton 		    do {
18018224Slinton 			++i;
18118224Slinton 		    } while (linetab[i].addr < addr and i < nlhdr.nlines);
18218224Slinton 		    r = linetab[i].line;
18318224Slinton 		}
18418224Slinton 	    }
18518224Slinton 	}
18618224Slinton     }
18718224Slinton     return r;
1889671Slinton }
1899671Slinton 
1909671Slinton /*
1919671Slinton  * Look for a line exactly corresponding to the given address.
1929671Slinton  */
1939671Slinton 
linelookup(addr)1949671Slinton public Lineno linelookup(addr)
1959671Slinton Address addr;
1969671Slinton {
19718224Slinton     integer i;
19818224Slinton     Lineno r;
19918224Slinton 
20018224Slinton     i = findline(addr, true);
20118224Slinton     if (i == -1) {
20218224Slinton 	r = 0;
20318224Slinton     } else {
20418224Slinton 	r = linetab[i].line;
20518224Slinton     }
20618224Slinton     return r;
2079671Slinton }
2089671Slinton 
2099671Slinton /*
2109671Slinton  * Lookup the object address of a given line from the named file.
2119671Slinton  *
2129671Slinton  * Potentially all files in the file table need to be checked
2139671Slinton  * until the line is found since a particular file name may appear
2149671Slinton  * more than once in the file table (caused by includes).
2159671Slinton  */
2169671Slinton 
objaddr(line,name)2179671Slinton public Address objaddr(line, name)
2189671Slinton Lineno line;
2199671Slinton String name;
2209671Slinton {
2219671Slinton     register Filetab *ftp;
2229671Slinton     register Lineno i, j;
2239671Slinton     Boolean foundfile;
2249671Slinton 
2259671Slinton     if (nlhdr.nlines == 0) {
2269671Slinton 	return NOADDR;
2279671Slinton     }
2289671Slinton     if (name == nil) {
2299671Slinton 	name = cursource;
2309671Slinton     }
2319671Slinton     foundfile = false;
2329671Slinton     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
2339671Slinton 	if (streq(ftp->filename, name)) {
2349671Slinton 	    foundfile = true;
2359671Slinton 	    i = ftp->lineindex;
2369671Slinton 	    if (ftp == &filetab[nlhdr.nfiles-1]) {
2379671Slinton 		j = nlhdr.nlines;
2389671Slinton 	    } else {
2399671Slinton 		j = (ftp + 1)->lineindex;
2409671Slinton 	    }
2419671Slinton 	    while (i < j) {
2429671Slinton 		if (linetab[i].line == line) {
2439671Slinton 		    return linetab[i].addr;
2449671Slinton 		}
2459671Slinton 		i++;
2469671Slinton 	    }
2479671Slinton 	}
2489671Slinton     }
2499671Slinton     if (not foundfile) {
25018224Slinton 	error("source file \"%s\" not compiled with -g", name);
2519671Slinton     }
2529671Slinton     return NOADDR;
2539671Slinton }
2549671Slinton 
2559671Slinton /*
2569671Slinton  * Table for going from object addresses to the functions in which they belong.
2579671Slinton  */
2589671Slinton 
25918224Slinton #define NFUNCS 500	/* initial size of function table */
2609671Slinton 
26114439Slinton typedef struct {
26214439Slinton     Symbol func;
26314439Slinton     Address addr;
26414439Slinton } AddrOfFunc;
26514439Slinton 
26618224Slinton private AddrOfFunc *functab;
26718224Slinton private int nfuncs = 0;
26818224Slinton private int functablesize = 0;
2699671Slinton 
2709671Slinton /*
2719671Slinton  * Insert a new function into the table.
2729671Slinton  */
2739671Slinton 
newfunc(f,addr)27414439Slinton public newfunc(f, addr)
2759671Slinton Symbol f;
27614439Slinton Address addr;
2779671Slinton {
27814439Slinton     register AddrOfFunc *af;
27918224Slinton     register int i;
28018224Slinton     AddrOfFunc *newfunctab;
28114439Slinton 
28218224Slinton     if (nfuncs >= functablesize) {
28318224Slinton 	if (functablesize == 0) {
28418224Slinton 	    functab = newarr(AddrOfFunc, NFUNCS);
28518224Slinton 	    functablesize = NFUNCS;
28618224Slinton 	} else {
28718224Slinton 	    functablesize *= 2;
28818224Slinton 	    newfunctab = newarr(AddrOfFunc, functablesize);
28918224Slinton 	    bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc));
29018224Slinton 	    dispose(functab);
29118224Slinton 	    functab = newfunctab;
29218224Slinton 	}
2939671Slinton     }
29414439Slinton     af = &functab[nfuncs];
29514439Slinton     af->func = f;
29614439Slinton     af->addr = addr;
2979671Slinton     ++nfuncs;
2989671Slinton }
2999671Slinton 
3009671Slinton /*
3019671Slinton  * Return the function that begins at the given address.
3029671Slinton  */
3039671Slinton 
whatblock(addr)3049671Slinton public Symbol whatblock(addr)
3059671Slinton Address addr;
3069671Slinton {
3079671Slinton     register int i, j, k;
3089671Slinton     Address a;
3099671Slinton 
3109671Slinton     i = 0;
3119671Slinton     j = nfuncs - 1;
31214439Slinton     if (addr < functab[i].addr) {
3139671Slinton 	return program;
31414439Slinton     } else if (addr == functab[i].addr) {
31514439Slinton 	return functab[i].func;
31614439Slinton     } else if (addr >= functab[j].addr) {
31714439Slinton 	return functab[j].func;
3189671Slinton     }
3199671Slinton     while (i <= j) {
3209671Slinton 	k = (i + j) / 2;
32114439Slinton 	a = functab[k].addr;
3229671Slinton 	if (a == addr) {
32314439Slinton 	    return functab[k].func;
3249671Slinton 	} else if (addr > a) {
3259671Slinton 	    i = k+1;
3269671Slinton 	} else {
3279671Slinton 	    j = k-1;
3289671Slinton 	}
3299671Slinton     }
33014439Slinton     if (addr > functab[i].addr) {
33114439Slinton 	return functab[i].func;
3329671Slinton     } else {
33314439Slinton 	return functab[i-1].func;
3349671Slinton     }
3359671Slinton     /* NOTREACHED */
3369671Slinton }
3379671Slinton 
3389671Slinton /*
3399671Slinton  * Order the functab.
3409671Slinton  */
3419671Slinton 
cmpfunc(f1,f2)3429671Slinton private int cmpfunc(f1, f2)
34314439Slinton AddrOfFunc *f1, *f2;
3449671Slinton {
3459671Slinton     register Address a1, a2;
3469671Slinton 
34714439Slinton     a1 = (*f1).addr;
34814439Slinton     a2 = (*f2).addr;
3499671Slinton     return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) );
3509671Slinton }
3519671Slinton 
ordfunctab()3529671Slinton public ordfunctab()
3539671Slinton {
35414439Slinton     qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc);
3559671Slinton }
3569671Slinton 
3579671Slinton /*
3589671Slinton  * Clear out the functab, used when re-reading the object information.
3599671Slinton  */
3609671Slinton 
clrfunctab()3619671Slinton public clrfunctab()
3629671Slinton {
3639671Slinton     nfuncs = 0;
3649671Slinton }
36512541Scsvaf 
dumpfunctab()36612541Scsvaf public dumpfunctab()
36712541Scsvaf {
36814439Slinton     int i;
36912541Scsvaf 
37014439Slinton     for (i = 0; i < nfuncs; i++) {
37114439Slinton 	psym(functab[i].func);
37214439Slinton     }
37312541Scsvaf }
374