xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/mipsread.c (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
1 /* Read a symbol table in MIPS' format (Third-Eye).
2 
3    Copyright (C) 1986-2019 Free Software Foundation, Inc.
4 
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 3 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, see <http://www.gnu.org/licenses/>.  */
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 "bfd.h"
28 #include "symtab.h"
29 #include "objfiles.h"
30 #include "stabsread.h"
31 #include "mdebugread.h"
32 
33 #include "coff/sym.h"
34 #include "coff/internal.h"
35 #include "coff/ecoff.h"
36 #include "libcoff.h"		/* Private BFD COFF information.  */
37 #include "libecoff.h"		/* Private BFD ECOFF information.  */
38 #include "elf/common.h"
39 #include "elf/internal.h"
40 #include "elf/mips.h"
41 
42 #include "psymtab.h"
43 
44 static void
45 read_alphacoff_dynamic_symtab (minimal_symbol_reader &,
46 			       struct section_offsets *,
47 			       struct objfile *objfile);
48 
49 /* Initialize anything that needs initializing when a completely new
50    symbol file is specified (not just adding some symbols from another
51    file, e.g. a shared library).  */
52 
53 static void
54 mipscoff_new_init (struct objfile *ignore)
55 {
56   stabsread_new_init ();
57 }
58 
59 /* Initialize to read a symbol file (nothing to do).  */
60 
61 static void
62 mipscoff_symfile_init (struct objfile *objfile)
63 {
64 }
65 
66 /* Read a symbol file from a file.  */
67 
68 static void
69 mipscoff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
70 {
71   bfd *abfd = objfile->obfd;
72 
73   minimal_symbol_reader reader (objfile);
74 
75   /* Now that the executable file is positioned at symbol table,
76      process it and define symbols accordingly.  */
77 
78   if (!((*ecoff_backend (abfd)->debug_swap.read_debug_info)
79 	(abfd, (asection *) NULL, &ecoff_data (abfd)->debug_info)))
80     error (_("Error reading symbol table: %s"), bfd_errmsg (bfd_get_error ()));
81 
82   mdebug_build_psymtabs (reader, objfile, &ecoff_backend (abfd)->debug_swap,
83 			 &ecoff_data (abfd)->debug_info);
84 
85   /* Add alpha coff dynamic symbols.  */
86 
87   read_alphacoff_dynamic_symtab (reader, objfile->section_offsets, objfile);
88 
89   /* Install any minimal symbols that have been collected as the current
90      minimal symbols for this objfile.  */
91 
92   reader.install ();
93 }
94 
95 /* Perform any local cleanups required when we are done with a
96    particular objfile.  */
97 
98 static void
99 mipscoff_symfile_finish (struct objfile *objfile)
100 {
101 }
102 
103 /* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a
104    standard COFF section.  The ELF format for the symbols differs from
105    the format defined in elf/external.h.  It seems that a normal ELF
106    32-bit format is used, and the representation only changes because
107    longs are 64-bit on the alpha.  In addition, the handling of
108    text/data section indices for symbols is different from the ELF
109    ABI.  As the BFD linker currently does not support dynamic linking
110    on the alpha, there seems to be no reason to pollute BFD with
111    another mixture of object file formats for now.  */
112 
113 /* Format of an alpha external ELF symbol.  */
114 
115 typedef struct
116 {
117   unsigned char st_name[4];	/* Symbol name, index in string table.  */
118   unsigned char st_pad[4];	/* Pad to long word boundary.  */
119   unsigned char st_value[8];	/* Value of the symbol.  */
120   unsigned char st_size[4];	/* Associated symbol size.  */
121   unsigned char st_info[1];	/* Type and binding attributes.  */
122   unsigned char st_other[1];	/* No defined meaning, 0.  */
123   unsigned char st_shndx[2];	/* Associated section index.  */
124 } Elfalpha_External_Sym;
125 
126 /* Format of an alpha external ELF dynamic info structure.  */
127 
128 typedef struct
129 {
130   unsigned char d_tag[4];	/* Tag.  */
131   unsigned char d_pad[4];	/* Pad to long word boundary.  */
132   union
133   {
134     unsigned char d_ptr[8];	/* Pointer value.  */
135     unsigned char d_val[4];	/* Integer value.  */
136   }
137   d_un;
138 } Elfalpha_External_Dyn;
139 
140 /* Struct to obtain the section pointers for alpha dynamic symbol info.  */
141 
142 struct alphacoff_dynsecinfo
143 {
144   asection *sym_sect;		/* Section pointer for .dynsym section.  */
145   asection *str_sect;		/* Section pointer for .dynstr section.  */
146   asection *dyninfo_sect;	/* Section pointer for .dynamic section.  */
147   asection *got_sect;		/* Section pointer for .got section.  */
148 };
149 
150 /* We are called once per section from read_alphacoff_dynamic_symtab.
151    We need to examine each section we are passed, check to see if it
152    is something we are interested in processing, and if so, stash away
153    some access information for the section.  */
154 
155 static void
156 alphacoff_locate_sections (bfd *ignore_abfd, asection *sectp, void *sip)
157 {
158   struct alphacoff_dynsecinfo *si;
159 
160   si = (struct alphacoff_dynsecinfo *) sip;
161 
162   if (strcmp (sectp->name, ".dynsym") == 0)
163     si->sym_sect = sectp;
164   else if (strcmp (sectp->name, ".dynstr") == 0)
165     si->str_sect = sectp;
166   else if (strcmp (sectp->name, ".dynamic") == 0)
167     si->dyninfo_sect = sectp;
168   else if (strcmp (sectp->name, ".got") == 0)
169       si->got_sect = sectp;
170 }
171 
172 /* Scan an alpha dynamic symbol table for symbols of interest and add
173    them to the minimal symbol table.  */
174 
175 static void
176 read_alphacoff_dynamic_symtab (minimal_symbol_reader &reader,
177 			       struct section_offsets *section_offsets,
178 			       struct objfile *objfile)
179 {
180   bfd *abfd = objfile->obfd;
181   struct alphacoff_dynsecinfo si;
182   int sym_count;
183   int i;
184   int stripped;
185   Elfalpha_External_Sym *x_symp;
186   gdb_byte *dyninfo_p;
187   gdb_byte *dyninfo_end;
188   int got_entry_size = 8;
189   int dt_mips_local_gotno = -1;
190   int dt_mips_gotsym = -1;
191 
192   /* We currently only know how to handle alpha dynamic symbols.  */
193   if (bfd_get_arch (abfd) != bfd_arch_alpha)
194     return;
195 
196   /* Locate the dynamic symbols sections and read them in.  */
197   memset ((char *) &si, 0, sizeof (si));
198   bfd_map_over_sections (abfd, alphacoff_locate_sections, (void *) & si);
199   if (si.sym_sect == NULL || si.str_sect == NULL
200       || si.dyninfo_sect == NULL || si.got_sect == NULL)
201     return;
202 
203   gdb::byte_vector sym_sec (bfd_get_section_size (si.sym_sect));
204   gdb::byte_vector str_sec (bfd_get_section_size (si.str_sect));
205   gdb::byte_vector dyninfo_sec (bfd_get_section_size (si.dyninfo_sect));
206   gdb::byte_vector got_sec (bfd_get_section_size (si.got_sect));
207 
208   if (!bfd_get_section_contents (abfd, si.sym_sect, sym_sec.data (),
209 				 (file_ptr) 0, sym_sec.size ()))
210     return;
211   if (!bfd_get_section_contents (abfd, si.str_sect, str_sec.data (),
212 				 (file_ptr) 0, str_sec.size ()))
213     return;
214   if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_sec.data (),
215 				 (file_ptr) 0, dyninfo_sec.size ()))
216     return;
217   if (!bfd_get_section_contents (abfd, si.got_sect, got_sec.data (),
218 				 (file_ptr) 0, got_sec.size ()))
219     return;
220 
221   /* Find the number of local GOT entries and the index for the
222      first dynamic symbol in the GOT.  */
223   for ((dyninfo_p = dyninfo_sec.data (),
224 	dyninfo_end = dyninfo_p + dyninfo_sec.size ());
225        dyninfo_p < dyninfo_end;
226        dyninfo_p += sizeof (Elfalpha_External_Dyn))
227     {
228       Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p;
229       long dyn_tag;
230 
231       dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
232       if (dyn_tag == DT_NULL)
233 	break;
234       else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
235 	{
236 	  if (dt_mips_local_gotno < 0)
237 	    dt_mips_local_gotno
238 	      = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
239 	}
240       else if (dyn_tag == DT_MIPS_GOTSYM)
241 	{
242 	  if (dt_mips_gotsym < 0)
243 	    dt_mips_gotsym
244 	      = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
245 	}
246     }
247   if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
248     return;
249 
250   /* Scan all dynamic symbols and enter them into the minimal symbol
251      table if appropriate.  */
252   sym_count = sym_sec.size () / sizeof (Elfalpha_External_Sym);
253   stripped = (bfd_get_symcount (abfd) == 0);
254 
255   /* Skip first symbol, which is a null dummy.  */
256   for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_sec.data () + 1;
257        i < sym_count;
258        i++, x_symp++)
259     {
260       unsigned long strx;
261       char *name;
262       bfd_vma sym_value;
263       unsigned char sym_info;
264       unsigned int sym_shndx;
265       int isglobal;
266       enum minimal_symbol_type ms_type;
267 
268       strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
269       if (strx >= str_sec.size ())
270 	continue;
271       name = (char *) (str_sec.data () + strx);
272       if (*name == '\0' || *name == '.')
273 	continue;
274 
275       sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
276       sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
277       sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
278       if (sym_shndx >= (SHN_LORESERVE & 0xffff))
279 	sym_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
280       isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);
281 
282       if (sym_shndx == SHN_UNDEF)
283 	{
284 	  /* Handle undefined functions which are defined in a shared
285 	     library.  */
286 	  if (ELF_ST_TYPE (sym_info) != STT_FUNC
287 	      || ELF_ST_BIND (sym_info) != STB_GLOBAL)
288 	    continue;
289 
290 	  ms_type = mst_solib_trampoline;
291 
292 	  /* If sym_value is nonzero, it points to the shared library
293 	     trampoline entry, which is what we are looking for.
294 
295 	     If sym_value is zero, then we have to get the GOT entry
296 	     for the symbol.
297 
298 	     If the GOT entry is nonzero, it represents the quickstart
299 	     address of the function and we use that as the symbol
300 	     value.
301 
302 	     If the GOT entry is zero, the function address has to be
303 	     resolved by the runtime loader before the executable is
304 	     started.  We are unable to find any meaningful address
305 	     for these functions in the executable file, so we skip
306 	     them.  */
307 	  if (sym_value == 0)
308 	    {
309 	      int got_entry_offset =
310 		(i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;
311 
312 	      if (got_entry_offset < 0
313 		  || got_entry_offset >= got_sec.size ())
314 		continue;
315 	      sym_value =
316 		bfd_h_get_64 (abfd,
317 			      (bfd_byte *) (got_sec.data ()
318 					    + got_entry_offset));
319 	      if (sym_value == 0)
320 		continue;
321 	    }
322 	}
323       else
324 	{
325 	  /* Symbols defined in the executable itself.  We only care
326 	     about them if this is a stripped executable, otherwise
327 	     they have been retrieved from the normal symbol table
328 	     already.  */
329 	  if (!stripped)
330 	    continue;
331 
332 	  if (sym_shndx == SHN_MIPS_TEXT)
333 	    {
334 	      if (isglobal)
335 		ms_type = mst_text;
336 	      else
337 		ms_type = mst_file_text;
338 	    }
339 	  else if (sym_shndx == SHN_MIPS_DATA)
340 	    {
341 	      if (isglobal)
342 		ms_type = mst_data;
343 	      else
344 		ms_type = mst_file_data;
345 	    }
346 	  else if (sym_shndx == SHN_MIPS_ACOMMON)
347 	    {
348 	      if (isglobal)
349 		ms_type = mst_bss;
350 	      else
351 		ms_type = mst_file_bss;
352 	    }
353 	  else if (sym_shndx == SHN_ABS)
354 	    {
355 	      ms_type = mst_abs;
356 	    }
357 	  else
358 	    {
359 	      continue;
360 	    }
361 	}
362 
363       reader.record (name, sym_value, ms_type);
364     }
365 }
366 
367 /* Initialization.  */
368 
369 static const struct sym_fns ecoff_sym_fns =
370 {
371   mipscoff_new_init,		/* init anything gbl to entire symtab */
372   mipscoff_symfile_init,	/* read initial info, setup for sym_read() */
373   mipscoff_symfile_read,	/* read a symbol file into symtab */
374   NULL,				/* sym_read_psymbols */
375   mipscoff_symfile_finish,	/* finished with file, cleanup */
376   default_symfile_offsets,	/* dummy FIXME til implem sym reloc */
377   default_symfile_segments,	/* Get segment information from a file.  */
378   NULL,
379   default_symfile_relocate,	/* Relocate a debug section.  */
380   NULL,				/* sym_probe_fns */
381   &psym_functions
382 };
383 
384 void
385 _initialize_mipsread (void)
386 {
387   add_symtab_fns (bfd_target_ecoff_flavour, &ecoff_sym_fns);
388 }
389