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