This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / gdb / somread.c
1 /* Read HP PA/Risc object files for GDB.
2    Copyright 1991, 1992, 1996, 1999 Free Software Foundation, Inc.
3    Written by Fred Fish at Cygnus Support.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "bfd.h"
24 #include <syms.h>
25 #include "symtab.h"
26 #include "symfile.h"
27 #include "objfiles.h"
28 #include "buildsym.h"
29 #include "stabsread.h"
30 #include "gdb-stabs.h"
31 #include "complaints.h"
32 #include "gdb_string.h"
33 #include "demangle.h"
34 #include "som.h"
35 #include "libhppa.h"
36
37 /* Various things we might complain about... */
38
39 static void
40 som_symfile_init PARAMS ((struct objfile *));
41
42 static void
43 som_new_init PARAMS ((struct objfile *));
44
45 static void
46 som_symfile_read PARAMS ((struct objfile *, int));
47
48 static void
49 som_symfile_finish PARAMS ((struct objfile *));
50
51 static void
52 som_symtab_read PARAMS ((bfd *, struct objfile *,
53                          struct section_offsets *));
54
55 static struct section_offsets *
56 som_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
57
58 /* FIXME: These should really be in a common header somewhere */
59
60 extern void
61 hpread_build_psymtabs PARAMS ((struct objfile *, struct section_offsets *, 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, 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
495 is_in_import_list (name, objfile)
496      char *name;
497      struct objfile *objfile;
498 {
499   register int i;
500
501   if (!objfile ||
502       !name ||
503       !*name)
504     return 0;
505
506   for (i = 0; i < objfile->import_list_size; i++)
507     if (objfile->import_list[i] && STREQ (name, objfile->import_list[i]))
508       return 1;
509   return 0;
510 }
511
512
513 /* Read in and initialize the SOM import list which is present
514    for all executables and shared libraries.  The import list
515    consists of the symbols that are referenced in OBJFILE but
516    not defined there.  (Variables that are imported are dealt
517    with as "loc_indirect" vars.)
518    Return value = number of import symbols read in. */
519 int
520 init_import_symbols (objfile)
521      struct objfile *objfile;
522 {
523   unsigned int import_list;
524   unsigned int import_list_size;
525   unsigned int string_table;
526   unsigned int string_table_size;
527   char *string_buffer;
528   register int i;
529   register int j;
530   register int k;
531   asection *text_section;       /* section handle */
532   unsigned int dl_header[12];   /* SOM executable header */
533
534   /* A struct for an entry in the SOM import list */
535   typedef struct
536     {
537       int name;                 /* index into the string table */
538       short dont_care1;         /* we don't use this */
539       unsigned char type;       /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
540       unsigned int reserved2:8; /* not used */
541     }
542   SomImportEntry;
543
544   /* We read 100 entries in at a time from the disk file. */
545 #define SOM_READ_IMPORTS_NUM         100
546 #define SOM_READ_IMPORTS_CHUNK_SIZE  (sizeof (SomImportEntry) * SOM_READ_IMPORTS_NUM)
547   SomImportEntry buffer[SOM_READ_IMPORTS_NUM];
548
549   /* Initialize in case we error out */
550   objfile->import_list = NULL;
551   objfile->import_list_size = 0;
552
553   /* It doesn't work, for some reason, to read in space $TEXT$;
554      the subspace $SHLIB_INFO$ has to be used.  Some BFD quirk? pai/1997-08-05 */
555   text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
556   if (!text_section)
557     return 0;
558   /* Get the SOM executable header */
559   bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
560
561   /* Check header version number for 10.x HP-UX */
562   /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
563      FIXME: Change for future HP-UX releases and mods to the SOM executable format */
564   if (dl_header[0] != 93092112)
565     return 0;
566
567   import_list = dl_header[4];
568   import_list_size = dl_header[5];
569   if (!import_list_size)
570     return 0;
571   string_table = dl_header[10];
572   string_table_size = dl_header[11];
573   if (!string_table_size)
574     return 0;
575
576   /* Suck in SOM string table */
577   string_buffer = (char *) xmalloc (string_table_size);
578   bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
579                             string_table, string_table_size);
580
581   /* Allocate import list in the psymbol obstack; this has nothing
582      to do with psymbols, just a matter of convenience.  We want the
583      import list to be freed when the objfile is deallocated */
584   objfile->import_list
585     = (ImportEntry *) obstack_alloc (&objfile->psymbol_obstack,
586                                    import_list_size * sizeof (ImportEntry));
587
588   /* Read in the import entries, a bunch at a time */
589   for (j = 0, k = 0;
590        j < (import_list_size / SOM_READ_IMPORTS_NUM);
591        j++)
592     {
593       bfd_get_section_contents (objfile->obfd, text_section, buffer,
594                               import_list + j * SOM_READ_IMPORTS_CHUNK_SIZE,
595                                 SOM_READ_IMPORTS_CHUNK_SIZE);
596       for (i = 0; i < SOM_READ_IMPORTS_NUM; 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                  /* null type */
606             objfile->import_list[k] = NULL;
607
608         }
609     }
610
611   /* Get the leftovers */
612   if (k < import_list_size)
613     bfd_get_section_contents (objfile->obfd, text_section, buffer,
614                               import_list + k * sizeof (SomImportEntry),
615                           (import_list_size - k) * sizeof (SomImportEntry));
616   for (i = 0; k < import_list_size; i++, k++)
617     {
618       if (buffer[i].type != (unsigned char) 0)
619         {
620           objfile->import_list[k]
621             = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
622           strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
623           /* Some day we might want to record the type and other information too */
624         }
625       else
626         objfile->import_list[k] = NULL;
627     }
628
629   objfile->import_list_size = import_list_size;
630   free (string_buffer);
631   return import_list_size;
632 }
633
634 /* Read in and initialize the SOM export list which is present
635    for all executables and shared libraries.  The import list
636    consists of the symbols that are referenced in OBJFILE but
637    not defined there.  (Variables that are imported are dealt
638    with as "loc_indirect" vars.)
639    Return value = number of import symbols read in. */
640 int
641 init_export_symbols (objfile)
642      struct objfile *objfile;
643 {
644   unsigned int export_list;
645   unsigned int export_list_size;
646   unsigned int string_table;
647   unsigned int string_table_size;
648   char *string_buffer;
649   register int i;
650   register int j;
651   register int k;
652   asection *text_section;       /* section handle */
653   unsigned int dl_header[12];   /* SOM executable header */
654
655   /* A struct for an entry in the SOM export list */
656   typedef struct
657     {
658       int next;                 /* for hash table use -- we don't use this */
659       int name;                 /* index into string table */
660       int value;                /* offset or plabel */
661       int dont_care1;           /* not used */
662       unsigned char type;       /* 0 = NULL, 2 = Data, 3 = Code, 7 = Storage, 13 = Plabel */
663       char dont_care2;          /* not used */
664       short dont_care3;         /* not used */
665     }
666   SomExportEntry;
667
668   /* We read 100 entries in at a time from the disk file. */
669 #define SOM_READ_EXPORTS_NUM         100
670 #define SOM_READ_EXPORTS_CHUNK_SIZE  (sizeof (SomExportEntry) * SOM_READ_EXPORTS_NUM)
671   SomExportEntry buffer[SOM_READ_EXPORTS_NUM];
672
673   /* Initialize in case we error out */
674   objfile->export_list = NULL;
675   objfile->export_list_size = 0;
676
677   /* It doesn't work, for some reason, to read in space $TEXT$;
678      the subspace $SHLIB_INFO$ has to be used.  Some BFD quirk? pai/1997-08-05 */
679   text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
680   if (!text_section)
681     return 0;
682   /* Get the SOM executable header */
683   bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
684
685   /* Check header version number for 10.x HP-UX */
686   /* Currently we deal only with 10.x systems; on 9.x the version # is 89060912.
687      FIXME: Change for future HP-UX releases and mods to the SOM executable format */
688   if (dl_header[0] != 93092112)
689     return 0;
690
691   export_list = dl_header[8];
692   export_list_size = dl_header[9];
693   if (!export_list_size)
694     return 0;
695   string_table = dl_header[10];
696   string_table_size = dl_header[11];
697   if (!string_table_size)
698     return 0;
699
700   /* Suck in SOM string table */
701   string_buffer = (char *) xmalloc (string_table_size);
702   bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
703                             string_table, string_table_size);
704
705   /* Allocate export list in the psymbol obstack; this has nothing
706      to do with psymbols, just a matter of convenience.  We want the
707      export list to be freed when the objfile is deallocated */
708   objfile->export_list
709     = (ExportEntry *) obstack_alloc (&objfile->psymbol_obstack,
710                                    export_list_size * sizeof (ExportEntry));
711
712   /* Read in the export entries, a bunch at a time */
713   for (j = 0, k = 0;
714        j < (export_list_size / SOM_READ_EXPORTS_NUM);
715        j++)
716     {
717       bfd_get_section_contents (objfile->obfd, text_section, buffer,
718                               export_list + j * SOM_READ_EXPORTS_CHUNK_SIZE,
719                                 SOM_READ_EXPORTS_CHUNK_SIZE);
720       for (i = 0; i < SOM_READ_EXPORTS_NUM; i++, k++)
721         {
722           if (buffer[i].type != (unsigned char) 0)
723             {
724               objfile->export_list[k].name
725                 = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
726               strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
727               objfile->export_list[k].address = buffer[i].value;
728               /* Some day we might want to record the type and other information too */
729             }
730           else
731             /* null type */
732             {
733               objfile->export_list[k].name = NULL;
734               objfile->export_list[k].address = 0;
735             }
736         }
737     }
738
739   /* Get the leftovers */
740   if (k < export_list_size)
741     bfd_get_section_contents (objfile->obfd, text_section, buffer,
742                               export_list + k * sizeof (SomExportEntry),
743                           (export_list_size - k) * sizeof (SomExportEntry));
744   for (i = 0; k < export_list_size; i++, k++)
745     {
746       if (buffer[i].type != (unsigned char) 0)
747         {
748           objfile->export_list[k].name
749             = (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
750           strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
751           /* Some day we might want to record the type and other information too */
752           objfile->export_list[k].address = buffer[i].value;
753         }
754       else
755         {
756           objfile->export_list[k].name = NULL;
757           objfile->export_list[k].address = 0;
758         }
759     }
760
761   objfile->export_list_size = export_list_size;
762   free (string_buffer);
763   return export_list_size;
764 }
765 \f
766
767
768 /* Register that we are able to handle SOM object file formats.  */
769
770 static struct sym_fns som_sym_fns =
771 {
772   bfd_target_som_flavour,
773   som_new_init,                 /* sym_new_init: init anything gbl to entire symtab */
774   som_symfile_init,             /* sym_init: read initial info, setup for sym_read() */
775   som_symfile_read,             /* sym_read: read a symbol file into symtab */
776   som_symfile_finish,           /* sym_finish: finished with file, cleanup */
777   som_symfile_offsets,          /* sym_offsets:  Translate ext. to int. relocation */
778   NULL                          /* next: pointer to next struct sym_fns */
779 };
780
781 void
782 _initialize_somread ()
783 {
784   add_symtab_fns (&som_sym_fns);
785 }