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.
7 This file is part of GDB.
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.
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.
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. */
23 /* Read symbols from an ECOFF file. Most of the work is done in
27 #include "gdb_string.h"
33 #include "stabsread.h"
34 #include "gdb-stabs.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"
44 extern void _initialize_mipsread
PARAMS ((void));
47 mipscoff_new_init
PARAMS ((struct objfile
*));
50 mipscoff_symfile_init
PARAMS ((struct objfile
*));
53 mipscoff_symfile_read
PARAMS ((struct objfile
*, struct section_offsets
*,
57 mipscoff_symfile_finish
PARAMS ((struct objfile
*));
60 read_alphacoff_dynamic_symtab
PARAMS ((struct section_offsets
*,
61 struct objfile
*objfile
));
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). */
67 extern CORE_ADDR sigtramp_address
;
70 mipscoff_new_init (ignore
)
71 struct objfile
*ignore
;
74 stabsread_new_init ();
78 /* Initialize to read a symbol file (nothing to do). */
81 mipscoff_symfile_init (objfile
)
82 struct objfile
*objfile
;
86 /* Read a symbol file from a file. */
89 mipscoff_symfile_read (objfile
, section_offsets
, mainline
)
90 struct objfile
*objfile
;
91 struct section_offsets
*section_offsets
;
94 bfd
*abfd
= objfile
->obfd
;
95 struct cleanup
* back_to
;
97 init_minimal_symbol_collection ();
98 back_to
= make_cleanup ((make_cleanup_func
) discard_minimal_symbols
, 0);
100 /* Now that the executable file is positioned at symbol table,
101 process it and define symbols accordingly. */
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 ()));
107 mdebug_build_psymtabs (objfile
, &ecoff_backend (abfd
)->debug_swap
,
108 &ecoff_data (abfd
)->debug_info
, section_offsets
);
110 /* Add alpha coff dynamic symbols. */
112 read_alphacoff_dynamic_symtab (section_offsets
, objfile
);
114 /* Install any minimal symbols that have been collected as the current
115 minimal symbols for this objfile. */
117 install_minimal_symbols (objfile
);
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. */
124 && objfile
->ei
.entry_point
!= INVALID_ENTRY_POINT
125 && objfile
->ei
.entry_file_lowpc
== INVALID_ENTRY_LOWPC
)
127 struct minimal_symbol
*m
;
129 m
= lookup_minimal_symbol_by_pc (objfile
->ei
.entry_point
);
130 if (m
&& SYMBOL_NAME (m
+ 1))
132 objfile
->ei
.entry_file_lowpc
= SYMBOL_VALUE_ADDRESS (m
);
133 objfile
->ei
.entry_file_highpc
= SYMBOL_VALUE_ADDRESS (m
+ 1);
137 do_cleanups (back_to
);
140 /* Perform any local cleanups required when we are done with a
141 particular objfile. */
144 mipscoff_symfile_finish (objfile
)
145 struct objfile
*objfile
;
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. */
159 /* Format of an alpha external ELF symbol. */
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
;
171 /* Format of an alpha external ELF dynamic info structure. */
174 unsigned char d_tag
[4]; /* Tag */
175 unsigned char d_pad
[4]; /* Pad to long word boundary */
177 unsigned char d_ptr
[8]; /* Pointer value */
178 unsigned char d_val
[4]; /* Integer value */
180 } Elfalpha_External_Dyn
;
182 /* Struct to obtain the section pointers for alpha dynamic symbol info. */
184 struct 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 */
192 alphacoff_locate_sections
PARAMS ((bfd
*, asection
*, void *));
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. */
200 alphacoff_locate_sections (ignore_abfd
, sectp
, sip
)
205 register struct alphacoff_dynsecinfo
*si
;
207 si
= (struct alphacoff_dynsecinfo
*) sip
;
209 if (STREQ (sectp
->name
, ".dynsym"))
211 si
->sym_sect
= sectp
;
213 else if (STREQ (sectp
->name
, ".dynstr"))
215 si
->str_sect
= sectp
;
217 else if (STREQ (sectp
->name
, ".dynamic"))
219 si
->dyninfo_sect
= sectp
;
221 else if (STREQ (sectp
->name
, ".got"))
223 si
->got_sect
= sectp
;
227 /* Scan an alpha dynamic symbol table for symbols of interest and
228 add them to the minimal symbol table. */
231 read_alphacoff_dynamic_symtab (section_offsets
, objfile
)
232 struct section_offsets
*section_offsets
;
233 struct objfile
*objfile
;
235 bfd
*abfd
= objfile
->obfd
;
236 struct alphacoff_dynsecinfo si
;
239 char *dyninfo_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
;
248 Elfalpha_External_Sym
*x_symp
;
251 int got_entry_size
= 8;
252 int dt_mips_local_gotno
= -1;
253 int dt_mips_gotsym
= -1;
256 /* We currently only know how to handle alpha dynamic symbols. */
257 if (bfd_get_arch (abfd
) != bfd_arch_alpha
)
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
)
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
);
278 if (!bfd_get_section_contents (abfd
, si
.sym_sect
, sym_secptr
,
279 (file_ptr
)0, sym_secsize
))
281 if (!bfd_get_section_contents (abfd
, si
.str_sect
, str_secptr
,
282 (file_ptr
)0, str_secsize
))
284 if (!bfd_get_section_contents (abfd
, si
.dyninfo_sect
, dyninfo_secptr
,
285 (file_ptr
)0, dyninfo_secsize
))
287 if (!bfd_get_section_contents (abfd
, si
.got_sect
, got_secptr
,
288 (file_ptr
)0, got_secsize
))
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
))
297 Elfalpha_External_Dyn
*x_dynp
= (Elfalpha_External_Dyn
*)dyninfo_p
;
300 dyn_tag
= bfd_h_get_32 (abfd
, (bfd_byte
*) x_dynp
->d_tag
);
301 if (dyn_tag
== DT_NULL
)
303 else if (dyn_tag
== DT_MIPS_LOCAL_GOTNO
)
305 if (dt_mips_local_gotno
< 0)
307 = bfd_h_get_32 (abfd
, (bfd_byte
*) x_dynp
->d_un
.d_val
);
309 else if (dyn_tag
== DT_MIPS_GOTSYM
)
311 if (dt_mips_gotsym
< 0)
313 = bfd_h_get_32 (abfd
, (bfd_byte
*) x_dynp
->d_un
.d_val
);
316 if (dt_mips_local_gotno
< 0 || dt_mips_gotsym
< 0)
319 /* Scan all dynamic symbols and enter them into the minimal symbol table
321 sym_count
= sym_secsize
/ sizeof (Elfalpha_External_Sym
);
322 stripped
= (bfd_get_symcount (abfd
) == 0);
324 /* Skip first symbol, which is a null dummy. */
325 for (i
= 1, x_symp
= (Elfalpha_External_Sym
*) sym_secptr
+ 1;
332 unsigned char sym_info
;
333 unsigned int sym_shndx
;
335 enum minimal_symbol_type ms_type
;
337 strx
= bfd_h_get_32 (abfd
, (bfd_byte
*) x_symp
->st_name
);
338 if (strx
>= str_secsize
)
340 name
= str_secptr
+ strx
;
341 if (*name
== '\0' || *name
== '.')
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
);
349 if (sym_shndx
== SHN_UNDEF
)
351 /* Handle undefined functions which are defined in a shared
353 if (ELF_ST_TYPE (sym_info
) != STT_FUNC
354 || ELF_ST_BIND (sym_info
) != STB_GLOBAL
)
357 ms_type
= mst_solib_trampoline
;
359 /* If sym_value is nonzero, it points to the shared library
360 trampoline entry, which is what we are looking for.
362 If sym_value is zero, then we have to get the GOT entry
364 If the GOT entry is nonzero, it represents the quickstart
365 address of the function and we use that as the symbol value.
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. */
373 int got_entry_offset
=
374 (i
- dt_mips_gotsym
+ dt_mips_local_gotno
) * got_entry_size
;
376 if (got_entry_offset
< 0 || got_entry_offset
>= got_secsize
)
380 (bfd_byte
*) (got_secptr
+ got_entry_offset
));
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. */
393 if (sym_shndx
== SHN_MIPS_TEXT
)
398 ms_type
= mst_file_text
;
399 sym_value
+= ANOFFSET (section_offsets
, SECT_OFF_TEXT
);
401 else if (sym_shndx
== SHN_MIPS_DATA
)
406 ms_type
= mst_file_data
;
407 sym_value
+= ANOFFSET (section_offsets
, SECT_OFF_DATA
);
409 else if (sym_shndx
== SHN_MIPS_ACOMMON
)
414 ms_type
= mst_file_bss
;
415 sym_value
+= ANOFFSET (section_offsets
, SECT_OFF_BSS
);
417 else if (sym_shndx
== SHN_ABS
)
427 prim_record_minimal_symbol (name
, sym_value
, ms_type
, objfile
);
433 static struct sym_fns ecoff_sym_fns
=
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 */
445 _initialize_mipsread ()
447 add_symtab_fns (&ecoff_sym_fns
);