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