"I am a person who works hard and plays hard."

Yuan Wei
Second Year Graduate Student Department of Computer Science
University of Virginia Charlottesville, VA 22903
Email: yw3f@cs.virginia.edu


Source Code Analysis

Main Page   Compound List   File List   Compound Members   File Members  

symbol.c

Go to the documentation of this file.
00001 /*
00002  * symbol.c - program symbol and line data routines
00003  *
00004  * This file is a part of the SimpleScalar tool suite written by
00005  * Todd M. Austin as a part of the Multiscalar Research Project.
00006  *  
00007  * The tool suite is currently maintained by Doug Burger and Todd M. Austin.
00008  * 
00009  * Copyright (C) 1994, 1995, 1996, 1997 by Todd M. Austin
00010  *
00011  * This source file is distributed "as is" in the hope that it will be
00012  * useful.  The tool set comes with no warranty, and no author or
00013  * distributor accepts any responsibility for the consequences of its
00014  * use. 
00015  * 
00016  * Everyone is granted permission to copy, modify and redistribute
00017  * this tool set under the following conditions:
00018  * 
00019  *    This source code is distributed for non-commercial use only. 
00020  *    Please contact the maintainer for restrictions applying to 
00021  *    commercial use.
00022  *
00023  *    Permission is granted to anyone to make or distribute copies
00024  *    of this source code, either as received or modified, in any
00025  *    medium, provided that all copyright notices, permission and
00026  *    nonwarranty notices are preserved, and that the distributor
00027  *    grants the recipient permission for further redistribution as
00028  *    permitted by this document.
00029  *
00030  *    Permission is granted to distribute this file in compiled
00031  *    or executable form under the same conditions that apply for
00032  *    source code, provided that either:
00033  *
00034  *    A. it is accompanied by the corresponding machine-readable
00035  *       source code,
00036  *    B. it is accompanied by a written offer, with no time limit,
00037  *       to give anyone a machine-readable copy of the corresponding
00038  *       source code in return for reimbursement of the cost of
00039  *       distribution.  This written offer must permit verbatim
00040  *       duplication by anyone, or
00041  *    C. it is distributed by someone who received only the
00042  *       executable form, and is accompanied by a copy of the
00043  *       written offer of source code that they received concurrently.
00044  *
00045  * In other words, you are welcome to use, share and improve this
00046  * source file.  You are forbidden to forbid anyone else to use, share
00047  * and improve what you give them.
00048  *
00049  * INTERNET: dburger@cs.wisc.edu
00050  * US Mail:  1210 W. Dayton Street, Madison, WI 53706
00051  *
00052  * $Id: symbol.c,v 1.1.1.1 2000/05/26 15:22:27 taustin Exp $
00053  *
00054  * $Log: symbol.c,v $
00055  * Revision 1.1.1.1  2000/05/26 15:22:27  taustin
00056  * SimpleScalar Tool Set
00057  *
00058  *
00059  * Revision 1.1  1998/08/27 16:54:29  taustin
00060  * Initial revision
00061  *
00062  * Revision 1.1  1998/05/06  01:08:39  calder
00063  * Initial revision
00064  *
00065  * Revision 1.2  1997/04/16  22:11:50  taustin
00066  * added standalone loader support
00067  *
00068  * Revision 1.1  1997/03/11  01:34:45  taustin
00069  * Initial revision
00070  *
00071  *
00072  */
00073 
00074 #include <stdio.h>
00075 #include <stdlib.h>
00076 
00077 #include "host.h"
00078 #include "misc.h"
00079 #include "loader.h"
00080 #include "symbol.h"
00081 
00082 #ifdef BFD_LOADER
00083 #include <bfd.h>
00084 #else /* !BFD_LOADER */
00085 #include "target-alpha/ecoff.h"
00086 #endif /* BFD_LOADER */
00087 
00088 /* #define PRINT_SYMS */
00089 
00090 /* symbol database in no particular order */
00091 struct sym_sym_t *sym_db = NULL;
00092 
00093 /* all symbol sorted by address */
00094 int sym_nsyms = 0;
00095 struct sym_sym_t **sym_syms = NULL;
00096 
00097 /* all symbols sorted by name */
00098 struct sym_sym_t **sym_syms_by_name = NULL;
00099 
00100 /* text symbols sorted by address */
00101 int sym_ntextsyms = 0;
00102 struct sym_sym_t **sym_textsyms = NULL;
00103 
00104 /* text symbols sorted by name */
00105 struct sym_sym_t **sym_textsyms_by_name = NULL;
00106 
00107 /* data symbols sorted by address */
00108 int sym_ndatasyms = 0;
00109 struct sym_sym_t **sym_datasyms = NULL;
00110 
00111 /* data symbols sorted by name */
00112 struct sym_sym_t **sym_datasyms_by_name = NULL;
00113 
00114 /* symbols loaded? */
00115 static int syms_loaded = FALSE;
00116 
00117 #ifdef PRINT_SYMS
00118 /* convert BFD symbols flags to a printable string */
00119 static char *                   /* symbol flags string */
00120 flags2str(unsigned int flags)   /* bfd symbol flags */
00121 {
00122   static char buf[256];
00123   char *p;
00124 
00125   if (!flags)
00126     return "";
00127 
00128   p = buf;
00129   *p = '\0';
00130 
00131   if (flags & BSF_LOCAL)
00132     {
00133       *p++ = 'L';
00134       *p++ = '|';
00135     }
00136   if (flags & BSF_GLOBAL)
00137     {
00138       *p++ = 'G';
00139       *p++ = '|';
00140     }
00141   if (flags & BSF_DEBUGGING)
00142     {
00143       *p++ = 'D';
00144       *p++ = '|';
00145     }
00146   if (flags & BSF_FUNCTION)
00147     {
00148       *p++ = 'F';
00149       *p++ = '|';
00150     }
00151   if (flags & BSF_KEEP)
00152     {
00153       *p++ = 'K';
00154       *p++ = '|';
00155     }
00156   if (flags & BSF_KEEP_G)
00157     {
00158       *p++ = 'k'; *p++ = '|';
00159     }
00160   if (flags & BSF_WEAK)
00161     {
00162       *p++ = 'W';
00163       *p++ = '|';
00164     }
00165   if (flags & BSF_SECTION_SYM)
00166     {
00167       *p++ = 'S'; *p++ = '|';
00168     }
00169   if (flags & BSF_OLD_COMMON)
00170     {
00171       *p++ = 'O';
00172       *p++ = '|';
00173     }
00174   if (flags & BSF_NOT_AT_END)
00175     {
00176       *p++ = 'N';
00177       *p++ = '|';
00178     }
00179   if (flags & BSF_CONSTRUCTOR)
00180     {
00181       *p++ = 'C';
00182       *p++ = '|';
00183     }
00184   if (flags & BSF_WARNING)
00185     {
00186       *p++ = 'w';
00187       *p++ = '|';
00188     }
00189   if (flags & BSF_INDIRECT)
00190     {
00191       *p++ = 'I';
00192       *p++ = '|';
00193     }
00194   if (flags & BSF_FILE)
00195     {
00196       *p++ = 'f';
00197       *p++ = '|';
00198     }
00199 
00200   if (p == buf)
00201     panic("no flags detected");
00202 
00203   *--p = '\0';
00204   return buf;
00205 }
00206 #endif /* PRINT_SYMS */
00207 
00208 /* qsort helper function */
00209 static int
00210 acmp(struct sym_sym_t **sym1, struct sym_sym_t **sym2)
00211 {
00212   return (int)((*sym1)->addr - (*sym2)->addr);
00213 }
00214 
00215 /* qsort helper function */
00216 static int
00217 ncmp(struct sym_sym_t **sym1, struct sym_sym_t **sym2)
00218 {
00219   return strcmp((*sym1)->name, (*sym2)->name);
00220 }
00221 
00222 #define RELEVANT_SCOPE(SYM)                                             \
00223 (/* global symbol */                                                    \
00224  ((SYM)->flags & BSF_GLOBAL)                                            \
00225  || (/* local symbol */                                                 \
00226      (((SYM)->flags & (BSF_LOCAL|BSF_DEBUGGING)) == BSF_LOCAL)          \
00227      && (SYM)->name[0] != '$')                                          \
00228  || (/* compiler local */                                               \
00229      load_locals                                                        \
00230      && ((/* basic block idents */                                      \
00231           ((SYM)->flags&(BSF_LOCAL|BSF_DEBUGGING))==(BSF_LOCAL|BSF_DEBUGGING)\
00232           && (SYM)->name[0] == '$')                                     \
00233          || (/* local constant idents */                                \
00234              ((SYM)->flags & (BSF_LOCAL|BSF_DEBUGGING)) == (BSF_LOCAL)  \
00235              && (SYM)->name[0] == '$'))))
00236      
00237 
00238 /* load symbols out of FNAME */
00239 void
00240 sym_loadsyms(char *fname,       /* file name containing symbols */
00241              int load_locals)   /* load local symbols */
00242 {
00243   int i, debug_cnt;
00244 #ifdef BFD_LOADER
00245   bfd *abfd;
00246   asymbol **syms;
00247   int storage, i, nsyms, debug_cnt;
00248 #else /* !BFD_LOADER */
00249   int len;
00250   FILE *fobj;
00251   struct ecoff_filehdr fhdr;
00252   struct ecoff_aouthdr ahdr;
00253   struct ecoff_symhdr_t symhdr;
00254   char *strtab = NULL;
00255   struct ecoff_EXTR *extr;
00256 #endif /* BFD_LOADER */
00257 
00258   if (syms_loaded)
00259     {
00260       /* symbols are already loaded */
00261       /* FIXME: can't handle symbols from multiple files */
00262       return;
00263     }
00264 
00265 #ifdef BFD_LOADER
00266 
00267   /* load the program into memory, try both endians */
00268   if (!(abfd = bfd_openr(fname, "ss-coff-big")))
00269     if (!(abfd = bfd_openr(fname, "ss-coff-little")))
00270       fatal("cannot open executable `%s'", fname);
00271 
00272   /* this call is mainly for its side effect of reading in the sections.
00273      we follow the traditional behavior of `strings' in that we don't
00274      complain if we don't recognize a file to be an object file.  */
00275   if (!bfd_check_format(abfd, bfd_object))
00276     {
00277       bfd_close(abfd);
00278       fatal("cannot open executable `%s'", fname);
00279     }
00280 
00281   /* sanity check, endian should be the same as loader.c encountered */
00282   if (abfd->xvec->byteorder_big_p != (unsigned)ld_target_big_endian)
00283     panic("binary endian changed");
00284 
00285   if ((bfd_get_file_flags(abfd) & (HAS_SYMS|HAS_LOCALS)))
00286     {
00287       /* file has locals, read them in */
00288       storage = bfd_get_symtab_upper_bound(abfd);
00289       if (storage <= 0)
00290         fatal("HAS_SYMS is set, but `%s' still lacks symbols", fname);
00291 
00292       syms = (asymbol **)calloc(storage, 1);
00293       if (!syms)
00294         fatal("out of virtual memory");
00295 
00296       nsyms = bfd_canonicalize_symtab (abfd, syms);
00297       if (nsyms <= 0)
00298         fatal("HAS_SYMS is set, but `%s' still lacks symbols", fname);
00299 
00300       /*
00301        * convert symbols to local format
00302        */
00303 
00304       /* first count symbols */
00305       sym_ndatasyms = 0; sym_ntextsyms = 0;
00306       for (i=0; i < nsyms; i++)
00307         {
00308           asymbol *sym = syms[i];
00309 
00310           /* decode symbol type */
00311           if (/* from the data section */
00312               (!strcmp(sym->section->name, ".rdata")
00313                || !strcmp(sym->section->name, ".data")
00314                || !strcmp(sym->section->name, ".sdata")
00315                || !strcmp(sym->section->name, ".bss")
00316                || !strcmp(sym->section->name, ".sbss"))
00317               /* from a scope we are interested in */
00318               && RELEVANT_SCOPE(sym))
00319             {
00320               /* data segment symbol */
00321               sym_ndatasyms++;
00322 #ifdef PRINT_SYMS
00323               fprintf(stderr,
00324                       "+sym: %s  sect: %s  flags: %s  value: 0x%08lx\n",
00325                       sym->name, sym->section->name, flags2str(sym->flags),
00326                       sym->value + sym->section->vma);
00327 #endif /* PRINT_SYMS */
00328             }
00329           else if (/* from the text section */
00330                    !strcmp(sym->section->name, ".text")
00331                    /* from a scope we are interested in */
00332                    && RELEVANT_SCOPE(sym))
00333             {
00334               /* text segment symbol */
00335               sym_ntextsyms++;
00336 #ifdef PRINT_SYMS
00337               fprintf(stderr,
00338                       "+sym: %s  sect: %s  flags: %s  value: 0x%08lx\n",
00339                       sym->name, sym->section->name, flags2str(sym->flags),
00340                       sym->value + sym->section->vma);
00341 #endif /* PRINT_SYMS */
00342             }
00343           else
00344             {
00345               /* non-segment sections */
00346 #ifdef PRINT_SYMS
00347               fprintf(stderr,
00348                       "-sym: %s  sect: %s  flags: %s  value: 0x%08lx\n",
00349                       sym->name, sym->section->name, flags2str(sym->flags),
00350                       sym->value + sym->section->vma);
00351 #endif /* PRINT_SYMS */
00352             }
00353         }
00354       sym_nsyms = sym_ntextsyms + sym_ndatasyms;
00355       if (sym_nsyms <= 0)
00356         fatal("`%s' has no text or data symbols", fname);
00357 
00358       /* allocate symbol space */
00359       sym_db = (struct sym_sym_t *)calloc(sym_nsyms, sizeof(struct sym_sym_t));
00360       if (!sym_db)
00361         fatal("out of virtual memory");
00362 
00363       /* convert symbols to internal format */
00364       for (debug_cnt=0, i=0; i < nsyms; i++)
00365         {
00366           asymbol *sym = syms[i];
00367 
00368           /* decode symbol type */
00369           if (/* from the data section */
00370               (!strcmp(sym->section->name, ".rdata")
00371                || !strcmp(sym->section->name, ".data")
00372                || !strcmp(sym->section->name, ".sdata")
00373                || !strcmp(sym->section->name, ".bss")
00374                || !strcmp(sym->section->name, ".sbss"))
00375               /* from a scope we are interested in */
00376               && RELEVANT_SCOPE(sym))
00377             {
00378               /* data segment symbol, insert into symbol database */
00379               sym_db[debug_cnt].name = mystrdup((char *)sym->name);
00380               sym_db[debug_cnt].seg = ss_data;
00381               sym_db[debug_cnt].initialized =
00382                 (!strcmp(sym->section->name, ".rdata")
00383                  || !strcmp(sym->section->name, ".data")
00384                  || !strcmp(sym->section->name, ".sdata"));
00385               sym_db[debug_cnt].pub = (sym->flags & BSF_GLOBAL);
00386               sym_db[debug_cnt].local = (sym->name[0] == '$');
00387               sym_db[debug_cnt].addr = sym->value + sym->section->vma;
00388 
00389               debug_cnt++;
00390             }
00391           else if (/* from the text section */
00392                    !strcmp(sym->section->name, ".text")
00393                    /* from a scope we are interested in */
00394                    && RELEVANT_SCOPE(sym))
00395             {
00396               /* text segment symbol, insert into symbol database */
00397               sym_db[debug_cnt].name = mystrdup((char *)sym->name);
00398               sym_db[debug_cnt].seg = ss_text;
00399               sym_db[debug_cnt].initialized = /* seems reasonable */TRUE;
00400               sym_db[debug_cnt].pub = (sym->flags & BSF_GLOBAL);
00401               sym_db[debug_cnt].local = (sym->name[0] == '$');
00402               sym_db[debug_cnt].addr = sym->value + sym->section->vma;
00403 
00404               debug_cnt++;
00405             }
00406           else
00407             {
00408               /* non-segment sections */
00409             }
00410         }
00411       /* sanity check */
00412       if (debug_cnt != sym_nsyms)
00413         panic("could not locate all counted symbols");
00414 
00415       /* release bfd symbol storage */
00416       free(syms);
00417     }
00418 
00419   /* done with file, close if */
00420   if (!bfd_close(abfd))
00421     fatal("could not close executable `%s'", fname);
00422 
00423 #else /* !BFD_LOADER */
00424 
00425   /* load the program into memory, try both endians */
00426 #if defined(__CYGWIN32__) || defined(_MSC_VER)
00427   fobj = fopen(fname, "rb");
00428 #else
00429   fobj = fopen(fname, "r");
00430 #endif
00431   if (!fobj)
00432     fatal("cannot open executable `%s'", fname);
00433 
00434   if (fread(&fhdr, sizeof(struct ecoff_filehdr), 1, fobj) < 1)
00435     fatal("cannot read header from executable `%s'", fname);
00436 
00437   /* record endian of target */
00438   if (fhdr.f_magic != ECOFF_ALPHAMAGIC)
00439     fatal("bad magic number in executable `%s'", fname);
00440 
00441   if (fread(&ahdr, sizeof(struct ecoff_aouthdr), 1, fobj) < 1)
00442     fatal("cannot read AOUT header from executable `%s'", fname);
00443 
00444   /* seek to the beginning of the symbolic header */
00445   fseek(fobj, (long)fhdr.f_symptr, 0);
00446 
00447   if (fread(&symhdr, sizeof(struct ecoff_symhdr_t), 1, fobj) < 1)
00448     fatal("could not read symbolic header from executable `%s'", fname);
00449 
00450   if (symhdr.magic != ECOFF_magicSym)
00451     fatal("bad magic number (0x%x) in symbolic header", symhdr.magic);
00452 
00453   /* allocate space for the string table */
00454   len = symhdr.issMax + symhdr.issExtMax;
00455   strtab = (char *)calloc(len, sizeof(char));
00456   if (!strtab)
00457     fatal("out of virtual memory");
00458 
00459   /* read all the symbol names into memory */
00460   fseek(fobj, (long)symhdr.cbSsExtOffset /* cbSsOffset */, 0);
00461   if (fread(strtab, len, 1, fobj) < 0)
00462     fatal("error while reading symbol table names");
00463 
00464   /* allocate symbol space */
00465   len = symhdr.isymMax + symhdr.iextMax;
00466   if (len <= 0)
00467     fatal("`%s' has no text or data symbols", fname);
00468   sym_db = (struct sym_sym_t *)calloc(len, sizeof(struct sym_sym_t));
00469   if (!sym_db)
00470     fatal("out of virtual memory");
00471 
00472   /* allocate space for the external symbol entries */
00473   extr =
00474     (struct ecoff_EXTR *)calloc(symhdr.iextMax, sizeof(struct ecoff_EXTR));
00475   if (!extr)
00476     fatal("out of virtual memory");
00477 
00478   fseek(fobj, (long)symhdr.cbExtOffset, 0);
00479   if (fread(extr, sizeof(struct ecoff_EXTR), symhdr.iextMax, fobj) < 0)
00480     fatal("error reading external symbol entries");
00481 
00482   sym_nsyms = 0; sym_ndatasyms = 0; sym_ntextsyms = 0;
00483 
00484   /* convert symbols to internal format */
00485   for (i=0; i < symhdr.iextMax; i++)
00486     {
00487       int str_offset;
00488 
00489       str_offset = symhdr.issMax + extr[i].asym.iss;
00490 
00491 #if 0
00492       printf("ext %2d: ifd = %2d, iss = %3d, value = %8x, st = %3x, "
00493              "sc = %3x, index = %3x\n",
00494              i, extr[i].ifd,
00495              extr[i].asym.iss, extr[i].asym.value,
00496              extr[i].asym.st, extr[i].asym.sc,
00497              extr[i].asym.index);
00498       printf("       %08x %2d %2d %s\n",
00499              extr[i].asym.value,
00500              extr[i].asym.st,
00501              extr[i].asym.sc,
00502              &strtab[str_offset]);
00503 #endif
00504 
00505       switch (extr[i].asym.st)
00506         {
00507         case ECOFF_stGlobal:
00508         case ECOFF_stStatic:
00509           /* from data segment */
00510           sym_db[sym_nsyms].name = mystrdup(&strtab[str_offset]);
00511           sym_db[sym_nsyms].seg = ss_data;
00512           sym_db[sym_nsyms].initialized = /* FIXME: ??? */TRUE;
00513           sym_db[sym_nsyms].pub = /* FIXME: ??? */TRUE;
00514           sym_db[sym_nsyms].local = /* FIXME: ??? */FALSE;
00515           sym_db[sym_nsyms].addr = extr[i].asym.value;
00516           sym_nsyms++;
00517           sym_ndatasyms++;
00518           break;
00519 
00520         case ECOFF_stProc:
00521         case ECOFF_stStaticProc:
00522         case ECOFF_stLabel:
00523           /* from text segment */
00524           sym_db[sym_nsyms].name = mystrdup(&strtab[str_offset]);
00525           sym_db[sym_nsyms].seg = ss_text;
00526           sym_db[sym_nsyms].initialized = /* FIXME: ??? */TRUE;
00527           sym_db[sym_nsyms].pub = /* FIXME: ??? */TRUE;
00528           sym_db[sym_nsyms].local = /* FIXME: ??? */FALSE;
00529           sym_db[sym_nsyms].addr = extr[i].asym.value;
00530           sym_nsyms++;
00531           sym_ntextsyms++;
00532           break;
00533 
00534         default:
00535           /* FIXME: ignored... */;
00536 #if 0
00537           fprintf(stderr, "** skipping: %s...\n", &strtab[str_offset]);
00538           break;
00539 #endif
00540         }
00541     }
00542   free(extr);
00543 
00544   /* done with the executable, close it */
00545   if (fclose(fobj))
00546     fatal("could not close executable `%s'", fname);
00547 
00548 #endif /* BFD_LOADER */
00549 
00550   /*
00551    * generate various sortings
00552    */
00553 
00554   /* all symbols sorted by address and name */
00555   sym_syms =
00556     (struct sym_sym_t **)calloc(sym_nsyms, sizeof(struct sym_sym_t *));
00557   if (!sym_syms)
00558     fatal("out of virtual memory");
00559 
00560   sym_syms_by_name =
00561     (struct sym_sym_t **)calloc(sym_nsyms, sizeof(struct sym_sym_t *));
00562   if (!sym_syms_by_name)
00563     fatal("out of virtual memory");
00564 
00565   for (debug_cnt=0, i=0; i<sym_nsyms; i++)
00566     {
00567       sym_syms[debug_cnt] = &sym_db[i];
00568       sym_syms_by_name[debug_cnt] = &sym_db[i];
00569       debug_cnt++;
00570     }
00571   /* sanity check */
00572   if (debug_cnt != sym_nsyms)
00573     panic("could not locate all symbols");
00574 
00575   /* sort by address */
00576   qsort(sym_syms, sym_nsyms, sizeof(struct sym_sym_t *), (void *)acmp);
00577 
00578   /* sort by name */
00579   qsort(sym_syms_by_name, sym_nsyms, sizeof(struct sym_sym_t *), (void *)ncmp);
00580 
00581   /* text segment sorted by address and name */
00582   sym_textsyms =
00583     (struct sym_sym_t **)calloc(sym_ntextsyms, sizeof(struct sym_sym_t *));
00584   if (!sym_textsyms)
00585     fatal("out of virtual memory");
00586 
00587   sym_textsyms_by_name =
00588     (struct sym_sym_t **)calloc(sym_ntextsyms, sizeof(struct sym_sym_t *));
00589   if (!sym_textsyms_by_name)
00590     fatal("out of virtual memory");
00591 
00592   for (debug_cnt=0, i=0; i<sym_nsyms; i++)
00593     {
00594       if (sym_db[i].seg == ss_text)
00595         {
00596           sym_textsyms[debug_cnt] = &sym_db[i];
00597           sym_textsyms_by_name[debug_cnt] = &sym_db[i];
00598           debug_cnt++;
00599         }
00600     }
00601   /* sanity check */
00602   if (debug_cnt != sym_ntextsyms)
00603     panic("could not locate all text symbols");
00604 
00605   /* sort by address */
00606   qsort(sym_textsyms, sym_ntextsyms, sizeof(struct sym_sym_t *), (void *)acmp);
00607 
00608   /* sort by name */
00609   qsort(sym_textsyms_by_name, sym_ntextsyms,
00610         sizeof(struct sym_sym_t *), (void *)ncmp);
00611 
00612   /* data segment sorted by address and name */
00613   sym_datasyms =
00614     (struct sym_sym_t **)calloc(sym_ndatasyms, sizeof(struct sym_sym_t *));
00615   if (!sym_datasyms)
00616     fatal("out of virtual memory");
00617 
00618   sym_datasyms_by_name =
00619     (struct sym_sym_t **)calloc(sym_ndatasyms, sizeof(struct sym_sym_t *));
00620   if (!sym_datasyms_by_name)
00621     fatal("out of virtual memory");
00622 
00623   for (debug_cnt=0, i=0; i<sym_nsyms; i++)
00624     {
00625       if (sym_db[i].seg == ss_data)
00626         {
00627           sym_datasyms[debug_cnt] = &sym_db[i];
00628           sym_datasyms_by_name[debug_cnt] = &sym_db[i];
00629           debug_cnt++;
00630         }
00631     }
00632   /* sanity check */
00633   if (debug_cnt != sym_ndatasyms)
00634     panic("could not locate all data symbols");
00635       
00636   /* sort by address */
00637   qsort(sym_datasyms, sym_ndatasyms, sizeof(struct sym_sym_t *), (void *)acmp);
00638 
00639   /* sort by name */
00640   qsort(sym_datasyms_by_name, sym_ndatasyms,
00641         sizeof(struct sym_sym_t *), (void *)ncmp);
00642 
00643   /* compute symbol sizes */
00644   for (i=0; i<sym_ntextsyms; i++)
00645     {
00646       sym_textsyms[i]->size =
00647         (i != (sym_ntextsyms - 1)
00648          ? (sym_textsyms[i+1]->addr - sym_textsyms[i]->addr)
00649          : ((ld_text_base + ld_text_size) - sym_textsyms[i]->addr));
00650     }
00651   for (i=0; i<sym_ndatasyms; i++)
00652     {
00653       sym_datasyms[i]->size =
00654         (i != (sym_ndatasyms - 1)
00655          ? (sym_datasyms[i+1]->addr - sym_datasyms[i]->addr)
00656          : ((ld_data_base + ld_data_size) - sym_datasyms[i]->addr));
00657     }
00658 
00659   /* symbols are now available for use */
00660   syms_loaded = TRUE;
00661 }
00662 
00663 /* dump symbol SYM to output stream FD */
00664 void
00665 sym_dumpsym(struct sym_sym_t *sym,      /* symbol to display */
00666             FILE *fd)                   /* output stream */
00667 {
00668   myfprintf(fd,
00669     "sym `%s': %s seg, init-%s, pub-%s, local-%s, addr=0x%08p, size=%d\n",
00670           sym->name,
00671           sym->seg == ss_data ? "data" : "text",
00672           sym->initialized ? "y" : "n",
00673           sym->pub ? "y" : "n",
00674           sym->local ? "y" : "n",
00675           sym->addr,
00676           sym->size);
00677 }
00678 
00679 /* dump all symbols to output stream FD */
00680 void
00681 sym_dumpsyms(FILE *fd)                  /* output stream */
00682 {
00683   int i;
00684 
00685   for (i=0; i < sym_nsyms; i++)
00686     sym_dumpsym(sym_syms[i], fd);
00687 }
00688 
00689 /* dump all symbol state to output stream FD */
00690 void
00691 sym_dumpstate(FILE *fd)                 /* output stream */
00692 {
00693   int i;
00694 
00695   if (fd == NULL)
00696     fd = stderr;
00697 
00698   fprintf(fd, "** All symbols sorted by address:\n");
00699   for (i=0; i < sym_nsyms; i++)
00700     sym_dumpsym(sym_syms[i], fd);
00701 
00702   fprintf(fd, "\n** All symbols sorted by name:\n");
00703   for (i=0; i < sym_nsyms; i++)
00704     sym_dumpsym(sym_syms_by_name[i], fd);
00705 
00706   fprintf(fd, "** Text symbols sorted by address:\n");
00707   for (i=0; i < sym_ntextsyms; i++)
00708     sym_dumpsym(sym_textsyms[i], fd);
00709 
00710   fprintf(fd, "\n** Text symbols sorted by name:\n");
00711   for (i=0; i < sym_ntextsyms; i++)
00712     sym_dumpsym(sym_textsyms_by_name[i], fd);
00713 
00714   fprintf(fd, "** Data symbols sorted by address:\n");
00715   for (i=0; i < sym_ndatasyms; i++)
00716     sym_dumpsym(sym_datasyms[i], fd);
00717 
00718   fprintf(fd, "\n** Data symbols sorted by name:\n");
00719   for (i=0; i < sym_ndatasyms; i++)
00720     sym_dumpsym(sym_datasyms_by_name[i], fd);
00721 }
00722 
00723 /* bind address ADDR to a symbol in symbol database DB, the address must
00724    match exactly if EXACT is non-zero, the index of the symbol in the
00725    requested symbol database is returned in *PINDEX if the pointer is
00726    non-NULL */
00727 struct sym_sym_t *                      /* symbol found, or NULL */
00728 sym_bind_addr(md_addr_t addr,   /* address of symbol to locate */
00729               int *pindex,              /* ptr to index result var */
00730               int exact,                /* require exact address match? */
00731               enum sym_db_t db)         /* symbol database to search */
00732 {
00733   int nsyms, low, high, pos;
00734   struct sym_sym_t **syms;
00735 
00736   switch (db)
00737     {
00738     case sdb_any:
00739       syms = sym_syms;
00740       nsyms = sym_nsyms;
00741       break;
00742     case sdb_text:
00743       syms = sym_textsyms;
00744       nsyms = sym_ntextsyms;
00745       break;
00746     case sdb_data:
00747       syms = sym_datasyms;
00748       nsyms = sym_ndatasyms;
00749       break;
00750     default:
00751       panic("bogus symbol database");
00752     }
00753 
00754   /* any symbols to search? */
00755   if (!nsyms)
00756     {
00757       if (pindex)
00758         *pindex = -1;
00759       return NULL;
00760     }
00761 
00762   /* binary search symbol database (sorted by address) */
00763   low = 0;
00764   high = nsyms-1;
00765   pos = (low + high) >> 1;
00766   while (!(/* exact match */
00767            (exact && syms[pos]->addr == addr)
00768            /* in bounds match */
00769            || (!exact
00770                && syms[pos]->addr <= addr
00771                && addr < (syms[pos]->addr + MAX(1, syms[pos]->size)))))
00772     {
00773       if (addr < syms[pos]->addr)
00774         high = pos - 1;
00775       else
00776         low = pos + 1;
00777       if (high >= low)
00778         pos = (low + high) >> 1;
00779       else
00780         {
00781           if (pindex)
00782             *pindex = -1;
00783           return NULL;
00784         }
00785     }
00786 
00787   /* bound! */
00788   if (pindex)
00789     *pindex = pos;
00790   return syms[pos];
00791 }
00792 
00793 /* bind name NAME to a symbol in symbol database DB, the index of the symbol
00794    in the requested symbol database is returned in *PINDEX if the pointer is
00795    non-NULL */
00796 struct sym_sym_t *                              /* symbol found, or NULL */
00797 sym_bind_name(char *name,                       /* symbol name to locate */
00798               int *pindex,                      /* ptr to index result var */
00799               enum sym_db_t db)                 /* symbol database to search */
00800 {
00801   int nsyms, low, high, pos, cmp;
00802   struct sym_sym_t **syms;
00803 
00804   switch (db)
00805     {
00806     case sdb_any:
00807       syms = sym_syms_by_name;
00808       nsyms = sym_nsyms;
00809       break;
00810     case sdb_text:
00811       syms = sym_textsyms_by_name;
00812       nsyms = sym_ntextsyms;
00813       break;
00814     case sdb_data:
00815       syms = sym_datasyms_by_name;
00816       nsyms = sym_ndatasyms;
00817       break;
00818     default:
00819       panic("bogus symbol database");
00820     }
00821 
00822   /* any symbols to search? */
00823   if (!nsyms)
00824     {
00825       if (pindex)
00826         *pindex = -1;
00827       return NULL;
00828     }
00829 
00830   /* binary search symbol database (sorted by name) */
00831   low = 0;
00832   high = nsyms-1;
00833   pos = (low + high) >> 1;
00834   while (!(/* exact string match */!(cmp = strcmp(syms[pos]->name, name))))
00835     {
00836       if (cmp > 0)
00837         high = pos - 1;
00838       else
00839         low = pos + 1;
00840       if (high >= low)
00841         pos = (low + high) >> 1;
00842       else
00843         {
00844           if (pindex)
00845             *pindex = -1;
00846           return NULL;
00847         }
00848     }
00849 
00850   /* bound! */
00851   if (pindex)
00852     *pindex = pos;
00853   return syms[pos];
00854 }


UVa CS Department of Computer Science
School of Engineering, University of Virginia
151 Engineer's Way, P.O. Box 400740
Charlottesville, Virginia 22904-4740

(434) 982-2200  Fax: (434) 982-2214