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