home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gdb-4.14-src.lha / gdb-4.14 / gdb / mipsread.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-06  |  13.5 KB  |  458 lines

  1. /* Read a symbol table in MIPS' format (Third-Eye).
  2.    Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994
  3.    Free Software Foundation, Inc.
  4.    Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU.  Major work
  5.    by Per Bothner, John Gilmore and Ian Lance Taylor at Cygnus Support.
  6.  
  7. This file is part of GDB.
  8.  
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  22.  
  23. /* Read symbols from an ECOFF file.  Most of the work is done in
  24.    mdebugread.c.  */
  25.  
  26. #include "defs.h"
  27. #include <string.h>
  28. #include "bfd.h"
  29. #include "symtab.h"
  30. #include "symfile.h"
  31. #include "objfiles.h"
  32. #include "buildsym.h"
  33. #include "stabsread.h"
  34. #include "gdb-stabs.h"
  35.  
  36. #include "coff/sym.h"
  37. #include "coff/internal.h"
  38. #include "coff/ecoff.h"
  39. #include "libcoff.h"        /* Private BFD COFF information.  */
  40. #include "libecoff.h"        /* Private BFD ECOFF information.  */
  41. #include "elf/common.h"
  42. #include "elf/mips.h"
  43.  
  44. static void
  45. mipscoff_new_init PARAMS ((struct objfile *));
  46.  
  47. static void
  48. mipscoff_symfile_init PARAMS ((struct objfile *));
  49.  
  50. static void
  51. mipscoff_symfile_read PARAMS ((struct objfile *, struct section_offsets *,
  52.                    int));
  53.  
  54. static void
  55. mipscoff_symfile_finish PARAMS ((struct objfile *));
  56.  
  57. static struct section_offsets *
  58. mipscoff_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
  59.  
  60. static void
  61. read_alphacoff_dynamic_symtab PARAMS ((struct section_offsets *,
  62.                        struct objfile *objfile));
  63.  
  64. /* Initialize anything that needs initializing when a completely new
  65.    symbol file is specified (not just adding some symbols from another
  66.    file, e.g. a shared library).  */
  67.  
  68. extern CORE_ADDR sigtramp_address;
  69.  
  70. static void
  71. mipscoff_new_init (ignore)
  72.      struct objfile *ignore;
  73. {
  74.   sigtramp_address = 0;
  75.   stabsread_new_init ();
  76.   buildsym_new_init ();
  77. }
  78.  
  79. /* Initialize to read a symbol file (nothing to do).  */
  80.  
  81. static void
  82. mipscoff_symfile_init (objfile)
  83.      struct objfile *objfile;
  84. {
  85. }
  86.  
  87. /* Read a symbol file from a file.  */
  88.  
  89. static void
  90. mipscoff_symfile_read (objfile, section_offsets, mainline)
  91.      struct objfile *objfile;
  92.      struct section_offsets *section_offsets;
  93.      int mainline;
  94. {
  95.   bfd *abfd = objfile->obfd;
  96.   struct cleanup * back_to;
  97.  
  98.   init_minimal_symbol_collection ();
  99.   back_to = make_cleanup (discard_minimal_symbols, 0);
  100.  
  101.   /* Now that the executable file is positioned at symbol table,
  102.      process it and define symbols accordingly.  */
  103.  
  104.   if (!((*ecoff_backend (abfd)->debug_swap.read_debug_info)
  105.     (abfd, (asection *) NULL, &ecoff_data (abfd)->debug_info)))
  106.     error ("Error reading symbol table: %s", bfd_errmsg (bfd_get_error ()));
  107.  
  108.   mdebug_build_psymtabs (objfile, &ecoff_backend (abfd)->debug_swap,
  109.              &ecoff_data (abfd)->debug_info, section_offsets);
  110.  
  111.   /* Add the dynamic symbols if we are reading the main symbol table.  */
  112.  
  113.   if (mainline)
  114.     read_alphacoff_dynamic_symtab (section_offsets, objfile);
  115.  
  116.   /* Install any minimal symbols that have been collected as the current
  117.      minimal symbols for this objfile. */
  118.  
  119.   install_minimal_symbols (objfile);
  120.  
  121.   do_cleanups (back_to);
  122. }
  123.  
  124. /* Perform any local cleanups required when we are done with a
  125.    particular objfile.  */
  126.  
  127. static void
  128. mipscoff_symfile_finish (objfile)
  129.      struct objfile *objfile;
  130. {
  131. }
  132.  
  133. /* Fake up identical offsets for all sections.  */
  134.  
  135. static struct section_offsets *
  136. mipscoff_symfile_offsets (objfile, addr)
  137.      struct objfile *objfile;
  138.      CORE_ADDR addr;
  139. {
  140.   struct section_offsets *section_offsets;
  141.   int i;
  142.  
  143.   objfile->num_sections = SECT_OFF_MAX;
  144.   section_offsets = ((struct section_offsets *)
  145.              obstack_alloc (&objfile->psymbol_obstack,
  146.                     (sizeof (struct section_offsets)
  147.                      + (sizeof (section_offsets->offsets)
  148.                     * (SECT_OFF_MAX - 1)))));
  149.  
  150.   for (i = 0; i < SECT_OFF_MAX; i++)
  151.     ANOFFSET (section_offsets, i) = addr;
  152.  
  153.   return section_offsets;
  154. }
  155.  
  156. /* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a
  157.    standard coff section.  The ELF format for the symbols differs from
  158.    the format defined in elf/external.h. It seems that a normal ELF 32 bit
  159.    format is used, and the representation only changes because longs are
  160.    64 bit on the alpha. In addition, the handling of text/data section
  161.    indices for symbols is different from the ELF ABI.
  162.    As the BFD linker currently does not support dynamic linking on the alpha,
  163.    there seems to be no reason to pollute BFD with another mixture of object
  164.    file formats for now.  */
  165.  
  166. /* Format of an alpha external ELF symbol.  */
  167.  
  168. typedef struct {
  169.   unsigned char    st_name[4];        /* Symbol name, index in string tbl */
  170.   unsigned char    st_pad[4];        /* Pad to long word boundary */
  171.   unsigned char    st_value[8];        /* Value of the symbol */
  172.   unsigned char    st_size[4];        /* Associated symbol size */
  173.   unsigned char    st_info[1];        /* Type and binding attributes */
  174.   unsigned char    st_other[1];        /* No defined meaning, 0 */
  175.   unsigned char    st_shndx[2];        /* Associated section index */
  176. } Elfalpha_External_Sym;
  177.  
  178. /* Format of an alpha external ELF dynamic info structure.  */
  179.  
  180. typedef struct {
  181.   unsigned char    d_tag[4];        /* Tag */
  182.   unsigned char    d_pad[4];        /* Pad to long word boundary */
  183.   union {
  184.     unsigned char d_ptr[8];        /* Pointer value */
  185.     unsigned char d_val[4];        /* Integer value */
  186.   } d_un;
  187. } Elfalpha_External_Dyn;
  188.  
  189. /* Struct to obtain the section pointers for alpha dynamic symbol info.  */
  190.  
  191. struct alphacoff_dynsecinfo {
  192.   asection *sym_sect;        /* Section pointer for .dynsym section */
  193.   asection *str_sect;        /* Section pointer for .dynstr section */
  194.   asection *dyninfo_sect;    /* Section pointer for .dynamic section */
  195.   asection *got_sect;        /* Section pointer for .got section */
  196. };
  197.  
  198. static void
  199. alphacoff_locate_sections PARAMS ((bfd *, asection *, void *));
  200.  
  201. /* We are called once per section from read_alphacoff_dynamic_symtab.
  202.    We need to examine each section we are passed, check to see
  203.    if it is something we are interested in processing, and
  204.    if so, stash away some access information for the section.  */
  205.  
  206. static void
  207. alphacoff_locate_sections (ignore_abfd, sectp, sip)
  208.      bfd *ignore_abfd;
  209.      asection *sectp;
  210.      PTR sip;
  211. {
  212.   register struct alphacoff_dynsecinfo *si;
  213.  
  214.   si = (struct alphacoff_dynsecinfo *) sip;
  215.  
  216.   if (STREQ (sectp->name, ".dynsym"))
  217.     {
  218.       si->sym_sect = sectp;
  219.     }
  220.   else if (STREQ (sectp->name, ".dynstr"))
  221.     {
  222.       si->str_sect = sectp;
  223.     }
  224.   else if (STREQ (sectp->name, ".dynamic"))
  225.     {
  226.       si->dyninfo_sect = sectp;
  227.     }
  228.   else if (STREQ (sectp->name, ".got"))
  229.     {
  230.       si->got_sect = sectp;
  231.     }
  232. }
  233.  
  234. /* Scan an alpha dynamic symbol table for symbols of interest and
  235.    add them to the minimal symbol table.  */
  236.  
  237. static void
  238. read_alphacoff_dynamic_symtab (section_offsets, objfile)
  239.      struct section_offsets *section_offsets;
  240.      struct objfile *objfile;
  241. {
  242.   bfd *abfd = objfile->obfd;
  243.   struct alphacoff_dynsecinfo si;
  244.   char *sym_secptr;
  245.   char *str_secptr;
  246.   char *dyninfo_secptr;
  247.   char *got_secptr;
  248.   bfd_size_type sym_secsize;
  249.   bfd_size_type str_secsize;
  250.   bfd_size_type dyninfo_secsize;
  251.   bfd_size_type got_secsize;
  252.   int sym_count;
  253.   int i;
  254.   int stripped;
  255.   Elfalpha_External_Sym *x_symp;
  256.   char *dyninfo_p;
  257.   char *dyninfo_end;
  258.   int got_entry_size = 8;
  259.   int dt_mips_local_gotno = -1;
  260.   int dt_mips_gotsym = -1;
  261.  
  262.  
  263.   /* We currently only know how to handle alpha dynamic symbols.  */
  264.   if (bfd_get_arch (abfd) != bfd_arch_alpha)
  265.     return;
  266.  
  267.   /* Locate the dynamic symbols sections and read them in.  */
  268.   memset ((char *) &si, 0, sizeof (si));
  269.   bfd_map_over_sections (abfd, alphacoff_locate_sections, (PTR) &si);
  270.   if (si.sym_sect == NULL
  271.       || si.str_sect == NULL
  272.       || si.dyninfo_sect == NULL
  273.       || si.got_sect == NULL)
  274.     return;
  275.  
  276.   sym_secsize = bfd_get_section_size_before_reloc (si.sym_sect);
  277.   str_secsize = bfd_get_section_size_before_reloc (si.str_sect);
  278.   dyninfo_secsize = bfd_get_section_size_before_reloc (si.dyninfo_sect);
  279.   got_secsize = bfd_get_section_size_before_reloc (si.got_sect);
  280.   sym_secptr = alloca (sym_secsize);
  281.   str_secptr = alloca (str_secsize);
  282.   dyninfo_secptr = alloca (dyninfo_secsize);
  283.   got_secptr = alloca (got_secsize);
  284.  
  285.   if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
  286.                  (file_ptr)0, sym_secsize))
  287.     return;
  288.   if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
  289.                  (file_ptr)0, str_secsize))
  290.     return;
  291.   if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
  292.                  (file_ptr)0, dyninfo_secsize))
  293.     return;
  294.   if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
  295.                  (file_ptr)0, got_secsize))
  296.     return;
  297.  
  298.   /* Find the number of local GOT entries and the index for the
  299.      the first dynamic symbol in the GOT. */
  300.   for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize;
  301.        dyninfo_p < dyninfo_end;
  302.        dyninfo_p += sizeof (Elfalpha_External_Dyn))
  303.     {
  304.       Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *)dyninfo_p;
  305.       long dyn_tag;
  306.  
  307.       dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
  308.       if (dyn_tag == DT_NULL)
  309.     break;
  310.       else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
  311.     {
  312.       dt_mips_local_gotno = bfd_h_get_32 (abfd,
  313.                           (bfd_byte *) x_dynp->d_un.d_val);
  314.     }
  315.       else if (dyn_tag == DT_MIPS_GOTSYM)
  316.     {
  317.       dt_mips_gotsym = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
  318.     }
  319.     }
  320.   if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
  321.     return;
  322.  
  323.   /* Scan all dynamic symbols and enter them into the minimal symbol table
  324.      if appropriate.  */
  325.   sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
  326.   stripped = (bfd_get_symcount (abfd) == 0);
  327.  
  328.   /* Skip first symbol, which is a null dummy.  */
  329.   for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
  330.        i < sym_count;
  331.        i++, x_symp++)
  332.     {
  333.       unsigned long strx;
  334.       char *name;
  335.       bfd_vma sym_value;
  336.       unsigned char sym_info;
  337.       unsigned int sym_shndx;
  338.       int isglobal;
  339.       enum minimal_symbol_type ms_type;
  340.  
  341.       strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
  342.       if (strx >= str_secsize)
  343.     continue;
  344.       name = str_secptr + strx;
  345.       if (*name == '\0' || *name == '.')
  346.     continue;
  347.  
  348.       sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
  349.       sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
  350.       sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
  351.       isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);
  352.  
  353.       if (sym_shndx == SHN_UNDEF)
  354.     {
  355.       /* Handle undefined functions which are defined in a shared
  356.          library.  */
  357.       if (ELF_ST_TYPE (sym_info) != STT_FUNC
  358.           || ELF_ST_BIND (sym_info) != STB_GLOBAL)
  359.         continue;
  360.  
  361.       ms_type = mst_solib_trampoline;
  362.  
  363.       /* If sym_value is nonzero, it points to the shared library
  364.          trampoline entry, which is what we are looking for.
  365.  
  366.          If sym_value is zero, then we have to get the GOT entry
  367.          for the symbol.
  368.          If the GOT entry is nonzero, it represents the quickstart
  369.          address of the function and we use that as the symbol value.
  370.  
  371.          If the GOT entry is zero, the function address has to be resolved
  372.          by the runtime loader before the executable is started.
  373.          We are unable to find any meaningful address for these
  374.          functions in the executable file, so we skip them.  */
  375.       if (sym_value == 0)
  376.         {
  377.           int got_entry_offset =
  378.         (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;
  379.  
  380.           if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
  381.         continue;
  382.           sym_value =
  383.         bfd_h_get_64 (abfd,
  384.                   (bfd_byte *) (got_secptr + got_entry_offset));
  385.           if (sym_value == 0)
  386.         continue;
  387.         }
  388.     }
  389.       else
  390.     {
  391.       /* Symbols defined in the executable itself. We only care about
  392.          them if this is a stripped executable, otherwise they have
  393.          been retrieved from the normal symbol table already.  */
  394.       if (!stripped)
  395.         continue;
  396.  
  397.       if (sym_shndx == SHN_MIPS_TEXT)
  398.         {
  399.           if (isglobal)
  400.         ms_type = mst_text;
  401.           else
  402.         ms_type = mst_file_text;
  403.           sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
  404.         }
  405.       else if (sym_shndx == SHN_MIPS_DATA)
  406.         {
  407.           if (isglobal)
  408.         ms_type = mst_data;
  409.           else
  410.         ms_type = mst_file_data;
  411.           sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA);
  412.         }
  413.       else if (sym_shndx == SHN_MIPS_ACOMMON)
  414.         {
  415.           if (isglobal)
  416.         ms_type = mst_bss;
  417.           else
  418.         ms_type = mst_file_bss;
  419.           sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS);
  420.         }
  421.       else if (sym_shndx == SHN_ABS)
  422.         {
  423.           ms_type = mst_abs;
  424.         }
  425.       else
  426.         {
  427.           continue;
  428.         }
  429.     }
  430.  
  431.       prim_record_minimal_symbol (obsavestring (name,
  432.                         strlen (name),
  433.                         &objfile -> symbol_obstack),
  434.                   sym_value,
  435.                   ms_type,
  436.                   objfile);
  437.     }
  438. }
  439.  
  440. /* Initialization */
  441.  
  442. static struct sym_fns ecoff_sym_fns =
  443. {
  444.   bfd_target_ecoff_flavour,
  445.   mipscoff_new_init,        /* sym_new_init: init anything gbl to entire symtab */
  446.   mipscoff_symfile_init,    /* sym_init: read initial info, setup for sym_read() */
  447.   mipscoff_symfile_read,    /* sym_read: read a symbol file into symtab */
  448.   mipscoff_symfile_finish,    /* sym_finish: finished with file, cleanup */
  449.   mipscoff_symfile_offsets,    /* sym_offsets: dummy FIXME til implem sym reloc */
  450.   NULL                /* next: pointer to next struct sym_fns */
  451. };
  452.  
  453. void
  454. _initialize_mipsread ()
  455. {
  456.   add_symtab_fns (&ecoff_sym_fns);
  457. }
  458.