xref: /csrg-svn/old/dbx/mappings.c (revision 38105)
121611Sdist /*
2*38105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3*38105Sbostic  * All rights reserved.
4*38105Sbostic  *
5*38105Sbostic  * Redistribution and use in source and binary forms are permitted
6*38105Sbostic  * provided that the above copyright notice and this paragraph are
7*38105Sbostic  * duplicated in all such forms and that any documentation,
8*38105Sbostic  * advertising materials, and other materials related to such
9*38105Sbostic  * distribution and use acknowledge that the software was developed
10*38105Sbostic  * by the University of California, Berkeley.  The name of the
11*38105Sbostic  * University may not be used to endorse or promote products derived
12*38105Sbostic  * from this software without specific prior written permission.
13*38105Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*38105Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*38105Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621611Sdist  */
179671Slinton 
1821611Sdist #ifndef lint
19*38105Sbostic static char sccsid[] = "@(#)mappings.c	5.4 (Berkeley) 05/23/89";
20*38105Sbostic #endif /* not lint */
219671Slinton 
229671Slinton /*
239671Slinton  * Source-to-object and vice versa mappings.
249671Slinton  */
259671Slinton 
269671Slinton #include "defs.h"
279671Slinton #include "mappings.h"
289671Slinton #include "symbols.h"
299671Slinton #include "source.h"
309671Slinton #include "object.h"
319671Slinton #include "machine.h"
329671Slinton 
339671Slinton #ifndef public
349671Slinton #include "machine.h"
359671Slinton #include "source.h"
369671Slinton #include "symbols.h"
379671Slinton 
389671Slinton typedef struct {
399671Slinton     Address addr;
409671Slinton     String filename;
419671Slinton     Lineno lineindex;		/* index to first linetab entry */
429671Slinton } Filetab;
439671Slinton 
449671Slinton typedef struct {
459671Slinton     Lineno line;
469671Slinton     Address addr;
479671Slinton } Linetab;
489671Slinton 
499671Slinton Filetab *filetab;
509671Slinton Linetab *linetab;
519671Slinton 
529671Slinton #define NOADDR ((Address) -1)	/* no address for line or procedure */
539671Slinton 
549671Slinton #endif
559671Slinton 
569671Slinton /*
579671Slinton  * Get the source file name associated with a given address.
589671Slinton  */
599671Slinton 
609671Slinton public String srcfilename(addr)
619671Slinton Address addr;
629671Slinton {
639671Slinton     register Address i, j, k;
649671Slinton     Address a;
659671Slinton     Filetab *ftp;
669671Slinton     String s;
679671Slinton 
689671Slinton     s = nil;
699671Slinton     if (nlhdr.nfiles != 0 and addr >= filetab[0].addr) {
709671Slinton 	i = 0;
719671Slinton 	j = nlhdr.nfiles - 1;
729671Slinton 	while (i < j) {
739671Slinton 	    k = (i + j) / 2;
749671Slinton 	    ftp = &filetab[k];
759671Slinton 	    a = ftp->addr;
769671Slinton 	    if (a == addr) {
779671Slinton 		s = ftp->filename;
789671Slinton 		break;
799671Slinton 	    } else if (addr > a) {
809671Slinton 		i = k + 1;
819671Slinton 	    } else {
829671Slinton 		j = k - 1;
839671Slinton 	    }
849671Slinton 	}
859671Slinton 	if (s == nil) {
869671Slinton 	    if (addr >= filetab[i].addr) {
879671Slinton 		s = filetab[i].filename;
889671Slinton 	    } else {
899671Slinton 		s = filetab[i-1].filename;
909671Slinton 	    }
919671Slinton 	}
929671Slinton     }
939671Slinton     return s;
949671Slinton }
959671Slinton 
969671Slinton /*
979671Slinton  * Find the line associated with the given address.
989671Slinton  * If the second parameter is true, then the address must match
999671Slinton  * a source line exactly.  Otherwise the nearest source line
10018224Slinton  * below the given address is returned.
10118224Slinton  *
10218224Slinton  * Return the index of the line table entry or -1 if none suitable.
1039671Slinton  */
1049671Slinton 
10518224Slinton private integer findline (addr, exact)
1069671Slinton Address addr;
1079671Slinton Boolean exact;
1089671Slinton {
1099671Slinton     register Address i, j, k;
1109671Slinton     register Lineno r;
1119671Slinton     register Address a;
1129671Slinton 
11333324Sdonn     if (nlhdr.nlines == 0 or addr < linetab[0].addr) {
11418224Slinton 	r = -1;
1159671Slinton     } else {
1169671Slinton 	i = 0;
1179671Slinton 	j = nlhdr.nlines - 1;
1189671Slinton 	if (addr == linetab[i].addr) {
11918224Slinton 	    r = i;
1209671Slinton 	} else if (addr == linetab[j].addr) {
12118224Slinton 	    r = j;
1229671Slinton 	} else if (addr > linetab[j].addr) {
12318224Slinton 	    r = exact ? -1 : j;
1249671Slinton 	} else {
1259671Slinton 	    do {
1269671Slinton 		k = (i + j) div 2;
1279671Slinton 		a = linetab[k].addr;
1289671Slinton 	    if (a == addr) break;
1299671Slinton 		if (addr > a) {
1309671Slinton 		    i = k + 1;
1319671Slinton 		} else {
1329671Slinton 		    j = k - 1;
1339671Slinton 		}
1349671Slinton 	    } while (i <= j);
1359671Slinton 	    if (a == addr) {
13618224Slinton 		r = k;
1379671Slinton 	    } else if (exact) {
13818224Slinton 		r = -1;
1399671Slinton 	    } else if (addr > linetab[i].addr) {
14018224Slinton 		r = i;
1419671Slinton 	    } else {
14218224Slinton 		r = i - 1;
1439671Slinton 	    }
1449671Slinton 	}
1459671Slinton     }
1469671Slinton     return r;
1479671Slinton }
1489671Slinton 
1499671Slinton /*
15018224Slinton  * Lookup the source line number nearest (from below) to an address.
15118224Slinton  *
15218224Slinton  * It is possible (unfortunately) that the compiler will generate
15318224Slinton  * code before line number for a procedure.  Therefore we check
15418224Slinton  * to see that the found line is in the same procedure as the given address.
15518224Slinton  * If it isn't, then we walk forward until the first suitable line is found.
1569671Slinton  */
1579671Slinton 
15833324Sdonn public Lineno srcline (addr)
1599671Slinton Address addr;
1609671Slinton {
16133324Sdonn     Lineno i, r;
16218224Slinton     Symbol f1, f2;
16333324Sdonn     Address a;
16418224Slinton 
16518224Slinton     i = findline(addr, false);
16618224Slinton     if (i == -1) {
16733324Sdonn 	f1 = whatblock(addr);
16833324Sdonn 	if (f1 == nil or nosource(f1)) {
16933324Sdonn 	    r = 0;
17033324Sdonn 	} else {
17133324Sdonn 	    a = codeloc(f1);
17233324Sdonn 	    for (;;) {
17333324Sdonn 		r = linelookup(a);
17433324Sdonn 		if (r != 0 or a >= CODESTART + objsize) {
17533324Sdonn 		    break;
17633324Sdonn 		}
17733324Sdonn 		++a;
17833324Sdonn 	    }
17933324Sdonn 	}
18018224Slinton     } else {
18118224Slinton 	r = linetab[i].line;
18218224Slinton 	if (linetab[i].addr != addr) {
18318224Slinton 	    f1 = whatblock(addr);
18418224Slinton 	    if (nosource(f1)) {
18518224Slinton 		r = 0;
18618224Slinton 	    } else {
18718224Slinton 		f2 = whatblock(linetab[i].addr + 1);
18818224Slinton 		if (f1 != f2) {
18918224Slinton 		    do {
19018224Slinton 			++i;
19118224Slinton 		    } while (linetab[i].addr < addr and i < nlhdr.nlines);
19218224Slinton 		    r = linetab[i].line;
19318224Slinton 		}
19418224Slinton 	    }
19518224Slinton 	}
19618224Slinton     }
19718224Slinton     return r;
1989671Slinton }
1999671Slinton 
2009671Slinton /*
2019671Slinton  * Look for a line exactly corresponding to the given address.
2029671Slinton  */
2039671Slinton 
2049671Slinton public Lineno linelookup(addr)
2059671Slinton Address addr;
2069671Slinton {
20718224Slinton     integer i;
20818224Slinton     Lineno r;
20918224Slinton 
21018224Slinton     i = findline(addr, true);
21118224Slinton     if (i == -1) {
21218224Slinton 	r = 0;
21318224Slinton     } else {
21418224Slinton 	r = linetab[i].line;
21518224Slinton     }
21618224Slinton     return r;
2179671Slinton }
2189671Slinton 
2199671Slinton /*
2209671Slinton  * Lookup the object address of a given line from the named file.
2219671Slinton  *
2229671Slinton  * Potentially all files in the file table need to be checked
2239671Slinton  * until the line is found since a particular file name may appear
2249671Slinton  * more than once in the file table (caused by includes).
2259671Slinton  */
2269671Slinton 
2279671Slinton public Address objaddr(line, name)
2289671Slinton Lineno line;
2299671Slinton String name;
2309671Slinton {
2319671Slinton     register Filetab *ftp;
2329671Slinton     register Lineno i, j;
2339671Slinton     Boolean foundfile;
2349671Slinton 
2359671Slinton     if (nlhdr.nlines == 0) {
2369671Slinton 	return NOADDR;
2379671Slinton     }
2389671Slinton     if (name == nil) {
2399671Slinton 	name = cursource;
2409671Slinton     }
2419671Slinton     foundfile = false;
2429671Slinton     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
2439671Slinton 	if (streq(ftp->filename, name)) {
2449671Slinton 	    foundfile = true;
2459671Slinton 	    i = ftp->lineindex;
2469671Slinton 	    if (ftp == &filetab[nlhdr.nfiles-1]) {
2479671Slinton 		j = nlhdr.nlines;
2489671Slinton 	    } else {
2499671Slinton 		j = (ftp + 1)->lineindex;
2509671Slinton 	    }
2519671Slinton 	    while (i < j) {
2529671Slinton 		if (linetab[i].line == line) {
2539671Slinton 		    return linetab[i].addr;
2549671Slinton 		}
2559671Slinton 		i++;
2569671Slinton 	    }
2579671Slinton 	}
2589671Slinton     }
2599671Slinton     if (not foundfile) {
26018224Slinton 	error("source file \"%s\" not compiled with -g", name);
2619671Slinton     }
2629671Slinton     return NOADDR;
2639671Slinton }
2649671Slinton 
2659671Slinton /*
2669671Slinton  * Table for going from object addresses to the functions in which they belong.
2679671Slinton  */
2689671Slinton 
26918224Slinton #define NFUNCS 500	/* initial size of function table */
2709671Slinton 
27114439Slinton typedef struct {
27214439Slinton     Symbol func;
27314439Slinton     Address addr;
27414439Slinton } AddrOfFunc;
27514439Slinton 
27618224Slinton private AddrOfFunc *functab;
27718224Slinton private int nfuncs = 0;
27818224Slinton private int functablesize = 0;
2799671Slinton 
2809671Slinton /*
2819671Slinton  * Insert a new function into the table.
2829671Slinton  */
2839671Slinton 
28414439Slinton public newfunc(f, addr)
2859671Slinton Symbol f;
28614439Slinton Address addr;
2879671Slinton {
28814439Slinton     register AddrOfFunc *af;
28918224Slinton     register int i;
29018224Slinton     AddrOfFunc *newfunctab;
29114439Slinton 
29218224Slinton     if (nfuncs >= functablesize) {
29318224Slinton 	if (functablesize == 0) {
29418224Slinton 	    functab = newarr(AddrOfFunc, NFUNCS);
29518224Slinton 	    functablesize = NFUNCS;
29618224Slinton 	} else {
29718224Slinton 	    functablesize *= 2;
29818224Slinton 	    newfunctab = newarr(AddrOfFunc, functablesize);
29918224Slinton 	    bcopy(functab, newfunctab, nfuncs * sizeof(AddrOfFunc));
30018224Slinton 	    dispose(functab);
30118224Slinton 	    functab = newfunctab;
30218224Slinton 	}
3039671Slinton     }
30414439Slinton     af = &functab[nfuncs];
30514439Slinton     af->func = f;
30614439Slinton     af->addr = addr;
3079671Slinton     ++nfuncs;
3089671Slinton }
3099671Slinton 
3109671Slinton /*
3119671Slinton  * Return the function that begins at the given address.
3129671Slinton  */
3139671Slinton 
3149671Slinton public Symbol whatblock(addr)
3159671Slinton Address addr;
3169671Slinton {
3179671Slinton     register int i, j, k;
3189671Slinton     Address a;
3199671Slinton 
3209671Slinton     i = 0;
3219671Slinton     j = nfuncs - 1;
32214439Slinton     if (addr < functab[i].addr) {
3239671Slinton 	return program;
32414439Slinton     } else if (addr == functab[i].addr) {
32514439Slinton 	return functab[i].func;
32614439Slinton     } else if (addr >= functab[j].addr) {
32714439Slinton 	return functab[j].func;
3289671Slinton     }
3299671Slinton     while (i <= j) {
3309671Slinton 	k = (i + j) / 2;
33114439Slinton 	a = functab[k].addr;
3329671Slinton 	if (a == addr) {
33314439Slinton 	    return functab[k].func;
3349671Slinton 	} else if (addr > a) {
3359671Slinton 	    i = k+1;
3369671Slinton 	} else {
3379671Slinton 	    j = k-1;
3389671Slinton 	}
3399671Slinton     }
34014439Slinton     if (addr > functab[i].addr) {
34114439Slinton 	return functab[i].func;
3429671Slinton     } else {
34314439Slinton 	return functab[i-1].func;
3449671Slinton     }
3459671Slinton     /* NOTREACHED */
3469671Slinton }
3479671Slinton 
3489671Slinton /*
3499671Slinton  * Order the functab.
3509671Slinton  */
3519671Slinton 
3529671Slinton private int cmpfunc(f1, f2)
35314439Slinton AddrOfFunc *f1, *f2;
3549671Slinton {
3559671Slinton     register Address a1, a2;
3569671Slinton 
35714439Slinton     a1 = (*f1).addr;
35814439Slinton     a2 = (*f2).addr;
3599671Slinton     return ( (a1 < a2) ? -1 : ( (a1 == a2) ? 0 : 1 ) );
3609671Slinton }
3619671Slinton 
3629671Slinton public ordfunctab()
3639671Slinton {
36414439Slinton     qsort(functab, nfuncs, sizeof(AddrOfFunc), cmpfunc);
3659671Slinton }
3669671Slinton 
3679671Slinton /*
3689671Slinton  * Clear out the functab, used when re-reading the object information.
3699671Slinton  */
3709671Slinton 
3719671Slinton public clrfunctab()
3729671Slinton {
3739671Slinton     nfuncs = 0;
3749671Slinton }
37512541Scsvaf 
37612541Scsvaf public dumpfunctab()
37712541Scsvaf {
37814439Slinton     int i;
37912541Scsvaf 
38014439Slinton     for (i = 0; i < nfuncs; i++) {
38114439Slinton 	psym(functab[i].func);
38214439Slinton     }
38312541Scsvaf }
384