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