#include "defs.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "breakpoint.h"
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
#include "buildsym.h"
#include "obstack.h"
#include "gdb-stabs.h"
#include "stabsread.h"
#include "gdbcmd.h"
#include "complaints.h"
#include "block.h"
#include "dictionary.h"
#include "readline/tilde.h"
#include "xsym.h"
#include <string.h>
#include <stdio.h>
struct type *sym_builtin_type_pstr;
struct type *sym_builtin_type_cstr;
static void
sym_complaint (void)
{
complaint (&symfile_complaints, "error parsing SYM-format symbol table");
}
struct sym_symfile_info
{
asymbol **syms;
long nsyms;
};
static void
sym_new_init (struct objfile *objfile)
{
}
static struct type *
sym_lookup_builtin_type (unsigned int num)
{
switch (num)
{
case 0:
return builtin_type_void;
case 1:
return sym_builtin_type_pstr;
case 2:
return builtin_type_unsigned_long;
case 3:
return builtin_type_long;
case 4:
return builtin_type_error;
case 5:
return builtin_type_bool;
case 6:
return builtin_type_uint8;
case 7:
return builtin_type_int8;
case 8:
return builtin_type_char;
case 9:
return builtin_type_short;
case 10:
return builtin_type_unsigned_short;
case 11:
return builtin_type_short;
case 12:
return builtin_type_error;
case 13:
return builtin_type_error;
case 14:
return builtin_type_error;
case 15:
return builtin_type_error;
case 16:
return sym_builtin_type_cstr;
case 17:
return builtin_type_error;
default:
return NULL;
}
}
int
sym_parse_type (struct objfile *objfile,
struct type **typevec,
size_t ntypes,
unsigned char *buf,
size_t len,
size_t offset,
size_t * offsetptr,
struct type **tptr, char **nptr, unsigned long *vptr)
{
unsigned int typecode = 0;
struct type *type = NULL;
char *typename = NULL;
struct type *target = NULL;
char *targname = NULL;
unsigned long value = 0;
int retval = 0;
int ret;
if (offset >= len)
{
type = builtin_type_error;
retval = -1;
goto end;
}
typecode = buf[offset];
offset++;
if (!(typecode & 0x80))
{
type = sym_lookup_builtin_type (typecode);
goto end;
}
switch (typecode & 0x3f)
{
case 1:
{
long value;
ret = bfd_sym_fetch_long (buf, len, offset, &offset, &value);
if (ret < 0)
{
sym_complaint ();
break;
}
if (value < 0)
{
sym_complaint ();
break;
}
if (value >= ntypes)
{
sym_complaint ();
break;
}
if (typevec[value] == NULL)
{
sym_complaint ();
break;
}
type = typevec[value];
break;
}
case 2:
{
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&target, NULL, NULL);
if ((ret < 0) || (target == NULL))
{
sym_complaint ();
break;
}
if (target == NULL)
{
sym_complaint ();
break;
}
type = make_pointer_type (target, NULL);
break;
}
case 3:
{
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&type, NULL, NULL);
if ((ret < 0) || (type == NULL))
{
sym_complaint ();
break;
}
ret = bfd_sym_fetch_long (buf, len, offset, &offset, &value);
if (ret < 0)
{
sym_complaint ();
break;
}
break;
}
case 5:
{
long lower, upper, nelem;
unsigned long i;
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&target, NULL, NULL);
bfd_sym_fetch_long (buf, len, offset, &offset, &lower);
bfd_sym_fetch_long (buf, len, offset, &offset, &upper);
bfd_sym_fetch_long (buf, len, offset, &offset, &nelem);
type = alloc_type (objfile);
TYPE_LENGTH (type) = TARGET_INT_BIT / HOST_CHAR_BIT;
TYPE_CODE (type) = TYPE_CODE_ENUM;
TYPE_NFIELDS (type) = nelem;
TYPE_FIELDS (type) =
(struct field *) TYPE_ALLOC (type, sizeof (struct field) * nelem);
memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nelem);
for (i = 0; i < nelem; i++)
{
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset,
&offset, &target, &targname, &value);
if ((ret < 0) || (target == NULL))
{
sym_complaint ();
break;
}
if (targname == NULL)
{
sym_complaint ();
targname = "";
}
TYPE_FIELD_TYPE (type, i) = target;
TYPE_FIELD_NAME (type, i) = targname;
TYPE_FIELD_BITPOS (type, i) = value;
TYPE_FIELD_BITSIZE (type, i) = 0;
}
break;
}
case 6:
{
struct type *index;
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&index, NULL, NULL);
if ((ret < 0) || (index == NULL))
{
sym_complaint ();
break;
}
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&target, NULL, NULL);
if ((ret < 0) || (target == NULL))
{
sym_complaint ();
break;
}
type = create_array_type (NULL, target, index);
break;
}
case 7:
case 8:
{
long nrec, eloff, i;
ret = bfd_sym_fetch_long (buf, len, offset, &offset, &nrec);
if (ret < 0)
{
sym_complaint ();
break;
}
if (nrec < 0)
{
sym_complaint ();
break;
}
type = alloc_type (objfile);
if ((typecode & 0x3f) == 7)
{
TYPE_CODE (type) = TYPE_CODE_STRUCT;
}
else
{
TYPE_CODE (type) = TYPE_CODE_UNION;
}
INIT_CPLUS_SPECIFIC (type);
TYPE_FIELDS (type) =
(struct field *) TYPE_ALLOC (type, nrec * sizeof (struct field));
TYPE_NFIELDS (type) = nrec;
TYPE_LENGTH (type) = 0;
for (i = 0; i < nrec; i++)
{
ret = bfd_sym_fetch_long (buf, len, offset, &offset, &eloff);
if (ret < 0)
{
sym_complaint ();
break;
}
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset,
&offset, &target, &targname, NULL);
if ((ret < 0) || (target == NULL))
{
sym_complaint ();
break;
}
if ((eloff < 0) || (targname == NULL))
{
type = NULL;
break;
}
TYPE_FIELD_TYPE (type, i) = target;
TYPE_FIELD_NAME (type, i) = targname;
TYPE_FIELD_BITPOS (type, i) = TARGET_CHAR_BIT * eloff;
TYPE_FIELD_BITSIZE (type, i) = 0;
TYPE_LENGTH (type) = eloff + TYPE_LENGTH (target);
}
break;
}
case 9:
{
struct type *lower, *upper;
unsigned long lval, uval;
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&target, NULL, NULL);
if ((ret < 0) || (target == NULL))
{
sym_complaint ();
break;
}
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&lower, NULL, &lval);
if ((ret < 0) || (lower == NULL))
{
sym_complaint ();
break;
}
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&upper, NULL, &uval);
if ((ret < 0) || (upper == NULL))
{
sym_complaint ();
break;
}
type = create_range_type (NULL, target, lval, uval);
break;
}
case 11:
{
long value;
const unsigned char *name;
ret = bfd_sym_fetch_long (buf, len, offset, &offset, &value);
if (ret < 0)
{
sym_complaint ();
break;
}
ret =
sym_parse_type (objfile, typevec, ntypes, buf, len, offset, &offset,
&type, NULL, NULL);
if ((ret < 0) || (type == NULL))
{
sym_complaint ();
break;
}
name = bfd_sym_symbol_name (objfile->obfd, value);
typename =
(char *) obstack_alloc (&objfile->objfile_obstack, name[0] + 1);
sprintf (typename, "%.*s", name[0], name + 1);
break;
}
default:
complaint (&symfile_complaints, "unknown SYM typecode %d", typecode);
type = builtin_type_error;
break;
}
if (typecode == (0x40 | 0x6))
{
long n, width, m;
long l;
long i;
bfd_sym_fetch_long (buf, len, offset, &offset, &n);
bfd_sym_fetch_long (buf, len, offset, &offset, &width);
bfd_sym_fetch_long (buf, len, offset, &offset, &m);
for (i = 0; i < m; i++)
{
bfd_sym_fetch_long (buf, len, offset, &offset, &l);
}
}
else if (typecode & 0x40)
{
long msb, lsb;
bfd_sym_fetch_long (buf, len, offset, &offset, &msb);
bfd_sym_fetch_long (buf, len, offset, &offset, &lsb);
}
end:
if (offsetptr != NULL)
{
*offsetptr = offset;
}
if (tptr != NULL)
{
*tptr = type;
}
if (nptr != NULL)
{
*nptr = typename;
}
if (vptr != NULL)
{
*vptr = value;
}
return 0;
}
static void
sym_read_type (struct objfile *objfile,
struct type **typevec,
unsigned long ntypes,
struct type *itype, struct symbol **psymbol, unsigned long i)
{
bfd *abfd = NULL;
bfd_sym_data_struct *sdata = NULL;
bfd_sym_type_table_entry index;
bfd_sym_type_information_table_entry entry;
unsigned char buf[4096];
struct type *type = NULL;
struct symbol *symbol = NULL;
const unsigned char *typename = NULL;
char *ntypename = NULL;
int ret = 0;
CHECK_FATAL (objfile != NULL);
abfd = objfile->obfd;
CHECK_FATAL (abfd != NULL);
CHECK_FATAL (abfd->filename != NULL);
CHECK_FATAL (bfd_sym_valid (abfd));
sdata = abfd->tdata.sym_data;
*psymbol = NULL;
if (i <= 99)
{
struct type *builtin = sym_lookup_builtin_type (i);
if (builtin != NULL)
{
*itype = *builtin;
}
return;
}
if (bfd_sym_fetch_type_table_entry (abfd, &index, i - 100) < 0)
{
return;
}
if (bfd_sym_fetch_type_information_table_entry (abfd, &entry, index) < 0)
{
return;
}
if (entry.physical_size > 4096)
{
return;
}
if (bfd_seek (abfd, entry.offset, SEEK_SET) < 0)
{
return;
}
if (bfd_bread (buf, entry.physical_size, abfd) != entry.physical_size)
{
return;
}
typename = bfd_sym_symbol_name (objfile->obfd, entry.nte_index);
if (typename[0] > 0)
{
ntypename =
(char *) obstack_alloc (&objfile->objfile_obstack, typename[0] + 1);
sprintf (ntypename, "%.*s", typename[0], typename + 1);
}
else
{
if (0)
{
ntypename = (char *) obstack_alloc (&objfile->objfile_obstack, 16);
sprintf (ntypename, "type%lu", i);
}
}
ret =
sym_parse_type (objfile, typevec, ntypes, buf, entry.physical_size, 0,
NULL, &type, NULL, NULL);
if ((ret != 0) || (type == NULL))
{
return;
}
if (ntypename != NULL)
{
if ((TYPE_CODE (type) == TYPE_CODE_STRUCT)
|| (TYPE_CODE (type) == TYPE_CODE_UNION))
{
TYPE_TAG_NAME (type) = ntypename;
}
symbol =
(struct symbol *) obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symbol));
SYMBOL_TYPE (symbol) = type;
SYMBOL_LINKAGE_NAME (symbol) = ntypename;
SYMBOL_VALUE (symbol) = 0;
SYMBOL_LANGUAGE (symbol) = 0;
SYMBOL_SECTION (symbol) = 0;
SYMBOL_BFD_SECTION (symbol) = 0;
SYMBOL_DOMAIN (symbol) = VAR_DOMAIN;
SYMBOL_CLASS (symbol) = LOC_TYPEDEF;
SYMBOL_LINE (symbol) = 0;
SYMBOL_BASEREG (symbol) = 0;
}
*itype = *type;
*psymbol = symbol;
}
static void
sym_read_types (struct objfile *objfile,
unsigned long *pmaxtypes,
struct type ***ptypevec,
unsigned long *pntypes,
struct symbol ***ptypedefvec, unsigned long *pntypedefs)
{
bfd *abfd = NULL;
bfd_sym_data_struct *sdata = NULL;
struct type **typevec = NULL;
struct symbol **typedefvec = NULL;
unsigned long ntypes = 0;
unsigned long ntypedefs = 0;
unsigned long maxtypes = 0;
unsigned long i;
CHECK_FATAL (objfile != NULL);
abfd = objfile->obfd;
CHECK_FATAL (abfd != NULL);
CHECK_FATAL (abfd->filename != NULL);
CHECK_FATAL (bfd_sym_valid (abfd));
sdata = abfd->tdata.sym_data;
maxtypes = sdata->header.dshb_tte.dti_object_count + 1;
typevec =
obstack_alloc (&objfile->objfile_obstack,
maxtypes * sizeof (struct type *));
typedefvec =
obstack_alloc (&objfile->objfile_obstack,
maxtypes * sizeof (struct symbol *));
for (i = 0; i < maxtypes; i++)
{
typevec[i] = alloc_type (objfile);
typedefvec[i] = 0;
}
for (i = 0; i < maxtypes; i++)
{
sym_read_type (objfile, typevec, maxtypes, typevec[i], &typedefvec[i],
i);
ntypes++;
if (typedefvec[i] != NULL)
{
ntypedefs++;
}
}
*ptypevec = typevec;
*ptypedefvec = typedefvec;
*pmaxtypes = maxtypes;
*pntypes = ntypes;
*pntypedefs = ntypedefs;
}
static void
sym_read_contained_variables (struct objfile *objfile,
struct bfd_sym_modules_table_entry *entry,
struct type **typevec,
unsigned long ntypes,
struct field *argvec,
unsigned long *pnargs,
struct symbol **localvec,
unsigned long *pnlocals,
struct symbol **globalvec,
unsigned long *pnglobals)
{
bfd *abfd = NULL;
bfd_sym_data_struct *sdata = NULL;
bfd_sym_contained_variables_table_entry cventry;
unsigned long nargs = 0;
unsigned long nlocals = 0;
unsigned long nglobals = 0;
int ret = 0;
unsigned long i = 0;
CHECK_FATAL (objfile != NULL);
abfd = objfile->obfd;
CHECK_FATAL (abfd != NULL);
CHECK_FATAL (abfd->filename != NULL);
CHECK_FATAL (bfd_sym_valid (abfd));
sdata = abfd->tdata.sym_data;
*pnargs = 0;
*pnlocals = 0;
*pnglobals = 0;
i = entry->mte_cvte_index;
if (i == 0)
{
return;
}
if (i > sdata->header.dshb_cvte.dti_object_count)
{
sym_complaint ();
goto end;
}
ret = bfd_sym_fetch_contained_variables_table_entry (abfd, &cventry, i);
if (ret < 0)
{
sym_complaint ();
goto end;
}
if (cventry.generic.type != BFD_SYM_SOURCE_FILE_CHANGE)
{
sym_complaint ();
goto end;
}
i++;
for (;;)
{
const unsigned char *nname = NULL;
if (i > sdata->header.dshb_cvte.dti_object_count)
{
sym_complaint ();
goto end;
}
ret = bfd_sym_fetch_contained_variables_table_entry (abfd, &cventry, i);
i++;
if (ret < 0)
{
sym_complaint ();
goto end;
}
if (cventry.generic.type == BFD_SYM_END_OF_LIST)
{
break;
}
if (cventry.generic.type == BFD_SYM_SOURCE_FILE_CHANGE)
{
goto end;
}
if (cventry.entry.tte_index > ntypes)
{
sym_complaint ();
goto end;
}
if (typevec[cventry.entry.tte_index] == NULL)
{
sym_complaint ();
goto end;
}
if (cventry.entry.la_size != BFD_SYM_CVTE_SCA)
{
sym_complaint ();
goto end;
}
nname = bfd_sym_symbol_name (abfd, cventry.entry.nte_index);
if (cventry.entry.address.scstruct.sca_kind ==
BFD_SYM_STORAGE_KIND_VALUE)
{
if (argvec != NULL)
{
FIELD_TYPE (argvec[nargs]) = typevec[cventry.entry.tte_index];
FIELD_NAME (argvec[nargs]) =
(char *) obstack_alloc (&objfile->objfile_obstack,
nname[0] + 1);
sprintf (FIELD_NAME (argvec[nargs]), "%.*s", nname[0],
nname + 1);
FIELD_BITPOS (argvec[nargs]) = 0;
FIELD_BITSIZE (argvec[nargs]) = 0;
}
nargs++;
}
if ((localvec != NULL) && (globalvec != NULL))
{
struct symbol *lsym = NULL;
lsym =
(struct symbol *) obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symbol));
SYMBOL_TYPE (lsym) = typevec[cventry.entry.tte_index];
SYMBOL_LINKAGE_NAME (lsym) =
obstack_alloc (&objfile->objfile_obstack, nname[0] + 1);
sprintf (SYMBOL_LINKAGE_NAME (lsym), "%.*s", nname[0], nname + 1);
SYMBOL_LANGUAGE (lsym) = language_cplus;
SYMBOL_SECTION (lsym) = 0;
SYMBOL_BFD_SECTION (lsym) = 0;
SYMBOL_LINE (lsym) = 0;
SYMBOL_BASEREG (lsym) = 0;
switch (cventry.entry.address.scstruct.sca_kind)
{
case BFD_SYM_STORAGE_KIND_VALUE:
switch (cventry.entry.address.scstruct.sca_class)
{
case BFD_SYM_STORAGE_CLASS_REGISTER:
SYMBOL_DOMAIN (lsym) = VAR_DOMAIN;
SYMBOL_CLASS (lsym) = LOC_REGPARM;
SYMBOL_VALUE (lsym) =
cventry.entry.address.scstruct.sca_offset;
break;
case BFD_SYM_STORAGE_CLASS_STACK_RELATIVE:
case BFD_SYM_STORAGE_CLASS_FRAME_RELATIVE:
SYMBOL_DOMAIN (lsym) = VAR_DOMAIN;
SYMBOL_CLASS (lsym) = LOC_ARG;
SYMBOL_VALUE (lsym) =
cventry.entry.address.scstruct.sca_offset;
break;
default:
sym_complaint ();
goto end;
}
break;
case BFD_SYM_STORAGE_KIND_LOCAL:
switch (cventry.entry.address.scstruct.sca_class)
{
case BFD_SYM_STORAGE_CLASS_GLOBAL:
SYMBOL_DOMAIN (lsym) = VAR_DOMAIN;
SYMBOL_CLASS (lsym) = LOC_BASEREG;
SYMBOL_VALUE (lsym) =
cventry.entry.address.scstruct.sca_offset - 276;
SYMBOL_BASEREG (lsym) = 31;
#if 0
SYMBOL_DOMAIN (lsym) = VAR_DOMAIN;
SYMBOL_CLASS (lsym) = LOC_STATIC;
SYMBOL_VALUE_ADDRESS (lsym) =
cventry.entry.address.scstruct.sca_offset;
SYMBOL_VALUE_ADDRESS (lsym) +=
objfile_data_section_offset (objfile);
#endif
break;
case BFD_SYM_STORAGE_CLASS_REGISTER:
SYMBOL_DOMAIN (lsym) = VAR_DOMAIN;
SYMBOL_CLASS (lsym) = LOC_REGISTER;
SYMBOL_VALUE (lsym) =
cventry.entry.address.scstruct.sca_offset;
break;
case BFD_SYM_STORAGE_CLASS_STACK_RELATIVE:
case BFD_SYM_STORAGE_CLASS_FRAME_RELATIVE:
SYMBOL_DOMAIN (lsym) = VAR_DOMAIN;
SYMBOL_CLASS (lsym) = LOC_LOCAL;
SYMBOL_VALUE (lsym) =
cventry.entry.address.scstruct.sca_offset;
break;
default:
sym_complaint ();
goto end;
}
break;
default:
sym_complaint ();
goto end;
}
if (cventry.entry.address.scstruct.sca_class ==
BFD_SYM_STORAGE_CLASS_GLOBAL)
{
localvec[nlocals] = lsym;
}
else
{
localvec[nlocals] = lsym;
}
}
if (cventry.entry.address.scstruct.sca_class ==
BFD_SYM_STORAGE_CLASS_GLOBAL)
{
nlocals++;
}
else
{
nlocals++;
}
}
end:
*pnargs = nargs;
*pnlocals = nlocals;
*pnglobals = nglobals;
}
static void
sym_read_functions (struct objfile *objfile,
struct type **typevec,
unsigned long ntypes,
struct symbol ***pfuncvec, unsigned long *pnfuncs)
{
bfd *abfd = NULL;
bfd_sym_data_struct *sdata = NULL;
struct symbol **funcvec = NULL;
unsigned long nfuncs = 0;
unsigned long maxfuncs;
unsigned long i, j;
int ret;
CORE_ADDR text_section_offset = 0;
CHECK_FATAL (objfile != NULL);
abfd = objfile->obfd;
CHECK_FATAL (abfd != NULL);
CHECK_FATAL (abfd->filename != NULL);
CHECK_FATAL (bfd_sym_valid (abfd));
sdata = abfd->tdata.sym_data;
maxfuncs = sdata->header.dshb_mte.dti_object_count + 1;
funcvec =
obstack_alloc (&objfile->objfile_obstack,
maxfuncs * sizeof (struct symbol *));
text_section_offset = objfile_text_section_offset (objfile);
for (i = 1; i < maxfuncs; i++)
{
bfd_sym_modules_table_entry entry;
const unsigned char *name;
struct field *argvec;
unsigned long nargs;
struct symbol **localvec;
unsigned long nlocals;
struct symbol **globalvec;
unsigned long nglobals;
struct symbol *fsymbol;
struct block *fblock;
struct type *ftype;
ret = bfd_sym_fetch_modules_table_entry (abfd, &entry, i);
if (ret < 0)
{
continue;
}
if ((entry.mte_scope) != BFD_SYM_SYMBOL_SCOPE_GLOBAL)
{
continue;
}
if ((entry.mte_kind != BFD_SYM_MODULE_KIND_FUNCTION)
&& (entry.mte_kind != BFD_SYM_MODULE_KIND_PROCEDURE))
{
continue;
}
sym_read_contained_variables (objfile, &entry, typevec, ntypes, NULL,
&nargs, NULL, &nlocals, NULL, &nglobals);
argvec =
(struct field *) obstack_alloc (&objfile->objfile_obstack,
nargs * sizeof (struct field));
localvec =
(struct symbol **) obstack_alloc (&objfile->objfile_obstack,
nlocals * sizeof (struct symbol *));
globalvec =
(struct symbol **) obstack_alloc (&objfile->objfile_obstack,
nglobals *
sizeof (struct symbol *));
sym_read_contained_variables (objfile, &entry, typevec, ntypes, argvec,
&nargs, localvec, &nlocals, globalvec,
&nglobals);
ftype = alloc_type (objfile);
TYPE_TARGET_TYPE (ftype) = builtin_type_error;
TYPE_LENGTH (ftype) = 1;
TYPE_CODE (ftype) = TYPE_CODE_FUNC;
fblock =
(struct block *) TYPE_ALLOC (ftype,
(sizeof (struct block) +
((nlocals -
1) * sizeof (struct symbol *))));
fsymbol =
(struct symbol *) obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symbol));
BLOCK_FUNCTION (fblock) = fsymbol;
BLOCK_START (fblock) = entry.mte_res_offset;
BLOCK_END (fblock) = entry.mte_res_offset + entry.mte_size;
BLOCK_SUPERBLOCK (fblock) = NULL;
BLOCK_GCC_COMPILED (fblock) = 0;
BLOCK_START (fblock) += text_section_offset;
BLOCK_END (fblock) += text_section_offset;
BLOCK_DICT (fblock) = dict_create_hashed_expandable ();
for (i = 0; i < nlocals; j++)
{
dict_add_symbol (BLOCK_DICT (fblock), localvec[i]);
}
TYPE_NFIELDS (ftype) = nargs;
TYPE_FIELDS (ftype) = argvec;
SYMBOL_TYPE (fsymbol) = ftype;
name = bfd_sym_symbol_name (abfd, entry.mte_nte_index);
SYMBOL_LINKAGE_NAME (fsymbol) =
obstack_alloc (&objfile->objfile_obstack, name[0] + 1);
if ((name[0] > 0) && (name[1] == '.'))
{
sprintf (SYMBOL_LINKAGE_NAME (fsymbol), "%.*s", name[0] - 1,
name + 2);
}
else
{
sprintf (SYMBOL_LINKAGE_NAME (fsymbol), "%.*s", name[0], name + 1);
}
SYMBOL_BLOCK_VALUE (fsymbol) = fblock;
SYMBOL_LANGUAGE (fsymbol) = language_cplus;
SYMBOL_SECTION (fsymbol) = 0;
SYMBOL_BFD_SECTION (fsymbol) = 0;
SYMBOL_DOMAIN (fsymbol) = VAR_DOMAIN;
SYMBOL_CLASS (fsymbol) = LOC_BLOCK;
SYMBOL_LINE (fsymbol) = 0;
SYMBOL_BASEREG (fsymbol) = 0;
funcvec[nfuncs] = fsymbol;
nfuncs++;
}
*pnfuncs = nfuncs;
*pfuncvec = funcvec;
}
static void
sym_symfile_init (struct objfile *objfile)
{
objfile->deprecated_sym_stab_info =
xmmalloc (objfile->md, sizeof (struct dbx_symfile_info));
memset ((PTR) objfile->deprecated_sym_stab_info, 0, sizeof (struct dbx_symfile_info));
objfile->deprecated_sym_private =
xmmalloc (objfile->md, sizeof (struct sym_symfile_info));
memset (objfile->deprecated_sym_private, 0, sizeof (struct sym_symfile_info));
objfile->flags |= OBJF_REORDERED;
init_entry_point_info (objfile);
}
static void
convert_path_colons (unsigned char *dst, const unsigned char *src, size_t len)
{
size_t i;
dst[0] = '/';
for (i = 0; i < len; i++)
{
if (src[i] == '/')
{
dst[i + 1] = ':';
}
else if (src[i] == ':')
{
dst[i + 1] = '/';
}
else
{
dst[i + 1] = src[i];
}
}
dst[len + 1] = '\0';
}
static void
convert_path (unsigned char *dst,
const unsigned char *src, size_t len, bfd_sym_version version)
{
switch (version)
{
case BFD_SYM_VERSION_3_3R0:
sprintf (dst, "%.*s", (int) len, src);
break;
case BFD_SYM_VERSION_3_5:
case BFD_SYM_VERSION_3_4:
case BFD_SYM_VERSION_3_3:
case BFD_SYM_VERSION_3_2:
case BFD_SYM_VERSION_3_1:
default:
convert_path_colons (dst, src, len);
}
}
static void
sym_symfile_read (struct objfile *objfile, int mainline)
{
bfd *abfd = NULL;
bfd_sym_data_struct *sdata = NULL;
struct blockvector *bv;
struct block *gblock, *sblock;
struct type **typevec = NULL;
struct symbol **typedefvec = NULL;
struct symbol **funcvec = NULL;
unsigned long ntypes;
unsigned long ntypedefs;
unsigned long nfuncs;
unsigned long maxtypes;
unsigned long i;
CORE_ADDR text_section_offset = 0;
CHECK_FATAL (objfile != NULL);
abfd = objfile->obfd;
CHECK_FATAL (abfd != NULL);
CHECK_FATAL (abfd->filename != NULL);
CHECK_FATAL (bfd_sym_valid (abfd));
sdata = abfd->tdata.sym_data;
sym_read_types (objfile, &maxtypes, &typevec, &ntypes, &typedefvec,
&ntypedefs);
sym_read_functions (objfile, typevec, maxtypes, &funcvec, &nfuncs);
gblock = allocate_block (&objfile->objfile_obstack);
BLOCK_DICT (gblock) = dict_create_hashed_expandable ();
sblock = allocate_block (&objfile->objfile_obstack);
BLOCK_SUPERBLOCK (sblock) = gblock;
BLOCK_DICT (sblock) = dict_create_hashed_expandable ();
text_section_offset = objfile_text_section_offset (objfile);
for (i = 0; i < maxtypes; i++)
{
if (typedefvec[i] != NULL)
{
dict_add_symbol (BLOCK_DICT (gblock), typedefvec[i]);
}
}
for (i = 0; i < nfuncs; i++)
{
CHECK_FATAL (funcvec[i] != NULL);
dict_add_symbol (BLOCK_DICT (gblock), funcvec[i]);
}
bv = (struct blockvector *) obstack_alloc
(&objfile->objfile_obstack,
(sizeof (struct blockvector) +
(nfuncs + 2 - 1) * sizeof (struct block *)));
BLOCKVECTOR_NBLOCKS (bv) = nfuncs + 2;
BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = gblock;
BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = sblock;
{
unsigned long i;
for (i = 0; i < nfuncs; i++)
{
BLOCKVECTOR_BLOCK (bv, i + 2) = SYMBOL_BLOCK_VALUE (funcvec[i]);
BLOCK_SUPERBLOCK (SYMBOL_BLOCK_VALUE (funcvec[i])) = sblock;
}
}
{
CORE_ADDR minaddr = (CORE_ADDR) - 1;
CORE_ADDR maxaddr = 0;
unsigned long i;
for (i = 0; i < nfuncs; i++)
{
if (BLOCK_LOWEST_PC (BLOCKVECTOR_BLOCK (bv, i + 2)) < minaddr)
{
minaddr = BLOCK_LOWEST_PC (BLOCKVECTOR_BLOCK (bv, i + 2));
}
if(!BLOCK_RANGES (BLOCKVECTOR_BLOCK (bv, i + 2))
&& BLOCK_END (BLOCKVECTOR_BLOCK (bv, i + 2)) > maxaddr)
{
maxaddr = BLOCK_END (BLOCKVECTOR_BLOCK (bv, i + 2));
}
else if (BLOCK_RANGES (BLOCKVECTOR_BLOCK (bv, i + 2)))
{
int j;
for (j = 0; j < BLOCK_RANGES (BLOCKVECTOR_BLOCK (bv, i + 2))->nelts;
j++)
if (BLOCK_RANGE_END (BLOCKVECTOR_BLOCK (bv, i + 2), j) > maxaddr)
maxaddr = BLOCK_RANGE_END (BLOCKVECTOR_BLOCK (bv, i + 2), j);
}
}
BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = minaddr;
BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = maxaddr;
BLOCK_START (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = minaddr;
BLOCK_END (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = maxaddr;
}
{
unsigned int linetable_maxentries = 20000;
struct symtab *symtab = NULL;
struct linetable *linetable = NULL;
unsigned long curpos = 0;
unsigned long curitem = 0;
int ret = 0;
bfd_sym_contained_statements_table_entry entry;
bfd_sym_file_references_table_entry frtentry;
bfd_sym_modules_table_entry mtentry;
unsigned long i;
for (i = 1; i <= sdata->header.dshb_csnte.dti_object_count; i++)
{
ret =
bfd_sym_fetch_contained_statements_table_entry (abfd, &entry, i);
if (ret < 0)
{
break;
}
switch (entry.generic.type)
{
case BFD_SYM_END_OF_LIST:
{
struct linetable *temp = NULL;
if (curitem >= linetable_maxentries)
{
sym_complaint ();
}
else if (0)
{
linetable->item[curitem].line = -1;
linetable->item[curitem].pc =
mtentry.mte_res_offset + mtentry.mte_size;
linetable->item[curitem].pc += text_section_offset;
curitem++;
linetable->nitems = curitem;
}
temp = (struct linetable *) xmalloc
(sizeof (struct linetable) +
sizeof (struct linetable_entry) * (linetable->nitems - 1));
memcpy (temp, linetable,
sizeof (struct linetable) +
sizeof (struct linetable_entry) * (linetable->nitems -
1));
xfree (linetable);
linetable = temp;
LINETABLE (symtab) = linetable;
symtab = NULL;
linetable = NULL;
curpos = 0;
curitem = 0;
break;
}
case BFD_SYM_SOURCE_FILE_CHANGE:
{
const unsigned char *namebuf = NULL;
char *name = NULL;
ret =
bfd_sym_fetch_file_references_table_entry (abfd, &frtentry,
entry.file.fref.
fref_frte_index);
if ((ret < 0)
|| (frtentry.generic.type != BFD_SYM_FILE_NAME_INDEX))
{
name = "[UNKNOWN]";
}
else
{
namebuf =
bfd_sym_symbol_name (abfd, frtentry.filename.nte_index);
name = xmalloc (namebuf[0] + 1 + 1);
convert_path (name, namebuf + 1, namebuf[0],
sdata->version);
}
symtab = allocate_symtab (name, objfile);
linetable = (struct linetable *) xmalloc
(sizeof (struct linetable) +
sizeof (struct linetable_entry) * linetable_maxentries);
linetable->lines_are_chars = 1;
BLOCKVECTOR (symtab) = bv;
LINETABLE (symtab) = linetable;
symtab->dirname = NULL;
symtab->free_code = free_nothing;
symtab->free_func = NULL;
symtab->primary = 0;
symtab->debugformat =
obsavestring ("xSYM", 4, &objfile->objfile_obstack);
SYMTAB_OBSOLETED (symtab) = 50;
curpos = entry.file.fref.fref_offset;
curitem = 0;
break;
}
default:
{
ret =
bfd_sym_fetch_modules_table_entry (abfd, &mtentry,
entry.entry.mte_index);
if (ret < 0)
{
break;
}
curpos += entry.entry.file_delta;
if (curitem >= linetable_maxentries)
{
sym_complaint ();
}
else
{
if (curitem == 0)
{
linetable->item[curitem].line = curpos;
linetable->item[curitem].pc = mtentry.mte_res_offset;
linetable->item[curitem].pc += text_section_offset;
curitem++;
linetable->nitems = curitem;
}
linetable->item[curitem].line = curpos;
linetable->item[curitem].pc =
mtentry.mte_res_offset + entry.entry.mte_offset;
linetable->item[curitem].pc += text_section_offset;
curitem++;
linetable->nitems = curitem;
}
}
}
}
}
if (objfile->symtabs)
objfile->symtabs->primary = 1;
init_minimal_symbol_collection ();
make_cleanup_discard_minimal_symbols ();
install_minimal_symbols (objfile);
}
static void
sym_symfile_finish (struct objfile *objfile)
{
}
static void
sym_symfile_offsets (struct objfile *objfile, struct section_addr_info *addrs)
{
unsigned int i;
objfile->num_sections = addrs->num_sections;
objfile->section_offsets = (struct section_offsets *)
obstack_alloc (&objfile->objfile_obstack,
SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
memset (objfile->section_offsets, 0,
SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
if (addrs->other[0].addr != 0)
{
for (i = 0; i < objfile->sections_end - objfile->sections; i++)
{
objfile->sections[i].addr += addrs->other[0].addr;
objfile->sections[i].endaddr += addrs->other[0].addr;
}
}
for (i = 0; i < objfile->num_sections; i++)
{
objfile->section_offsets->offsets[i] = (long) addrs->other[0].addr;
}
objfile->sect_index_text = 0;
objfile->sect_index_data = 0;
objfile->sect_index_bss = 0;
objfile->sect_index_rodata = 0;
}
static void
sym_symfile_display (bfd *abfd, FILE *f)
{
bfd_sym_data_struct *sdata = NULL;
CHECK_FATAL (abfd != NULL);
CHECK_FATAL (abfd->filename != NULL);
CHECK_FATAL (bfd_sym_valid (abfd));
sdata = abfd->tdata.sym_data;
bfd_sym_display_header (f, &sdata->header);
fprintf (f, "\n");
bfd_sym_display_name_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_resources_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_modules_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_file_references_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_contained_modules_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_contained_variables_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_contained_statements_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_contained_labels_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_contained_types_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_type_information_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_file_references_index_table (abfd, f);
fprintf (f, "\n");
bfd_sym_display_constant_pool (abfd, f);
fprintf (f, "\n");
}
static struct sym_fns sym_sym_fns = {
bfd_target_sym_flavour,
sym_new_init,
sym_symfile_init,
sym_symfile_read,
sym_symfile_finish,
sym_symfile_offsets,
NULL
};
void
sym_dump_command (char *args, int from_tty)
{
char **argv;
struct cleanup *cleanups;
char *symname = NULL;
char *filename = "/dev/tty";
FILE *f = NULL;
bfd *abfd = NULL;
dont_repeat ();
if (args == NULL)
{
error ("Usage: sym-dump <symfile> <outfile>");
}
if ((argv = buildargv (args)) == NULL)
{
nomem (0);
}
cleanups = make_cleanup_freeargv (argv);
if (argv[0] == NULL)
{
error ("Usage: sym-dump <symfile> <outfile>");
}
symname = argv[0];
if (argv[1] != NULL)
{
filename = argv[1];
}
if ((argv[1] != NULL) && (argv[2] != NULL))
{
error ("Usage: sym-dump <symfile> <outfile>");
}
filename = tilde_expand (filename);
make_cleanup (free, filename);
symname = tilde_expand (symname);
make_cleanup (free, symname);
f = fopen (filename, "w");
if (f == NULL)
{
error ("Unable to open \"%s\" for writing: %s", filename,
strerror (errno));
}
abfd = bfd_openr (symname, "sym");
if (abfd == NULL)
{
error ("Unable to open \"%s\" for reading: %s", symname,
bfd_errmsg (bfd_get_error ()));
}
if (!bfd_check_format (abfd, bfd_object))
{
error ("Unable to process \"%s\": %s", symname,
bfd_errmsg (bfd_get_error ()));
}
immediate_quit++;
sym_symfile_display (abfd, f);
immediate_quit--;
do_cleanups (cleanups);
}
void
_initialize_symread (void)
{
sym_builtin_type_pstr = make_pointer_type (builtin_type_char, NULL);
sym_builtin_type_cstr = make_pointer_type (builtin_type_char, NULL);
add_symtab_fns (&sym_sym_fns);
add_com ("sym-dump", class_run, sym_dump_command,
"Print the contents of the specified SYM-format symbol file.");
}