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