* coffread.c: Remove redundant static declarations. Replace
[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 /* We are called once per section from read_alphacoff_dynamic_symtab.
189    We need to examine each section we are passed, check to see
190    if it is something we are interested in processing, and
191    if so, stash away some access information for the section.  */
192
193 static void
194 alphacoff_locate_sections (bfd *ignore_abfd, asection *sectp, void *sip)
195 {
196   register struct alphacoff_dynsecinfo *si;
197
198   si = (struct alphacoff_dynsecinfo *) sip;
199
200   if (STREQ (sectp->name, ".dynsym"))
201     {
202       si->sym_sect = sectp;
203     }
204   else if (STREQ (sectp->name, ".dynstr"))
205     {
206       si->str_sect = sectp;
207     }
208   else if (STREQ (sectp->name, ".dynamic"))
209     {
210       si->dyninfo_sect = sectp;
211     }
212   else if (STREQ (sectp->name, ".got"))
213     {
214       si->got_sect = sectp;
215     }
216 }
217
218 /* Scan an alpha dynamic symbol table for symbols of interest and
219    add them to the minimal symbol table.  */
220
221 static void
222 read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets,
223                                struct objfile *objfile)
224 {
225   bfd *abfd = objfile->obfd;
226   struct alphacoff_dynsecinfo si;
227   char *sym_secptr;
228   char *str_secptr;
229   char *dyninfo_secptr;
230   char *got_secptr;
231   bfd_size_type sym_secsize;
232   bfd_size_type str_secsize;
233   bfd_size_type dyninfo_secsize;
234   bfd_size_type got_secsize;
235   int sym_count;
236   int i;
237   int stripped;
238   Elfalpha_External_Sym *x_symp;
239   char *dyninfo_p;
240   char *dyninfo_end;
241   int got_entry_size = 8;
242   int dt_mips_local_gotno = -1;
243   int dt_mips_gotsym = -1;
244   struct cleanup *cleanups;
245
246
247   /* We currently only know how to handle alpha dynamic symbols.  */
248   if (bfd_get_arch (abfd) != bfd_arch_alpha)
249     return;
250
251   /* Locate the dynamic symbols sections and read them in.  */
252   memset ((char *) &si, 0, sizeof (si));
253   bfd_map_over_sections (abfd, alphacoff_locate_sections, (void *) & si);
254   if (si.sym_sect == NULL
255       || si.str_sect == NULL
256       || si.dyninfo_sect == NULL
257       || si.got_sect == NULL)
258     return;
259
260   sym_secsize = bfd_get_section_size_before_reloc (si.sym_sect);
261   str_secsize = bfd_get_section_size_before_reloc (si.str_sect);
262   dyninfo_secsize = bfd_get_section_size_before_reloc (si.dyninfo_sect);
263   got_secsize = bfd_get_section_size_before_reloc (si.got_sect);
264   sym_secptr = xmalloc (sym_secsize);
265   cleanups = make_cleanup (free, sym_secptr);
266   str_secptr = xmalloc (str_secsize);
267   make_cleanup (free, str_secptr);
268   dyninfo_secptr = xmalloc (dyninfo_secsize);
269   make_cleanup (free, dyninfo_secptr);
270   got_secptr = xmalloc (got_secsize);
271   make_cleanup (free, got_secptr);
272
273   if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
274                                  (file_ptr) 0, sym_secsize))
275     return;
276   if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
277                                  (file_ptr) 0, str_secsize))
278     return;
279   if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
280                                  (file_ptr) 0, dyninfo_secsize))
281     return;
282   if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
283                                  (file_ptr) 0, got_secsize))
284     return;
285
286   /* Find the number of local GOT entries and the index for the
287      the first dynamic symbol in the GOT. */
288   for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize;
289        dyninfo_p < dyninfo_end;
290        dyninfo_p += sizeof (Elfalpha_External_Dyn))
291     {
292       Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p;
293       long dyn_tag;
294
295       dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
296       if (dyn_tag == DT_NULL)
297         break;
298       else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
299         {
300           if (dt_mips_local_gotno < 0)
301             dt_mips_local_gotno
302               = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
303         }
304       else if (dyn_tag == DT_MIPS_GOTSYM)
305         {
306           if (dt_mips_gotsym < 0)
307             dt_mips_gotsym
308               = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
309         }
310     }
311   if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
312     return;
313
314   /* Scan all dynamic symbols and enter them into the minimal symbol table
315      if appropriate.  */
316   sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
317   stripped = (bfd_get_symcount (abfd) == 0);
318
319   /* Skip first symbol, which is a null dummy.  */
320   for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
321        i < sym_count;
322        i++, x_symp++)
323     {
324       unsigned long strx;
325       char *name;
326       bfd_vma sym_value;
327       unsigned char sym_info;
328       unsigned int sym_shndx;
329       int isglobal;
330       enum minimal_symbol_type ms_type;
331
332       strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
333       if (strx >= str_secsize)
334         continue;
335       name = str_secptr + strx;
336       if (*name == '\0' || *name == '.')
337         continue;
338
339       sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
340       sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
341       sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
342       isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);
343
344       if (sym_shndx == SHN_UNDEF)
345         {
346           /* Handle undefined functions which are defined in a shared
347              library.  */
348           if (ELF_ST_TYPE (sym_info) != STT_FUNC
349               || ELF_ST_BIND (sym_info) != STB_GLOBAL)
350             continue;
351
352           ms_type = mst_solib_trampoline;
353
354           /* If sym_value is nonzero, it points to the shared library
355              trampoline entry, which is what we are looking for.
356
357              If sym_value is zero, then we have to get the GOT entry
358              for the symbol.
359              If the GOT entry is nonzero, it represents the quickstart
360              address of the function and we use that as the symbol value.
361
362              If the GOT entry is zero, the function address has to be resolved
363              by the runtime loader before the executable is started.
364              We are unable to find any meaningful address for these
365              functions in the executable file, so we skip them.  */
366           if (sym_value == 0)
367             {
368               int got_entry_offset =
369               (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;
370
371               if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
372                 continue;
373               sym_value =
374                 bfd_h_get_64 (abfd,
375                               (bfd_byte *) (got_secptr + got_entry_offset));
376               if (sym_value == 0)
377                 continue;
378             }
379         }
380       else
381         {
382           /* Symbols defined in the executable itself. We only care about
383              them if this is a stripped executable, otherwise they have
384              been retrieved from the normal symbol table already.  */
385           if (!stripped)
386             continue;
387
388           if (sym_shndx == SHN_MIPS_TEXT)
389             {
390               if (isglobal)
391                 ms_type = mst_text;
392               else
393                 ms_type = mst_file_text;
394               sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
395             }
396           else if (sym_shndx == SHN_MIPS_DATA)
397             {
398               if (isglobal)
399                 ms_type = mst_data;
400               else
401                 ms_type = mst_file_data;
402               sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile));
403             }
404           else if (sym_shndx == SHN_MIPS_ACOMMON)
405             {
406               if (isglobal)
407                 ms_type = mst_bss;
408               else
409                 ms_type = mst_file_bss;
410               sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile));
411             }
412           else if (sym_shndx == SHN_ABS)
413             {
414               ms_type = mst_abs;
415             }
416           else
417             {
418               continue;
419             }
420         }
421
422       prim_record_minimal_symbol (name, sym_value, ms_type, objfile);
423     }
424
425   do_cleanups (cleanups);
426 }
427
428 /* Initialization */
429
430 static struct sym_fns ecoff_sym_fns =
431 {
432   bfd_target_ecoff_flavour,
433   mipscoff_new_init,            /* sym_new_init: init anything gbl to entire symtab */
434   mipscoff_symfile_init,        /* sym_init: read initial info, setup for sym_read() */
435   mipscoff_symfile_read,        /* sym_read: read a symbol file into symtab */
436   mipscoff_symfile_finish,      /* sym_finish: finished with file, cleanup */
437   default_symfile_offsets,      /* sym_offsets: dummy FIXME til implem sym reloc */
438   NULL                          /* next: pointer to next struct sym_fns */
439 };
440
441 void
442 _initialize_mipsread (void)
443 {
444   add_symtab_fns (&ecoff_sym_fns);
445 }