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