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