* somread.c: Simplify by using stabsect_build_psymtabs.
[binutils-gdb.git] / gdb / somread.c
1 /* Read HP PA/Risc object files for GDB.
2 Copyright 1991, 1992 Free Software Foundation, Inc.
3 Written by Fred Fish at Cygnus Support.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include "defs.h"
22 #include "bfd.h"
23 #include <time.h> /* For time_t in libbfd.h. */
24 #include <sys/types.h> /* For time_t, if not in time.h. */
25 #include "libbfd.h"
26 #include "som.h"
27 #include "libhppa.h"
28 #include <syms.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 #include "complaints.h"
36 #include <string.h>
37 #include "demangle.h"
38 #include <sys/file.h>
39
40 /* Size of n_value and n_strx fields in a stab symbol. */
41 #define BYTES_IN_WORD 4
42
43 #if 0
44 #include "aout/aout64.h"
45 #endif
46
47 /* Various things we might complain about... */
48
49 static void
50 som_symfile_init PARAMS ((struct objfile *));
51
52 static void
53 som_new_init PARAMS ((struct objfile *));
54
55 static void
56 som_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
57
58 static void
59 som_symfile_finish PARAMS ((struct objfile *));
60
61 static void
62 som_symtab_read PARAMS ((bfd *, CORE_ADDR, struct objfile *));
63
64 static struct section_offsets *
65 som_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
66
67 static void
68 record_minimal_symbol PARAMS ((char *, CORE_ADDR,
69 enum minimal_symbol_type,
70 struct objfile *));
71
72 static void
73 record_minimal_symbol (name, address, ms_type, objfile)
74 char *name;
75 CORE_ADDR address;
76 enum minimal_symbol_type ms_type;
77 struct objfile *objfile;
78 {
79 name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
80 prim_record_minimal_symbol (name, address, ms_type, objfile);
81 }
82
83 /*
84
85 LOCAL FUNCTION
86
87 som_symtab_read -- read the symbol table of a SOM file
88
89 SYNOPSIS
90
91 void som_symtab_read (bfd *abfd, CORE_ADDR addr,
92 struct objfile *objfile)
93
94 DESCRIPTION
95
96 Given an open bfd, a base address to relocate symbols to, and a
97 flag that specifies whether or not this bfd is for an executable
98 or not (may be shared library for example), add all the global
99 function and data symbols to the minimal symbol table.
100 */
101
102 static void
103 som_symtab_read (abfd, addr, objfile)
104 bfd *abfd;
105 CORE_ADDR addr;
106 struct objfile *objfile;
107 {
108 unsigned int number_of_symbols;
109 int val, dynamic;
110 char *stringtab;
111 asection *shlib_info;
112 struct symbol_dictionary_record *buf, *bufp, *endbufp;
113 char *symname;
114 CONST int symsize = sizeof (struct symbol_dictionary_record);
115
116 number_of_symbols = bfd_get_symcount (abfd);
117
118 buf = alloca (symsize * number_of_symbols);
119 bfd_seek (abfd, obj_som_sym_filepos (abfd), L_SET);
120 val = bfd_read (buf, symsize * number_of_symbols, 1, abfd);
121 if (val != symsize * number_of_symbols)
122 error ("Couldn't read symbol dictionary!");
123
124 stringtab = alloca (obj_som_stringtab_size (abfd));
125 bfd_seek (abfd, obj_som_str_filepos (abfd), L_SET);
126 val = bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd);
127 if (val != obj_som_stringtab_size (abfd))
128 error ("Can't read in HP string table.");
129
130 /* We need to determine if objfile is a dynamic executable (so we
131 can do the right thing for ST_ENTRY vs ST_CODE symbols).
132
133 There's nothing in the header which easily allows us to do
134 this. The only reliable way I know of is to check for the
135 existance of a $SHLIB_INFO$ section with a non-zero size. */
136 shlib_info = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
137 if (shlib_info)
138 dynamic = (bfd_section_size (objfile->obfd, shlib_info) != 0);
139 else
140 dynamic = 0;
141
142 endbufp = buf + number_of_symbols;
143 for (bufp = buf; bufp < endbufp; ++bufp)
144 {
145 enum minimal_symbol_type ms_type;
146
147 QUIT;
148
149 switch (bufp->symbol_scope)
150 {
151 case SS_UNIVERSAL:
152 case SS_EXTERNAL:
153 switch (bufp->symbol_type)
154 {
155 case ST_SYM_EXT:
156 case ST_ARG_EXT:
157 continue;
158
159 case ST_CODE:
160 case ST_PRI_PROG:
161 case ST_SEC_PROG:
162 case ST_MILLICODE:
163 symname = bufp->name.n_strx + stringtab;
164 ms_type = mst_text;
165 #ifdef SMASH_TEXT_ADDRESS
166 SMASH_TEXT_ADDRESS (bufp->symbol_value);
167 #endif
168 break;
169
170 case ST_ENTRY:
171 symname = bufp->name.n_strx + stringtab;
172 /* For a dynamic executable, ST_ENTRY symbols are
173 the stubs, while the ST_CODE symbol is the real
174 function. */
175 if (dynamic)
176 ms_type = mst_solib_trampoline;
177 else
178 ms_type = mst_text;
179 #ifdef SMASH_TEXT_ADDRESS
180 SMASH_TEXT_ADDRESS (bufp->symbol_value);
181 #endif
182 break;
183
184 case ST_STUB:
185 symname = bufp->name.n_strx + stringtab;
186 ms_type = mst_solib_trampoline;
187 #ifdef SMASH_TEXT_ADDRESS
188 SMASH_TEXT_ADDRESS (bufp->symbol_value);
189 #endif
190 break;
191
192 case ST_DATA:
193 symname = bufp->name.n_strx + stringtab;
194 ms_type = mst_data;
195 break;
196 default:
197 continue;
198 }
199 break;
200
201 #if 0
202 /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */
203 case SS_GLOBAL:
204 #endif
205 case SS_LOCAL:
206 switch (bufp->symbol_type)
207 {
208 case ST_SYM_EXT:
209 case ST_ARG_EXT:
210 continue;
211
212 case ST_CODE:
213 symname = bufp->name.n_strx + stringtab;
214 ms_type = mst_file_text;
215 #ifdef SMASH_TEXT_ADDRESS
216 SMASH_TEXT_ADDRESS (bufp->symbol_value);
217 #endif
218
219 check_strange_names:
220 /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local
221 label prefixes for stabs, constant data, etc. So we need
222 only filter out L$ symbols which are left in due to
223 limitations in how GAS generates SOM relocations.
224
225 When linking in the HPUX C-library the HP linker has
226 the nasty habit of placing section symbols from the literal
227 subspaces in the middle of the program's text. Filter
228 those out as best we can. Check for first and last character
229 being '$'. */
230 if ((symname[0] == 'L' && symname[1] == '$')
231 || (symname[0] == '$' && symname[strlen(symname) - 1] == '$'))
232 continue;
233 break;
234
235 case ST_PRI_PROG:
236 case ST_SEC_PROG:
237 case ST_MILLICODE:
238 symname = bufp->name.n_strx + stringtab;
239 ms_type = mst_file_text;
240 #ifdef SMASH_TEXT_ADDRESS
241 SMASH_TEXT_ADDRESS (bufp->symbol_value);
242 #endif
243 break;
244
245 case ST_ENTRY:
246 symname = bufp->name.n_strx + stringtab;
247 /* For a dynamic executable, ST_ENTRY symbols are
248 the stubs, while the ST_CODE symbol is the real
249 function. */
250 if (dynamic)
251 ms_type = mst_solib_trampoline;
252 else
253 ms_type = mst_file_text;
254 #ifdef SMASH_TEXT_ADDRESS
255 SMASH_TEXT_ADDRESS (bufp->symbol_value);
256 #endif
257 break;
258
259 case ST_STUB:
260 symname = bufp->name.n_strx + stringtab;
261 ms_type = mst_solib_trampoline;
262 #ifdef SMASH_TEXT_ADDRESS
263 SMASH_TEXT_ADDRESS (bufp->symbol_value);
264 #endif
265 break;
266
267
268 case ST_DATA:
269 symname = bufp->name.n_strx + stringtab;
270 ms_type = mst_file_data;
271 goto check_strange_names;
272
273 default:
274 continue;
275 }
276 break;
277
278 default:
279 continue;
280 }
281
282 if (bufp->name.n_strx > obj_som_stringtab_size (abfd))
283 error ("Invalid symbol data; bad HP string table offset: %d",
284 bufp->name.n_strx);
285
286 record_minimal_symbol (symname,
287 bufp->symbol_value, ms_type,
288 objfile);
289 }
290 }
291
292 /* Scan and build partial symbols for a symbol file.
293 We have been initialized by a call to som_symfile_init, which
294 currently does nothing.
295
296 SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
297 in each section. This is ignored, as it isn't needed for SOM.
298
299 MAINLINE is true if we are reading the main symbol
300 table (as opposed to a shared lib or dynamically loaded file).
301
302 This function only does the minimum work necessary for letting the
303 user "name" things symbolically; it does not read the entire symtab.
304 Instead, it reads the external and static symbols and puts them in partial
305 symbol tables. When more extensive information is requested of a
306 file, the corresponding partial symbol table is mutated into a full
307 fledged symbol table by going back and reading the symbols
308 for real.
309
310 We look for sections with specific names, to tell us what debug
311 format to look for: FIXME!!!
312
313 somstab_build_psymtabs() handles STABS symbols.
314
315 Note that SOM files have a "minimal" symbol table, which is vaguely
316 reminiscent of a COFF symbol table, but has only the minimal information
317 necessary for linking. We process this also, and use the information to
318 build gdb's minimal symbol table. This gives us some minimal debugging
319 capability even for files compiled without -g. */
320
321 static void
322 som_symfile_read (objfile, section_offsets, mainline)
323 struct objfile *objfile;
324 struct section_offsets *section_offsets;
325 int mainline;
326 {
327 bfd *abfd = objfile->obfd;
328 struct cleanup *back_to;
329 CORE_ADDR offset;
330
331 init_minimal_symbol_collection ();
332 back_to = make_cleanup (discard_minimal_symbols, 0);
333
334 /* FIXME, should take a section_offsets param, not just an offset. */
335
336 offset = ANOFFSET (section_offsets, 0);
337
338 /* Process the normal SOM symbol table first. */
339
340 som_symtab_read (abfd, offset, objfile);
341
342 /* Now read information from the debugging sections. */
343 stabsect_build_psymtabs (objfile, section_offsets, mainline,
344 "$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$");
345
346 /* Install any minimal symbols that have been collected as the current
347 minimal symbols for this objfile. */
348 install_minimal_symbols (objfile);
349
350 do_cleanups (back_to);
351 }
352
353 /* Initialize anything that needs initializing when a completely new symbol
354 file is specified (not just adding some symbols from another file, e.g. a
355 shared library).
356
357 We reinitialize buildsym, since we may be reading stabs from a SOM file. */
358
359 static void
360 som_new_init (ignore)
361 struct objfile *ignore;
362 {
363 stabsread_new_init ();
364 buildsym_new_init ();
365 }
366
367 /* Perform any local cleanups required when we are done with a particular
368 objfile. I.E, we are in the process of discarding all symbol information
369 for an objfile, freeing up all memory held for it, and unlinking the
370 objfile struct from the global list of known objfiles. */
371
372 static void
373 som_symfile_finish (objfile)
374 struct objfile *objfile;
375 {
376 if (objfile -> sym_stab_info != NULL)
377 {
378 mfree (objfile -> md, objfile -> sym_stab_info);
379 }
380 }
381
382 /* SOM specific initialization routine for reading symbols.
383
384 Nothing SOM specific left to do anymore. */
385 static void
386 som_symfile_init (ignore)
387 struct objfile *ignore;
388 {
389 }
390
391 /* SOM specific parsing routine for section offsets.
392
393 Plain and simple for now. */
394
395 static struct section_offsets *
396 som_symfile_offsets (objfile, addr)
397 struct objfile *objfile;
398 CORE_ADDR addr;
399 {
400 struct section_offsets *section_offsets;
401 int i;
402
403 objfile->num_sections = SECT_OFF_MAX;
404 section_offsets = (struct section_offsets *)
405 obstack_alloc (&objfile -> psymbol_obstack,
406 sizeof (struct section_offsets)
407 + sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
408
409 for (i = 0; i < SECT_OFF_MAX; i++)
410 ANOFFSET (section_offsets, i) = addr;
411
412 return section_offsets;
413 }
414 \f
415 /* Register that we are able to handle SOM object file formats. */
416
417 static struct sym_fns som_sym_fns =
418 {
419 bfd_target_som_flavour,
420 som_new_init, /* sym_new_init: init anything gbl to entire symtab */
421 som_symfile_init, /* sym_init: read initial info, setup for sym_read() */
422 som_symfile_read, /* sym_read: read a symbol file into symtab */
423 som_symfile_finish, /* sym_finish: finished with file, cleanup */
424 som_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
425 NULL /* next: pointer to next struct sym_fns */
426 };
427
428 void
429 _initialize_somread ()
430 {
431 add_symtab_fns (&som_sym_fns);
432 }