]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gdb/gdb/mipsread.c
This commit was generated by cvs2svn to compensate for changes in r37510,
[FreeBSD/FreeBSD.git] / contrib / gdb / gdb / mipsread.c
1 /* Read a symbol table in MIPS' format (Third-Eye).
2    Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "gdb_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 alpha coff dynamic symbols.  */
112
113   read_alphacoff_dynamic_symtab (section_offsets, objfile);
114
115   /* Install any minimal symbols that have been collected as the current
116      minimal symbols for this objfile. */
117
118   install_minimal_symbols (objfile);
119
120   /* If the entry_file bounds are still unknown after processing the
121      partial symbols, then try to set them from the minimal symbols
122      surrounding the entry_point.  */
123
124   if (mainline
125       && objfile->ei.entry_point != INVALID_ENTRY_POINT
126       && objfile->ei.entry_file_lowpc == INVALID_ENTRY_LOWPC)
127     {
128       struct minimal_symbol *m;
129
130       m = lookup_minimal_symbol_by_pc (objfile->ei.entry_point);
131       if (m && SYMBOL_NAME (m + 1))
132         {
133           objfile->ei.entry_file_lowpc = SYMBOL_VALUE_ADDRESS (m);
134           objfile->ei.entry_file_highpc = SYMBOL_VALUE_ADDRESS (m + 1);
135         }
136     }
137
138   do_cleanups (back_to);
139 }
140
141 /* Perform any local cleanups required when we are done with a
142    particular objfile.  */
143
144 static void
145 mipscoff_symfile_finish (objfile)
146      struct objfile *objfile;
147 {
148 }
149
150 /* Fake up identical offsets for all sections.  */
151
152 static struct section_offsets *
153 mipscoff_symfile_offsets (objfile, addr)
154      struct objfile *objfile;
155      CORE_ADDR addr;
156 {
157   struct section_offsets *section_offsets;
158   int i;
159
160   objfile->num_sections = SECT_OFF_MAX;
161   section_offsets = ((struct section_offsets *)
162                      obstack_alloc (&objfile->psymbol_obstack,
163                                     (sizeof (struct section_offsets)
164                                      + (sizeof (section_offsets->offsets)
165                                         * (SECT_OFF_MAX - 1)))));
166
167   for (i = 0; i < SECT_OFF_MAX; i++)
168     ANOFFSET (section_offsets, i) = addr;
169
170   return section_offsets;
171 }
172
173 /* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a
174    standard coff section.  The ELF format for the symbols differs from
175    the format defined in elf/external.h. It seems that a normal ELF 32 bit
176    format is used, and the representation only changes because longs are
177    64 bit on the alpha. In addition, the handling of text/data section
178    indices for symbols is different from the ELF ABI.
179    As the BFD linker currently does not support dynamic linking on the alpha,
180    there seems to be no reason to pollute BFD with another mixture of object
181    file formats for now.  */
182
183 /* Format of an alpha external ELF symbol.  */
184
185 typedef struct {
186   unsigned char st_name[4];             /* Symbol name, index in string tbl */
187   unsigned char st_pad[4];              /* Pad to long word boundary */
188   unsigned char st_value[8];            /* Value of the symbol */
189   unsigned char st_size[4];             /* Associated symbol size */
190   unsigned char st_info[1];             /* Type and binding attributes */
191   unsigned char st_other[1];            /* No defined meaning, 0 */
192   unsigned char st_shndx[2];            /* Associated section index */
193 } Elfalpha_External_Sym;
194
195 /* Format of an alpha external ELF dynamic info structure.  */
196
197 typedef struct {
198   unsigned char d_tag[4];               /* Tag */
199   unsigned char d_pad[4];               /* Pad to long word boundary */
200   union {
201     unsigned char d_ptr[8];             /* Pointer value */
202     unsigned char d_val[4];             /* Integer value */
203   } d_un;
204 } Elfalpha_External_Dyn;
205
206 /* Struct to obtain the section pointers for alpha dynamic symbol info.  */
207
208 struct alphacoff_dynsecinfo {
209   asection *sym_sect;           /* Section pointer for .dynsym section */
210   asection *str_sect;           /* Section pointer for .dynstr section */
211   asection *dyninfo_sect;       /* Section pointer for .dynamic section */
212   asection *got_sect;           /* Section pointer for .got section */
213 };
214
215 static void
216 alphacoff_locate_sections PARAMS ((bfd *, asection *, void *));
217
218 /* We are called once per section from read_alphacoff_dynamic_symtab.
219    We need to examine each section we are passed, check to see
220    if it is something we are interested in processing, and
221    if so, stash away some access information for the section.  */
222
223 static void
224 alphacoff_locate_sections (ignore_abfd, sectp, sip)
225      bfd *ignore_abfd;
226      asection *sectp;
227      PTR sip;
228 {
229   register struct alphacoff_dynsecinfo *si;
230
231   si = (struct alphacoff_dynsecinfo *) sip;
232
233   if (STREQ (sectp->name, ".dynsym"))
234     {
235       si->sym_sect = sectp;
236     }
237   else if (STREQ (sectp->name, ".dynstr"))
238     {
239       si->str_sect = sectp;
240     }
241   else if (STREQ (sectp->name, ".dynamic"))
242     {
243       si->dyninfo_sect = sectp;
244     }
245   else if (STREQ (sectp->name, ".got"))
246     {
247       si->got_sect = sectp;
248     }
249 }
250
251 /* Scan an alpha dynamic symbol table for symbols of interest and
252    add them to the minimal symbol table.  */
253
254 static void
255 read_alphacoff_dynamic_symtab (section_offsets, objfile)
256      struct section_offsets *section_offsets;
257      struct objfile *objfile;
258 {
259   bfd *abfd = objfile->obfd;
260   struct alphacoff_dynsecinfo si;
261   char *sym_secptr;
262   char *str_secptr;
263   char *dyninfo_secptr;
264   char *got_secptr;
265   bfd_size_type sym_secsize;
266   bfd_size_type str_secsize;
267   bfd_size_type dyninfo_secsize;
268   bfd_size_type got_secsize;
269   int sym_count;
270   int i;
271   int stripped;
272   Elfalpha_External_Sym *x_symp;
273   char *dyninfo_p;
274   char *dyninfo_end;
275   int got_entry_size = 8;
276   int dt_mips_local_gotno = -1;
277   int dt_mips_gotsym = -1;
278
279
280   /* We currently only know how to handle alpha dynamic symbols.  */
281   if (bfd_get_arch (abfd) != bfd_arch_alpha)
282     return;
283
284   /* Locate the dynamic symbols sections and read them in.  */
285   memset ((char *) &si, 0, sizeof (si));
286   bfd_map_over_sections (abfd, alphacoff_locate_sections, (PTR) &si);
287   if (si.sym_sect == NULL
288       || si.str_sect == NULL
289       || si.dyninfo_sect == NULL
290       || si.got_sect == NULL)
291     return;
292
293   sym_secsize = bfd_get_section_size_before_reloc (si.sym_sect);
294   str_secsize = bfd_get_section_size_before_reloc (si.str_sect);
295   dyninfo_secsize = bfd_get_section_size_before_reloc (si.dyninfo_sect);
296   got_secsize = bfd_get_section_size_before_reloc (si.got_sect);
297   sym_secptr = alloca (sym_secsize);
298   str_secptr = alloca (str_secsize);
299   dyninfo_secptr = alloca (dyninfo_secsize);
300   got_secptr = alloca (got_secsize);
301
302   if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
303                                  (file_ptr)0, sym_secsize))
304     return;
305   if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
306                                  (file_ptr)0, str_secsize))
307     return;
308   if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
309                                  (file_ptr)0, dyninfo_secsize))
310     return;
311   if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
312                                  (file_ptr)0, got_secsize))
313     return;
314
315   /* Find the number of local GOT entries and the index for the
316      the first dynamic symbol in the GOT. */
317   for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize;
318        dyninfo_p < dyninfo_end;
319        dyninfo_p += sizeof (Elfalpha_External_Dyn))
320     {
321       Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *)dyninfo_p;
322       long dyn_tag;
323
324       dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
325       if (dyn_tag == DT_NULL)
326         break;
327       else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
328         {
329           if (dt_mips_local_gotno < 0)
330             dt_mips_local_gotno
331               = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
332         }
333       else if (dyn_tag == DT_MIPS_GOTSYM)
334         {
335           if (dt_mips_gotsym < 0)
336             dt_mips_gotsym
337               = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
338         }
339     }
340   if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
341     return;
342
343   /* Scan all dynamic symbols and enter them into the minimal symbol table
344      if appropriate.  */
345   sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
346   stripped = (bfd_get_symcount (abfd) == 0);
347
348   /* Skip first symbol, which is a null dummy.  */
349   for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
350        i < sym_count;
351        i++, x_symp++)
352     {
353       unsigned long strx;
354       char *name;
355       bfd_vma sym_value;
356       unsigned char sym_info;
357       unsigned int sym_shndx;
358       int isglobal;
359       enum minimal_symbol_type ms_type;
360
361       strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
362       if (strx >= str_secsize)
363         continue;
364       name = str_secptr + strx;
365       if (*name == '\0' || *name == '.')
366         continue;
367
368       sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
369       sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
370       sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
371       isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);
372
373       if (sym_shndx == SHN_UNDEF)
374         {
375           /* Handle undefined functions which are defined in a shared
376              library.  */
377           if (ELF_ST_TYPE (sym_info) != STT_FUNC
378               || ELF_ST_BIND (sym_info) != STB_GLOBAL)
379             continue;
380
381           ms_type = mst_solib_trampoline;
382
383           /* If sym_value is nonzero, it points to the shared library
384              trampoline entry, which is what we are looking for.
385
386              If sym_value is zero, then we have to get the GOT entry
387              for the symbol.
388              If the GOT entry is nonzero, it represents the quickstart
389              address of the function and we use that as the symbol value.
390
391              If the GOT entry is zero, the function address has to be resolved
392              by the runtime loader before the executable is started.
393              We are unable to find any meaningful address for these
394              functions in the executable file, so we skip them.  */
395           if (sym_value == 0)
396             {
397               int got_entry_offset =
398                 (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;
399
400               if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
401                 continue;
402               sym_value =
403                 bfd_h_get_64 (abfd,
404                               (bfd_byte *) (got_secptr + got_entry_offset));
405               if (sym_value == 0)
406                 continue;
407             }
408         }
409       else
410         {
411           /* Symbols defined in the executable itself. We only care about
412              them if this is a stripped executable, otherwise they have
413              been retrieved from the normal symbol table already.  */
414           if (!stripped)
415             continue;
416
417           if (sym_shndx == SHN_MIPS_TEXT)
418             {
419               if (isglobal)
420                 ms_type = mst_text;
421               else
422                 ms_type = mst_file_text;
423               sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
424             }
425           else if (sym_shndx == SHN_MIPS_DATA)
426             {
427               if (isglobal)
428                 ms_type = mst_data;
429               else
430                 ms_type = mst_file_data;
431               sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA);
432             }
433           else if (sym_shndx == SHN_MIPS_ACOMMON)
434             {
435               if (isglobal)
436                 ms_type = mst_bss;
437               else
438                 ms_type = mst_file_bss;
439               sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS);
440             }
441           else if (sym_shndx == SHN_ABS)
442             {
443               ms_type = mst_abs;
444             }
445           else
446             {
447               continue;
448             }
449         }
450
451       prim_record_minimal_symbol (obsavestring (name,
452                                                 strlen (name),
453                                                 &objfile -> symbol_obstack),
454                                   sym_value,
455                                   ms_type,
456                                   objfile);
457     }
458 }
459
460 /* Initialization */
461
462 static struct sym_fns ecoff_sym_fns =
463 {
464   bfd_target_ecoff_flavour,
465   mipscoff_new_init,            /* sym_new_init: init anything gbl to entire symtab */
466   mipscoff_symfile_init,        /* sym_init: read initial info, setup for sym_read() */
467   mipscoff_symfile_read,        /* sym_read: read a symbol file into symtab */
468   mipscoff_symfile_finish,      /* sym_finish: finished with file, cleanup */
469   mipscoff_symfile_offsets,     /* sym_offsets: dummy FIXME til implem sym reloc */
470   NULL                          /* next: pointer to next struct sym_fns */
471 };
472
473 void
474 _initialize_mipsread ()
475 {
476   add_symtab_fns (&ecoff_sym_fns);
477 }