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,
22 Boston, MA 02111-1307, USA. */
24 /* Read symbols from an ECOFF file. Most of the work is done in
28 #include "gdb_string.h"
34 #include "stabsread.h"
35 #include "gdb-stabs.h"
38 #include "coff/internal.h"
39 #include "coff/ecoff.h"
40 #include "libcoff.h" /* Private BFD COFF information. */
41 #include "libecoff.h" /* Private BFD ECOFF information. */
42 #include "elf/common.h"
45 extern void _initialize_mipsread
PARAMS ((void));
48 mipscoff_new_init
PARAMS ((struct objfile
*));
51 mipscoff_symfile_init
PARAMS ((struct objfile
*));
54 mipscoff_symfile_read
PARAMS ((struct objfile
*, struct section_offsets
*,
58 mipscoff_symfile_finish
PARAMS ((struct objfile
*));
61 read_alphacoff_dynamic_symtab
PARAMS ((struct section_offsets
*,
62 struct objfile
* objfile
));
64 /* Initialize anything that needs initializing when a completely new
65 symbol file is specified (not just adding some symbols from another
66 file, e.g. a shared library). */
68 extern CORE_ADDR sigtramp_address
;
71 mipscoff_new_init (ignore
)
72 struct objfile
*ignore
;
75 stabsread_new_init ();
79 /* Initialize to read a symbol file (nothing to do). */
82 mipscoff_symfile_init (objfile
)
83 struct objfile
*objfile
;
87 /* Read a symbol file from a file. */
90 mipscoff_symfile_read (objfile
, section_offsets
, mainline
)
91 struct objfile
*objfile
;
92 struct section_offsets
*section_offsets
;
95 bfd
*abfd
= objfile
->obfd
;
96 struct cleanup
*back_to
;
98 init_minimal_symbol_collection ();
99 back_to
= make_cleanup ((make_cleanup_func
) discard_minimal_symbols
, 0);
101 /* Now that the executable file is positioned at symbol table,
102 process it and define symbols accordingly. */
104 if (!((*ecoff_backend (abfd
)->debug_swap
.read_debug_info
)
105 (abfd
, (asection
*) NULL
, &ecoff_data (abfd
)->debug_info
)))
106 error ("Error reading symbol table: %s", bfd_errmsg (bfd_get_error ()));
108 mdebug_build_psymtabs (objfile
, &ecoff_backend (abfd
)->debug_swap
,
109 &ecoff_data (abfd
)->debug_info
, section_offsets
);
111 /* Add alpha coff dynamic symbols. */
113 read_alphacoff_dynamic_symtab (section_offsets
, objfile
);
115 /* Install any minimal symbols that have been collected as the current
116 minimal symbols for this objfile. */
118 install_minimal_symbols (objfile
);
120 /* If the entry_file bounds are still unknown after processing the
121 partial symbols, then try to set them from the minimal symbols
122 surrounding the entry_point. */
125 && objfile
->ei
.entry_point
!= INVALID_ENTRY_POINT
126 && objfile
->ei
.entry_file_lowpc
== INVALID_ENTRY_LOWPC
)
128 struct minimal_symbol
*m
;
130 m
= lookup_minimal_symbol_by_pc (objfile
->ei
.entry_point
);
131 if (m
&& SYMBOL_NAME (m
+ 1))
133 objfile
->ei
.entry_file_lowpc
= SYMBOL_VALUE_ADDRESS (m
);
134 objfile
->ei
.entry_file_highpc
= SYMBOL_VALUE_ADDRESS (m
+ 1);
138 do_cleanups (back_to
);
141 /* Perform any local cleanups required when we are done with a
142 particular objfile. */
145 mipscoff_symfile_finish (objfile
)
146 struct objfile
*objfile
;
150 /* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a
151 standard coff section. The ELF format for the symbols differs from
152 the format defined in elf/external.h. It seems that a normal ELF 32 bit
153 format is used, and the representation only changes because longs are
154 64 bit on the alpha. In addition, the handling of text/data section
155 indices for symbols is different from the ELF ABI.
156 As the BFD linker currently does not support dynamic linking on the alpha,
157 there seems to be no reason to pollute BFD with another mixture of object
158 file formats for now. */
160 /* Format of an alpha external ELF symbol. */
164 unsigned char st_name
[4]; /* Symbol name, index in string tbl */
165 unsigned char st_pad
[4]; /* Pad to long word boundary */
166 unsigned char st_value
[8]; /* Value of the symbol */
167 unsigned char st_size
[4]; /* Associated symbol size */
168 unsigned char st_info
[1]; /* Type and binding attributes */
169 unsigned char st_other
[1]; /* No defined meaning, 0 */
170 unsigned char st_shndx
[2]; /* Associated section index */
172 Elfalpha_External_Sym
;
174 /* Format of an alpha external ELF dynamic info structure. */
178 unsigned char d_tag
[4]; /* Tag */
179 unsigned char d_pad
[4]; /* Pad to long word boundary */
182 unsigned char d_ptr
[8]; /* Pointer value */
183 unsigned char d_val
[4]; /* Integer value */
187 Elfalpha_External_Dyn
;
189 /* Struct to obtain the section pointers for alpha dynamic symbol info. */
191 struct alphacoff_dynsecinfo
193 asection
*sym_sect
; /* Section pointer for .dynsym section */
194 asection
*str_sect
; /* Section pointer for .dynstr section */
195 asection
*dyninfo_sect
; /* Section pointer for .dynamic section */
196 asection
*got_sect
; /* Section pointer for .got section */
200 alphacoff_locate_sections
PARAMS ((bfd
*, asection
*, void *));
202 /* We are called once per section from read_alphacoff_dynamic_symtab.
203 We need to examine each section we are passed, check to see
204 if it is something we are interested in processing, and
205 if so, stash away some access information for the section. */
208 alphacoff_locate_sections (ignore_abfd
, sectp
, sip
)
213 register struct alphacoff_dynsecinfo
*si
;
215 si
= (struct alphacoff_dynsecinfo
*) sip
;
217 if (STREQ (sectp
->name
, ".dynsym"))
219 si
->sym_sect
= sectp
;
221 else if (STREQ (sectp
->name
, ".dynstr"))
223 si
->str_sect
= sectp
;
225 else if (STREQ (sectp
->name
, ".dynamic"))
227 si
->dyninfo_sect
= sectp
;
229 else if (STREQ (sectp
->name
, ".got"))
231 si
->got_sect
= sectp
;
235 /* Scan an alpha dynamic symbol table for symbols of interest and
236 add them to the minimal symbol table. */
239 read_alphacoff_dynamic_symtab (section_offsets
, objfile
)
240 struct section_offsets
*section_offsets
;
241 struct objfile
*objfile
;
243 bfd
*abfd
= objfile
->obfd
;
244 struct alphacoff_dynsecinfo si
;
247 char *dyninfo_secptr
;
249 bfd_size_type sym_secsize
;
250 bfd_size_type str_secsize
;
251 bfd_size_type dyninfo_secsize
;
252 bfd_size_type got_secsize
;
256 Elfalpha_External_Sym
*x_symp
;
259 int got_entry_size
= 8;
260 int dt_mips_local_gotno
= -1;
261 int dt_mips_gotsym
= -1;
264 /* We currently only know how to handle alpha dynamic symbols. */
265 if (bfd_get_arch (abfd
) != bfd_arch_alpha
)
268 /* Locate the dynamic symbols sections and read them in. */
269 memset ((char *) &si
, 0, sizeof (si
));
270 bfd_map_over_sections (abfd
, alphacoff_locate_sections
, (PTR
) & si
);
271 if (si
.sym_sect
== NULL
272 || si
.str_sect
== NULL
273 || si
.dyninfo_sect
== NULL
274 || si
.got_sect
== NULL
)
277 sym_secsize
= bfd_get_section_size_before_reloc (si
.sym_sect
);
278 str_secsize
= bfd_get_section_size_before_reloc (si
.str_sect
);
279 dyninfo_secsize
= bfd_get_section_size_before_reloc (si
.dyninfo_sect
);
280 got_secsize
= bfd_get_section_size_before_reloc (si
.got_sect
);
281 sym_secptr
= alloca (sym_secsize
);
282 str_secptr
= alloca (str_secsize
);
283 dyninfo_secptr
= alloca (dyninfo_secsize
);
284 got_secptr
= alloca (got_secsize
);
286 if (!bfd_get_section_contents (abfd
, si
.sym_sect
, sym_secptr
,
287 (file_ptr
) 0, sym_secsize
))
289 if (!bfd_get_section_contents (abfd
, si
.str_sect
, str_secptr
,
290 (file_ptr
) 0, str_secsize
))
292 if (!bfd_get_section_contents (abfd
, si
.dyninfo_sect
, dyninfo_secptr
,
293 (file_ptr
) 0, dyninfo_secsize
))
295 if (!bfd_get_section_contents (abfd
, si
.got_sect
, got_secptr
,
296 (file_ptr
) 0, got_secsize
))
299 /* Find the number of local GOT entries and the index for the
300 the first dynamic symbol in the GOT. */
301 for (dyninfo_p
= dyninfo_secptr
, dyninfo_end
= dyninfo_p
+ dyninfo_secsize
;
302 dyninfo_p
< dyninfo_end
;
303 dyninfo_p
+= sizeof (Elfalpha_External_Dyn
))
305 Elfalpha_External_Dyn
*x_dynp
= (Elfalpha_External_Dyn
*) dyninfo_p
;
308 dyn_tag
= bfd_h_get_32 (abfd
, (bfd_byte
*) x_dynp
->d_tag
);
309 if (dyn_tag
== DT_NULL
)
311 else if (dyn_tag
== DT_MIPS_LOCAL_GOTNO
)
313 if (dt_mips_local_gotno
< 0)
315 = bfd_h_get_32 (abfd
, (bfd_byte
*) x_dynp
->d_un
.d_val
);
317 else if (dyn_tag
== DT_MIPS_GOTSYM
)
319 if (dt_mips_gotsym
< 0)
321 = bfd_h_get_32 (abfd
, (bfd_byte
*) x_dynp
->d_un
.d_val
);
324 if (dt_mips_local_gotno
< 0 || dt_mips_gotsym
< 0)
327 /* Scan all dynamic symbols and enter them into the minimal symbol table
329 sym_count
= sym_secsize
/ sizeof (Elfalpha_External_Sym
);
330 stripped
= (bfd_get_symcount (abfd
) == 0);
332 /* Skip first symbol, which is a null dummy. */
333 for (i
= 1, x_symp
= (Elfalpha_External_Sym
*) sym_secptr
+ 1;
340 unsigned char sym_info
;
341 unsigned int sym_shndx
;
343 enum minimal_symbol_type ms_type
;
345 strx
= bfd_h_get_32 (abfd
, (bfd_byte
*) x_symp
->st_name
);
346 if (strx
>= str_secsize
)
348 name
= str_secptr
+ strx
;
349 if (*name
== '\0' || *name
== '.')
352 sym_value
= bfd_h_get_64 (abfd
, (bfd_byte
*) x_symp
->st_value
);
353 sym_info
= bfd_h_get_8 (abfd
, (bfd_byte
*) x_symp
->st_info
);
354 sym_shndx
= bfd_h_get_16 (abfd
, (bfd_byte
*) x_symp
->st_shndx
);
355 isglobal
= (ELF_ST_BIND (sym_info
) == STB_GLOBAL
);
357 if (sym_shndx
== SHN_UNDEF
)
359 /* Handle undefined functions which are defined in a shared
361 if (ELF_ST_TYPE (sym_info
) != STT_FUNC
362 || ELF_ST_BIND (sym_info
) != STB_GLOBAL
)
365 ms_type
= mst_solib_trampoline
;
367 /* If sym_value is nonzero, it points to the shared library
368 trampoline entry, which is what we are looking for.
370 If sym_value is zero, then we have to get the GOT entry
372 If the GOT entry is nonzero, it represents the quickstart
373 address of the function and we use that as the symbol value.
375 If the GOT entry is zero, the function address has to be resolved
376 by the runtime loader before the executable is started.
377 We are unable to find any meaningful address for these
378 functions in the executable file, so we skip them. */
381 int got_entry_offset
=
382 (i
- dt_mips_gotsym
+ dt_mips_local_gotno
) * got_entry_size
;
384 if (got_entry_offset
< 0 || got_entry_offset
>= got_secsize
)
388 (bfd_byte
*) (got_secptr
+ got_entry_offset
));
395 /* Symbols defined in the executable itself. We only care about
396 them if this is a stripped executable, otherwise they have
397 been retrieved from the normal symbol table already. */
401 if (sym_shndx
== SHN_MIPS_TEXT
)
406 ms_type
= mst_file_text
;
407 sym_value
+= ANOFFSET (section_offsets
, SECT_OFF_TEXT
);
409 else if (sym_shndx
== SHN_MIPS_DATA
)
414 ms_type
= mst_file_data
;
415 sym_value
+= ANOFFSET (section_offsets
, SECT_OFF_DATA
);
417 else if (sym_shndx
== SHN_MIPS_ACOMMON
)
422 ms_type
= mst_file_bss
;
423 sym_value
+= ANOFFSET (section_offsets
, SECT_OFF_BSS
);
425 else if (sym_shndx
== SHN_ABS
)
435 prim_record_minimal_symbol (name
, sym_value
, ms_type
, objfile
);
441 static struct sym_fns ecoff_sym_fns
=
443 bfd_target_ecoff_flavour
,
444 mipscoff_new_init
, /* sym_new_init: init anything gbl to entire symtab */
445 mipscoff_symfile_init
, /* sym_init: read initial info, setup for sym_read() */
446 mipscoff_symfile_read
, /* sym_read: read a symbol file into symtab */
447 mipscoff_symfile_finish
, /* sym_finish: finished with file, cleanup */
448 default_symfile_offsets
, /* sym_offsets: dummy FIXME til implem sym reloc */
449 NULL
/* next: pointer to next struct sym_fns */
453 _initialize_mipsread ()
455 add_symtab_fns (&ecoff_sym_fns
);