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