* gdb.texinfo: Proofreading changes from Brian Youmans.
[external/binutils.git] / gdb / somread.c
1 /* Read HP PA/Risc object files for GDB.
2    Copyright 1991, 1992, 1996, 1999 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., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "bfd.h"
24 #include <syms.h>
25 #include "symtab.h"
26 #include "symfile.h"
27 #include "objfiles.h"
28 #include "buildsym.h"
29 #include "stabsread.h"
30 #include "gdb-stabs.h"
31 #include "complaints.h"
32 #include "gdb_string.h"
33 #include "demangle.h"
34 #include "som.h"
35 #include "libhppa.h"
36
37 /* Various things we might complain about... */
38
39 static void
40 som_symfile_init PARAMS ((struct objfile *));
41
42 static void
43 som_new_init PARAMS ((struct objfile *));
44
45 static void
46 som_symfile_read PARAMS ((struct objfile *, int));
47
48 static void
49 som_symfile_finish PARAMS ((struct objfile *));
50
51 static void
52 som_symtab_read PARAMS ((bfd *, struct objfile *,
53                          struct section_offsets *));
54
55 static void
56 som_symfile_offsets PARAMS ((struct objfile *, struct section_addr_info *));
57
58 /* FIXME: These should really be in a common header somewhere */
59
60 extern void
61 hpread_build_psymtabs PARAMS ((struct objfile *, int));
62
63 extern void
64 hpread_symfile_finish PARAMS ((struct objfile *));
65
66 extern void
67 hpread_symfile_init PARAMS ((struct objfile *));
68
69 extern void
70 do_pxdb PARAMS ((bfd *));
71
72 /*
73
74    LOCAL FUNCTION
75
76    som_symtab_read -- read the symbol table of a SOM file
77
78    SYNOPSIS
79
80    void som_symtab_read (bfd *abfd, struct objfile *objfile,
81    struct section_offsets *section_offsets)
82
83    DESCRIPTION
84
85    Given an open bfd, a base address to relocate symbols to, and a
86    flag that specifies whether or not this bfd is for an executable
87    or not (may be shared library for example), add all the global
88    function and data symbols to the minimal symbol table.
89  */
90
91 static void
92 som_symtab_read (abfd, objfile, section_offsets)
93      bfd *abfd;
94      struct objfile *objfile;
95      struct section_offsets *section_offsets;
96 {
97   unsigned int number_of_symbols;
98   int val, dynamic;
99   char *stringtab;
100   asection *shlib_info;
101   struct symbol_dictionary_record *buf, *bufp, *endbufp;
102   char *symname;
103   CONST int symsize = sizeof (struct symbol_dictionary_record);
104   CORE_ADDR text_offset, data_offset;
105
106
107   text_offset = ANOFFSET (section_offsets, 0);
108   data_offset = ANOFFSET (section_offsets, 1);
109
110   number_of_symbols = bfd_get_symcount (abfd);
111
112   buf = alloca (symsize * number_of_symbols);
113   bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET);
114   val = bfd_read (buf, symsize * number_of_symbols, 1, abfd);
115   if (val != symsize * number_of_symbols)
116     error ("Couldn't read symbol dictionary!");
117
118   stringtab = alloca (obj_som_stringtab_size (abfd));
119   bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET);
120   val = bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd);
121   if (val != obj_som_stringtab_size (abfd))
122     error ("Can't read in HP string table.");
123
124   /* We need to determine if objfile is a dynamic executable (so we
125      can do the right thing for ST_ENTRY vs ST_CODE symbols).
126
127      There's nothing in the header which easily allows us to do
128      this.  The only reliable way I know of is to check for the
129      existance of a $SHLIB_INFO$ section with a non-zero size.  */
130   /* The code below is not a reliable way to check whether an
131    * executable is dynamic, so I commented it out - RT
132    * shlib_info = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
133    * if (shlib_info)
134    *   dynamic = (bfd_section_size (objfile->obfd, shlib_info) != 0);
135    * else
136    *   dynamic = 0;
137    */
138   /* I replaced the code with a simple check for text offset not being
139    * zero. Still not 100% reliable, but a more reliable way of asking
140    * "is this a dynamic executable?" than the above. RT
141    */
142   dynamic = (text_offset != 0);
143
144   endbufp = buf + number_of_symbols;
145   for (bufp = buf; bufp < endbufp; ++bufp)
146     {
147       enum minimal_symbol_type ms_type;
148
149       QUIT;
150
151       switch (bufp->symbol_scope)
152         {
153         case SS_UNIVERSAL:
154         case SS_EXTERNAL:
155           switch (bufp->symbol_type)
156             {
157             case ST_SYM_EXT:
158             case ST_ARG_EXT:
159               continue;
160
161             case ST_CODE:
162             case ST_PRI_PROG:
163             case ST_SEC_PROG:
164             case ST_MILLICODE:
165               symname = bufp->name.n_strx + stringtab;
166               ms_type = mst_text;
167               bufp->symbol_value += text_offset;
168 #ifdef SMASH_TEXT_ADDRESS
169               SMASH_TEXT_ADDRESS (bufp->symbol_value);
170 #endif
171               break;
172
173             case ST_ENTRY:
174               symname = bufp->name.n_strx + stringtab;
175               /* For a dynamic executable, ST_ENTRY symbols are
176                  the stubs, while the ST_CODE symbol is the real
177                  function.  */
178               if (dynamic)
179                 ms_type = mst_solib_trampoline;
180               else
181                 ms_type = mst_text;
182               bufp->symbol_value += text_offset;
183 #ifdef SMASH_TEXT_ADDRESS
184               SMASH_TEXT_ADDRESS (bufp->symbol_value);
185 #endif
186               break;
187
188             case ST_STUB:
189               symname = bufp->name.n_strx + stringtab;
190               ms_type = mst_solib_trampoline;
191               bufp->symbol_value += text_offset;
192 #ifdef SMASH_TEXT_ADDRESS
193               SMASH_TEXT_ADDRESS (bufp->symbol_value);
194 #endif
195               break;
196
197             case ST_DATA:
198               symname = bufp->name.n_strx + stringtab;
199               bufp->symbol_value += data_offset;
200               ms_type = mst_data;
201               break;
202             default:
203               continue;
204             }
205           break;
206
207 #if 0
208           /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!).  */
209         case SS_GLOBAL:
210 #endif
211         case SS_LOCAL:
212           switch (bufp->symbol_type)
213             {
214             case ST_SYM_EXT:
215             case ST_ARG_EXT:
216               continue;
217
218             case ST_CODE:
219               symname = bufp->name.n_strx + stringtab;
220               ms_type = mst_file_text;
221               bufp->symbol_value += text_offset;
222 #ifdef SMASH_TEXT_ADDRESS
223               SMASH_TEXT_ADDRESS (bufp->symbol_value);
224 #endif
225
226             check_strange_names:
227               /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local
228                  label prefixes for stabs, constant data, etc.  So we need
229                  only filter out L$ symbols which are left in due to
230                  limitations in how GAS generates SOM relocations.
231
232                  When linking in the HPUX C-library the HP linker has
233                  the nasty habit of placing section symbols from the literal
234                  subspaces in the middle of the program's text.  Filter
235                  those out as best we can.  Check for first and last character
236                  being '$'. 
237
238                  And finally, the newer HP compilers emit crud like $PIC_foo$N
239                  in some circumstance (PIC code I guess).  It's also claimed
240                  that they emit D$ symbols too.  What stupidity.  */
241               if ((symname[0] == 'L' && symname[1] == '$')
242               || (symname[0] == '$' && symname[strlen (symname) - 1] == '$')
243                   || (symname[0] == 'D' && symname[1] == '$')
244                   || (strncmp (symname, "$PIC", 4) == 0))
245                 continue;
246               break;
247
248             case ST_PRI_PROG:
249             case ST_SEC_PROG:
250             case ST_MILLICODE:
251               symname = bufp->name.n_strx + stringtab;
252               ms_type = mst_file_text;
253               bufp->symbol_value += text_offset;
254 #ifdef SMASH_TEXT_ADDRESS
255               SMASH_TEXT_ADDRESS (bufp->symbol_value);
256 #endif
257               break;
258
259             case ST_ENTRY:
260               symname = bufp->name.n_strx + stringtab;
261               /* For a dynamic executable, ST_ENTRY symbols are
262                  the stubs, while the ST_CODE symbol is the real
263                  function.  */
264               if (dynamic)
265                 ms_type = mst_solib_trampoline;
266               else
267                 ms_type = mst_file_text;
268               bufp->symbol_value += text_offset;
269 #ifdef SMASH_TEXT_ADDRESS
270               SMASH_TEXT_ADDRESS (bufp->symbol_value);
271 #endif
272               break;
273
274             case ST_STUB:
275               symname = bufp->name.n_strx + stringtab;
276               ms_type = mst_solib_trampoline;
277               bufp->symbol_value += text_offset;
278 #ifdef SMASH_TEXT_ADDRESS
279               SMASH_TEXT_ADDRESS (bufp->symbol_value);
280 #endif
281               break;
282
283
284             case ST_DATA:
285               symname = bufp->name.n_strx + stringtab;
286               bufp->symbol_value += data_offset;
287               ms_type = mst_file_data;
288               goto check_strange_names;
289
290             default:
291               continue;
292             }
293           break;
294
295           /* This can happen for common symbols when -E is passed to the
296              final link.  No idea _why_ that would make the linker force
297              common symbols to have an SS_UNSAT scope, but it does.
298
299              This also happens for weak symbols, but their type is
300              ST_DATA.  */
301         case SS_UNSAT:
302           switch (bufp->symbol_type)
303             {
304             case ST_STORAGE:
305             case ST_DATA:
306               symname = bufp->name.n_strx + stringtab;
307               bufp->symbol_value += data_offset;
308               ms_type = mst_data;
309               break;
310
311             default:
312               continue;
313             }
314           break;
315
316         default:
317           continue;
318         }
319
320       if (bufp->name.n_strx > obj_som_stringtab_size (abfd))
321         error ("Invalid symbol data; bad HP string table offset: %d",
322                bufp->name.n_strx);
323
324       prim_record_minimal_symbol (symname, bufp->symbol_value, ms_type,
325                                   objfile);
326     }
327 }
328
329 /* Scan and build partial symbols for a symbol file.
330    We have been initialized by a call to som_symfile_init, which 
331    currently does nothing.
332
333    SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
334    in each section.  This is ignored, as it isn't needed for SOM.
335
336    MAINLINE is true if we are reading the main symbol
337    table (as opposed to a shared lib or dynamically loaded file).
338
339    This function only does the minimum work necessary for letting the
340    user "name" things symbolically; it does not read the entire symtab.
341    Instead, it reads the external and static symbols and puts them in partial
342    symbol tables.  When more extensive information is requested of a
343    file, the corresponding partial symbol table is mutated into a full
344    fledged symbol table by going back and reading the symbols
345    for real.
346
347    We look for sections with specific names, to tell us what debug
348    format to look for:  FIXME!!!
349
350    somstab_build_psymtabs() handles STABS symbols.
351
352    Note that SOM files have a "minimal" symbol table, which is vaguely
353    reminiscent of a COFF symbol table, but has only the minimal information
354    necessary for linking.  We process this also, and use the information to
355    build gdb's minimal symbol table.  This gives us some minimal debugging
356    capability even for files compiled without -g.  */
357
358 static void
359 som_symfile_read (objfile, mainline)
360      struct objfile *objfile;
361      int mainline;
362 {
363   bfd *abfd = objfile->obfd;
364   struct cleanup *back_to;
365
366   do_pxdb (symfile_bfd_open (objfile->name));
367
368   init_minimal_symbol_collection ();
369   back_to = make_cleanup ((make_cleanup_func) discard_minimal_symbols, 0);
370
371   /* Read in the import list and the export list.  Currently
372      the export list isn't used; the import list is used in
373      hp-symtab-read.c to handle static vars declared in other
374      shared libraries. */
375   init_import_symbols (objfile);
376 #if 0                           /* Export symbols not used today 1997-08-05 */
377   init_export_symbols (objfile);
378 #else
379   objfile->export_list = NULL;
380   objfile->export_list_size = 0;
381 #endif
382
383   /* Process the normal SOM symbol table first. 
384      This reads in the DNTT and string table, but doesn't
385      actually scan the DNTT. It does scan the linker symbol
386      table and thus build up a "minimal symbol table". */
387
388   som_symtab_read (abfd, objfile, objfile->section_offsets);
389
390   /* Now read information from the stabs debug sections.
391      This is a no-op for SOM.
392      Perhaps it is intended for some kind of mixed STABS/SOM
393      situation? */
394   stabsect_build_psymtabs (objfile, mainline,
395                            "$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$");
396
397   /* Now read the native debug information. 
398      This builds the psymtab. This used to be done via a scan of
399      the DNTT, but is now done via the PXDB-built quick-lookup tables
400      together with a scan of the GNTT. See hp-psymtab-read.c. */
401   hpread_build_psymtabs (objfile, mainline);
402
403   /* Install any minimal symbols that have been collected as the current
404      minimal symbols for this objfile. 
405      Further symbol-reading is done incrementally, file-by-file,
406      in a step known as "psymtab-to-symtab" expansion. hp-symtab-read.c
407      contains the code to do the actual DNTT scanning and symtab building. */
408   install_minimal_symbols (objfile);
409
410   /* Force hppa-tdep.c to re-read the unwind descriptors.  */
411   objfile->obj_private = NULL;
412   do_cleanups (back_to);
413 }
414
415 /* Initialize anything that needs initializing when a completely new symbol
416    file is specified (not just adding some symbols from another file, e.g. a
417    shared library).
418
419    We reinitialize buildsym, since we may be reading stabs from a SOM file.  */
420
421 static void
422 som_new_init (ignore)
423      struct objfile *ignore;
424 {
425   stabsread_new_init ();
426   buildsym_new_init ();
427 }
428
429 /* Perform any local cleanups required when we are done with a particular
430    objfile.  I.E, we are in the process of discarding all symbol information
431    for an objfile, freeing up all memory held for it, and unlinking the
432    objfile struct from the global list of known objfiles. */
433
434 static void
435 som_symfile_finish (objfile)
436      struct objfile *objfile;
437 {
438   if (objfile->sym_stab_info != NULL)
439     {
440       mfree (objfile->md, objfile->sym_stab_info);
441     }
442   hpread_symfile_finish (objfile);
443 }
444
445 /* SOM specific initialization routine for reading symbols.  */
446
447 static void
448 som_symfile_init (objfile)
449      struct objfile *objfile;
450 {
451   /* SOM objects may be reordered, so set OBJF_REORDERED.  If we
452      find this causes a significant slowdown in gdb then we could
453      set it in the debug symbol readers only when necessary.  */
454   objfile->flags |= OBJF_REORDERED;
455   hpread_symfile_init (objfile);
456 }
457
458 /* SOM specific parsing routine for section offsets.
459
460    Plain and simple for now.  */
461
462 static void
463 som_symfile_offsets (objfile, addrs)
464      struct objfile *objfile;
465      struct section_addr_info *addrs;
466 {
467   int i;
468   CORE_ADDR text_addr;
469
470   objfile->num_sections = SECT_OFF_MAX;
471   objfile->section_offsets = (struct section_offsets *)
472     obstack_alloc (&objfile->psymbol_obstack, SIZEOF_SECTION_OFFSETS);
473
474   /* FIXME: ezannoni 2000-04-20 The section names in SOM are not
475      .text, .data, etc, but $TEXT$, $DATA$,... We should initialize
476      SET_OFF_* from bfd. (See default_symfile_offsets()). But I don't
477      know the correspondence between SOM sections and GDB's idea of
478      section names. So for now we default to what is was before these
479      changes.*/
480   objfile->sect_index_text = 0;
481   objfile->sect_index_data = 1;
482   objfile->sect_index_bss = 2;
483   objfile->sect_index_rodata = 3;
484
485   /* First see if we're a shared library.  If so, get the section
486      offsets from the library, else get them from addrs.  */
487   if (!som_solib_section_offsets (objfile, objfile->section_offsets))
488     {
489       /* Note: Here is OK to compare with ".text" because this is the
490          name that gdb itself gives to that section, not the SOM
491          name. */
492       for (i = 0; i < SECT_OFF_MAX && addrs->other[i].name; i++)
493         if (strcmp (addrs->other[i].name, ".text") == 0)
494           break;
495       text_addr = addrs->other[i].addr;
496
497       for (i = 0; i < SECT_OFF_MAX; i++)
498         ANOFFSET (objfile->section_offsets, i) = text_addr;
499     }
500 }
501
502 /* Read in and initialize the SOM import list which is present
503    for all executables and shared libraries.  The import list
504    consists of the symbols that are referenced in OBJFILE but
505    not defined there.  (Variables that are imported are dealt
506    with as "loc_indirect" vars.)
507    Return value = number of import symbols read in. */
508 int
509 init_import_symbols (objfile)
510      struct objfile *objfile;
511 {
512   unsigned int import_list;
513   unsigned int import_list_size;
514   unsigned int string_table;
515   unsigned int string_table_size;
516   char *string_buffer;
517   register int i;
518   register int j;
519   register int k;
520   asection *text_section;       /* section handle */
521   unsigned int dl_header[12];   /* SOM executable header */
522
523   /* A struct for an entry in the SOM import list */
524   typedef struct
525     {
526       int name;                 /* index into the string table */
527       short dont_care1;         /* we don't use this */
528       unsigned char type;       /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
529       unsigned int reserved2:8; /* not used */
530     }
531   SomImportEntry;
532
533   /* We read 100 entries in at a time from the disk file. */
534 #define SOM_READ_IMPORTS_NUM         100
535 #define SOM_READ_IMPORTS_CHUNK_SIZE  (sizeof (SomImportEntry) * SOM_READ_IMPORTS_NUM)
536   SomImportEntry buffer[SOM_READ_IMPORTS_NUM];
537
538   /* Initialize in case we error out */
539   objfile->import_list = NULL;
540   objfile->import_list_size = 0;
541
542   /* It doesn't work, for some reason, to read in space $TEXT$;
543      the subspace $SHLIB_INFO$ has to be used.  Some BFD quirk? pai/1997-08-05 */
544   text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
545   if (!text_section)
546     return 0;
547   /* Get the SOM executable header */
548   bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
549
550   /* Check header version number for 10.x HP-UX */
551   /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
552      FIXME: Change for future HP-UX releases and mods to the SOM executable format */
553   if (dl_header[0] != 93092112)
554     return 0;
555
556   import_list = dl_header[4];
557   import_list_size = dl_header[5];
558   if (!import_list_size)
559     return 0;
560   string_table = dl_header[10];
561   string_table_size = dl_header[11];
562   if (!string_table_size)
563     return 0;
564
565   /* Suck in SOM string table */
566   string_buffer = (char *) xmalloc (string_table_size);
567   bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
568                             string_table, string_table_size);
569
570   /* Allocate import list in the psymbol obstack; this has nothing
571      to do with psymbols, just a matter of convenience.  We want the
572      import list to be freed when the objfile is deallocated */
573   objfile->import_list
574     = (ImportEntry *) obstack_alloc (&objfile->psymbol_obstack,
575                                    import_list_size * sizeof (ImportEntry));
576
577   /* Read in the import entries, a bunch at a time */
578   for (j = 0, k = 0;
579        j < (import_list_size / SOM_READ_IMPORTS_NUM);
580        j++)
581     {
582       bfd_get_section_contents (objfile->obfd, text_section, buffer,
583                               import_list + j * SOM_READ_IMPORTS_CHUNK_SIZE,
584                                 SOM_READ_IMPORTS_CHUNK_SIZE);
585       for (i = 0; i < SOM_READ_IMPORTS_NUM; i++, k++)
586         {
587           if (buffer[i].type != (unsigned char) 0)
588             {
589               objfile->import_list[k]
590                 = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
591               strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
592               /* Some day we might want to record the type and other information too */
593             }
594           else                  /* null type */
595             objfile->import_list[k] = NULL;
596
597         }
598     }
599
600   /* Get the leftovers */
601   if (k < import_list_size)
602     bfd_get_section_contents (objfile->obfd, text_section, buffer,
603                               import_list + k * sizeof (SomImportEntry),
604                           (import_list_size - k) * sizeof (SomImportEntry));
605   for (i = 0; k < import_list_size; i++, k++)
606     {
607       if (buffer[i].type != (unsigned char) 0)
608         {
609           objfile->import_list[k]
610             = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
611           strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
612           /* Some day we might want to record the type and other information too */
613         }
614       else
615         objfile->import_list[k] = NULL;
616     }
617
618   objfile->import_list_size = import_list_size;
619   free (string_buffer);
620   return import_list_size;
621 }
622
623 /* Read in and initialize the SOM export list which is present
624    for all executables and shared libraries.  The import list
625    consists of the symbols that are referenced in OBJFILE but
626    not defined there.  (Variables that are imported are dealt
627    with as "loc_indirect" vars.)
628    Return value = number of import symbols read in. */
629 int
630 init_export_symbols (objfile)
631      struct objfile *objfile;
632 {
633   unsigned int export_list;
634   unsigned int export_list_size;
635   unsigned int string_table;
636   unsigned int string_table_size;
637   char *string_buffer;
638   register int i;
639   register int j;
640   register int k;
641   asection *text_section;       /* section handle */
642   unsigned int dl_header[12];   /* SOM executable header */
643
644   /* A struct for an entry in the SOM export list */
645   typedef struct
646     {
647       int next;                 /* for hash table use -- we don't use this */
648       int name;                 /* index into string table */
649       int value;                /* offset or plabel */
650       int dont_care1;           /* not used */
651       unsigned char type;       /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
652       char dont_care2;          /* not used */
653       short dont_care3;         /* not used */
654     }
655   SomExportEntry;
656
657   /* We read 100 entries in at a time from the disk file. */
658 #define SOM_READ_EXPORTS_NUM         100
659 #define SOM_READ_EXPORTS_CHUNK_SIZE  (sizeof (SomExportEntry) * SOM_READ_EXPORTS_NUM)
660   SomExportEntry buffer[SOM_READ_EXPORTS_NUM];
661
662   /* Initialize in case we error out */
663   objfile->export_list = NULL;
664   objfile->export_list_size = 0;
665
666   /* It doesn't work, for some reason, to read in space $TEXT$;
667      the subspace $SHLIB_INFO$ has to be used.  Some BFD quirk? pai/1997-08-05 */
668   text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
669   if (!text_section)
670     return 0;
671   /* Get the SOM executable header */
672   bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
673
674   /* Check header version number for 10.x HP-UX */
675   /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
676      FIXME: Change for future HP-UX releases and mods to the SOM executable format */
677   if (dl_header[0] != 93092112)
678     return 0;
679
680   export_list = dl_header[8];
681   export_list_size = dl_header[9];
682   if (!export_list_size)
683     return 0;
684   string_table = dl_header[10];
685   string_table_size = dl_header[11];
686   if (!string_table_size)
687     return 0;
688
689   /* Suck in SOM string table */
690   string_buffer = (char *) xmalloc (string_table_size);
691   bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
692                             string_table, string_table_size);
693
694   /* Allocate export list in the psymbol obstack; this has nothing
695      to do with psymbols, just a matter of convenience.  We want the
696      export list to be freed when the objfile is deallocated */
697   objfile->export_list
698     = (ExportEntry *) obstack_alloc (&objfile->psymbol_obstack,
699                                    export_list_size * sizeof (ExportEntry));
700
701   /* Read in the export entries, a bunch at a time */
702   for (j = 0, k = 0;
703        j < (export_list_size / SOM_READ_EXPORTS_NUM);
704        j++)
705     {
706       bfd_get_section_contents (objfile->obfd, text_section, buffer,
707                               export_list + j * SOM_READ_EXPORTS_CHUNK_SIZE,
708                                 SOM_READ_EXPORTS_CHUNK_SIZE);
709       for (i = 0; i < SOM_READ_EXPORTS_NUM; i++, k++)
710         {
711           if (buffer[i].type != (unsigned char) 0)
712             {
713               objfile->export_list[k].name
714                 = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
715               strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
716               objfile->export_list[k].address = buffer[i].value;
717               /* Some day we might want to record the type and other information too */
718             }
719           else
720             /* null type */
721             {
722               objfile->export_list[k].name = NULL;
723               objfile->export_list[k].address = 0;
724             }
725         }
726     }
727
728   /* Get the leftovers */
729   if (k < export_list_size)
730     bfd_get_section_contents (objfile->obfd, text_section, buffer,
731                               export_list + k * sizeof (SomExportEntry),
732                           (export_list_size - k) * sizeof (SomExportEntry));
733   for (i = 0; k < export_list_size; i++, k++)
734     {
735       if (buffer[i].type != (unsigned char) 0)
736         {
737           objfile->export_list[k].name
738             = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
739           strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
740           /* Some day we might want to record the type and other information too */
741           objfile->export_list[k].address = buffer[i].value;
742         }
743       else
744         {
745           objfile->export_list[k].name = NULL;
746           objfile->export_list[k].address = 0;
747         }
748     }
749
750   objfile->export_list_size = export_list_size;
751   free (string_buffer);
752   return export_list_size;
753 }
754 \f
755
756
757 /* Register that we are able to handle SOM object file formats.  */
758
759 static struct sym_fns som_sym_fns =
760 {
761   bfd_target_som_flavour,
762   som_new_init,                 /* sym_new_init: init anything gbl to entire symtab */
763   som_symfile_init,             /* sym_init: read initial info, setup for sym_read() */
764   som_symfile_read,             /* sym_read: read a symbol file into symtab */
765   som_symfile_finish,           /* sym_finish: finished with file, cleanup */
766   som_symfile_offsets,          /* sym_offsets:  Translate ext. to int. relocation */
767   NULL                          /* next: pointer to next struct sym_fns */
768 };
769
770 void
771 _initialize_somread ()
772 {
773   add_symtab_fns (&som_sym_fns);
774 }