2000-03-21 J.T. Conklin <jtc@redback.com>
[platform/upstream/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
469   objfile->num_sections = SECT_OFF_MAX;
470   objfile->section_offsets = (struct section_offsets *)
471     obstack_alloc (&objfile->psymbol_obstack, SIZEOF_SECTION_OFFSETS);
472
473   /* First see if we're a shared library.  If so, get the section
474      offsets from the library, else get them from addrs.  */
475   if (!som_solib_section_offsets (objfile, objfile->section_offsets))
476     {
477       for (i = 0; i < SECT_OFF_MAX; i++)
478         ANOFFSET (objfile->section_offsets, i) = addrs -> text_addr;
479     }
480 }
481
482 /* Read in and initialize the SOM import list which is present
483    for all executables and shared libraries.  The import list
484    consists of the symbols that are referenced in OBJFILE but
485    not defined there.  (Variables that are imported are dealt
486    with as "loc_indirect" vars.)
487    Return value = number of import symbols read in. */
488 int
489 init_import_symbols (objfile)
490      struct objfile *objfile;
491 {
492   unsigned int import_list;
493   unsigned int import_list_size;
494   unsigned int string_table;
495   unsigned int string_table_size;
496   char *string_buffer;
497   register int i;
498   register int j;
499   register int k;
500   asection *text_section;       /* section handle */
501   unsigned int dl_header[12];   /* SOM executable header */
502
503   /* A struct for an entry in the SOM import list */
504   typedef struct
505     {
506       int name;                 /* index into the string table */
507       short dont_care1;         /* we don't use this */
508       unsigned char type;       /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
509       unsigned int reserved2:8; /* not used */
510     }
511   SomImportEntry;
512
513   /* We read 100 entries in at a time from the disk file. */
514 #define SOM_READ_IMPORTS_NUM         100
515 #define SOM_READ_IMPORTS_CHUNK_SIZE  (sizeof (SomImportEntry) * SOM_READ_IMPORTS_NUM)
516   SomImportEntry buffer[SOM_READ_IMPORTS_NUM];
517
518   /* Initialize in case we error out */
519   objfile->import_list = NULL;
520   objfile->import_list_size = 0;
521
522   /* It doesn't work, for some reason, to read in space $TEXT$;
523      the subspace $SHLIB_INFO$ has to be used.  Some BFD quirk? pai/1997-08-05 */
524   text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
525   if (!text_section)
526     return 0;
527   /* Get the SOM executable header */
528   bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
529
530   /* Check header version number for 10.x HP-UX */
531   /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
532      FIXME: Change for future HP-UX releases and mods to the SOM executable format */
533   if (dl_header[0] != 93092112)
534     return 0;
535
536   import_list = dl_header[4];
537   import_list_size = dl_header[5];
538   if (!import_list_size)
539     return 0;
540   string_table = dl_header[10];
541   string_table_size = dl_header[11];
542   if (!string_table_size)
543     return 0;
544
545   /* Suck in SOM string table */
546   string_buffer = (char *) xmalloc (string_table_size);
547   bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
548                             string_table, string_table_size);
549
550   /* Allocate import list in the psymbol obstack; this has nothing
551      to do with psymbols, just a matter of convenience.  We want the
552      import list to be freed when the objfile is deallocated */
553   objfile->import_list
554     = (ImportEntry *) obstack_alloc (&objfile->psymbol_obstack,
555                                    import_list_size * sizeof (ImportEntry));
556
557   /* Read in the import entries, a bunch at a time */
558   for (j = 0, k = 0;
559        j < (import_list_size / SOM_READ_IMPORTS_NUM);
560        j++)
561     {
562       bfd_get_section_contents (objfile->obfd, text_section, buffer,
563                               import_list + j * SOM_READ_IMPORTS_CHUNK_SIZE,
564                                 SOM_READ_IMPORTS_CHUNK_SIZE);
565       for (i = 0; i < SOM_READ_IMPORTS_NUM; i++, k++)
566         {
567           if (buffer[i].type != (unsigned char) 0)
568             {
569               objfile->import_list[k]
570                 = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
571               strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
572               /* Some day we might want to record the type and other information too */
573             }
574           else                  /* null type */
575             objfile->import_list[k] = NULL;
576
577         }
578     }
579
580   /* Get the leftovers */
581   if (k < import_list_size)
582     bfd_get_section_contents (objfile->obfd, text_section, buffer,
583                               import_list + k * sizeof (SomImportEntry),
584                           (import_list_size - k) * sizeof (SomImportEntry));
585   for (i = 0; k < import_list_size; 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
595         objfile->import_list[k] = NULL;
596     }
597
598   objfile->import_list_size = import_list_size;
599   free (string_buffer);
600   return import_list_size;
601 }
602
603 /* Read in and initialize the SOM export list which is present
604    for all executables and shared libraries.  The import list
605    consists of the symbols that are referenced in OBJFILE but
606    not defined there.  (Variables that are imported are dealt
607    with as "loc_indirect" vars.)
608    Return value = number of import symbols read in. */
609 int
610 init_export_symbols (objfile)
611      struct objfile *objfile;
612 {
613   unsigned int export_list;
614   unsigned int export_list_size;
615   unsigned int string_table;
616   unsigned int string_table_size;
617   char *string_buffer;
618   register int i;
619   register int j;
620   register int k;
621   asection *text_section;       /* section handle */
622   unsigned int dl_header[12];   /* SOM executable header */
623
624   /* A struct for an entry in the SOM export list */
625   typedef struct
626     {
627       int next;                 /* for hash table use -- we don't use this */
628       int name;                 /* index into string table */
629       int value;                /* offset or plabel */
630       int dont_care1;           /* not used */
631       unsigned char type;       /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
632       char dont_care2;          /* not used */
633       short dont_care3;         /* not used */
634     }
635   SomExportEntry;
636
637   /* We read 100 entries in at a time from the disk file. */
638 #define SOM_READ_EXPORTS_NUM         100
639 #define SOM_READ_EXPORTS_CHUNK_SIZE  (sizeof (SomExportEntry) * SOM_READ_EXPORTS_NUM)
640   SomExportEntry buffer[SOM_READ_EXPORTS_NUM];
641
642   /* Initialize in case we error out */
643   objfile->export_list = NULL;
644   objfile->export_list_size = 0;
645
646   /* It doesn't work, for some reason, to read in space $TEXT$;
647      the subspace $SHLIB_INFO$ has to be used.  Some BFD quirk? pai/1997-08-05 */
648   text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
649   if (!text_section)
650     return 0;
651   /* Get the SOM executable header */
652   bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
653
654   /* Check header version number for 10.x HP-UX */
655   /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
656      FIXME: Change for future HP-UX releases and mods to the SOM executable format */
657   if (dl_header[0] != 93092112)
658     return 0;
659
660   export_list = dl_header[8];
661   export_list_size = dl_header[9];
662   if (!export_list_size)
663     return 0;
664   string_table = dl_header[10];
665   string_table_size = dl_header[11];
666   if (!string_table_size)
667     return 0;
668
669   /* Suck in SOM string table */
670   string_buffer = (char *) xmalloc (string_table_size);
671   bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
672                             string_table, string_table_size);
673
674   /* Allocate export list in the psymbol obstack; this has nothing
675      to do with psymbols, just a matter of convenience.  We want the
676      export list to be freed when the objfile is deallocated */
677   objfile->export_list
678     = (ExportEntry *) obstack_alloc (&objfile->psymbol_obstack,
679                                    export_list_size * sizeof (ExportEntry));
680
681   /* Read in the export entries, a bunch at a time */
682   for (j = 0, k = 0;
683        j < (export_list_size / SOM_READ_EXPORTS_NUM);
684        j++)
685     {
686       bfd_get_section_contents (objfile->obfd, text_section, buffer,
687                               export_list + j * SOM_READ_EXPORTS_CHUNK_SIZE,
688                                 SOM_READ_EXPORTS_CHUNK_SIZE);
689       for (i = 0; i < SOM_READ_EXPORTS_NUM; i++, k++)
690         {
691           if (buffer[i].type != (unsigned char) 0)
692             {
693               objfile->export_list[k].name
694                 = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
695               strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
696               objfile->export_list[k].address = buffer[i].value;
697               /* Some day we might want to record the type and other information too */
698             }
699           else
700             /* null type */
701             {
702               objfile->export_list[k].name = NULL;
703               objfile->export_list[k].address = 0;
704             }
705         }
706     }
707
708   /* Get the leftovers */
709   if (k < export_list_size)
710     bfd_get_section_contents (objfile->obfd, text_section, buffer,
711                               export_list + k * sizeof (SomExportEntry),
712                           (export_list_size - k) * sizeof (SomExportEntry));
713   for (i = 0; k < export_list_size; i++, k++)
714     {
715       if (buffer[i].type != (unsigned char) 0)
716         {
717           objfile->export_list[k].name
718             = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
719           strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
720           /* Some day we might want to record the type and other information too */
721           objfile->export_list[k].address = buffer[i].value;
722         }
723       else
724         {
725           objfile->export_list[k].name = NULL;
726           objfile->export_list[k].address = 0;
727         }
728     }
729
730   objfile->export_list_size = export_list_size;
731   free (string_buffer);
732   return export_list_size;
733 }
734 \f
735
736
737 /* Register that we are able to handle SOM object file formats.  */
738
739 static struct sym_fns som_sym_fns =
740 {
741   bfd_target_som_flavour,
742   som_new_init,                 /* sym_new_init: init anything gbl to entire symtab */
743   som_symfile_init,             /* sym_init: read initial info, setup for sym_read() */
744   som_symfile_read,             /* sym_read: read a symbol file into symtab */
745   som_symfile_finish,           /* sym_finish: finished with file, cleanup */
746   som_symfile_offsets,          /* sym_offsets:  Translate ext. to int. relocation */
747   NULL                          /* next: pointer to next struct sym_fns */
748 };
749
750 void
751 _initialize_somread ()
752 {
753   add_symtab_fns (&som_sym_fns);
754 }