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