xref: /csrg-svn/old/dbx/mappings.c (revision 33324)
121611Sdist /*
221611Sdist  * Copyright (c) 1983 Regents of the University of California.
321611Sdist  * All rights reserved.  The Berkeley software License Agreement
421611Sdist  * specifies the terms and conditions for redistribution.
521611Sdist  */
69671Slinton 
721611Sdist #ifndef lint
8*33324Sdonn static char sccsid[] = "@(#)mappings.c	5.3 (Berkeley) 01/12/88";
921611Sdist #endif not lint
109671Slinton 
11*33324Sdonn static char rcsid[] = "$Header: mappings.c,v 1.3 87/03/26 19:41:55 donn Exp $";
1218224Slinton 
139671Slinton /*
149671Slinton  * Source-to-object and vice versa mappings.
159671Slinton  */
169671Slinton 
179671Slinton #include "defs.h"
189671Slinton #include "mappings.h"
199671Slinton #include "symbols.h"
209671Slinton #include "source.h"
219671Slinton #include "object.h"
229671Slinton #include "machine.h"
239671Slinton 
249671Slinton #ifndef public
259671Slinton #include "machine.h"
269671Slinton #include "source.h"
279671Slinton #include "symbols.h"
289671Slinton 
299671Slinton typedef struct {
309671Slinton     Address addr;
319671Slinton     String filename;
329671Slinton     Lineno lineindex;		/* index to first linetab entry */
339671Slinton } Filetab;
349671Slinton 
359671Slinton typedef struct {
369671Slinton     Lineno line;
379671Slinton     Address addr;
389671Slinton } Linetab;
399671Slinton 
409671Slinton Filetab *filetab;
419671Slinton Linetab *linetab;
429671Slinton 
439671Slinton #define NOADDR ((Address) -1)	/* no address for line or procedure */
449671Slinton 
459671Slinton #endif
469671Slinton 
479671Slinton /*
489671Slinton  * Get the source file name associated with a given address.
499671Slinton  */
509671Slinton 
519671Slinton public String srcfilename(addr)
529671Slinton Address addr;
539671Slinton {
549671Slinton     register Address i, j, k;
559671Slinton     Address a;
569671Slinton     Filetab *ftp;
579671Slinton     String s;
589671Slinton 
599671Slinton     s = nil;
609671Slinton     if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) {
619671Slinton 	i = 0;
629671Slinton 	j = nlhdr.nfiles - 1;
639671Slinton 	while (i < j) {
649671Slinton 	    k = (i + j) / 2;
659671Slinton 	    ftp = &filetab[k];
669671Slinton 	    a = ftp->addr;
679671Slinton 	    if (a == addr) {
689671Slinton 		s = ftp->filename;
699671Slinton 		break;
709671Slinton 	    } else if (addr > a) {
719671Slinton 		i = k + 1;
729671Slinton 	    } else {
739671Slinton 		j = k - 1;
749671Slinton 	    }
759671Slinton 	}
769671Slinton 	if (s == nil) {
779671Slinton 	    if (addr >= filetab[i].addr) {
789671Slinton 		s = filetab[i].filename;
799671Slinton 	    } else {
809671Slinton 		s = filetab[i-1].filename;
819671Slinton 	    }
829671Slinton 	}
839671Slinton     }
849671Slinton     return s;
859671Slinton }
869671Slinton 
879671Slinton /*
889671Slinton  * Find the line associated with the given address.
899671Slinton  * If the second parameter is true, then the address must match
909671Slinton  * a source line exactly.  Otherwise the nearest source line
9118224Slinton  * below the given address is returned.
9218224Slinton  *
9318224Slinton  * Return the index of the line table entry or -1 if none suitable.
949671Slinton  */
959671Slinton 
9618224Slinton private integer findline (addr, exact)
979671Slinton Address addr;
989671Slinton Boolean exact;
999671Slinton {
1009671Slinton     register Address i, j, k;
1019671Slinton     register Lineno r;
1029671Slinton     register Address a;
1039671Slinton 
104*33324Sdonn     if (nlhdr.nlines == 0 or addr < linetab[0].addr) {
10518224Slinton 	r = -1;
1069671Slinton     } else {
1079671Slinton 	i = 0;
1089671Slinton 	j = nlhdr.nlines - 1;
1099671Slinton 	if (addr == linetab[i].addr) {
11018224Slinton 	    r = i;
1119671Slinton 	} else if (addr == linetab[j].addr) {
11218224Slinton 	    r = j;
1139671Slinton 	} else if (addr > linetab[j].addr) {
11418224Slinton 	    r = exact ? -1 : j;
1159671Slinton 	} else {
1169671Slinton 	    do {
1179671Slinton 		k = (i + j) div 2;
1189671Slinton 		a = linetab[k].addr;
1199671Slinton 	    if (a == addr) break;
1209671Slinton 		if (addr > a) {
1219671Slinton 		    i = k + 1;
1229671Slinton 		} else {
1239671Slinton 		    j = k - 1;
1249671Slinton 		}
1259671Slinton 	    } while (i <= j);
1269671Slinton 	    if (a == addr) {
12718224Slinton 		r = k;
1289671Slinton 	    } else if (exact) {
12918224Slinton 		r = -1;
1309671Slinton 	    } else if (addr > linetab[i].addr) {
13118224Slinton 		r = i;
1329671Slinton 	    } else {
13318224Slinton 		r = i - 1;
1349671Slinton 	    }
1359671Slinton 	}
1369671Slinton     }
1379671Slinton     return r;
1389671Slinton }
1399671Slinton 
1409671Slinton /*
14118224Slinton  * Lookup the source line number nearest (from below) to an address.
14218224Slinton  *
14318224Slinton  * It is possible (unfortunately) that the compiler will generate
14418224Slinton  * code before line number for a procedure.  Therefore we check
14518224Slinton  * to see that the found line is in the same procedure as the given address.
14618224Slinton  * If it isn't, then we walk forward until the first suitable line is found.
1479671Slinton  */
1489671Slinton 
149*33324Sdonn public Lineno srcline (addr)
1509671Slinton Address addr;
1519671Slinton {
152*33324Sdonn     Lineno i, r;
15318224Slinton     Symbol f1, f2;
154*33324Sdonn     Address a;
15518224Slinton 
15618224Slinton     i = findline(addr, false);
15718224Slinton     if (i == -1) {
158*33324Sdonn 	f1 = whatblock(addr);
159*33324Sdonn 	if (f1 == nil or nosource(f1)) {
160*33324Sdonn 	    r = 0;
161*33324Sdonn 	} else {
162*33324Sdonn 	    a = codeloc(f1);
163*33324Sdonn 	    for (;;) {
164*33324Sdonn 		r = linelookup(a);
165*33324Sdonn 		if (r != 0 or a >= CODESTART + objsize) {
166*33324Sdonn 		    break;
167*33324Sdonn 		}
168*33324Sdonn 		++a;
169*33324Sdonn 	    }
170*33324Sdonn 	}
17118224Slinton     } else {
17218224Slinton 	r = linetab[i].line;
17318224Slinton 	if (linetab[i].addr != addr) {
17418224Slinton 	    f1 = whatblock(addr);
17518224Slinton 	    if (nosource(f1)) {
17618224Slinton 		r = 0;
17718224Slinton 	    } else {
17818224Slinton 		f2 = whatblock(linetab[i].addr + 1);
17918224Slinton 		if (f1 != f2) {
18018224Slinton 		    do {
18118224Slinton 			++i;
18218224Slinton 		    } while (linetab[i].addr < addr and i < nlhdr.nlines);
18318224Slinton 		    r = linetab[i].line;
18418224Slinton 		}
18518224Slinton 	    }
18618224Slinton 	}
18718224Slinton     }
18818224Slinton     return r;
1899671Slinton }
1909671Slinton 
1919671Slinton /*
1929671Slinton  * Look for a line exactly corresponding to the given address.
1939671Slinton  */
1949671Slinton 
1959671Slinton public Lineno linelookup(addr)
1969671Slinton Address addr;
1979671Slinton {
19818224Slinton     integer i;
19918224Slinton     Lineno r;
20018224Slinton 
20118224Slinton     i = findline(addr, true);
20218224Slinton     if (i == -1) {
20318224Slinton 	r = 0;
20418224Slinton     } else {
20518224Slinton 	r = linetab[i].line;
20618224Slinton     }
20718224Slinton     return r;
2089671Slinton }
2099671Slinton 
2109671Slinton /*
2119671Slinton  * Lookup the object address of a given line from the named file.
2129671Slinton  *
2139671Slinton  * Potentially all files in the file table need to be checked
2149671Slinton  * until the line is found since a particular file name may appear
2159671Slinton  * more than once in the file table (caused by includes).
2169671Slinton  */
2179671Slinton 
2189671Slinton public Address objaddr(line, name)
2199671Slinton Lineno line;
2209671Slinton String name;
2219671Slinton {
2229671Slinton     register Filetab *ftp;
2239671Slinton     register Lineno i, j;
2249671Slinton     Boolean foundfile;
2259671Slinton 
2269671Slinton     if (nlhdr.nlines == 0) {
2279671Slinton 	return NOADDR;
2289671Slinton     }
2299671Slinton     if (name == nil) {
2309671Slinton 	name = cursource;
2319671Slinton     }
2329671Slinton     foundfile = false;
2339671Slinton     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
2349671Slinton 	if (streq(ftp->filename, name)) {
2359671Slinton 	    foundfile = true;
2369671Slinton 	    i = ftp->lineindex;
2379671Slinton 	    if (ftp == &filetab[nlhdr.nfiles-1]) {
2389671Slinton 		j = nlhdr.nlines;
2399671Slinton 	    } else {
2409671Slinton 		j = (ftp + 1)->lineindex;
2419671Slinton 	    }
2429671Slinton 	    while (i < j) {
2439671Slinton 		if (linetab[i].line == line) {
2449671Slinton 		    return linetab[i].addr;
2459671Slinton 		}
2469671Slinton 		i++;
2479671Slinton 	    }
2489671Slinton 	}
2499671Slinton     }
2509671Slinton     if (not foundfile) {
25118224Slinton 	error("source file \"%s\" not compiled with -g", name);
2529671Slinton     }
2539671Slinton     return NOADDR;
2549671Slinton }
2559671Slinton 
2569671Slinton /*
2579671Slinton  * Table for going from object addresses to the functions in which they belong.
2589671Slinton  */
2599671Slinton 
26018224Slinton #define NFUNCS 500	/* initial size of function table */
2619671Slinton 
26214439Slinton typedef struct {
26314439Slinton     Symbol func;
26414439Slinton     Address addr;
26514439Slinton } AddrOfFunc;
26614439Slinton 
26718224Slinton private AddrOfFunc *functab;
26818224Slinton private int nfuncs = 0;
26918224Slinton private int functablesize = 0;
2709671Slinton 
2719671Slinton /*
2729671Slinton  * Insert a new function into the table.
2739671Slinton  */
2749671Slinton 
27514439Slinton public newfunc(f, addr)
2769671Slinton Symbol f;
27714439Slinton Address addr;
2789671Slinton {
27914439Slinton     register AddrOfFunc *af;
28018224Slinton     register int i;
28118224Slinton     AddrOfFunc *newfunctab;
28214439Slinton 
28318224Slinton     if (nfuncs >= functablesize) {
28418224Slinton 	if (functablesize == 0) {
28518224Slinton 	    functab = newarr(AddrOfFunc, NFUNCS);
28618224Slinton 	    functablesize = NFUNCS;
28718224Slinton 	} else {
28818224Slinton 	    functablesize *= 2;
28918224Slinton 	    newfunctab = newarr(AddrOfFunc, functablesize);
29018224Slinton 	    bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc));
29118224Slinton 	    dispose(functab);
29218224Slinton 	    functab = newfunctab;
29318224Slinton 	}
2949671Slinton     }
29514439Slinton     af = &functab[nfuncs];
29614439Slinton     af->func = f;
29714439Slinton     af->addr = addr;
2989671Slinton     ++nfuncs;
2999671Slinton }
3009671Slinton 
3019671Slinton /*
3029671Slinton  * Return the function that begins at the given address.
3039671Slinton  */
3049671Slinton 
3059671Slinton public Symbol whatblock(addr)
3069671Slinton Address addr;
3079671Slinton {
3089671Slinton     register int i, j, k;
3099671Slinton     Address a;
3109671Slinton 
3119671Slinton     i = 0;
3129671Slinton     j = nfuncs - 1;
31314439Slinton     if (addr < functab[i].addr) {
3149671Slinton 	return program;
31514439Slinton     } else if (addr == functab[i].addr) {
31614439Slinton 	return functab[i].func;
31714439Slinton     } else if (addr >= functab[j].addr) {
31814439Slinton 	return functab[j].func;
3199671Slinton     }
3209671Slinton     while (i <= j) {
3219671Slinton 	k = (i + j) / 2;
32214439Slinton 	a = functab[k].addr;
3239671Slinton 	if (a == addr) {
32414439Slinton 	    return functab[k].func;
3259671Slinton 	} else if (addr > a) {
3269671Slinton 	    i = k+1;
3279671Slinton 	} else {
3289671Slinton 	    j = k-1;
3299671Slinton 	}
3309671Slinton     }
33114439Slinton     if (addr > functab[i].addr) {
33214439Slinton 	return functab[i].func;
3339671Slinton     } else {
33414439Slinton 	return functab[i-1].func;
3359671Slinton     }
3369671Slinton     /* NOTREACHED */
3379671Slinton }
3389671Slinton 
3399671Slinton /*
3409671Slinton  * Order the functab.
3419671Slinton  */
3429671Slinton 
3439671Slinton private int cmpfunc(f1, f2)
34414439Slinton AddrOfFunc *f1, *f2;
3459671Slinton {
3469671Slinton     register Address a1, a2;
3479671Slinton 
34814439Slinton     a1 = (*f1).addr;
34914439Slinton     a2 = (*f2).addr;
3509671Slinton     return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) );
3519671Slinton }
3529671Slinton 
3539671Slinton public ordfunctab()
3549671Slinton {
35514439Slinton     qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc);
3569671Slinton }
3579671Slinton 
3589671Slinton /*
3599671Slinton  * Clear out the functab, used when re-reading the object information.
3609671Slinton  */
3619671Slinton 
3629671Slinton public clrfunctab()
3639671Slinton {
3649671Slinton     nfuncs = 0;
3659671Slinton }
36612541Scsvaf 
36712541Scsvaf public dumpfunctab()
36812541Scsvaf {
36914439Slinton     int i;
37012541Scsvaf 
37114439Slinton     for (i = 0; i < nfuncs; i++) {
37214439Slinton 	psym(functab[i].func);
37314439Slinton     }
37412541Scsvaf }
375