OSDN Git Service

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