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