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