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