GDB (API)
/home/stan/gdb/src/gdb/mipsread.c
Go to the documentation of this file.
00001 /* Read a symbol table in MIPS' format (Third-Eye).
00002 
00003    Copyright (C) 1986-2013 Free Software Foundation, Inc.
00004 
00005    Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU.  Major work
00006    by Per Bothner, John Gilmore and Ian Lance Taylor at Cygnus Support.
00007 
00008    This file is part of GDB.
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 3 of the License, or
00013    (at your option) any later version.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00022 
00023 /* Read symbols from an ECOFF file.  Most of the work is done in
00024    mdebugread.c.  */
00025 
00026 #include "defs.h"
00027 #include "gdb_string.h"
00028 #include "bfd.h"
00029 #include "symtab.h"
00030 #include "objfiles.h"
00031 #include "buildsym.h"
00032 #include "stabsread.h"
00033 
00034 #include "coff/sym.h"
00035 #include "coff/internal.h"
00036 #include "coff/ecoff.h"
00037 #include "libcoff.h"            /* Private BFD COFF information.  */
00038 #include "libecoff.h"           /* Private BFD ECOFF information.  */
00039 #include "elf/common.h"
00040 #include "elf/internal.h"
00041 #include "elf/mips.h"
00042 
00043 #include "psymtab.h"
00044 
00045 static void
00046 read_alphacoff_dynamic_symtab (struct section_offsets *,
00047                                struct objfile *objfile);
00048 
00049 /* Initialize anything that needs initializing when a completely new
00050    symbol file is specified (not just adding some symbols from another
00051    file, e.g. a shared library).  */
00052 
00053 static void
00054 mipscoff_new_init (struct objfile *ignore)
00055 {
00056   stabsread_new_init ();
00057   buildsym_new_init ();
00058 }
00059 
00060 /* Initialize to read a symbol file (nothing to do).  */
00061 
00062 static void
00063 mipscoff_symfile_init (struct objfile *objfile)
00064 {
00065 }
00066 
00067 /* Read a symbol file from a file.  */
00068 
00069 static void
00070 mipscoff_symfile_read (struct objfile *objfile, int symfile_flags)
00071 {
00072   bfd *abfd = objfile->obfd;
00073   struct cleanup *back_to;
00074 
00075   init_minimal_symbol_collection ();
00076   back_to = make_cleanup_discard_minimal_symbols ();
00077 
00078   /* Now that the executable file is positioned at symbol table,
00079      process it and define symbols accordingly.  */
00080 
00081   if (!((*ecoff_backend (abfd)->debug_swap.read_debug_info)
00082         (abfd, (asection *) NULL, &ecoff_data (abfd)->debug_info)))
00083     error (_("Error reading symbol table: %s"), bfd_errmsg (bfd_get_error ()));
00084 
00085   mdebug_build_psymtabs (objfile, &ecoff_backend (abfd)->debug_swap,
00086                          &ecoff_data (abfd)->debug_info);
00087 
00088   /* Add alpha coff dynamic symbols.  */
00089 
00090   read_alphacoff_dynamic_symtab (objfile->section_offsets, objfile);
00091 
00092   /* Install any minimal symbols that have been collected as the current
00093      minimal symbols for this objfile.  */
00094 
00095   install_minimal_symbols (objfile);
00096   do_cleanups (back_to);
00097 }
00098 
00099 /* Perform any local cleanups required when we are done with a
00100    particular objfile.  */
00101 
00102 static void
00103 mipscoff_symfile_finish (struct objfile *objfile)
00104 {
00105 }
00106 
00107 /* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a
00108    standard COFF section.  The ELF format for the symbols differs from
00109    the format defined in elf/external.h.  It seems that a normal ELF
00110    32-bit format is used, and the representation only changes because
00111    longs are 64-bit on the alpha.  In addition, the handling of
00112    text/data section indices for symbols is different from the ELF
00113    ABI.  As the BFD linker currently does not support dynamic linking
00114    on the alpha, there seems to be no reason to pollute BFD with
00115    another mixture of object file formats for now.  */
00116 
00117 /* Format of an alpha external ELF symbol.  */
00118 
00119 typedef struct
00120 {
00121   unsigned char st_name[4];     /* Symbol name, index in string table.  */
00122   unsigned char st_pad[4];      /* Pad to long word boundary.  */
00123   unsigned char st_value[8];    /* Value of the symbol.  */
00124   unsigned char st_size[4];     /* Associated symbol size.  */
00125   unsigned char st_info[1];     /* Type and binding attributes.  */
00126   unsigned char st_other[1];    /* No defined meaning, 0.  */
00127   unsigned char st_shndx[2];    /* Associated section index.  */
00128 } Elfalpha_External_Sym;
00129 
00130 /* Format of an alpha external ELF dynamic info structure.  */
00131 
00132 typedef struct
00133 {
00134   unsigned char d_tag[4];       /* Tag.  */
00135   unsigned char d_pad[4];       /* Pad to long word boundary.  */
00136   union
00137   {
00138     unsigned char d_ptr[8];     /* Pointer value.  */
00139     unsigned char d_val[4];     /* Integer value.  */
00140   }
00141   d_un;
00142 } Elfalpha_External_Dyn;
00143 
00144 /* Struct to obtain the section pointers for alpha dynamic symbol info.  */
00145 
00146 struct alphacoff_dynsecinfo
00147 {
00148   asection *sym_sect;           /* Section pointer for .dynsym section.  */
00149   asection *str_sect;           /* Section pointer for .dynstr section.  */
00150   asection *dyninfo_sect;       /* Section pointer for .dynamic section.  */
00151   asection *got_sect;           /* Section pointer for .got section.  */
00152 };
00153 
00154 /* We are called once per section from read_alphacoff_dynamic_symtab.
00155    We need to examine each section we are passed, check to see if it
00156    is something we are interested in processing, and if so, stash away
00157    some access information for the section.  */
00158 
00159 static void
00160 alphacoff_locate_sections (bfd *ignore_abfd, asection *sectp, void *sip)
00161 {
00162   struct alphacoff_dynsecinfo *si;
00163 
00164   si = (struct alphacoff_dynsecinfo *) sip;
00165 
00166   if (strcmp (sectp->name, ".dynsym") == 0)
00167     si->sym_sect = sectp;
00168   else if (strcmp (sectp->name, ".dynstr") == 0)
00169     si->str_sect = sectp;
00170   else if (strcmp (sectp->name, ".dynamic") == 0)
00171     si->dyninfo_sect = sectp;
00172   else if (strcmp (sectp->name, ".got") == 0)
00173       si->got_sect = sectp;
00174 }
00175 
00176 /* Scan an alpha dynamic symbol table for symbols of interest and add
00177    them to the minimal symbol table.  */
00178 
00179 static void
00180 read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets,
00181                                struct objfile *objfile)
00182 {
00183   bfd *abfd = objfile->obfd;
00184   struct alphacoff_dynsecinfo si;
00185   char *sym_secptr;
00186   char *str_secptr;
00187   char *dyninfo_secptr;
00188   char *got_secptr;
00189   bfd_size_type sym_secsize;
00190   bfd_size_type str_secsize;
00191   bfd_size_type dyninfo_secsize;
00192   bfd_size_type got_secsize;
00193   int sym_count;
00194   int i;
00195   int stripped;
00196   Elfalpha_External_Sym *x_symp;
00197   char *dyninfo_p;
00198   char *dyninfo_end;
00199   int got_entry_size = 8;
00200   int dt_mips_local_gotno = -1;
00201   int dt_mips_gotsym = -1;
00202   struct cleanup *cleanups;
00203 
00204   /* We currently only know how to handle alpha dynamic symbols.  */
00205   if (bfd_get_arch (abfd) != bfd_arch_alpha)
00206     return;
00207 
00208   /* Locate the dynamic symbols sections and read them in.  */
00209   memset ((char *) &si, 0, sizeof (si));
00210   bfd_map_over_sections (abfd, alphacoff_locate_sections, (void *) & si);
00211   if (si.sym_sect == NULL || si.str_sect == NULL
00212       || si.dyninfo_sect == NULL || si.got_sect == NULL)
00213     return;
00214 
00215   sym_secsize = bfd_get_section_size (si.sym_sect);
00216   str_secsize = bfd_get_section_size (si.str_sect);
00217   dyninfo_secsize = bfd_get_section_size (si.dyninfo_sect);
00218   got_secsize = bfd_get_section_size (si.got_sect);
00219   sym_secptr = xmalloc (sym_secsize);
00220   cleanups = make_cleanup (xfree, sym_secptr);
00221   str_secptr = xmalloc (str_secsize);
00222   make_cleanup (xfree, str_secptr);
00223   dyninfo_secptr = xmalloc (dyninfo_secsize);
00224   make_cleanup (xfree, dyninfo_secptr);
00225   got_secptr = xmalloc (got_secsize);
00226   make_cleanup (xfree, got_secptr);
00227 
00228   if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
00229                                  (file_ptr) 0, sym_secsize))
00230     {
00231       do_cleanups (cleanups);
00232       return;
00233     }
00234   if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
00235                                  (file_ptr) 0, str_secsize))
00236     {
00237       do_cleanups (cleanups);
00238       return;
00239     }
00240   if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
00241                                  (file_ptr) 0, dyninfo_secsize))
00242     {
00243       do_cleanups (cleanups);
00244       return;
00245     }
00246   if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
00247                                  (file_ptr) 0, got_secsize))
00248     {
00249       do_cleanups (cleanups);
00250       return;
00251     }
00252 
00253   /* Find the number of local GOT entries and the index for the
00254      first dynamic symbol in the GOT.  */
00255   for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize;
00256        dyninfo_p < dyninfo_end;
00257        dyninfo_p += sizeof (Elfalpha_External_Dyn))
00258     {
00259       Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p;
00260       long dyn_tag;
00261 
00262       dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
00263       if (dyn_tag == DT_NULL)
00264         break;
00265       else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
00266         {
00267           if (dt_mips_local_gotno < 0)
00268             dt_mips_local_gotno
00269               = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
00270         }
00271       else if (dyn_tag == DT_MIPS_GOTSYM)
00272         {
00273           if (dt_mips_gotsym < 0)
00274             dt_mips_gotsym
00275               = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
00276         }
00277     }
00278   if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
00279     {
00280       do_cleanups (cleanups);
00281       return;
00282     }
00283 
00284   /* Scan all dynamic symbols and enter them into the minimal symbol
00285      table if appropriate.  */
00286   sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
00287   stripped = (bfd_get_symcount (abfd) == 0);
00288 
00289   /* Skip first symbol, which is a null dummy.  */
00290   for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
00291        i < sym_count;
00292        i++, x_symp++)
00293     {
00294       unsigned long strx;
00295       char *name;
00296       bfd_vma sym_value;
00297       unsigned char sym_info;
00298       unsigned int sym_shndx;
00299       int isglobal;
00300       enum minimal_symbol_type ms_type;
00301 
00302       strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
00303       if (strx >= str_secsize)
00304         continue;
00305       name = str_secptr + strx;
00306       if (*name == '\0' || *name == '.')
00307         continue;
00308 
00309       sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
00310       sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
00311       sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
00312       if (sym_shndx >= (SHN_LORESERVE & 0xffff))
00313         sym_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
00314       isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);
00315 
00316       if (sym_shndx == SHN_UNDEF)
00317         {
00318           /* Handle undefined functions which are defined in a shared
00319              library.  */
00320           if (ELF_ST_TYPE (sym_info) != STT_FUNC
00321               || ELF_ST_BIND (sym_info) != STB_GLOBAL)
00322             continue;
00323 
00324           ms_type = mst_solib_trampoline;
00325 
00326           /* If sym_value is nonzero, it points to the shared library
00327              trampoline entry, which is what we are looking for.
00328 
00329              If sym_value is zero, then we have to get the GOT entry
00330              for the symbol.
00331 
00332              If the GOT entry is nonzero, it represents the quickstart
00333              address of the function and we use that as the symbol
00334              value.
00335 
00336              If the GOT entry is zero, the function address has to be
00337              resolved by the runtime loader before the executable is
00338              started.  We are unable to find any meaningful address
00339              for these functions in the executable file, so we skip
00340              them.  */
00341           if (sym_value == 0)
00342             {
00343               int got_entry_offset =
00344                 (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;
00345 
00346               if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
00347                 continue;
00348               sym_value =
00349                 bfd_h_get_64 (abfd,
00350                               (bfd_byte *) (got_secptr + got_entry_offset));
00351               if (sym_value == 0)
00352                 continue;
00353             }
00354         }
00355       else
00356         {
00357           /* Symbols defined in the executable itself.  We only care
00358              about them if this is a stripped executable, otherwise
00359              they have been retrieved from the normal symbol table
00360              already.  */
00361           if (!stripped)
00362             continue;
00363 
00364           if (sym_shndx == SHN_MIPS_TEXT)
00365             {
00366               if (isglobal)
00367                 ms_type = mst_text;
00368               else
00369                 ms_type = mst_file_text;
00370               sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
00371             }
00372           else if (sym_shndx == SHN_MIPS_DATA)
00373             {
00374               if (isglobal)
00375                 ms_type = mst_data;
00376               else
00377                 ms_type = mst_file_data;
00378               sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile));
00379             }
00380           else if (sym_shndx == SHN_MIPS_ACOMMON)
00381             {
00382               if (isglobal)
00383                 ms_type = mst_bss;
00384               else
00385                 ms_type = mst_file_bss;
00386               sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile));
00387             }
00388           else if (sym_shndx == SHN_ABS)
00389             {
00390               ms_type = mst_abs;
00391             }
00392           else
00393             {
00394               continue;
00395             }
00396         }
00397 
00398       prim_record_minimal_symbol (name, sym_value, ms_type, objfile);
00399     }
00400 
00401   do_cleanups (cleanups);
00402 }
00403 
00404 /* Initialization.  */
00405 
00406 static const struct sym_fns ecoff_sym_fns =
00407 {
00408   mipscoff_new_init,            /* init anything gbl to entire symtab */
00409   mipscoff_symfile_init,        /* read initial info, setup for sym_read() */
00410   mipscoff_symfile_read,        /* read a symbol file into symtab */
00411   NULL,                         /* sym_read_psymbols */
00412   mipscoff_symfile_finish,      /* finished with file, cleanup */
00413   default_symfile_offsets,      /* dummy FIXME til implem sym reloc */
00414   default_symfile_segments,     /* Get segment information from a file.  */
00415   NULL,
00416   default_symfile_relocate,     /* Relocate a debug section.  */
00417   NULL,                         /* sym_probe_fns */
00418   &psym_functions
00419 };
00420 
00421 /* Provide a prototype to silence -Wmissing-prototypes.  */
00422 void _initialize_mipsread (void);
00423 
00424 void
00425 _initialize_mipsread (void)
00426 {
00427   add_symtab_fns (bfd_target_ecoff_flavour, &ecoff_sym_fns);
00428 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines