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