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