#include "defs.h"
#include "bfd.h"
#include <syms.h>
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
#include "buildsym.h"
#include "stabsread.h"
#include "gdb-stabs.h"
#include "complaints.h"
#include "gdb_string.h"
#include "demangle.h"
#include "som.h"
#include "libhppa.h"
static void som_symfile_init (struct objfile *);
static void som_new_init (struct objfile *);
static void som_symfile_read (struct objfile *, int);
static void som_symfile_finish (struct objfile *);
static void
som_symtab_read (bfd *, struct objfile *, struct section_offsets *);
static void
som_symfile_offsets (struct objfile *, struct section_addr_info *);
extern void hpread_build_psymtabs (struct objfile *, int);
extern void hpread_symfile_finish (struct objfile *);
extern void hpread_symfile_init (struct objfile *);
extern void do_pxdb (bfd *);
static void
som_symtab_read (bfd *abfd, struct objfile *objfile,
struct section_offsets *section_offsets)
{
unsigned int number_of_symbols;
int val, dynamic;
char *stringtab;
asection *shlib_info;
struct symbol_dictionary_record *buf, *bufp, *endbufp;
char *symname;
CONST int symsize = sizeof (struct symbol_dictionary_record);
CORE_ADDR text_offset, data_offset;
text_offset = ANOFFSET (section_offsets, 0);
data_offset = ANOFFSET (section_offsets, 1);
number_of_symbols = bfd_get_symcount (abfd);
buf = alloca (symsize * number_of_symbols);
bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET);
val = bfd_bread (buf, symsize * number_of_symbols, abfd);
if (val != symsize * number_of_symbols)
error ("Couldn't read symbol dictionary!");
stringtab = alloca (obj_som_stringtab_size (abfd));
bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET);
val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd);
if (val != obj_som_stringtab_size (abfd))
error ("Can't read in HP string table.");
dynamic = (text_offset != 0);
endbufp = buf + number_of_symbols;
for (bufp = buf; bufp < endbufp; ++bufp)
{
enum minimal_symbol_type ms_type;
QUIT;
switch (bufp->symbol_scope)
{
case SS_UNIVERSAL:
case SS_EXTERNAL:
switch (bufp->symbol_type)
{
case ST_SYM_EXT:
case ST_ARG_EXT:
continue;
case ST_CODE:
case ST_PRI_PROG:
case ST_SEC_PROG:
case ST_MILLICODE:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_ENTRY:
symname = bufp->name.n_strx + stringtab;
if (dynamic)
ms_type = mst_solib_trampoline;
else
ms_type = mst_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_STUB:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_solib_trampoline;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_DATA:
symname = bufp->name.n_strx + stringtab;
bufp->symbol_value += data_offset;
ms_type = mst_data;
break;
default:
continue;
}
break;
#if 0
case SS_GLOBAL:
#endif
case SS_LOCAL:
switch (bufp->symbol_type)
{
case ST_SYM_EXT:
case ST_ARG_EXT:
continue;
case ST_CODE:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_file_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
check_strange_names:
if ((symname[0] == 'L' && symname[1] == '$')
|| (symname[0] == '$' && symname[strlen (symname) - 1] == '$')
|| (symname[0] == 'D' && symname[1] == '$')
|| (strncmp (symname, "$PIC", 4) == 0))
continue;
break;
case ST_PRI_PROG:
case ST_SEC_PROG:
case ST_MILLICODE:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_file_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_ENTRY:
symname = bufp->name.n_strx + stringtab;
if (dynamic)
ms_type = mst_solib_trampoline;
else
ms_type = mst_file_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_STUB:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_solib_trampoline;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_DATA:
symname = bufp->name.n_strx + stringtab;
bufp->symbol_value += data_offset;
ms_type = mst_file_data;
goto check_strange_names;
default:
continue;
}
break;
case SS_UNSAT:
switch (bufp->symbol_type)
{
case ST_STORAGE:
case ST_DATA:
symname = bufp->name.n_strx + stringtab;
bufp->symbol_value += data_offset;
ms_type = mst_data;
break;
default:
continue;
}
break;
default:
continue;
}
if (bufp->name.n_strx > obj_som_stringtab_size (abfd))
error ("Invalid symbol data; bad HP string table offset: %d",
bufp->name.n_strx);
prim_record_minimal_symbol (symname, bufp->symbol_value, ms_type,
objfile);
}
}
static void
som_symfile_read (struct objfile *objfile, int mainline)
{
bfd *abfd = objfile->obfd;
struct cleanup *back_to;
do_pxdb (symfile_bfd_open (objfile->name));
init_import_symbols (objfile);
#if 0
init_export_symbols (objfile);
#else
objfile->export_list = NULL;
objfile->export_list_size = 0;
#endif
init_minimal_symbol_collection ();
som_symtab_read (abfd, objfile, objfile->section_offsets);
install_minimal_symbols (objfile);
init_minimal_symbol_collection ();
stabsect_build_psymtabs (objfile, mainline,
"$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$", "$DATA", "$BSS$");
install_minimal_symbols (objfile);
init_minimal_symbol_collection ();
hpread_build_psymtabs (objfile, mainline);
install_minimal_symbols (objfile);
install_minimal_symbols (objfile);
objfile->obj_private = NULL;
do_cleanups (back_to);
}
static void
som_new_init (struct objfile *ignore)
{
stabsread_new_init ();
buildsym_new_init ();
}
static void
som_symfile_finish (struct objfile *objfile)
{
if (objfile->sym_stab_info != NULL)
{
xmfree (objfile->md, objfile->sym_stab_info);
}
hpread_symfile_finish (objfile);
}
static void
som_symfile_init (struct objfile *objfile)
{
objfile->flags |= OBJF_REORDERED;
hpread_symfile_init (objfile);
}
static void
som_symfile_offsets (struct objfile *objfile, struct section_addr_info *addrs)
{
int i;
CORE_ADDR text_addr;
objfile->num_sections = SECT_OFF_MAX;
objfile->section_offsets = (struct section_offsets *)
obstack_alloc (&objfile->psymbol_obstack, SIZEOF_SECTION_OFFSETS);
objfile->sect_index_text = 0;
objfile->sect_index_data = 1;
objfile->sect_index_bss = 2;
objfile->sect_index_rodata = 3;
if (!som_solib_section_offsets (objfile, objfile->section_offsets))
{
for (i = 0; i < SECT_OFF_MAX && addrs->other[i].name; i++)
if (strcmp (addrs->other[i].name, ".text") == 0)
break;
text_addr = addrs->other[i].addr;
for (i = 0; i < SECT_OFF_MAX; i++)
(objfile->section_offsets)->offsets[i] = text_addr;
}
}
int
init_import_symbols (struct objfile *objfile)
{
unsigned int import_list;
unsigned int import_list_size;
unsigned int string_table;
unsigned int string_table_size;
char *string_buffer;
register int i;
register int j;
register int k;
asection *text_section;
unsigned int dl_header[12];
typedef struct
{
int name;
short dont_care1;
unsigned char type;
unsigned int reserved2:8;
}
SomImportEntry;
#define SOM_READ_IMPORTS_NUM 100
#define SOM_READ_IMPORTS_CHUNK_SIZE (sizeof (SomImportEntry) * SOM_READ_IMPORTS_NUM)
SomImportEntry buffer[SOM_READ_IMPORTS_NUM];
objfile->import_list = NULL;
objfile->import_list_size = 0;
text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
if (!text_section)
return 0;
bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
if (dl_header[0] != 93092112)
return 0;
import_list = dl_header[4];
import_list_size = dl_header[5];
if (!import_list_size)
return 0;
string_table = dl_header[10];
string_table_size = dl_header[11];
if (!string_table_size)
return 0;
string_buffer = (char *) xmalloc (string_table_size);
bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
string_table, string_table_size);
objfile->import_list
= (ImportEntry *) obstack_alloc (&objfile->psymbol_obstack,
import_list_size * sizeof (ImportEntry));
for (j = 0, k = 0;
j < (import_list_size / SOM_READ_IMPORTS_NUM);
j++)
{
bfd_get_section_contents (objfile->obfd, text_section, buffer,
import_list + j * SOM_READ_IMPORTS_CHUNK_SIZE,
SOM_READ_IMPORTS_CHUNK_SIZE);
for (i = 0; i < SOM_READ_IMPORTS_NUM; i++, k++)
{
if (buffer[i].type != (unsigned char) 0)
{
objfile->import_list[k]
= (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
}
else
objfile->import_list[k] = NULL;
}
}
if (k < import_list_size)
bfd_get_section_contents (objfile->obfd, text_section, buffer,
import_list + k * sizeof (SomImportEntry),
(import_list_size - k) * sizeof (SomImportEntry));
for (i = 0; k < import_list_size; i++, k++)
{
if (buffer[i].type != (unsigned char) 0)
{
objfile->import_list[k]
= (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
strcpy (objfile->import_list[k], string_buffer + buffer[i].name);
}
else
objfile->import_list[k] = NULL;
}
objfile->import_list_size = import_list_size;
xfree (string_buffer);
return import_list_size;
}
int
init_export_symbols (struct objfile *objfile)
{
unsigned int export_list;
unsigned int export_list_size;
unsigned int string_table;
unsigned int string_table_size;
char *string_buffer;
register int i;
register int j;
register int k;
asection *text_section;
unsigned int dl_header[12];
typedef struct
{
int next;
int name;
int value;
int dont_care1;
unsigned char type;
char dont_care2;
short dont_care3;
}
SomExportEntry;
#define SOM_READ_EXPORTS_NUM 100
#define SOM_READ_EXPORTS_CHUNK_SIZE (sizeof (SomExportEntry) * SOM_READ_EXPORTS_NUM)
SomExportEntry buffer[SOM_READ_EXPORTS_NUM];
objfile->export_list = NULL;
objfile->export_list_size = 0;
text_section = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
if (!text_section)
return 0;
bfd_get_section_contents (objfile->obfd, text_section, dl_header, 0, 12 * sizeof (int));
if (dl_header[0] != 93092112)
return 0;
export_list = dl_header[8];
export_list_size = dl_header[9];
if (!export_list_size)
return 0;
string_table = dl_header[10];
string_table_size = dl_header[11];
if (!string_table_size)
return 0;
string_buffer = (char *) xmalloc (string_table_size);
bfd_get_section_contents (objfile->obfd, text_section, string_buffer,
string_table, string_table_size);
objfile->export_list
= (ExportEntry *) obstack_alloc (&objfile->psymbol_obstack,
export_list_size * sizeof (ExportEntry));
for (j = 0, k = 0;
j < (export_list_size / SOM_READ_EXPORTS_NUM);
j++)
{
bfd_get_section_contents (objfile->obfd, text_section, buffer,
export_list + j * SOM_READ_EXPORTS_CHUNK_SIZE,
SOM_READ_EXPORTS_CHUNK_SIZE);
for (i = 0; i < SOM_READ_EXPORTS_NUM; i++, k++)
{
if (buffer[i].type != (unsigned char) 0)
{
objfile->export_list[k].name
= (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
objfile->export_list[k].address = buffer[i].value;
}
else
{
objfile->export_list[k].name = NULL;
objfile->export_list[k].address = 0;
}
}
}
if (k < export_list_size)
bfd_get_section_contents (objfile->obfd, text_section, buffer,
export_list + k * sizeof (SomExportEntry),
(export_list_size - k) * sizeof (SomExportEntry));
for (i = 0; k < export_list_size; i++, k++)
{
if (buffer[i].type != (unsigned char) 0)
{
objfile->export_list[k].name
= (char *) obstack_alloc (&objfile->psymbol_obstack, strlen (string_buffer + buffer[i].name) + 1);
strcpy (objfile->export_list[k].name, string_buffer + buffer[i].name);
objfile->export_list[k].address = buffer[i].value;
}
else
{
objfile->export_list[k].name = NULL;
objfile->export_list[k].address = 0;
}
}
objfile->export_list_size = export_list_size;
xfree (string_buffer);
return export_list_size;
}
static struct sym_fns som_sym_fns =
{
bfd_target_som_flavour,
som_new_init,
som_symfile_init,
som_symfile_read,
som_symfile_finish,
som_symfile_offsets,
NULL
};
void
_initialize_somread (void)
{
add_symtab_fns (&som_sym_fns);
}