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