]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/mipsread.c
import gdb-1999-07-07 post reformat
[thirdparty/binutils-gdb.git] / gdb / mipsread.c
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
7 This file is part of GDB.
8
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.
13
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.
18
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. */
23
24 /* Read symbols from an ECOFF file. Most of the work is done in
25 mdebugread.c. */
26
27 #include "defs.h"
28 #include "gdb_string.h"
29 #include "bfd.h"
30 #include "symtab.h"
31 #include "symfile.h"
32 #include "objfiles.h"
33 #include "buildsym.h"
34 #include "stabsread.h"
35 #include "gdb-stabs.h"
36
37 #include "coff/sym.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"
43 #include "elf/mips.h"
44
45 extern void _initialize_mipsread PARAMS ((void));
46
47 static void
48 mipscoff_new_init PARAMS ((struct objfile *));
49
50 static void
51 mipscoff_symfile_init PARAMS ((struct objfile *));
52
53 static void
54 mipscoff_symfile_read PARAMS ((struct objfile *, struct section_offsets *,
55 int));
56
57 static void
58 mipscoff_symfile_finish PARAMS ((struct objfile *));
59
60 static void
61 read_alphacoff_dynamic_symtab PARAMS ((struct section_offsets *,
62 struct objfile * objfile));
63
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). */
67
68 extern CORE_ADDR sigtramp_address;
69
70 static void
71 mipscoff_new_init (ignore)
72 struct objfile *ignore;
73 {
74 sigtramp_address = 0;
75 stabsread_new_init ();
76 buildsym_new_init ();
77 }
78
79 /* Initialize to read a symbol file (nothing to do). */
80
81 static void
82 mipscoff_symfile_init (objfile)
83 struct objfile *objfile;
84 {
85 }
86
87 /* Read a symbol file from a file. */
88
89 static void
90 mipscoff_symfile_read (objfile, section_offsets, mainline)
91 struct objfile *objfile;
92 struct section_offsets *section_offsets;
93 int mainline;
94 {
95 bfd *abfd = objfile->obfd;
96 struct cleanup *back_to;
97
98 init_minimal_symbol_collection ();
99 back_to = make_cleanup ((make_cleanup_func) discard_minimal_symbols, 0);
100
101 /* Now that the executable file is positioned at symbol table,
102 process it and define symbols accordingly. */
103
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 ()));
107
108 mdebug_build_psymtabs (objfile, &ecoff_backend (abfd)->debug_swap,
109 &ecoff_data (abfd)->debug_info, section_offsets);
110
111 /* Add alpha coff dynamic symbols. */
112
113 read_alphacoff_dynamic_symtab (section_offsets, objfile);
114
115 /* Install any minimal symbols that have been collected as the current
116 minimal symbols for this objfile. */
117
118 install_minimal_symbols (objfile);
119
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. */
123
124 if (mainline
125 && objfile->ei.entry_point != INVALID_ENTRY_POINT
126 && objfile->ei.entry_file_lowpc == INVALID_ENTRY_LOWPC)
127 {
128 struct minimal_symbol *m;
129
130 m = lookup_minimal_symbol_by_pc (objfile->ei.entry_point);
131 if (m && SYMBOL_NAME (m + 1))
132 {
133 objfile->ei.entry_file_lowpc = SYMBOL_VALUE_ADDRESS (m);
134 objfile->ei.entry_file_highpc = SYMBOL_VALUE_ADDRESS (m + 1);
135 }
136 }
137
138 do_cleanups (back_to);
139 }
140
141 /* Perform any local cleanups required when we are done with a
142 particular objfile. */
143
144 static void
145 mipscoff_symfile_finish (objfile)
146 struct objfile *objfile;
147 {
148 }
149
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. */
159
160 /* Format of an alpha external ELF symbol. */
161
162 typedef struct
163 {
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 */
171 }
172 Elfalpha_External_Sym;
173
174 /* Format of an alpha external ELF dynamic info structure. */
175
176 typedef struct
177 {
178 unsigned char d_tag[4]; /* Tag */
179 unsigned char d_pad[4]; /* Pad to long word boundary */
180 union
181 {
182 unsigned char d_ptr[8]; /* Pointer value */
183 unsigned char d_val[4]; /* Integer value */
184 }
185 d_un;
186 }
187 Elfalpha_External_Dyn;
188
189 /* Struct to obtain the section pointers for alpha dynamic symbol info. */
190
191 struct alphacoff_dynsecinfo
192 {
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 */
197 };
198
199 static void
200 alphacoff_locate_sections PARAMS ((bfd *, asection *, void *));
201
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. */
206
207 static void
208 alphacoff_locate_sections (ignore_abfd, sectp, sip)
209 bfd *ignore_abfd;
210 asection *sectp;
211 PTR sip;
212 {
213 register struct alphacoff_dynsecinfo *si;
214
215 si = (struct alphacoff_dynsecinfo *) sip;
216
217 if (STREQ (sectp->name, ".dynsym"))
218 {
219 si->sym_sect = sectp;
220 }
221 else if (STREQ (sectp->name, ".dynstr"))
222 {
223 si->str_sect = sectp;
224 }
225 else if (STREQ (sectp->name, ".dynamic"))
226 {
227 si->dyninfo_sect = sectp;
228 }
229 else if (STREQ (sectp->name, ".got"))
230 {
231 si->got_sect = sectp;
232 }
233 }
234
235 /* Scan an alpha dynamic symbol table for symbols of interest and
236 add them to the minimal symbol table. */
237
238 static void
239 read_alphacoff_dynamic_symtab (section_offsets, objfile)
240 struct section_offsets *section_offsets;
241 struct objfile *objfile;
242 {
243 bfd *abfd = objfile->obfd;
244 struct alphacoff_dynsecinfo si;
245 char *sym_secptr;
246 char *str_secptr;
247 char *dyninfo_secptr;
248 char *got_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;
253 int sym_count;
254 int i;
255 int stripped;
256 Elfalpha_External_Sym *x_symp;
257 char *dyninfo_p;
258 char *dyninfo_end;
259 int got_entry_size = 8;
260 int dt_mips_local_gotno = -1;
261 int dt_mips_gotsym = -1;
262
263
264 /* We currently only know how to handle alpha dynamic symbols. */
265 if (bfd_get_arch (abfd) != bfd_arch_alpha)
266 return;
267
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)
275 return;
276
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);
285
286 if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
287 (file_ptr) 0, sym_secsize))
288 return;
289 if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
290 (file_ptr) 0, str_secsize))
291 return;
292 if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
293 (file_ptr) 0, dyninfo_secsize))
294 return;
295 if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
296 (file_ptr) 0, got_secsize))
297 return;
298
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))
304 {
305 Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p;
306 long dyn_tag;
307
308 dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
309 if (dyn_tag == DT_NULL)
310 break;
311 else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
312 {
313 if (dt_mips_local_gotno < 0)
314 dt_mips_local_gotno
315 = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
316 }
317 else if (dyn_tag == DT_MIPS_GOTSYM)
318 {
319 if (dt_mips_gotsym < 0)
320 dt_mips_gotsym
321 = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
322 }
323 }
324 if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
325 return;
326
327 /* Scan all dynamic symbols and enter them into the minimal symbol table
328 if appropriate. */
329 sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
330 stripped = (bfd_get_symcount (abfd) == 0);
331
332 /* Skip first symbol, which is a null dummy. */
333 for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
334 i < sym_count;
335 i++, x_symp++)
336 {
337 unsigned long strx;
338 char *name;
339 bfd_vma sym_value;
340 unsigned char sym_info;
341 unsigned int sym_shndx;
342 int isglobal;
343 enum minimal_symbol_type ms_type;
344
345 strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
346 if (strx >= str_secsize)
347 continue;
348 name = str_secptr + strx;
349 if (*name == '\0' || *name == '.')
350 continue;
351
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);
356
357 if (sym_shndx == SHN_UNDEF)
358 {
359 /* Handle undefined functions which are defined in a shared
360 library. */
361 if (ELF_ST_TYPE (sym_info) != STT_FUNC
362 || ELF_ST_BIND (sym_info) != STB_GLOBAL)
363 continue;
364
365 ms_type = mst_solib_trampoline;
366
367 /* If sym_value is nonzero, it points to the shared library
368 trampoline entry, which is what we are looking for.
369
370 If sym_value is zero, then we have to get the GOT entry
371 for the symbol.
372 If the GOT entry is nonzero, it represents the quickstart
373 address of the function and we use that as the symbol value.
374
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. */
379 if (sym_value == 0)
380 {
381 int got_entry_offset =
382 (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;
383
384 if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
385 continue;
386 sym_value =
387 bfd_h_get_64 (abfd,
388 (bfd_byte *) (got_secptr + got_entry_offset));
389 if (sym_value == 0)
390 continue;
391 }
392 }
393 else
394 {
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. */
398 if (!stripped)
399 continue;
400
401 if (sym_shndx == SHN_MIPS_TEXT)
402 {
403 if (isglobal)
404 ms_type = mst_text;
405 else
406 ms_type = mst_file_text;
407 sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
408 }
409 else if (sym_shndx == SHN_MIPS_DATA)
410 {
411 if (isglobal)
412 ms_type = mst_data;
413 else
414 ms_type = mst_file_data;
415 sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA);
416 }
417 else if (sym_shndx == SHN_MIPS_ACOMMON)
418 {
419 if (isglobal)
420 ms_type = mst_bss;
421 else
422 ms_type = mst_file_bss;
423 sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS);
424 }
425 else if (sym_shndx == SHN_ABS)
426 {
427 ms_type = mst_abs;
428 }
429 else
430 {
431 continue;
432 }
433 }
434
435 prim_record_minimal_symbol (name, sym_value, ms_type, objfile);
436 }
437 }
438
439 /* Initialization */
440
441 static struct sym_fns ecoff_sym_fns =
442 {
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 */
450 };
451
452 void
453 _initialize_mipsread ()
454 {
455 add_symtab_fns (&ecoff_sym_fns);
456 }