#include <stdio.h>
#include <assert.h>
#include "bfd.h"
#include "ieee.h"
#include "bucomm.h"
#include "libiberty.h"
#include "debug.h"
#include "budbg.h"
#include "filenames.h"
struct ieee_block
{
int kind;
const char *filename;
unsigned int fnindx;
bfd_boolean skip;
};
#define BLOCKSTACK_SIZE (16)
struct ieee_blockstack
{
struct ieee_block *bsp;
struct ieee_block stack[BLOCKSTACK_SIZE];
};
struct ieee_var
{
const char *name;
unsigned long namlen;
debug_type type;
debug_type *pslot;
enum
{
IEEE_UNKNOWN,
IEEE_EXTERNAL,
IEEE_GLOBAL,
IEEE_STATIC,
IEEE_LOCAL,
IEEE_FUNCTION
} kind;
};
struct ieee_vars
{
unsigned int alloc;
struct ieee_var *vars;
};
struct ieee_type
{
debug_type type;
debug_type *pslot;
debug_type *arg_slots;
unsigned long bitsize;
};
struct ieee_types
{
unsigned int alloc;
struct ieee_type *types;
#define BUILTIN_TYPE_COUNT (60)
debug_type builtins[BUILTIN_TYPE_COUNT];
};
struct ieee_tag
{
struct ieee_tag *next;
const char *name;
debug_type type;
debug_type slot;
debug_type *fslots;
};
struct ieee_info
{
void *dhandle;
bfd *abfd;
const bfd_byte *bytes;
const bfd_byte *pend;
struct ieee_blockstack blockstack;
bfd_boolean saw_filename;
struct ieee_vars vars;
struct ieee_vars *global_vars;
struct ieee_types types;
struct ieee_types *global_types;
struct ieee_tag *tags;
};
enum builtin_types
{
builtin_unknown = 0,
builtin_void = 1,
builtin_signed_char = 2,
builtin_unsigned_char = 3,
builtin_signed_short_int = 4,
builtin_unsigned_short_int = 5,
builtin_signed_long = 6,
builtin_unsigned_long = 7,
builtin_signed_long_long = 8,
builtin_unsigned_long_long = 9,
builtin_float = 10,
builtin_double = 11,
builtin_long_double = 12,
builtin_long_long_double = 13,
builtin_quoted_string = 14,
builtin_instruction_address = 15,
builtin_int = 16,
builtin_unsigned = 17,
builtin_unsigned_int = 18,
builtin_char = 19,
builtin_long = 20,
builtin_short = 21,
builtin_unsigned_short = 22,
builtin_short_int = 23,
builtin_signed_short = 24,
builtin_bcd_float = 25
};
#define BASEFLAGS_PRIVATE (0x1)
#define BASEFLAGS_VIRTUAL (0x2)
#define BASEFLAGS_FRIEND (0x10)
#define CXXFLAGS_VISIBILITY (0x3)
#define CXXFLAGS_VISIBILITY_PUBLIC (0x0)
#define CXXFLAGS_VISIBILITY_PRIVATE (0x1)
#define CXXFLAGS_VISIBILITY_PROTECTED (0x2)
#define CXXFLAGS_STATIC (0x4)
#define CXXFLAGS_OVERRIDE (0x8)
#define CXXFLAGS_FRIEND (0x10)
#define CXXFLAGS_CONST (0x20)
#define CXXFLAGS_VOLATILE (0x40)
#define CXXFLAGS_OVERLOADED (0x80)
#define CXXFLAGS_OPERATOR (0x100)
#define CXXFLAGS_CTORDTOR (0x400)
#define CXXFLAGS_CTOR (0x200)
#define CXXFLAGS_INLINE (0x800)
static void ieee_error (struct ieee_info *, const bfd_byte *, const char *);
static void ieee_eof (struct ieee_info *);
static char *savestring (const char *, unsigned long);
static bfd_boolean ieee_read_number
(struct ieee_info *, const bfd_byte **, bfd_vma *);
static bfd_boolean ieee_read_optional_number
(struct ieee_info *, const bfd_byte **, bfd_vma *, bfd_boolean *);
static bfd_boolean ieee_read_id
(struct ieee_info *, const bfd_byte **, const char **, unsigned long *);
static bfd_boolean ieee_read_optional_id
(struct ieee_info *, const bfd_byte **, const char **, unsigned long *,
bfd_boolean *);
static bfd_boolean ieee_read_expression
(struct ieee_info *, const bfd_byte **, bfd_vma *);
static debug_type ieee_builtin_type
(struct ieee_info *, const bfd_byte *, unsigned int);
static bfd_boolean ieee_alloc_type
(struct ieee_info *, unsigned int, bfd_boolean);
static bfd_boolean ieee_read_type_index
(struct ieee_info *, const bfd_byte **, debug_type *);
static int ieee_regno_to_genreg (bfd *, int);
static int ieee_genreg_to_regno (bfd *, int);
static bfd_boolean parse_ieee_bb (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_be (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_nn (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_ty (struct ieee_info *, const bfd_byte **);
static bfd_boolean parse_ieee_atn (struct ieee_info *, const bfd_byte **);
static bfd_boolean ieee_read_cxx_misc
(struct ieee_info *, const bfd_byte **, unsigned long);
static bfd_boolean ieee_read_cxx_class
(struct ieee_info *, const bfd_byte **, unsigned long);
static bfd_boolean ieee_read_cxx_defaults
(struct ieee_info *, const bfd_byte **, unsigned long);
static bfd_boolean ieee_read_reference
(struct ieee_info *, const bfd_byte **);
static bfd_boolean ieee_require_asn
(struct ieee_info *, const bfd_byte **, bfd_vma *);
static bfd_boolean ieee_require_atn65
(struct ieee_info *, const bfd_byte **, const char **, unsigned long *);
static void
ieee_error (struct ieee_info *info, const bfd_byte *p, const char *s)
{
if (p != NULL)
fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd),
(unsigned long) (p - info->bytes), s, *p);
else
fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s);
}
static void
ieee_eof (struct ieee_info *info)
{
ieee_error (info, (const bfd_byte *) NULL,
_("unexpected end of debugging information"));
}
static char *
savestring (const char *start, unsigned long len)
{
char *ret;
ret = (char *) xmalloc (len + 1);
memcpy (ret, start, len);
ret[len] = '\0';
return ret;
}
static bfd_boolean
ieee_read_number (struct ieee_info *info, const bfd_byte **pp, bfd_vma *pv)
{
return ieee_read_optional_number (info, pp, pv, (bfd_boolean *) NULL);
}
static bfd_boolean
ieee_read_optional_number (struct ieee_info *info, const bfd_byte **pp,
bfd_vma *pv, bfd_boolean *ppresent)
{
ieee_record_enum_type b;
if (*pp >= info->pend)
{
if (ppresent != NULL)
{
*ppresent = FALSE;
return TRUE;
}
ieee_eof (info);
return FALSE;
}
b = (ieee_record_enum_type) **pp;
++*pp;
if (b <= ieee_number_end_enum)
{
*pv = (bfd_vma) b;
if (ppresent != NULL)
*ppresent = TRUE;
return TRUE;
}
if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum)
{
unsigned int i;
i = (int) b - (int) ieee_number_repeat_start_enum;
if (*pp + i - 1 >= info->pend)
{
ieee_eof (info);
return FALSE;
}
*pv = 0;
for (; i > 0; i--)
{
*pv <<= 8;
*pv += **pp;
++*pp;
}
if (ppresent != NULL)
*ppresent = TRUE;
return TRUE;
}
if (ppresent != NULL)
{
--*pp;
*ppresent = FALSE;
return TRUE;
}
ieee_error (info, *pp - 1, _("invalid number"));
return FALSE;
}
static bfd_boolean
ieee_read_id (struct ieee_info *info, const bfd_byte **pp,
const char **pname, unsigned long *pnamlen)
{
return ieee_read_optional_id (info, pp, pname, pnamlen, (bfd_boolean *) NULL);
}
static bfd_boolean
ieee_read_optional_id (struct ieee_info *info, const bfd_byte **pp,
const char **pname, unsigned long *pnamlen,
bfd_boolean *ppresent)
{
bfd_byte b;
unsigned long len;
if (*pp >= info->pend)
{
ieee_eof (info);
return FALSE;
}
b = **pp;
++*pp;
if (b <= 0x7f)
len = b;
else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum)
{
len = **pp;
++*pp;
}
else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum)
{
len = (**pp << 8) + (*pp)[1];
*pp += 2;
}
else
{
if (ppresent != NULL)
{
--*pp;
*ppresent = FALSE;
return TRUE;
}
ieee_error (info, *pp - 1, _("invalid string length"));
return FALSE;
}
if ((unsigned long) (info->pend - *pp) < len)
{
ieee_eof (info);
return FALSE;
}
*pname = (const char *) *pp;
*pnamlen = len;
*pp += len;
if (ppresent != NULL)
*ppresent = TRUE;
return TRUE;
}
static bfd_boolean
ieee_read_expression (struct ieee_info *info, const bfd_byte **pp,
bfd_vma *pv)
{
const bfd_byte *expr_start;
#define EXPR_STACK_SIZE (10)
bfd_vma expr_stack[EXPR_STACK_SIZE];
bfd_vma *esp;
expr_start = *pp;
esp = expr_stack;
while (1)
{
const bfd_byte *start;
bfd_vma val;
bfd_boolean present;
ieee_record_enum_type c;
start = *pp;
if (! ieee_read_optional_number (info, pp, &val, &present))
return FALSE;
if (present)
{
if (esp - expr_stack >= EXPR_STACK_SIZE)
{
ieee_error (info, start, _("expression stack overflow"));
return FALSE;
}
*esp++ = val;
continue;
}
c = (ieee_record_enum_type) **pp;
if (c >= ieee_module_beginning_enum)
break;
++*pp;
if (c == ieee_comma)
break;
switch (c)
{
default:
ieee_error (info, start, _("unsupported IEEE expression operator"));
break;
case ieee_variable_R_enum:
{
bfd_vma indx;
asection *s;
if (! ieee_read_number (info, pp, &indx))
return FALSE;
for (s = info->abfd->sections; s != NULL; s = s->next)
if ((bfd_vma) s->target_index == indx)
break;
if (s == NULL)
{
ieee_error (info, start, _("unknown section"));
return FALSE;
}
if (esp - expr_stack >= EXPR_STACK_SIZE)
{
ieee_error (info, start, _("expression stack overflow"));
return FALSE;
}
*esp++ = bfd_get_section_vma (info->abfd, s);
}
break;
case ieee_function_plus_enum:
case ieee_function_minus_enum:
{
bfd_vma v1, v2;
if (esp - expr_stack < 2)
{
ieee_error (info, start, _("expression stack underflow"));
return FALSE;
}
v1 = *--esp;
v2 = *--esp;
*esp++ = v1 + v2;
}
break;
}
}
if (esp - 1 != expr_stack)
{
ieee_error (info, expr_start, _("expression stack mismatch"));
return FALSE;
}
*pv = *--esp;
return TRUE;
}
static debug_type
ieee_builtin_type (struct ieee_info *info, const bfd_byte *p,
unsigned int indx)
{
void *dhandle;
debug_type type;
const char *name;
if (indx < BUILTIN_TYPE_COUNT
&& info->types.builtins[indx] != DEBUG_TYPE_NULL)
return info->types.builtins[indx];
dhandle = info->dhandle;
if (indx >= 32 && indx < 64)
{
type = debug_make_pointer_type (dhandle,
ieee_builtin_type (info, p, indx - 32));
assert (indx < BUILTIN_TYPE_COUNT);
info->types.builtins[indx] = type;
return type;
}
switch ((enum builtin_types) indx)
{
default:
ieee_error (info, p, _("unknown builtin type"));
return NULL;
case builtin_unknown:
type = debug_make_void_type (dhandle);
name = NULL;
break;
case builtin_void:
type = debug_make_void_type (dhandle);
name = "void";
break;
case builtin_signed_char:
type = debug_make_int_type (dhandle, 1, FALSE);
name = "signed char";
break;
case builtin_unsigned_char:
type = debug_make_int_type (dhandle, 1, TRUE);
name = "unsigned char";
break;
case builtin_signed_short_int:
type = debug_make_int_type (dhandle, 2, FALSE);
name = "signed short int";
break;
case builtin_unsigned_short_int:
type = debug_make_int_type (dhandle, 2, TRUE);
name = "unsigned short int";
break;
case builtin_signed_long:
type = debug_make_int_type (dhandle, 4, FALSE);
name = "signed long";
break;
case builtin_unsigned_long:
type = debug_make_int_type (dhandle, 4, TRUE);
name = "unsigned long";
break;
case builtin_signed_long_long:
type = debug_make_int_type (dhandle, 8, FALSE);
name = "signed long long";
break;
case builtin_unsigned_long_long:
type = debug_make_int_type (dhandle, 8, TRUE);
name = "unsigned long long";
break;
case builtin_float:
type = debug_make_float_type (dhandle, 4);
name = "float";
break;
case builtin_double:
type = debug_make_float_type (dhandle, 8);
name = "double";
break;
case builtin_long_double:
type = debug_make_float_type (dhandle, 12);
name = "long double";
break;
case builtin_long_long_double:
type = debug_make_float_type (dhandle, 16);
name = "long long double";
break;
case builtin_quoted_string:
type = debug_make_array_type (dhandle,
ieee_builtin_type (info, p,
((unsigned int)
builtin_char)),
ieee_builtin_type (info, p,
((unsigned int)
builtin_int)),
0, -1, TRUE);
name = "QUOTED STRING";
break;
case builtin_instruction_address:
type = debug_make_int_type (dhandle, 4, TRUE);
name = "instruction address";
break;
case builtin_int:
type = debug_make_int_type (dhandle, 4, FALSE);
name = "int";
break;
case builtin_unsigned:
type = debug_make_int_type (dhandle, 4, TRUE);
name = "unsigned";
break;
case builtin_unsigned_int:
type = debug_make_int_type (dhandle, 4, TRUE);
name = "unsigned int";
break;
case builtin_char:
type = debug_make_int_type (dhandle, 1, FALSE);
name = "char";
break;
case builtin_long:
type = debug_make_int_type (dhandle, 4, FALSE);
name = "long";
break;
case builtin_short:
type = debug_make_int_type (dhandle, 2, FALSE);
name = "short";
break;
case builtin_unsigned_short:
type = debug_make_int_type (dhandle, 2, TRUE);
name = "unsigned short";
break;
case builtin_short_int:
type = debug_make_int_type (dhandle, 2, FALSE);
name = "short int";
break;
case builtin_signed_short:
type = debug_make_int_type (dhandle, 2, FALSE);
name = "signed short";
break;
case builtin_bcd_float:
ieee_error (info, p, _("BCD float type not supported"));
return DEBUG_TYPE_NULL;
}
if (name != NULL)
type = debug_name_type (dhandle, name, type);
assert (indx < BUILTIN_TYPE_COUNT);
info->types.builtins[indx] = type;
return type;
}
static bfd_boolean
ieee_alloc_type (struct ieee_info *info, unsigned int indx, bfd_boolean ref)
{
unsigned int nalloc;
register struct ieee_type *t;
struct ieee_type *tend;
if (indx >= info->types.alloc)
{
nalloc = info->types.alloc;
if (nalloc == 0)
nalloc = 4;
while (indx >= nalloc)
nalloc *= 2;
info->types.types = ((struct ieee_type *)
xrealloc (info->types.types,
nalloc * sizeof *info->types.types));
memset (info->types.types + info->types.alloc, 0,
(nalloc - info->types.alloc) * sizeof *info->types.types);
tend = info->types.types + nalloc;
for (t = info->types.types + info->types.alloc; t < tend; t++)
t->type = DEBUG_TYPE_NULL;
info->types.alloc = nalloc;
}
if (ref)
{
t = info->types.types + indx;
if (t->type == NULL)
{
t->pslot = (debug_type *) xmalloc (sizeof *t->pslot);
*t->pslot = DEBUG_TYPE_NULL;
t->type = debug_make_indirect_type (info->dhandle, t->pslot,
(const char *) NULL);
if (t->type == NULL)
return FALSE;
}
}
return TRUE;
}
static bfd_boolean
ieee_read_type_index (struct ieee_info *info, const bfd_byte **pp,
debug_type *ptype)
{
const bfd_byte *start;
bfd_vma indx;
start = *pp;
if (! ieee_read_number (info, pp, &indx))
return FALSE;
if (indx < 256)
{
*ptype = ieee_builtin_type (info, start, indx);
if (*ptype == NULL)
return FALSE;
return TRUE;
}
indx -= 256;
if (! ieee_alloc_type (info, indx, TRUE))
return FALSE;
*ptype = info->types.types[indx].type;
return TRUE;
}
bfd_boolean
parse_ieee (void *dhandle, bfd *abfd, const bfd_byte *bytes, bfd_size_type len)
{
struct ieee_info info;
unsigned int i;
const bfd_byte *p, *pend;
info.dhandle = dhandle;
info.abfd = abfd;
info.bytes = bytes;
info.pend = bytes + len;
info.blockstack.bsp = info.blockstack.stack;
info.saw_filename = FALSE;
info.vars.alloc = 0;
info.vars.vars = NULL;
info.global_vars = NULL;
info.types.alloc = 0;
info.types.types = NULL;
info.global_types = NULL;
info.tags = NULL;
for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
info.types.builtins[i] = DEBUG_TYPE_NULL;
p = bytes;
pend = info.pend;
while (p < pend)
{
const bfd_byte *record_start;
ieee_record_enum_type c;
record_start = p;
c = (ieee_record_enum_type) *p++;
if (c == ieee_at_record_enum)
c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++);
if (c <= ieee_number_repeat_end_enum)
{
ieee_error (&info, record_start, _("unexpected number"));
return FALSE;
}
switch (c)
{
default:
ieee_error (&info, record_start, _("unexpected record type"));
return FALSE;
case ieee_bb_record_enum:
if (! parse_ieee_bb (&info, &p))
return FALSE;
break;
case ieee_be_record_enum:
if (! parse_ieee_be (&info, &p))
return FALSE;
break;
case ieee_nn_record:
if (! parse_ieee_nn (&info, &p))
return FALSE;
break;
case ieee_ty_record_enum:
if (! parse_ieee_ty (&info, &p))
return FALSE;
break;
case ieee_atn_record_enum:
if (! parse_ieee_atn (&info, &p))
return FALSE;
break;
}
}
if (info.blockstack.bsp != info.blockstack.stack)
{
ieee_error (&info, (const bfd_byte *) NULL,
_("blocks left on stack at end"));
return FALSE;
}
return TRUE;
}
static bfd_boolean
parse_ieee_bb (struct ieee_info *info, const bfd_byte **pp)
{
const bfd_byte *block_start;
bfd_byte b;
bfd_vma size;
const char *name;
unsigned long namlen;
char *namcopy = NULL;
unsigned int fnindx;
bfd_boolean skip;
block_start = *pp;
b = **pp;
++*pp;
if (! ieee_read_number (info, pp, &size)
|| ! ieee_read_id (info, pp, &name, &namlen))
return FALSE;
fnindx = (unsigned int) -1;
skip = FALSE;
switch (b)
{
case 1:
namcopy = savestring (name, namlen);
if (namcopy == NULL)
return FALSE;
if (! debug_set_filename (info->dhandle, namcopy))
return FALSE;
info->saw_filename = TRUE;
if (info->vars.vars != NULL)
free (info->vars.vars);
info->vars.vars = NULL;
info->vars.alloc = 0;
if (info->types.types != NULL)
free (info->types.types);
info->types.types = NULL;
info->types.alloc = 0;
if (info->global_types != NULL)
{
info->types.alloc = info->global_types->alloc;
info->types.types = ((struct ieee_type *)
xmalloc (info->types.alloc
* sizeof (*info->types.types)));
memcpy (info->types.types, info->global_types->types,
info->types.alloc * sizeof (*info->types.types));
}
break;
case 2:
if (! debug_set_filename (info->dhandle, "*global*"))
return FALSE;
info->saw_filename = TRUE;
break;
case 3:
break;
case 4:
{
bfd_vma stackspace, typindx, offset;
debug_type return_type;
if (! ieee_read_number (info, pp, &stackspace)
|| ! ieee_read_number (info, pp, &typindx)
|| ! ieee_read_expression (info, pp, &offset))
return FALSE;
if (typindx < 256)
{
return_type = ieee_builtin_type (info, block_start, typindx);
if (return_type == DEBUG_TYPE_NULL)
return FALSE;
}
else
{
typindx -= 256;
if (! ieee_alloc_type (info, typindx, TRUE))
return FALSE;
fnindx = typindx;
return_type = info->types.types[typindx].type;
if (debug_get_type_kind (info->dhandle, return_type)
== DEBUG_KIND_FUNCTION)
return_type = debug_get_return_type (info->dhandle,
return_type);
}
namcopy = savestring (name, namlen);
if (namcopy == NULL)
return FALSE;
if (! debug_record_function (info->dhandle, namcopy, return_type,
TRUE, offset))
return FALSE;
}
break;
case 5:
{
unsigned int i;
for (i = 0; i < 6; i++)
{
bfd_vma ignore;
bfd_boolean present;
if (! ieee_read_optional_number (info, pp, &ignore, &present))
return FALSE;
if (! present)
break;
}
namcopy = savestring (name, namlen);
if (namcopy == NULL)
return FALSE;
if (! debug_start_source (info->dhandle, namcopy))
return FALSE;
}
break;
case 6:
{
bfd_vma stackspace, typindx, offset;
if (! ieee_read_number (info, pp, &stackspace)
|| ! ieee_read_number (info, pp, &typindx)
|| ! ieee_read_expression (info, pp, &offset))
return FALSE;
if (namlen == 0)
{
if (! debug_start_block (info->dhandle, offset))
return FALSE;
b = 0x86;
}
else
{
if (strncmp (name, "__XRYCPP", namlen) == 0)
skip = TRUE;
else
{
debug_type return_type;
if (typindx < 256)
{
return_type = ieee_builtin_type (info, block_start,
typindx);
if (return_type == NULL)
return FALSE;
}
else
{
typindx -= 256;
if (! ieee_alloc_type (info, typindx, TRUE))
return FALSE;
fnindx = typindx;
return_type = info->types.types[typindx].type;
if (debug_get_type_kind (info->dhandle, return_type)
== DEBUG_KIND_FUNCTION)
return_type = debug_get_return_type (info->dhandle,
return_type);
}
namcopy = savestring (name, namlen);
if (namcopy == NULL)
return FALSE;
if (! debug_record_function (info->dhandle, namcopy,
return_type, FALSE, offset))
return FALSE;
}
}
}
break;
case 10:
{
const char *inam, *vstr;
unsigned long inamlen, vstrlen;
bfd_vma tool_type;
bfd_boolean present;
unsigned int i;
if (! info->saw_filename)
{
namcopy = savestring (name, namlen);
if (namcopy == NULL)
return FALSE;
if (! debug_set_filename (info->dhandle, namcopy))
return FALSE;
info->saw_filename = TRUE;
}
if (! ieee_read_id (info, pp, &inam, &inamlen)
|| ! ieee_read_number (info, pp, &tool_type)
|| ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present))
return FALSE;
for (i = 0; i < 6; i++)
{
bfd_vma ignore;
if (! ieee_read_optional_number (info, pp, &ignore, &present))
return FALSE;
if (! present)
break;
}
}
break;
case 11:
{
bfd_vma sectype, secindx, offset, map;
bfd_boolean present;
if (! ieee_read_number (info, pp, §ype)
|| ! ieee_read_number (info, pp, &secindx)
|| ! ieee_read_expression (info, pp, &offset)
|| ! ieee_read_optional_number (info, pp, &map, &present))
return FALSE;
}
break;
default:
ieee_error (info, block_start, _("unknown BB type"));
return FALSE;
}
if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE)
{
ieee_error (info, (const bfd_byte *) NULL, _("stack overflow"));
return FALSE;
}
info->blockstack.bsp->kind = b;
if (b == 5)
info->blockstack.bsp->filename = namcopy;
info->blockstack.bsp->fnindx = fnindx;
info->blockstack.bsp->skip = skip;
++info->blockstack.bsp;
return TRUE;
}
static bfd_boolean
parse_ieee_be (struct ieee_info *info, const bfd_byte **pp)
{
bfd_vma offset;
if (info->blockstack.bsp <= info->blockstack.stack)
{
ieee_error (info, *pp, _("stack underflow"));
return FALSE;
}
--info->blockstack.bsp;
switch (info->blockstack.bsp->kind)
{
case 2:
info->global_vars = ((struct ieee_vars *)
xmalloc (sizeof *info->global_vars));
info->global_vars->alloc = info->vars.alloc;
info->global_vars->vars = ((struct ieee_var *)
xmalloc (info->vars.alloc
* sizeof (*info->vars.vars)));
memcpy (info->global_vars->vars, info->vars.vars,
info->vars.alloc * sizeof (*info->vars.vars));
info->global_types = ((struct ieee_types *)
xmalloc (sizeof *info->global_types));
info->global_types->alloc = info->types.alloc;
info->global_types->types = ((struct ieee_type *)
xmalloc (info->types.alloc
* sizeof (*info->types.types)));
memcpy (info->global_types->types, info->types.types,
info->types.alloc * sizeof (*info->types.types));
memset (info->global_types->builtins, 0,
sizeof (info->global_types->builtins));
break;
case 4:
case 6:
if (! ieee_read_expression (info, pp, &offset))
return FALSE;
if (! info->blockstack.bsp->skip)
{
if (! debug_end_function (info->dhandle, offset + 1))
return FALSE;
}
break;
case 0x86:
if (! ieee_read_expression (info, pp, &offset))
return FALSE;
if (! debug_end_block (info->dhandle, offset + 1))
return FALSE;
break;
case 5:
if (info->blockstack.bsp > info->blockstack.stack)
{
struct ieee_block *bl;
bl = info->blockstack.bsp;
do
{
--bl;
if (bl->kind == 5)
{
if (! debug_start_source (info->dhandle, bl->filename))
return FALSE;
break;
}
}
while (bl != info->blockstack.stack);
}
break;
case 11:
if (! ieee_read_expression (info, pp, &offset))
return FALSE;
break;
default:
break;
}
return TRUE;
}
static bfd_boolean
parse_ieee_nn (struct ieee_info *info, const bfd_byte **pp)
{
const bfd_byte *nn_start;
bfd_vma varindx;
const char *name;
unsigned long namlen;
nn_start = *pp;
if (! ieee_read_number (info, pp, &varindx)
|| ! ieee_read_id (info, pp, &name, &namlen))
return FALSE;
if (varindx < 32)
{
ieee_error (info, nn_start, _("illegal variable index"));
return FALSE;
}
varindx -= 32;
if (varindx >= info->vars.alloc)
{
unsigned int alloc;
alloc = info->vars.alloc;
if (alloc == 0)
alloc = 4;
while (varindx >= alloc)
alloc *= 2;
info->vars.vars = ((struct ieee_var *)
xrealloc (info->vars.vars,
alloc * sizeof *info->vars.vars));
memset (info->vars.vars + info->vars.alloc, 0,
(alloc - info->vars.alloc) * sizeof *info->vars.vars);
info->vars.alloc = alloc;
}
info->vars.vars[varindx].name = name;
info->vars.vars[varindx].namlen = namlen;
return TRUE;
}
static bfd_boolean
parse_ieee_ty (struct ieee_info *info, const bfd_byte **pp)
{
const bfd_byte *ty_start, *ty_var_start, *ty_code_start;
bfd_vma typeindx, varindx, tc;
void *dhandle;
bfd_boolean tag, typdef;
debug_type *arg_slots;
unsigned long type_bitsize;
debug_type type;
ty_start = *pp;
if (! ieee_read_number (info, pp, &typeindx))
return FALSE;
if (typeindx < 256)
{
ieee_error (info, ty_start, _("illegal type index"));
return FALSE;
}
typeindx -= 256;
if (! ieee_alloc_type (info, typeindx, FALSE))
return FALSE;
if (**pp != 0xce)
{
ieee_error (info, *pp, _("unknown TY code"));
return FALSE;
}
++*pp;
ty_var_start = *pp;
if (! ieee_read_number (info, pp, &varindx))
return FALSE;
if (varindx < 32)
{
ieee_error (info, ty_var_start, _("illegal variable index"));
return FALSE;
}
varindx -= 32;
if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL)
{
ieee_error (info, ty_var_start, _("undefined variable in TY"));
return FALSE;
}
ty_code_start = *pp;
if (! ieee_read_number (info, pp, &tc))
return FALSE;
dhandle = info->dhandle;
tag = FALSE;
typdef = FALSE;
arg_slots = NULL;
type_bitsize = 0;
switch (tc)
{
default:
ieee_error (info, ty_code_start, _("unknown TY code"));
return FALSE;
case '!':
{
bfd_vma size;
if (! ieee_read_number (info, pp, &size))
return FALSE;
type = debug_make_int_type (dhandle, size, FALSE);
}
break;
case 'A':
case 'a':
{
debug_type ele_type;
bfd_vma lower, upper;
if (! ieee_read_type_index (info, pp, &ele_type)
|| ! ieee_read_number (info, pp, &lower)
|| ! ieee_read_number (info, pp, &upper))
return FALSE;
type = debug_make_array_type (dhandle, ele_type,
ieee_builtin_type (info, ty_code_start,
((unsigned int)
builtin_int)),
(bfd_signed_vma) lower,
(bfd_signed_vma) upper,
FALSE);
}
break;
case 'E':
{
bfd_vma size;
unsigned int alloc;
const char **names;
unsigned int c;
bfd_signed_vma *vals;
unsigned int i;
if (! ieee_read_number (info, pp, &size))
return FALSE;
alloc = 10;
names = (const char **) xmalloc (alloc * sizeof *names);
memset (names, 0, alloc * sizeof *names);
c = 0;
while (1)
{
const char *name;
unsigned long namlen;
bfd_boolean present;
if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
return FALSE;
if (! present)
break;
if (c + 1 >= alloc)
{
alloc += 10;
names = ((const char **)
xrealloc (names, alloc * sizeof *names));
}
names[c] = savestring (name, namlen);
if (names[c] == NULL)
return FALSE;
++c;
}
names[c] = NULL;
vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals);
for (i = 0; i < c; i++)
vals[i] = i;
type = debug_make_enum_type (dhandle, names, vals);
tag = TRUE;
}
break;
case 'G':
{
bfd_vma size;
unsigned int alloc;
debug_field *fields;
unsigned int c;
if (! ieee_read_number (info, pp, &size))
return FALSE;
alloc = 10;
fields = (debug_field *) xmalloc (alloc * sizeof *fields);
c = 0;
while (1)
{
const char *name;
unsigned long namlen;
bfd_boolean present;
debug_type ftype;
bfd_vma bitpos, bitsize;
if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
return FALSE;
if (! present)
break;
if (! ieee_read_type_index (info, pp, &ftype)
|| ! ieee_read_number (info, pp, &bitpos)
|| ! ieee_read_number (info, pp, &bitsize))
return FALSE;
if (c + 1 >= alloc)
{
alloc += 10;
fields = ((debug_field *)
xrealloc (fields, alloc * sizeof *fields));
}
fields[c] = debug_make_field (dhandle, savestring (name, namlen),
ftype, bitpos, bitsize,
DEBUG_VISIBILITY_PUBLIC);
if (fields[c] == NULL)
return FALSE;
++c;
}
fields[c] = NULL;
type = debug_make_struct_type (dhandle, TRUE, size, fields);
tag = TRUE;
}
break;
case 'N':
{
unsigned int alloc;
const char **names;
bfd_signed_vma *vals;
unsigned int c;
alloc = 10;
names = (const char **) xmalloc (alloc * sizeof *names);
vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names);
c = 0;
while (1)
{
const char *name;
unsigned long namlen;
bfd_boolean present;
bfd_vma val;
if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
return FALSE;
if (! present)
break;
if (! ieee_read_number (info, pp, &val))
return FALSE;
if (namlen == 0)
continue;
if (c + 1 >= alloc)
{
alloc += 10;
names = ((const char **)
xrealloc (names, alloc * sizeof *names));
vals = ((bfd_signed_vma *)
xrealloc (vals, alloc * sizeof *vals));
}
names[c] = savestring (name, namlen);
if (names[c] == NULL)
return FALSE;
vals[c] = (bfd_signed_vma) val;
++c;
}
names[c] = NULL;
type = debug_make_enum_type (dhandle, names, vals);
tag = TRUE;
}
break;
case 'O':
case 'P':
{
debug_type t;
if (! ieee_read_type_index (info, pp, &t))
return FALSE;
type = debug_make_pointer_type (dhandle, t);
}
break;
case 'R':
{
bfd_vma low, high, signedp, size;
if (! ieee_read_number (info, pp, &low)
|| ! ieee_read_number (info, pp, &high)
|| ! ieee_read_number (info, pp, &signedp)
|| ! ieee_read_number (info, pp, &size))
return FALSE;
type = debug_make_range_type (dhandle,
debug_make_int_type (dhandle, size,
! signedp),
(bfd_signed_vma) low,
(bfd_signed_vma) high);
}
break;
case 'S':
case 'U':
{
bfd_vma size;
unsigned int alloc;
debug_field *fields;
unsigned int c;
if (! ieee_read_number (info, pp, &size))
return FALSE;
alloc = 10;
fields = (debug_field *) xmalloc (alloc * sizeof *fields);
c = 0;
while (1)
{
const char *name;
unsigned long namlen;
bfd_boolean present;
bfd_vma tindx;
bfd_vma offset;
debug_type ftype;
bfd_vma bitsize;
if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
return FALSE;
if (! present)
break;
if (! ieee_read_number (info, pp, &tindx)
|| ! ieee_read_number (info, pp, &offset))
return FALSE;
if (tindx < 256)
{
ftype = ieee_builtin_type (info, ty_code_start, tindx);
bitsize = 0;
offset *= 8;
}
else
{
struct ieee_type *t;
tindx -= 256;
if (! ieee_alloc_type (info, tindx, TRUE))
return FALSE;
t = info->types.types + tindx;
ftype = t->type;
bitsize = t->bitsize;
if (bitsize == 0)
offset *= 8;
}
if (c + 1 >= alloc)
{
alloc += 10;
fields = ((debug_field *)
xrealloc (fields, alloc * sizeof *fields));
}
fields[c] = debug_make_field (dhandle, savestring (name, namlen),
ftype, offset, bitsize,
DEBUG_VISIBILITY_PUBLIC);
if (fields[c] == NULL)
return FALSE;
++c;
}
fields[c] = NULL;
type = debug_make_struct_type (dhandle, tc == 'S', size, fields);
tag = TRUE;
}
break;
case 'T':
if (! ieee_read_type_index (info, pp, &type))
return FALSE;
typdef = TRUE;
break;
case 'X':
{
bfd_vma attr;
debug_type rtype;
bfd_vma nargs;
bfd_boolean present;
struct ieee_var *pv;
if (! ieee_read_number (info, pp, &attr)
|| ! ieee_read_type_index (info, pp, &rtype)
|| ! ieee_read_number (info, pp, &nargs))
return FALSE;
do
{
const char *name;
unsigned long namlen;
if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
return FALSE;
}
while (present);
pv = info->vars.vars + varindx;
pv->kind = IEEE_EXTERNAL;
if (pv->namlen > 0
&& debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
{
pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
*pv->pslot = rtype;
rtype = debug_make_indirect_type (dhandle, pv->pslot,
(const char *) NULL);
}
type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL,
FALSE);
}
break;
case 'V':
type = debug_make_void_type (dhandle);
break;
case 'Z':
{
debug_type etype;
bfd_vma high;
if (! ieee_read_type_index (info, pp, &etype)
|| ! ieee_read_number (info, pp, &high))
return FALSE;
type = debug_make_array_type (dhandle, etype,
ieee_builtin_type (info, ty_code_start,
((unsigned int)
builtin_int)),
0, (bfd_signed_vma) high, FALSE);
}
break;
case 'c':
case 'd':
{
const char *name;
unsigned long namlen;
if (! ieee_read_id (info, pp, &name, &namlen))
return FALSE;
type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8);
}
break;
case 'f':
ieee_error (info, ty_code_start, _("Pascal file name not supported"));
return FALSE;
case 'g':
{
bfd_vma signedp, bitsize, dummy;
const bfd_byte *hold;
bfd_boolean present;
if (! ieee_read_number (info, pp, &signedp)
|| ! ieee_read_number (info, pp, &bitsize))
return FALSE;
hold = *pp;
if (! ieee_read_optional_number (info, pp, &dummy, &present))
return FALSE;
if (! present)
{
type = debug_make_int_type (dhandle, 4,
signedp ? FALSE : TRUE);
}
else
{
*pp = hold;
if (! ieee_read_type_index (info, pp, &type))
return FALSE;
}
type_bitsize = bitsize;
}
break;
case 'n':
{
bfd_vma kind;
debug_type t;
if (! ieee_read_number (info, pp, &kind)
|| ! ieee_read_type_index (info, pp, &t))
return FALSE;
switch (kind)
{
default:
ieee_error (info, ty_start, _("unsupported qualifier"));
return FALSE;
case 1:
type = debug_make_const_type (dhandle, t);
break;
case 2:
type = debug_make_volatile_type (dhandle, t);
break;
}
}
break;
case 's':
{
bfd_vma size;
debug_type etype;
if (! ieee_read_number (info, pp, &size)
|| ! ieee_read_type_index (info, pp, &etype))
return FALSE;
type = debug_make_set_type (dhandle, etype, FALSE);
}
break;
case 'x':
{
struct ieee_var *pv;
bfd_vma attr, frame_type, push_mask, nargs, level, father;
debug_type rtype;
debug_type *arg_types;
bfd_boolean varargs;
bfd_boolean present;
pv = info->vars.vars + varindx;
if (! ieee_read_number (info, pp, &attr)
|| ! ieee_read_number (info, pp, &frame_type)
|| ! ieee_read_number (info, pp, &push_mask)
|| ! ieee_read_type_index (info, pp, &rtype)
|| ! ieee_read_number (info, pp, &nargs))
return FALSE;
if (nargs == (bfd_vma) -1)
{
arg_types = NULL;
varargs = FALSE;
}
else
{
unsigned int i;
arg_types = ((debug_type *)
xmalloc ((nargs + 1) * sizeof *arg_types));
for (i = 0; i < nargs; i++)
if (! ieee_read_type_index (info, pp, arg_types + i))
return FALSE;
varargs = FALSE;
if (nargs > 0)
{
debug_type last;
last = arg_types[nargs - 1];
if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER
&& (debug_get_type_kind (dhandle,
debug_get_target_type (dhandle,
last))
== DEBUG_KIND_VOID))
{
--nargs;
varargs = TRUE;
}
}
for (i = 0; i < nargs; i++)
{
if (debug_get_type_kind (dhandle, arg_types[i])
== DEBUG_KIND_POINTER)
{
if (arg_slots == NULL)
{
arg_slots = ((debug_type *)
xmalloc (nargs * sizeof *arg_slots));
memset (arg_slots, 0, nargs * sizeof *arg_slots);
}
arg_slots[i] = arg_types[i];
arg_types[i] =
debug_make_indirect_type (dhandle,
arg_slots + i,
(const char *) NULL);
}
}
arg_types[nargs] = DEBUG_TYPE_NULL;
}
if (! ieee_read_number (info, pp, &level)
|| ! ieee_read_optional_number (info, pp, &father, &present))
return FALSE;
pv->kind = IEEE_FUNCTION;
if (pv->namlen > 0
&& debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
{
pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
*pv->pslot = rtype;
rtype = debug_make_indirect_type (dhandle, pv->pslot,
(const char *) NULL);
}
type = debug_make_function_type (dhandle, rtype, arg_types, varargs);
}
break;
}
if (type == DEBUG_TYPE_NULL)
return FALSE;
info->vars.vars[varindx].type = type;
if ((tag || typdef)
&& info->vars.vars[varindx].namlen > 0)
{
const char *name;
name = savestring (info->vars.vars[varindx].name,
info->vars.vars[varindx].namlen);
if (typdef)
type = debug_name_type (dhandle, name, type);
else if (tc == 'E' || tc == 'N')
type = debug_tag_type (dhandle, name, type);
else
{
struct ieee_tag *it;
it = (struct ieee_tag *) xmalloc (sizeof *it);
memset (it, 0, sizeof *it);
it->next = info->tags;
info->tags = it;
it->name = name;
it->slot = type;
type = debug_make_indirect_type (dhandle, &it->slot, name);
type = debug_tag_type (dhandle, name, type);
it->type = type;
}
if (type == NULL)
return FALSE;
}
info->types.types[typeindx].type = type;
info->types.types[typeindx].arg_slots = arg_slots;
info->types.types[typeindx].bitsize = type_bitsize;
if (info->types.types[typeindx].pslot != NULL)
*info->types.types[typeindx].pslot = type;
return TRUE;
}
static bfd_boolean
parse_ieee_atn (struct ieee_info *info, const bfd_byte **pp)
{
const bfd_byte *atn_start, *atn_code_start;
bfd_vma varindx;
struct ieee_var *pvar;
debug_type type;
bfd_vma atn_code;
void *dhandle;
bfd_vma v, v2, v3, v4, v5;
const char *name;
unsigned long namlen;
char *namcopy;
bfd_boolean present;
int blocktype;
atn_start = *pp;
if (! ieee_read_number (info, pp, &varindx)
|| ! ieee_read_type_index (info, pp, &type))
return FALSE;
atn_code_start = *pp;
if (! ieee_read_number (info, pp, &atn_code))
return FALSE;
if (varindx == 0)
{
pvar = NULL;
name = "";
namlen = 0;
}
else if (varindx < 32)
{
if (atn_code == 9)
return ieee_read_number (info, pp, &v);
ieee_error (info, atn_start, _("illegal variable index"));
return FALSE;
}
else
{
varindx -= 32;
if (varindx >= info->vars.alloc
|| info->vars.vars[varindx].name == NULL)
{
if (atn_code == 62)
{
if (varindx >= info->vars.alloc)
{
unsigned int alloc;
alloc = info->vars.alloc;
if (alloc == 0)
alloc = 4;
while (varindx >= alloc)
alloc *= 2;
info->vars.vars = ((struct ieee_var *)
xrealloc (info->vars.vars,
(alloc
* sizeof *info->vars.vars)));
memset (info->vars.vars + info->vars.alloc, 0,
((alloc - info->vars.alloc)
* sizeof *info->vars.vars));
info->vars.alloc = alloc;
}
pvar = info->vars.vars + varindx;
pvar->name = "";
pvar->namlen = 0;
}
else
{
ieee_error (info, atn_start, _("undefined variable in ATN"));
return FALSE;
}
}
pvar = info->vars.vars + varindx;
pvar->type = type;
name = pvar->name;
namlen = pvar->namlen;
}
dhandle = info->dhandle;
if (pvar != NULL
&& type != DEBUG_TYPE_NULL
&& debug_get_type_kind (dhandle, type) == DEBUG_KIND_POINTER)
{
switch (atn_code)
{
case 1:
case 2:
case 3:
case 5:
case 8:
case 10:
pvar->pslot = (debug_type *) xmalloc (sizeof *pvar->pslot);
*pvar->pslot = type;
type = debug_make_indirect_type (dhandle, pvar->pslot,
(const char *) NULL);
pvar->type = type;
break;
}
}
switch (atn_code)
{
default:
ieee_error (info, atn_code_start, _("unknown ATN type"));
return FALSE;
case 1:
if (! ieee_read_number (info, pp, &v))
return FALSE;
namcopy = savestring (name, namlen);
if (type == NULL)
type = debug_make_void_type (dhandle);
if (pvar != NULL)
pvar->kind = IEEE_LOCAL;
return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v);
case 2:
if (! ieee_read_number (info, pp, &v))
return FALSE;
namcopy = savestring (name, namlen);
if (type == NULL)
type = debug_make_void_type (dhandle);
if (pvar != NULL)
pvar->kind = IEEE_LOCAL;
return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER,
ieee_regno_to_genreg (info->abfd, v));
case 3:
if (! ieee_require_asn (info, pp, &v))
return FALSE;
namcopy = savestring (name, namlen);
if (type == NULL)
type = debug_make_void_type (dhandle);
if (info->blockstack.bsp <= info->blockstack.stack)
blocktype = 0;
else
blocktype = info->blockstack.bsp[-1].kind;
if (pvar != NULL)
{
if (blocktype == 4 || blocktype == 6)
pvar->kind = IEEE_LOCAL;
else
pvar->kind = IEEE_STATIC;
}
return debug_record_variable (dhandle, namcopy, type,
(blocktype == 4 || blocktype == 6
? DEBUG_LOCAL_STATIC
: DEBUG_STATIC),
v);
case 4:
if (pvar != NULL)
pvar->kind = IEEE_EXTERNAL;
return TRUE;
case 5:
if (pvar != NULL)
pvar->kind = IEEE_EXTERNAL;
return TRUE;
case 7:
if (! ieee_read_number (info, pp, &v)
|| ! ieee_read_number (info, pp, &v2)
|| ! ieee_read_optional_number (info, pp, &v3, &present))
return FALSE;
if (present)
{
if (! ieee_read_optional_number (info, pp, &v4, &present))
return FALSE;
}
if (! ieee_require_asn (info, pp, &v3))
return FALSE;
return debug_record_line (dhandle, v, v3);
case 8:
if (! ieee_require_asn (info, pp, &v))
return FALSE;
namcopy = savestring (name, namlen);
if (type == NULL)
type = debug_make_void_type (dhandle);
if (pvar != NULL)
pvar->kind = IEEE_GLOBAL;
return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v);
case 9:
if (! ieee_read_number (info, pp, &v))
return FALSE;
return TRUE;
case 10:
if (! ieee_read_number (info, pp, &v)
|| ! ieee_read_optional_number (info, pp, &v2, &present))
return FALSE;
namcopy = savestring (name, namlen);
if (type == NULL)
type = debug_make_void_type (dhandle);
if (pvar != NULL)
pvar->kind = IEEE_LOCAL;
return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v);
case 11:
ieee_error (info, atn_code_start, _("unsupported ATN11"));
return TRUE;
case 12:
v3 = 0;
v4 = 0x80;
v5 = 0;
if (! ieee_read_number (info, pp, &v)
|| ! ieee_read_number (info, pp, &v2)
|| ! ieee_read_optional_number (info, pp, &v3, &present))
return FALSE;
if (present)
{
if (! ieee_read_optional_number (info, pp, &v4, &present))
return FALSE;
if (present)
{
if (! ieee_read_optional_number (info, pp, &v5, &present))
return FALSE;
}
}
ieee_error (info, atn_code_start, _("unsupported ATN12"));
return TRUE;
case 16:
if (! ieee_read_number (info, pp, &v)
|| ! ieee_read_optional_number (info, pp, &v2, &present))
return FALSE;
if (present)
{
if (! ieee_read_optional_number (info, pp, &v2, &present))
return FALSE;
if (present)
{
if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
return FALSE;
}
}
if ((ieee_record_enum_type) **pp == ieee_e2_first_byte_enum)
{
if (! ieee_require_asn (info, pp, &v3))
return FALSE;
}
return TRUE;
case 19:
v2 = 0;
if (! ieee_read_number (info, pp, &v)
|| ! ieee_read_optional_number (info, pp, &v2, &present)
|| ! ieee_require_asn (info, pp, &v3))
return FALSE;
namcopy = savestring (name, namlen);
return debug_record_variable (dhandle, namcopy,
debug_make_void_type (dhandle),
v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC,
v3);
case 62:
case 63:
case 64:
if (! ieee_read_number (info, pp, &v)
|| ! ieee_read_number (info, pp, &v2)
|| ! ieee_read_optional_id (info, pp, &name, &namlen, &present))
return FALSE;
if (atn_code == 62 && v == 80)
{
if (present)
{
ieee_error (info, atn_code_start,
_("unexpected string in C++ misc"));
return FALSE;
}
return ieee_read_cxx_misc (info, pp, v2);
}
for (; v2 > 0; --v2)
{
switch ((ieee_record_enum_type) **pp)
{
default:
ieee_error (info, *pp, _("bad misc record"));
return FALSE;
case ieee_at_record_enum:
if (! ieee_require_atn65 (info, pp, &name, &namlen))
return FALSE;
break;
case ieee_e2_first_byte_enum:
if (! ieee_require_asn (info, pp, &v3))
return FALSE;
break;
}
}
return TRUE;
}
}
static bfd_boolean
ieee_read_cxx_misc (struct ieee_info *info, const bfd_byte **pp,
unsigned long count)
{
const bfd_byte *start;
bfd_vma category;
start = *pp;
if (! ieee_require_asn (info, pp, &category))
return FALSE;
--count;
switch (category)
{
default:
ieee_error (info, start, _("unrecognized C++ misc record"));
return FALSE;
case 'T':
if (! ieee_read_cxx_class (info, pp, count))
return FALSE;
break;
case 'M':
{
bfd_vma flags;
const char *name;
unsigned long namlen;
if (! ieee_require_asn (info, pp, &flags))
return FALSE;
if (*pp < info->pend
&& (ieee_record_enum_type) **pp == ieee_at_record_enum)
{
if (! ieee_require_atn65 (info, pp, &name, &namlen))
return FALSE;
}
}
break;
case 'B':
if (! ieee_read_cxx_defaults (info, pp, count))
return FALSE;
break;
case 'z':
{
const char *name, *mangled, *class;
unsigned long namlen, mangledlen, classlen;
bfd_vma control;
if (! ieee_require_atn65 (info, pp, &name, &namlen)
|| ! ieee_require_atn65 (info, pp, &mangled, &mangledlen)
|| ! ieee_require_atn65 (info, pp, &class, &classlen)
|| ! ieee_require_asn (info, pp, &control))
return FALSE;
}
break;
case 'R':
if (! ieee_read_reference (info, pp))
return FALSE;
break;
}
return TRUE;
}
static bfd_boolean
ieee_read_cxx_class (struct ieee_info *info, const bfd_byte **pp,
unsigned long count)
{
const bfd_byte *start;
bfd_vma class;
const char *tag;
unsigned long taglen;
struct ieee_tag *it;
void *dhandle;
debug_field *fields;
unsigned int field_count, field_alloc;
debug_baseclass *baseclasses;
unsigned int baseclasses_count, baseclasses_alloc;
const debug_field *structfields;
struct ieee_method
{
const char *name;
unsigned long namlen;
debug_method_variant *variants;
unsigned count;
unsigned int alloc;
} *methods;
unsigned int methods_count, methods_alloc;
debug_type vptrbase;
bfd_boolean ownvptr;
debug_method *dmethods;
start = *pp;
if (! ieee_require_asn (info, pp, &class))
return FALSE;
--count;
if (! ieee_require_atn65 (info, pp, &tag, &taglen))
return FALSE;
--count;
for (it = info->tags; it != NULL; it = it->next)
if (it->name[0] == tag[0]
&& strncmp (it->name, tag, taglen) == 0
&& strlen (it->name) == taglen)
break;
if (it == NULL)
{
ieee_error (info, start, _("undefined C++ object"));
return FALSE;
}
dhandle = info->dhandle;
fields = NULL;
field_count = 0;
field_alloc = 0;
baseclasses = NULL;
baseclasses_count = 0;
baseclasses_alloc = 0;
methods = NULL;
methods_count = 0;
methods_alloc = 0;
vptrbase = DEBUG_TYPE_NULL;
ownvptr = FALSE;
structfields = debug_get_fields (dhandle, it->type);
while (count > 0)
{
bfd_vma id;
const bfd_byte *spec_start;
spec_start = *pp;
if (! ieee_require_asn (info, pp, &id))
return FALSE;
--count;
switch (id)
{
default:
ieee_error (info, spec_start, _("unrecognized C++ object spec"));
return FALSE;
case 'b':
{
bfd_vma flags, cinline;
const char *basename, *fieldname;
unsigned long baselen, fieldlen;
char *basecopy;
debug_type basetype;
bfd_vma bitpos;
bfd_boolean virtualp;
enum debug_visibility visibility;
debug_baseclass baseclass;
if (! ieee_require_asn (info, pp, &flags)
|| ! ieee_require_atn65 (info, pp, &basename, &baselen)
|| ! ieee_require_asn (info, pp, &cinline)
|| ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen))
return FALSE;
count -= 4;
if ((flags & BASEFLAGS_FRIEND) != 0)
break;
if ((fieldlen == 0) == (cinline == 0))
{
ieee_error (info, start, _("unsupported C++ object type"));
return FALSE;
}
basecopy = savestring (basename, baselen);
basetype = debug_find_tagged_type (dhandle, basecopy,
DEBUG_KIND_ILLEGAL);
free (basecopy);
if (basetype == DEBUG_TYPE_NULL)
{
ieee_error (info, start, _("C++ base class not defined"));
return FALSE;
}
if (fieldlen == 0)
bitpos = 0;
else
{
const debug_field *pf;
if (structfields == NULL)
{
ieee_error (info, start, _("C++ object has no fields"));
return FALSE;
}
for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++)
{
const char *fname;
fname = debug_get_field_name (dhandle, *pf);
if (fname == NULL)
return FALSE;
if (fname[0] == fieldname[0]
&& strncmp (fname, fieldname, fieldlen) == 0
&& strlen (fname) == fieldlen)
break;
}
if (*pf == DEBUG_FIELD_NULL)
{
ieee_error (info, start,
_("C++ base class not found in container"));
return FALSE;
}
bitpos = debug_get_field_bitpos (dhandle, *pf);
}
if ((flags & BASEFLAGS_VIRTUAL) != 0)
virtualp = TRUE;
else
virtualp = FALSE;
if ((flags & BASEFLAGS_PRIVATE) != 0)
visibility = DEBUG_VISIBILITY_PRIVATE;
else
visibility = DEBUG_VISIBILITY_PUBLIC;
baseclass = debug_make_baseclass (dhandle, basetype, bitpos,
virtualp, visibility);
if (baseclass == DEBUG_BASECLASS_NULL)
return FALSE;
if (baseclasses_count + 1 >= baseclasses_alloc)
{
baseclasses_alloc += 10;
baseclasses = ((debug_baseclass *)
xrealloc (baseclasses,
(baseclasses_alloc
* sizeof *baseclasses)));
}
baseclasses[baseclasses_count] = baseclass;
++baseclasses_count;
baseclasses[baseclasses_count] = DEBUG_BASECLASS_NULL;
}
break;
case 'd':
{
bfd_vma flags;
const char *fieldname, *mangledname;
unsigned long fieldlen, mangledlen;
char *fieldcopy;
bfd_boolean staticp;
debug_type ftype;
const debug_field *pf = NULL;
enum debug_visibility visibility;
debug_field field;
if (! ieee_require_asn (info, pp, &flags)
|| ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen)
|| ! ieee_require_atn65 (info, pp, &mangledname, &mangledlen))
return FALSE;
count -= 3;
fieldcopy = savestring (fieldname, fieldlen);
staticp = (flags & CXXFLAGS_STATIC) != 0 ? TRUE : FALSE;
if (staticp)
{
struct ieee_var *pv, *pvend;
pv = info->vars.vars;
pvend = pv + info->vars.alloc;
for (; pv < pvend; pv++)
if (pv->namlen == mangledlen
&& strncmp (pv->name, mangledname, mangledlen) == 0)
break;
if (pv < pvend)
ftype = pv->type;
else
{
ftype = ieee_builtin_type (info, start,
(unsigned int) builtin_void);
}
}
else
{
unsigned int findx;
if (structfields == NULL)
{
ieee_error (info, start, _("C++ object has no fields"));
return FALSE;
}
for (pf = structfields, findx = 0;
*pf != DEBUG_FIELD_NULL;
pf++, findx++)
{
const char *fname;
fname = debug_get_field_name (dhandle, *pf);
if (fname == NULL)
return FALSE;
if (fname[0] == mangledname[0]
&& strncmp (fname, mangledname, mangledlen) == 0
&& strlen (fname) == mangledlen)
break;
}
if (*pf == DEBUG_FIELD_NULL)
{
ieee_error (info, start,
_("C++ data member not found in container"));
return FALSE;
}
ftype = debug_get_field_type (dhandle, *pf);
if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER)
{
if (it->fslots == NULL)
{
unsigned int fcnt;
const debug_field *pfcnt;
fcnt = 0;
for (pfcnt = structfields;
*pfcnt != DEBUG_FIELD_NULL;
pfcnt++)
++fcnt;
it->fslots = ((debug_type *)
xmalloc (fcnt * sizeof *it->fslots));
memset (it->fslots, 0,
fcnt * sizeof *it->fslots);
}
if (ftype == DEBUG_TYPE_NULL)
return FALSE;
it->fslots[findx] = ftype;
ftype = debug_make_indirect_type (dhandle,
it->fslots + findx,
(const char *) NULL);
}
}
if (ftype == DEBUG_TYPE_NULL)
return FALSE;
switch (flags & CXXFLAGS_VISIBILITY)
{
default:
ieee_error (info, start, _("unknown C++ visibility"));
return FALSE;
case CXXFLAGS_VISIBILITY_PUBLIC:
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
case CXXFLAGS_VISIBILITY_PRIVATE:
visibility = DEBUG_VISIBILITY_PRIVATE;
break;
case CXXFLAGS_VISIBILITY_PROTECTED:
visibility = DEBUG_VISIBILITY_PROTECTED;
break;
}
if (staticp)
{
char *mangledcopy;
mangledcopy = savestring (mangledname, mangledlen);
field = debug_make_static_member (dhandle, fieldcopy,
ftype, mangledcopy,
visibility);
}
else
{
bfd_vma bitpos, bitsize;
bitpos = debug_get_field_bitpos (dhandle, *pf);
bitsize = debug_get_field_bitsize (dhandle, *pf);
if (bitpos == (bfd_vma) -1 || bitsize == (bfd_vma) -1)
{
ieee_error (info, start, _("bad C++ field bit pos or size"));
return FALSE;
}
field = debug_make_field (dhandle, fieldcopy, ftype, bitpos,
bitsize, visibility);
}
if (field == DEBUG_FIELD_NULL)
return FALSE;
if (field_count + 1 >= field_alloc)
{
field_alloc += 10;
fields = ((debug_field *)
xrealloc (fields, field_alloc * sizeof *fields));
}
fields[field_count] = field;
++field_count;
fields[field_count] = DEBUG_FIELD_NULL;
}
break;
case 'm':
case 'v':
{
bfd_vma flags, voffset, control;
const char *name, *mangled;
unsigned long namlen, mangledlen;
struct ieee_var *pv, *pvend;
debug_type type;
enum debug_visibility visibility;
bfd_boolean constp, volatilep;
char *mangledcopy;
debug_method_variant mv;
struct ieee_method *meth;
unsigned int im;
if (! ieee_require_asn (info, pp, &flags)
|| ! ieee_require_atn65 (info, pp, &name, &namlen)
|| ! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
return FALSE;
count -= 3;
if (id != 'v')
voffset = 0;
else
{
if (! ieee_require_asn (info, pp, &voffset))
return FALSE;
--count;
}
if (! ieee_require_asn (info, pp, &control))
return FALSE;
--count;
if ((flags & CXXFLAGS_FRIEND) != 0)
break;
pv = info->vars.vars;
pvend = pv + info->vars.alloc;
for (; pv < pvend; pv++)
if (pv->namlen == mangledlen
&& strncmp (pv->name, mangled, mangledlen) == 0)
break;
if (pv >= pvend)
{
type = (debug_make_function_type
(dhandle,
ieee_builtin_type (info, start,
(unsigned int) builtin_void),
(debug_type *) NULL,
FALSE));
}
else
{
debug_type return_type;
const debug_type *arg_types;
bfd_boolean varargs;
if (debug_get_type_kind (dhandle, pv->type)
!= DEBUG_KIND_FUNCTION)
{
ieee_error (info, start,
_("bad type for C++ method function"));
return FALSE;
}
return_type = debug_get_return_type (dhandle, pv->type);
arg_types = debug_get_parameter_types (dhandle, pv->type,
&varargs);
if (return_type == DEBUG_TYPE_NULL || arg_types == NULL)
{
ieee_error (info, start,
_("no type information for C++ method function"));
return FALSE;
}
type = debug_make_method_type (dhandle, return_type, it->type,
(debug_type *) arg_types,
varargs);
}
if (type == DEBUG_TYPE_NULL)
return FALSE;
switch (flags & CXXFLAGS_VISIBILITY)
{
default:
ieee_error (info, start, _("unknown C++ visibility"));
return FALSE;
case CXXFLAGS_VISIBILITY_PUBLIC:
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
case CXXFLAGS_VISIBILITY_PRIVATE:
visibility = DEBUG_VISIBILITY_PRIVATE;
break;
case CXXFLAGS_VISIBILITY_PROTECTED:
visibility = DEBUG_VISIBILITY_PROTECTED;
break;
}
constp = (flags & CXXFLAGS_CONST) != 0 ? TRUE : FALSE;
volatilep = (flags & CXXFLAGS_VOLATILE) != 0 ? TRUE : FALSE;
mangledcopy = savestring (mangled, mangledlen);
if ((flags & CXXFLAGS_STATIC) != 0)
{
if (id == 'v')
{
ieee_error (info, start, _("C++ static virtual method"));
return FALSE;
}
mv = debug_make_static_method_variant (dhandle, mangledcopy,
type, visibility,
constp, volatilep);
}
else
{
debug_type vcontext;
if (id != 'v')
vcontext = DEBUG_TYPE_NULL;
else
{
vcontext = it->type;
}
mv = debug_make_method_variant (dhandle, mangledcopy, type,
visibility, constp,
volatilep, voffset,
vcontext);
}
if (mv == DEBUG_METHOD_VARIANT_NULL)
return FALSE;
for (meth = methods, im = 0; im < methods_count; meth++, im++)
if (meth->namlen == namlen
&& strncmp (meth->name, name, namlen) == 0)
break;
if (im >= methods_count)
{
if (methods_count >= methods_alloc)
{
methods_alloc += 10;
methods = ((struct ieee_method *)
xrealloc (methods,
methods_alloc * sizeof *methods));
}
methods[methods_count].name = name;
methods[methods_count].namlen = namlen;
methods[methods_count].variants = NULL;
methods[methods_count].count = 0;
methods[methods_count].alloc = 0;
meth = methods + methods_count;
++methods_count;
}
if (meth->count + 1 >= meth->alloc)
{
meth->alloc += 10;
meth->variants = ((debug_method_variant *)
xrealloc (meth->variants,
(meth->alloc
* sizeof *meth->variants)));
}
meth->variants[meth->count] = mv;
++meth->count;
meth->variants[meth->count] = DEBUG_METHOD_VARIANT_NULL;
}
break;
case 'o':
{
bfd_vma spec;
if (! ieee_require_asn (info, pp, &spec))
return FALSE;
--count;
if ((spec & 4) != 0)
{
const char *filename;
unsigned long filenamlen;
bfd_vma lineno;
if (! ieee_require_atn65 (info, pp, &filename, &filenamlen)
|| ! ieee_require_asn (info, pp, &lineno))
return FALSE;
count -= 2;
}
else if ((spec & 8) != 0)
{
const char *mangled;
unsigned long mangledlen;
if (! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
return FALSE;
--count;
}
else
{
ieee_error (info, start,
_("unrecognized C++ object overhead spec"));
return FALSE;
}
}
break;
case 'z':
{
const char *vname, *basename;
unsigned long vnamelen, baselen;
bfd_vma vsize, control;
if (! ieee_require_atn65 (info, pp, &vname, &vnamelen)
|| ! ieee_require_asn (info, pp, &vsize)
|| ! ieee_require_atn65 (info, pp, &basename, &baselen)
|| ! ieee_require_asn (info, pp, &control))
return FALSE;
count -= 4;
if (baselen == 0)
ownvptr = TRUE;
else
{
char *basecopy;
basecopy = savestring (basename, baselen);
vptrbase = debug_find_tagged_type (dhandle, basecopy,
DEBUG_KIND_ILLEGAL);
free (basecopy);
if (vptrbase == DEBUG_TYPE_NULL)
{
ieee_error (info, start, _("undefined C++ vtable"));
return FALSE;
}
}
}
break;
}
}
if (methods_count == 0)
dmethods = NULL;
else
{
unsigned int i;
dmethods = ((debug_method *)
xmalloc ((methods_count + 1) * sizeof *dmethods));
for (i = 0; i < methods_count; i++)
{
char *namcopy;
namcopy = savestring (methods[i].name, methods[i].namlen);
dmethods[i] = debug_make_method (dhandle, namcopy,
methods[i].variants);
if (dmethods[i] == DEBUG_METHOD_NULL)
return FALSE;
}
dmethods[i] = DEBUG_METHOD_NULL;
free (methods);
}
it->slot = debug_make_object_type (dhandle,
class != 'u',
debug_get_type_size (dhandle,
it->slot),
fields, baseclasses, dmethods,
vptrbase, ownvptr);
if (it->slot == DEBUG_TYPE_NULL)
return FALSE;
return TRUE;
}
static bfd_boolean
ieee_read_cxx_defaults (struct ieee_info *info, const bfd_byte **pp,
unsigned long count)
{
const bfd_byte *start;
const char *fnname;
unsigned long fnlen;
bfd_vma defcount;
start = *pp;
if (info->blockstack.bsp <= info->blockstack.stack
|| info->blockstack.bsp[-1].fnindx == (unsigned int) -1)
{
ieee_error (info, start, _("C++ default values not in a function"));
return FALSE;
}
if (! ieee_require_atn65 (info, pp, &fnname, &fnlen)
|| ! ieee_require_asn (info, pp, &defcount))
return FALSE;
count -= 2;
while (defcount-- > 0)
{
bfd_vma type, val;
const char *strval;
unsigned long strvallen;
if (! ieee_require_asn (info, pp, &type))
return FALSE;
--count;
switch (type)
{
case 0:
case 4:
break;
case 1:
case 2:
if (! ieee_require_asn (info, pp, &val))
return FALSE;
--count;
break;
case 3:
case 7:
if (! ieee_require_atn65 (info, pp, &strval, &strvallen))
return FALSE;
--count;
break;
default:
ieee_error (info, start, _("unrecognized C++ default type"));
return FALSE;
}
}
if (count > 0)
{
void *dhandle;
debug_type *arg_slots;
dhandle = info->dhandle;
arg_slots = info->types.types[info->blockstack.bsp[-1].fnindx].arg_slots;
while (count-- > 0)
{
bfd_vma indx;
debug_type target;
if (! ieee_require_asn (info, pp, &indx))
return FALSE;
--indx;
if (arg_slots == NULL
|| arg_slots[indx] == DEBUG_TYPE_NULL
|| (debug_get_type_kind (dhandle, arg_slots[indx])
!= DEBUG_KIND_POINTER))
{
ieee_error (info, start, _("reference parameter is not a pointer"));
return FALSE;
}
target = debug_get_target_type (dhandle, arg_slots[indx]);
arg_slots[indx] = debug_make_reference_type (dhandle, target);
if (arg_slots[indx] == DEBUG_TYPE_NULL)
return FALSE;
}
}
return TRUE;
}
static bfd_boolean
ieee_read_reference (struct ieee_info *info, const bfd_byte **pp)
{
const bfd_byte *start;
bfd_vma flags;
const char *class, *name;
unsigned long classlen, namlen;
debug_type *pslot;
debug_type target;
start = *pp;
if (! ieee_require_asn (info, pp, &flags))
return FALSE;
if (flags == 3)
{
if (! ieee_require_atn65 (info, pp, &class, &classlen))
return FALSE;
}
if (! ieee_require_atn65 (info, pp, &name, &namlen))
return FALSE;
pslot = NULL;
if (flags != 3)
{
int pass;
for (pass = 0; pass < 2; pass++)
{
struct ieee_vars *vars;
int i;
struct ieee_var *pv = NULL;
if (pass == 0)
vars = &info->vars;
else
{
vars = info->global_vars;
if (vars == NULL)
break;
}
for (i = (int) vars->alloc - 1; i >= 0; i--)
{
bfd_boolean found;
pv = vars->vars + i;
if (pv->pslot == NULL
|| pv->namlen != namlen
|| strncmp (pv->name, name, namlen) != 0)
continue;
found = FALSE;
switch (flags)
{
default:
ieee_error (info, start,
_("unrecognized C++ reference type"));
return FALSE;
case 0:
if (pv->kind == IEEE_GLOBAL
|| pv->kind == IEEE_EXTERNAL
|| pv->kind == IEEE_FUNCTION)
found = TRUE;
break;
case 1:
if (pv->kind == IEEE_STATIC
|| pv->kind == IEEE_FUNCTION)
found = TRUE;
break;
case 2:
if (pv->kind == IEEE_LOCAL)
found = TRUE;
break;
}
if (found)
break;
}
if (i >= 0)
{
pslot = pv->pslot;
break;
}
}
}
else
{
struct ieee_tag *it;
for (it = info->tags; it != NULL; it = it->next)
{
if (it->name[0] == class[0]
&& strncmp (it->name, class, classlen) == 0
&& strlen (it->name) == classlen)
{
if (it->fslots != NULL)
{
const debug_field *pf;
unsigned int findx;
pf = debug_get_fields (info->dhandle, it->type);
if (pf == NULL)
{
ieee_error (info, start,
"C++ reference in class with no fields");
return FALSE;
}
for (findx = 0; *pf != DEBUG_FIELD_NULL; pf++, findx++)
{
const char *fname;
fname = debug_get_field_name (info->dhandle, *pf);
if (fname == NULL)
return FALSE;
if (strncmp (fname, name, namlen) == 0
&& strlen (fname) == namlen)
{
pslot = it->fslots + findx;
break;
}
}
}
break;
}
}
}
if (pslot == NULL)
{
ieee_error (info, start, _("C++ reference not found"));
return FALSE;
}
if (debug_get_type_kind (info->dhandle, *pslot) != DEBUG_KIND_POINTER)
{
ieee_error (info, start, _("C++ reference is not pointer"));
return FALSE;
}
target = debug_get_target_type (info->dhandle, *pslot);
*pslot = debug_make_reference_type (info->dhandle, target);
if (*pslot == DEBUG_TYPE_NULL)
return FALSE;
return TRUE;
}
static bfd_boolean
ieee_require_asn (struct ieee_info *info, const bfd_byte **pp, bfd_vma *pv)
{
const bfd_byte *start;
ieee_record_enum_type c;
bfd_vma varindx;
start = *pp;
c = (ieee_record_enum_type) **pp;
if (c != ieee_e2_first_byte_enum)
{
ieee_error (info, start, _("missing required ASN"));
return FALSE;
}
++*pp;
c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
if (c != ieee_asn_record_enum)
{
ieee_error (info, start, _("missing required ASN"));
return FALSE;
}
++*pp;
if (! ieee_read_number (info, pp, &varindx))
return FALSE;
return ieee_read_expression (info, pp, pv);
}
static bfd_boolean
ieee_require_atn65 (struct ieee_info *info, const bfd_byte **pp,
const char **pname, unsigned long *pnamlen)
{
const bfd_byte *start;
ieee_record_enum_type c;
bfd_vma name_indx, type_indx, atn_code;
start = *pp;
c = (ieee_record_enum_type) **pp;
if (c != ieee_at_record_enum)
{
ieee_error (info, start, _("missing required ATN65"));
return FALSE;
}
++*pp;
c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
if (c != ieee_atn_record_enum)
{
ieee_error (info, start, _("missing required ATN65"));
return FALSE;
}
++*pp;
if (! ieee_read_number (info, pp, &name_indx)
|| ! ieee_read_number (info, pp, &type_indx)
|| ! ieee_read_number (info, pp, &atn_code))
return FALSE;
if (type_indx != 0 || atn_code != 65)
{
ieee_error (info, start, _("bad ATN65 record"));
return FALSE;
}
return ieee_read_id (info, pp, pname, pnamlen);
}
static int
ieee_regno_to_genreg (bfd *abfd, int r)
{
switch (bfd_get_arch (abfd))
{
case bfd_arch_m68k:
if (r >= 16)
r += 2;
break;
case bfd_arch_i960:
--r;
break;
default:
break;
}
return r;
}
static int
ieee_genreg_to_regno (bfd *abfd, int r)
{
switch (bfd_get_arch (abfd))
{
case bfd_arch_m68k:
if (r >= 18)
r -= 2;
break;
case bfd_arch_i960:
++r;
break;
default:
break;
}
return r;
}
#define IEEE_BUFSIZE (490)
struct ieee_buf
{
struct ieee_buf *next;
unsigned int c;
bfd_byte buf[IEEE_BUFSIZE];
};
struct ieee_buflist
{
struct ieee_buf *head;
struct ieee_buf *tail;
};
struct ieee_range
{
struct ieee_range *next;
bfd_vma low;
bfd_vma high;
};
struct ieee_type_class
{
unsigned int indx;
struct ieee_buflist pmiscbuf;
unsigned int pmisccount;
const char *vclass;
bfd_boolean ownvptr;
bfd_vma voffset;
const char *method;
struct ieee_buflist refs;
};
struct ieee_write_type
{
unsigned int indx;
unsigned int size;
const char *name;
struct ieee_buflist fndef;
struct ieee_buflist strdef;
struct ieee_type_class *classdef;
unsigned int unsignedp : 1;
unsigned int referencep : 1;
unsigned int localp : 1;
unsigned int ignorep : 1;
};
struct ieee_type_stack
{
struct ieee_type_stack *next;
struct ieee_write_type type;
};
struct ieee_name_type
{
struct ieee_name_type *next;
unsigned int id;
struct ieee_write_type type;
enum debug_type_kind kind;
};
struct ieee_name_type_hash_table
{
struct bfd_hash_table root;
};
struct ieee_name_type_hash_entry
{
struct bfd_hash_entry root;
struct ieee_name_type *types;
};
struct ieee_defined_enum
{
struct ieee_defined_enum *next;
unsigned int indx;
bfd_boolean defined;
const char *tag;
const char **names;
bfd_signed_vma *vals;
};
struct ieee_modified_type
{
unsigned int pointer;
unsigned int function;
unsigned int const_qualified;
unsigned int volatile_qualified;
struct ieee_modified_array_type *arrays;
};
struct ieee_modified_array_type
{
struct ieee_modified_array_type *next;
unsigned int indx;
bfd_signed_vma low;
bfd_signed_vma high;
};
struct ieee_pending_parm
{
struct ieee_pending_parm *next;
const char *name;
unsigned int type;
bfd_boolean referencep;
enum debug_parm_kind kind;
bfd_vma val;
};
struct ieee_handle
{
bfd *abfd;
bfd_boolean error;
struct ieee_buflist *current;
struct ieee_buf *curbuf;
const char *filename;
const char *modname;
struct ieee_buflist global_types;
struct ieee_buflist data;
struct ieee_buflist types;
struct ieee_buflist vars;
struct ieee_buflist cxx;
struct ieee_buflist linenos;
struct ieee_range *ranges;
struct ieee_range *global_ranges;
struct ieee_range *pending_ranges;
struct ieee_type_stack *type_stack;
unsigned int type_indx;
unsigned int name_indx;
struct ieee_name_type_hash_table typedefs;
struct ieee_name_type_hash_table tags;
struct ieee_defined_enum *enums;
struct ieee_modified_type *modified;
unsigned int modified_alloc;
unsigned int complex_float_index;
unsigned int complex_double_index;
unsigned int block_depth;
const char *fnname;
struct ieee_buflist fntype;
struct ieee_buflist fnargs;
unsigned int fnargcount;
struct ieee_pending_parm *pending_parms;
const char *lineno_filename;
unsigned int lineno_name_indx;
const char *pending_lineno_filename;
unsigned long pending_lineno;
bfd_vma pending_lineno_addr;
bfd_vma highaddr;
};
static bfd_boolean ieee_init_buffer
(struct ieee_handle *, struct ieee_buflist *);
static bfd_boolean ieee_change_buffer
(struct ieee_handle *, struct ieee_buflist *);
static bfd_boolean ieee_append_buffer
(struct ieee_handle *, struct ieee_buflist *, struct ieee_buflist *);
static bfd_boolean ieee_real_write_byte (struct ieee_handle *, int);
static bfd_boolean ieee_write_2bytes (struct ieee_handle *, int);
static bfd_boolean ieee_write_number (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_write_id (struct ieee_handle *, const char *);
static bfd_boolean ieee_write_asn
(struct ieee_handle *, unsigned int, bfd_vma);
static bfd_boolean ieee_write_atn65
(struct ieee_handle *, unsigned int, const char *);
static bfd_boolean ieee_push_type
(struct ieee_handle *, unsigned int, unsigned int, bfd_boolean,
bfd_boolean);
static unsigned int ieee_pop_type (struct ieee_handle *);
static void ieee_pop_unused_type (struct ieee_handle *);
static unsigned int ieee_pop_type_used (struct ieee_handle *, bfd_boolean);
static bfd_boolean ieee_add_range
(struct ieee_handle *, bfd_boolean, bfd_vma, bfd_vma);
static bfd_boolean ieee_start_range (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_end_range (struct ieee_handle *, bfd_vma);
static bfd_boolean ieee_define_type
(struct ieee_handle *, unsigned int, bfd_boolean, bfd_boolean);
static bfd_boolean ieee_define_named_type
(struct ieee_handle *, const char *, unsigned int, unsigned int,
bfd_boolean, bfd_boolean, struct ieee_buflist *);
static struct ieee_modified_type *ieee_get_modified_info
(struct ieee_handle *, unsigned int);
static struct bfd_hash_entry *ieee_name_type_newfunc
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
static bfd_boolean ieee_write_undefined_tag
(struct ieee_name_type_hash_entry *, void *);
static bfd_boolean ieee_finish_compilation_unit (struct ieee_handle *);
static void ieee_add_bb11_blocks (bfd *, asection *, void *);
static bfd_boolean ieee_add_bb11
(struct ieee_handle *, asection *, bfd_vma, bfd_vma);
static bfd_boolean ieee_output_pending_parms (struct ieee_handle *);
static unsigned int ieee_vis_to_flags (enum debug_visibility);
static bfd_boolean ieee_class_method_var
(struct ieee_handle *, const char *, enum debug_visibility, bfd_boolean,
bfd_boolean, bfd_boolean, bfd_vma, bfd_boolean);
static bfd_boolean ieee_start_compilation_unit (void *, const char *);
static bfd_boolean ieee_start_source (void *, const char *);
static bfd_boolean ieee_empty_type (void *);
static bfd_boolean ieee_void_type (void *);
static bfd_boolean ieee_int_type (void *, unsigned int, bfd_boolean);
static bfd_boolean ieee_float_type (void *, unsigned int);
static bfd_boolean ieee_complex_type (void *, unsigned int);
static bfd_boolean ieee_bool_type (void *, unsigned int);
static bfd_boolean ieee_enum_type
(void *, const char *, const char **, bfd_signed_vma *);
static bfd_boolean ieee_pointer_type (void *);
static bfd_boolean ieee_function_type (void *, int, bfd_boolean);
static bfd_boolean ieee_reference_type (void *);
static bfd_boolean ieee_range_type (void *, bfd_signed_vma, bfd_signed_vma);
static bfd_boolean ieee_array_type
(void *, bfd_signed_vma, bfd_signed_vma, bfd_boolean);
static bfd_boolean ieee_set_type (void *, bfd_boolean);
static bfd_boolean ieee_offset_type (void *);
static bfd_boolean ieee_method_type (void *, bfd_boolean, int, bfd_boolean);
static bfd_boolean ieee_const_type (void *);
static bfd_boolean ieee_volatile_type (void *);
static bfd_boolean ieee_start_struct_type
(void *, const char *, unsigned int, bfd_boolean, unsigned int);
static bfd_boolean ieee_struct_field
(void *, const char *, bfd_vma, bfd_vma, enum debug_visibility);
static bfd_boolean ieee_end_struct_type (void *);
static bfd_boolean ieee_start_class_type
(void *, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean,
bfd_boolean);
static bfd_boolean ieee_class_static_member
(void *, const char *, const char *, enum debug_visibility);
static bfd_boolean ieee_class_baseclass
(void *, bfd_vma, bfd_boolean, enum debug_visibility);
static bfd_boolean ieee_class_start_method (void *, const char *);
static bfd_boolean ieee_class_method_variant
(void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
bfd_vma, bfd_boolean);
static bfd_boolean ieee_class_static_method_variant
(void *, const char *, enum debug_visibility, bfd_boolean, bfd_boolean);
static bfd_boolean ieee_class_end_method (void *);
static bfd_boolean ieee_end_class_type (void *);
static bfd_boolean ieee_typedef_type (void *, const char *);
static bfd_boolean ieee_tag_type
(void *, const char *, unsigned int, enum debug_type_kind);
static bfd_boolean ieee_typdef (void *, const char *);
static bfd_boolean ieee_tag (void *, const char *);
static bfd_boolean ieee_int_constant (void *, const char *, bfd_vma);
static bfd_boolean ieee_float_constant (void *, const char *, double);
static bfd_boolean ieee_typed_constant (void *, const char *, bfd_vma);
static bfd_boolean ieee_variable
(void *, const char *, enum debug_var_kind, bfd_vma);
static bfd_boolean ieee_start_function (void *, const char *, bfd_boolean);
static bfd_boolean ieee_function_parameter
(void *, const char *, enum debug_parm_kind, bfd_vma);
static bfd_boolean ieee_start_block (void *, bfd_vma);
static bfd_boolean ieee_end_block (void *, bfd_vma);
static bfd_boolean ieee_end_function (void *);
static bfd_boolean ieee_lineno (void *, const char *, unsigned long, bfd_vma);
static const struct debug_write_fns ieee_fns =
{
ieee_start_compilation_unit,
ieee_start_source,
ieee_empty_type,
ieee_void_type,
ieee_int_type,
ieee_float_type,
ieee_complex_type,
ieee_bool_type,
ieee_enum_type,
ieee_pointer_type,
ieee_function_type,
ieee_reference_type,
ieee_range_type,
ieee_array_type,
ieee_set_type,
ieee_offset_type,
ieee_method_type,
ieee_const_type,
ieee_volatile_type,
ieee_start_struct_type,
ieee_struct_field,
ieee_end_struct_type,
ieee_start_class_type,
ieee_class_static_member,
ieee_class_baseclass,
ieee_class_start_method,
ieee_class_method_variant,
ieee_class_static_method_variant,
ieee_class_end_method,
ieee_end_class_type,
ieee_typedef_type,
ieee_tag_type,
ieee_typdef,
ieee_tag,
ieee_int_constant,
ieee_float_constant,
ieee_typed_constant,
ieee_variable,
ieee_start_function,
ieee_function_parameter,
ieee_start_block,
ieee_end_block,
ieee_end_function,
ieee_lineno
};
static bfd_boolean
ieee_init_buffer (struct ieee_handle *info ATTRIBUTE_UNUSED,
struct ieee_buflist *buflist)
{
buflist->head = NULL;
buflist->tail = NULL;
return TRUE;
}
#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL)
static bfd_boolean
ieee_change_buffer (struct ieee_handle *info, struct ieee_buflist *buflist)
{
if (buflist->head == NULL)
{
struct ieee_buf *buf;
buf = (struct ieee_buf *) xmalloc (sizeof *buf);
buf->next = NULL;
buf->c = 0;
buflist->head = buf;
buflist->tail = buf;
}
info->current = buflist;
info->curbuf = buflist->tail;
return TRUE;
}
static bfd_boolean
ieee_append_buffer (struct ieee_handle *info ATTRIBUTE_UNUSED,
struct ieee_buflist *mainbuf,
struct ieee_buflist *newbuf)
{
if (newbuf->head != NULL)
{
if (mainbuf->head == NULL)
mainbuf->head = newbuf->head;
else
mainbuf->tail->next = newbuf->head;
mainbuf->tail = newbuf->tail;
}
return TRUE;
}
#define ieee_write_byte(info, b) \
((info)->curbuf->c < IEEE_BUFSIZE \
? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), TRUE) \
: ieee_real_write_byte ((info), (b)))
static bfd_boolean
ieee_real_write_byte (struct ieee_handle *info, int b)
{
if (info->curbuf->c >= IEEE_BUFSIZE)
{
struct ieee_buf *n;
n = (struct ieee_buf *) xmalloc (sizeof *n);
n->next = NULL;
n->c = 0;
if (info->current->head == NULL)
info->current->head = n;
else
info->current->tail->next = n;
info->current->tail = n;
info->curbuf = n;
}
info->curbuf->buf[info->curbuf->c] = b;
++info->curbuf->c;
return TRUE;
}
static bfd_boolean
ieee_write_2bytes (struct ieee_handle *info, int i)
{
return (ieee_write_byte (info, i >> 8)
&& ieee_write_byte (info, i & 0xff));
}
static bfd_boolean
ieee_write_number (struct ieee_handle *info, bfd_vma v)
{
bfd_vma t;
bfd_byte ab[20];
bfd_byte *p;
unsigned int c;
if (v <= (bfd_vma) ieee_number_end_enum)
return ieee_write_byte (info, (int) v);
t = v;
p = ab + sizeof ab;
while (t != 0)
{
*--p = t & 0xff;
t >>= 8;
}
c = (ab + 20) - p;
if (c > (unsigned int) (ieee_number_repeat_end_enum
- ieee_number_repeat_start_enum))
{
fprintf (stderr, _("IEEE numeric overflow: 0x"));
fprintf_vma (stderr, v);
fprintf (stderr, "\n");
return FALSE;
}
if (! ieee_write_byte (info, (int) ieee_number_repeat_start_enum + c))
return FALSE;
for (; c > 0; --c, ++p)
{
if (! ieee_write_byte (info, *p))
return FALSE;
}
return TRUE;
}
static bfd_boolean
ieee_write_id (struct ieee_handle *info, const char *s)
{
unsigned int len;
len = strlen (s);
if (len <= 0x7f)
{
if (! ieee_write_byte (info, len))
return FALSE;
}
else if (len <= 0xff)
{
if (! ieee_write_byte (info, (int) ieee_extension_length_1_enum)
|| ! ieee_write_byte (info, len))
return FALSE;
}
else if (len <= 0xffff)
{
if (! ieee_write_byte (info, (int) ieee_extension_length_2_enum)
|| ! ieee_write_2bytes (info, len))
return FALSE;
}
else
{
fprintf (stderr, _("IEEE string length overflow: %u\n"), len);
return FALSE;
}
for (; *s != '\0'; s++)
if (! ieee_write_byte (info, *s))
return FALSE;
return TRUE;
}
static bfd_boolean
ieee_write_asn (struct ieee_handle *info, unsigned int indx, bfd_vma val)
{
return (ieee_write_2bytes (info, (int) ieee_asn_record_enum)
&& ieee_write_number (info, indx)
&& ieee_write_number (info, val));
}
static bfd_boolean
ieee_write_atn65 (struct ieee_handle *info, unsigned int indx, const char *s)
{
return (ieee_write_2bytes (info, (int) ieee_atn_record_enum)
&& ieee_write_number (info, indx)
&& ieee_write_number (info, 0)
&& ieee_write_number (info, 65)
&& ieee_write_id (info, s));
}
static bfd_boolean
ieee_push_type (struct ieee_handle *info, unsigned int indx,
unsigned int size, bfd_boolean unsignedp, bfd_boolean localp)
{
struct ieee_type_stack *ts;
ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
memset (ts, 0, sizeof *ts);
ts->type.indx = indx;
ts->type.size = size;
ts->type.unsignedp = unsignedp;
ts->type.localp = localp;
ts->next = info->type_stack;
info->type_stack = ts;
return TRUE;
}
static unsigned int
ieee_pop_type (struct ieee_handle *info)
{
return ieee_pop_type_used (info, TRUE);
}
static void
ieee_pop_unused_type (struct ieee_handle *info)
{
(void) ieee_pop_type_used (info, FALSE);
}
static unsigned int
ieee_pop_type_used (struct ieee_handle *info, bfd_boolean used)
{
struct ieee_type_stack *ts;
unsigned int ret;
ts = info->type_stack;
assert (ts != NULL);
if (used && ! ieee_buffer_emptyp (&ts->type.fndef))
{
struct ieee_buflist *buflist;
if (ts->type.localp)
{
if (ieee_buffer_emptyp (&info->types))
{
if (! ieee_change_buffer (info, &info->types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 1)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->modname))
return FALSE;
}
buflist = &info->types;
}
else
{
if (ieee_buffer_emptyp (&info->global_types))
{
if (! ieee_change_buffer (info, &info->global_types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 2)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, ""))
return FALSE;
}
buflist = &info->global_types;
}
if (! ieee_append_buffer (info, buflist, &ts->type.fndef))
return FALSE;
}
ret = ts->type.indx;
info->type_stack = ts->next;
free (ts);
return ret;
}
static bfd_boolean
ieee_add_range (struct ieee_handle *info, bfd_boolean global, bfd_vma low,
bfd_vma high)
{
struct ieee_range **plist, *r, **pr;
if (low == (bfd_vma) -1 || high == (bfd_vma) -1 || low == high)
return TRUE;
if (global)
plist = &info->global_ranges;
else
plist = &info->ranges;
for (r = *plist; r != NULL; r = r->next)
{
if (high >= r->low && low <= r->high)
{
if (low < r->low)
r->low = low;
if (high > r->high)
r->high = high;
pr = &r->next;
while (*pr != NULL && (*pr)->low <= r->high)
{
struct ieee_range *n;
if ((*pr)->high > r->high)
r->high = (*pr)->high;
n = (*pr)->next;
free (*pr);
*pr = n;
}
return TRUE;
}
}
r = (struct ieee_range *) xmalloc (sizeof *r);
memset (r, 0, sizeof *r);
r->low = low;
r->high = high;
for (pr = plist; *pr != NULL; pr = &(*pr)->next)
if ((*pr)->low > high)
break;
r->next = *pr;
*pr = r;
return TRUE;
}
static bfd_boolean
ieee_start_range (struct ieee_handle *info, bfd_vma low)
{
struct ieee_range *r;
r = (struct ieee_range *) xmalloc (sizeof *r);
memset (r, 0, sizeof *r);
r->low = low;
r->next = info->pending_ranges;
info->pending_ranges = r;
return TRUE;
}
static bfd_boolean
ieee_end_range (struct ieee_handle *info, bfd_vma high)
{
struct ieee_range *r;
bfd_vma low;
assert (info->pending_ranges != NULL);
r = info->pending_ranges;
low = r->low;
info->pending_ranges = r->next;
free (r);
return ieee_add_range (info, FALSE, low, high);
}
static bfd_boolean
ieee_define_type (struct ieee_handle *info, unsigned int size,
bfd_boolean unsignedp, bfd_boolean localp)
{
return ieee_define_named_type (info, (const char *) NULL,
(unsigned int) -1, size, unsignedp,
localp, (struct ieee_buflist *) NULL);
}
static bfd_boolean
ieee_define_named_type (struct ieee_handle *info, const char *name,
unsigned int indx, unsigned int size,
bfd_boolean unsignedp, bfd_boolean localp,
struct ieee_buflist *buflist)
{
unsigned int type_indx;
unsigned int name_indx;
if (indx != (unsigned int) -1)
type_indx = indx;
else
{
type_indx = info->type_indx;
++info->type_indx;
}
name_indx = info->name_indx;
++info->name_indx;
if (name == NULL)
name = "";
if (buflist != NULL)
{
if (! ieee_change_buffer (info, buflist))
return FALSE;
}
else if (localp)
{
if (! ieee_buffer_emptyp (&info->types))
{
if (! ieee_change_buffer (info, &info->types))
return FALSE;
}
else
{
if (! ieee_change_buffer (info, &info->types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 1)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->modname))
return FALSE;
}
}
else
{
if (! ieee_buffer_emptyp (&info->global_types))
{
if (! ieee_change_buffer (info, &info->global_types))
return FALSE;
}
else
{
if (! ieee_change_buffer (info, &info->global_types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 2)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, ""))
return FALSE;
}
}
if (! ieee_push_type (info, type_indx, size, unsignedp, localp))
return FALSE;
return (ieee_write_byte (info, (int) ieee_nn_record)
&& ieee_write_number (info, name_indx)
&& ieee_write_id (info, name)
&& ieee_write_byte (info, (int) ieee_ty_record_enum)
&& ieee_write_number (info, type_indx)
&& ieee_write_byte (info, 0xce)
&& ieee_write_number (info, name_indx));
}
static struct ieee_modified_type *
ieee_get_modified_info (struct ieee_handle *info, unsigned int indx)
{
if (indx >= info->modified_alloc)
{
unsigned int nalloc;
nalloc = info->modified_alloc;
if (nalloc == 0)
nalloc = 16;
while (indx >= nalloc)
nalloc *= 2;
info->modified = ((struct ieee_modified_type *)
xrealloc (info->modified,
nalloc * sizeof *info->modified));
memset (info->modified + info->modified_alloc, 0,
(nalloc - info->modified_alloc) * sizeof *info->modified);
info->modified_alloc = nalloc;
}
return info->modified + indx;
}
static struct bfd_hash_entry *
ieee_name_type_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table, const char *string)
{
struct ieee_name_type_hash_entry *ret =
(struct ieee_name_type_hash_entry *) entry;
if (ret == NULL)
ret = ((struct ieee_name_type_hash_entry *)
bfd_hash_allocate (table, sizeof *ret));
if (ret == NULL)
return NULL;
ret = ((struct ieee_name_type_hash_entry *)
bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
if (ret)
{
ret->types = NULL;
}
return (struct bfd_hash_entry *) ret;
}
#define ieee_name_type_hash_lookup(table, string, create, copy) \
((struct ieee_name_type_hash_entry *) \
bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
#define ieee_name_type_hash_traverse(table, func, info) \
(bfd_hash_traverse \
(&(table)->root, \
(bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func), \
(info)))
bfd_boolean
write_ieee_debugging_info (bfd *abfd, void *dhandle)
{
struct ieee_handle info;
asection *s;
const char *err;
struct ieee_buf *b;
memset (&info, 0, sizeof info);
info.abfd = abfd;
info.type_indx = 256;
info.name_indx = 32;
if (! bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc)
|| ! bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc))
return FALSE;
if (! ieee_init_buffer (&info, &info.global_types)
|| ! ieee_init_buffer (&info, &info.data)
|| ! ieee_init_buffer (&info, &info.types)
|| ! ieee_init_buffer (&info, &info.vars)
|| ! ieee_init_buffer (&info, &info.cxx)
|| ! ieee_init_buffer (&info, &info.linenos)
|| ! ieee_init_buffer (&info, &info.fntype)
|| ! ieee_init_buffer (&info, &info.fnargs))
return FALSE;
if (! debug_write (dhandle, &ieee_fns, (void *) &info))
return FALSE;
if (info.filename != NULL)
{
if (! ieee_finish_compilation_unit (&info))
return FALSE;
}
info.error = FALSE;
ieee_name_type_hash_traverse (&info.tags,
ieee_write_undefined_tag,
(void *) &info);
if (info.error)
return FALSE;
if (! ieee_buffer_emptyp (&info.global_types))
{
if (! ieee_change_buffer (&info, &info.global_types)
|| ! ieee_write_byte (&info, (int) ieee_nn_record)
|| ! ieee_write_number (&info, info.name_indx)
|| ! ieee_write_id (&info, "")
|| ! ieee_write_byte (&info, (int) ieee_ty_record_enum)
|| ! ieee_write_number (&info, info.type_indx)
|| ! ieee_write_byte (&info, 0xce)
|| ! ieee_write_number (&info, info.name_indx)
|| ! ieee_write_number (&info, 'P')
|| ! ieee_write_number (&info, (int) builtin_void + 32)
|| ! ieee_write_byte (&info, (int) ieee_be_record_enum))
return FALSE;
if (! ieee_append_buffer (&info, &info.global_types, &info.data))
return FALSE;
info.data = info.global_types;
}
info.error = FALSE;
if (! ieee_init_buffer (&info, &info.vars))
return FALSE;
bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (void *) &info);
if (info.error)
return FALSE;
if (! ieee_buffer_emptyp (&info.vars))
{
if (! ieee_change_buffer (&info, &info.vars)
|| ! ieee_write_byte (&info, (int) ieee_be_record_enum))
return FALSE;
if (! ieee_append_buffer (&info, &info.data, &info.vars))
return FALSE;
}
if (ieee_buffer_emptyp (&info.data))
{
return TRUE;
}
err = NULL;
s = bfd_make_section (abfd, ".debug");
if (s == NULL)
err = "bfd_make_section";
if (err == NULL)
{
if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS))
err = "bfd_set_section_flags";
}
if (err == NULL)
{
bfd_size_type size;
size = 0;
for (b = info.data.head; b != NULL; b = b->next)
size += b->c;
if (! bfd_set_section_size (abfd, s, size))
err = "bfd_set_section_size";
}
if (err == NULL)
{
file_ptr offset;
offset = 0;
for (b = info.data.head; b != NULL; b = b->next)
{
if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c))
{
err = "bfd_set_section_contents";
break;
}
offset += b->c;
}
}
if (err != NULL)
{
fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err,
bfd_errmsg (bfd_get_error ()));
return FALSE;
}
bfd_hash_table_free (&info.typedefs.root);
bfd_hash_table_free (&info.tags.root);
return TRUE;
}
static bfd_boolean
ieee_write_undefined_tag (struct ieee_name_type_hash_entry *h, void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
struct ieee_name_type *nt;
for (nt = h->types; nt != NULL; nt = nt->next)
{
unsigned int name_indx;
char code;
if (nt->kind == DEBUG_KIND_ILLEGAL)
continue;
if (ieee_buffer_emptyp (&info->global_types))
{
if (! ieee_change_buffer (info, &info->global_types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 2)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, ""))
{
info->error = TRUE;
return FALSE;
}
}
else
{
if (! ieee_change_buffer (info, &info->global_types))
{
info->error = TRUE;
return FALSE;
}
}
name_indx = info->name_indx;
++info->name_indx;
if (! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, name_indx)
|| ! ieee_write_id (info, nt->type.name)
|| ! ieee_write_byte (info, (int) ieee_ty_record_enum)
|| ! ieee_write_number (info, nt->type.indx)
|| ! ieee_write_byte (info, 0xce)
|| ! ieee_write_number (info, name_indx))
{
info->error = TRUE;
return FALSE;
}
switch (nt->kind)
{
default:
abort ();
info->error = TRUE;
return FALSE;
case DEBUG_KIND_STRUCT:
case DEBUG_KIND_CLASS:
code = 'S';
break;
case DEBUG_KIND_UNION:
case DEBUG_KIND_UNION_CLASS:
code = 'U';
break;
case DEBUG_KIND_ENUM:
code = 'E';
break;
}
if (! ieee_write_number (info, code)
|| ! ieee_write_number (info, 0))
{
info->error = TRUE;
return FALSE;
}
}
return TRUE;
}
static bfd_boolean
ieee_start_compilation_unit (void *p, const char *filename)
{
struct ieee_handle *info = (struct ieee_handle *) p;
const char *modname;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
const char *backslash;
#endif
char *c, *s;
unsigned int nindx;
if (info->filename != NULL)
{
if (! ieee_finish_compilation_unit (info))
return FALSE;
}
info->filename = filename;
modname = strrchr (filename, '/');
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
backslash = strrchr (filename, '\\');
if (modname == NULL || (backslash != NULL && backslash > modname))
modname = backslash;
#endif
if (modname != NULL)
++modname;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
else if (filename[0] && filename[1] == ':')
modname = filename + 2;
#endif
else
modname = filename;
c = xstrdup (modname);
s = strrchr (c, '.');
if (s != NULL)
*s = '\0';
info->modname = c;
if (! ieee_init_buffer (info, &info->types)
|| ! ieee_init_buffer (info, &info->vars)
|| ! ieee_init_buffer (info, &info->cxx)
|| ! ieee_init_buffer (info, &info->linenos))
return FALSE;
info->ranges = NULL;
if (! ieee_change_buffer (info, &info->types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 1)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->modname))
return FALSE;
nindx = info->name_indx;
++info->name_indx;
if (! ieee_change_buffer (info, &info->vars)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 3)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->modname))
return FALSE;
return TRUE;
}
static bfd_boolean
ieee_finish_compilation_unit (struct ieee_handle *info)
{
struct ieee_range *r;
if (! ieee_buffer_emptyp (&info->types))
{
if (! ieee_change_buffer (info, &info->types)
|| ! ieee_write_byte (info, (int) ieee_be_record_enum))
return FALSE;
}
if (! ieee_buffer_emptyp (&info->cxx))
{
assert (! ieee_buffer_emptyp (&info->vars));
if (! ieee_change_buffer (info, &info->vars))
return FALSE;
if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 6)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, "__XRYCPP")
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, info->highaddr - 1)
|| ! ieee_append_buffer (info, &info->vars, &info->cxx)
|| ! ieee_change_buffer (info, &info->vars)
|| ! ieee_write_byte (info, (int) ieee_be_record_enum)
|| ! ieee_write_number (info, info->highaddr - 1))
return FALSE;
}
if (! ieee_buffer_emptyp (&info->vars))
{
if (! ieee_change_buffer (info, &info->vars)
|| ! ieee_write_byte (info, (int) ieee_be_record_enum))
return FALSE;
}
if (info->pending_lineno_filename != NULL)
{
if (! ieee_lineno ((void *) info, (const char *) NULL, 0, (bfd_vma) -1))
return FALSE;
}
if (! ieee_buffer_emptyp (&info->linenos))
{
if (! ieee_change_buffer (info, &info->linenos)
|| ! ieee_write_byte (info, (int) ieee_be_record_enum))
return FALSE;
if (strcmp (info->filename, info->lineno_filename) != 0)
{
if (! ieee_write_byte (info, (int) ieee_be_record_enum))
return FALSE;
}
}
if (! ieee_append_buffer (info, &info->data, &info->types)
|| ! ieee_append_buffer (info, &info->data, &info->vars)
|| ! ieee_append_buffer (info, &info->data, &info->linenos))
return FALSE;
if (! ieee_change_buffer (info, &info->data))
return FALSE;
if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 10)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->modname)
|| ! ieee_write_id (info, "")
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, "GNU objcopy"))
return FALSE;
for (r = info->ranges; r != NULL; r = r->next)
{
bfd_vma low, high;
asection *s;
int kind;
low = r->low;
high = r->high;
for (s = info->abfd->sections; s != NULL; s = s->next)
{
if (bfd_get_section_vma (info->abfd, s) <= low
&& high <= (bfd_get_section_vma (info->abfd, s)
+ bfd_section_size (info->abfd, s)))
break;
}
if (s == NULL)
{
continue;
}
while (r->next != NULL
&& high + 0x1000 >= r->next->low
&& (r->next->high
<= (bfd_get_section_vma (info->abfd, s)
+ bfd_section_size (info->abfd, s))))
{
r = r->next;
high = r->high;
}
if ((s->flags & SEC_CODE) != 0)
kind = 1;
else if ((s->flags & SEC_READONLY) != 0)
kind = 3;
else
kind = 2;
if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 11)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, "")
|| ! ieee_write_number (info, kind)
|| ! ieee_write_number (info, s->index + IEEE_SECTION_NUMBER_BASE)
|| ! ieee_write_number (info, low)
|| ! ieee_write_byte (info, (int) ieee_be_record_enum)
|| ! ieee_write_number (info, high - low))
return FALSE;
if (! ieee_add_range (info, TRUE, low, high))
return FALSE;
}
if (! ieee_write_byte (info, (int) ieee_be_record_enum))
return FALSE;
return TRUE;
}
static void
ieee_add_bb11_blocks (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *data)
{
struct ieee_handle *info = (struct ieee_handle *) data;
bfd_vma low, high;
struct ieee_range *r;
low = bfd_get_section_vma (abfd, sec);
high = low + bfd_section_size (abfd, sec);
for (r = info->global_ranges; r != NULL; r = r->next)
if (r->high > low)
break;
while (low < high)
{
if (r == NULL || r->low >= high)
{
if (! ieee_add_bb11 (info, sec, low, high))
info->error = TRUE;
return;
}
if (low < r->low
&& r->low - low > 0x100)
{
if (! ieee_add_bb11 (info, sec, low, r->low))
{
info->error = TRUE;
return;
}
}
low = r->high;
r = r->next;
}
}
static bfd_boolean
ieee_add_bb11 (struct ieee_handle *info, asection *sec, bfd_vma low,
bfd_vma high)
{
int kind;
if (! ieee_buffer_emptyp (&info->vars))
{
if (! ieee_change_buffer (info, &info->vars))
return FALSE;
}
else
{
const char *filename, *modname;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
const char *backslash;
#endif
char *c, *s;
filename = bfd_get_filename (info->abfd);
modname = strrchr (filename, '/');
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
backslash = strrchr (filename, '\\');
if (modname == NULL || (backslash != NULL && backslash > modname))
modname = backslash;
#endif
if (modname != NULL)
++modname;
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
else if (filename[0] && filename[1] == ':')
modname = filename + 2;
#endif
else
modname = filename;
c = xstrdup (modname);
s = strrchr (c, '.');
if (s != NULL)
*s = '\0';
if (! ieee_change_buffer (info, &info->vars)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 10)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, c)
|| ! ieee_write_id (info, "")
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, "GNU objcopy"))
return FALSE;
free (c);
}
if ((sec->flags & SEC_CODE) != 0)
kind = 1;
else if ((sec->flags & SEC_READONLY) != 0)
kind = 3;
else
kind = 2;
if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 11)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, "")
|| ! ieee_write_number (info, kind)
|| ! ieee_write_number (info, sec->index + IEEE_SECTION_NUMBER_BASE)
|| ! ieee_write_number (info, low)
|| ! ieee_write_byte (info, (int) ieee_be_record_enum)
|| ! ieee_write_number (info, high - low))
return FALSE;
return TRUE;
}
static bfd_boolean
ieee_start_source (void *p ATTRIBUTE_UNUSED,
const char *filename ATTRIBUTE_UNUSED)
{
return TRUE;
}
static bfd_boolean
ieee_empty_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
return ieee_push_type (info, (int) builtin_unknown, 0, FALSE, FALSE);
}
static bfd_boolean
ieee_void_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
return ieee_push_type (info, (int) builtin_void, 0, FALSE, FALSE);
}
static bfd_boolean
ieee_int_type (void *p, unsigned int size, bfd_boolean unsignedp)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int indx;
switch (size)
{
case 1:
indx = (int) builtin_signed_char;
break;
case 2:
indx = (int) builtin_signed_short_int;
break;
case 4:
indx = (int) builtin_signed_long;
break;
case 8:
indx = (int) builtin_signed_long_long;
break;
default:
fprintf (stderr, _("IEEE unsupported integer type size %u\n"), size);
return FALSE;
}
if (unsignedp)
++indx;
return ieee_push_type (info, indx, size, unsignedp, FALSE);
}
static bfd_boolean
ieee_float_type (void *p, unsigned int size)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int indx;
switch (size)
{
case 4:
indx = (int) builtin_float;
break;
case 8:
indx = (int) builtin_double;
break;
case 12:
indx = (int) builtin_long_double;
break;
case 16:
indx = (int) builtin_long_long_double;
break;
default:
fprintf (stderr, _("IEEE unsupported float type size %u\n"), size);
return FALSE;
}
return ieee_push_type (info, indx, size, FALSE, FALSE);
}
static bfd_boolean
ieee_complex_type (void *p, unsigned int size)
{
struct ieee_handle *info = (struct ieee_handle *) p;
char code;
switch (size)
{
case 4:
if (info->complex_float_index != 0)
return ieee_push_type (info, info->complex_float_index, size * 2,
FALSE, FALSE);
code = 'c';
break;
case 12:
case 16:
case 8:
if (info->complex_double_index != 0)
return ieee_push_type (info, info->complex_double_index, size * 2,
FALSE, FALSE);
code = 'd';
break;
default:
fprintf (stderr, _("IEEE unsupported complex type size %u\n"), size);
return FALSE;
}
if (! ieee_define_type (info, size * 2, FALSE, FALSE)
|| ! ieee_write_number (info, code)
|| ! ieee_write_id (info, ""))
return FALSE;
if (size == 4)
info->complex_float_index = info->type_stack->type.indx;
else
info->complex_double_index = info->type_stack->type.indx;
return TRUE;
}
static bfd_boolean
ieee_bool_type (void *p, unsigned int size)
{
return ieee_int_type (p, size, TRUE);
}
static bfd_boolean
ieee_enum_type (void *p, const char *tag, const char **names,
bfd_signed_vma *vals)
{
struct ieee_handle *info = (struct ieee_handle *) p;
struct ieee_defined_enum *e;
bfd_boolean localp, simple;
unsigned int indx;
int i = 0;
localp = FALSE;
indx = (unsigned int) -1;
for (e = info->enums; e != NULL; e = e->next)
{
if (tag == NULL)
{
if (e->tag != NULL)
continue;
}
else
{
if (e->tag == NULL
|| tag[0] != e->tag[0]
|| strcmp (tag, e->tag) != 0)
continue;
}
if (! e->defined)
{
indx = e->indx;
break;
}
if (names != NULL && e->names != NULL)
{
for (i = 0; names[i] != NULL && e->names[i] != NULL; i++)
{
if (names[i][0] != e->names[i][0]
|| vals[i] != e->vals[i]
|| strcmp (names[i], e->names[i]) != 0)
break;
}
}
if ((names == NULL && e->names == NULL)
|| (names != NULL
&& e->names != NULL
&& names[i] == NULL
&& e->names[i] == NULL))
{
return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
}
if (tag != NULL)
{
localp = TRUE;
break;
}
}
simple = TRUE;
if (names != NULL)
{
for (i = 0; names[i] != NULL; i++)
{
if (vals[i] != i)
{
simple = FALSE;
break;
}
}
}
if (! ieee_define_named_type (info, tag, indx, 0, TRUE, localp,
(struct ieee_buflist *) NULL)
|| ! ieee_write_number (info, simple ? 'E' : 'N'))
return FALSE;
if (simple)
{
if (! ieee_write_number (info, 4))
return FALSE;
}
if (names != NULL)
{
for (i = 0; names[i] != NULL; i++)
{
if (! ieee_write_id (info, names[i]))
return FALSE;
if (! simple)
{
if (! ieee_write_number (info, vals[i]))
return FALSE;
}
}
}
if (! localp)
{
if (indx == (unsigned int) -1)
{
e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
memset (e, 0, sizeof *e);
e->indx = info->type_stack->type.indx;
e->tag = tag;
e->next = info->enums;
info->enums = e;
}
e->names = names;
e->vals = vals;
e->defined = TRUE;
}
return TRUE;
}
static bfd_boolean
ieee_pointer_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
bfd_boolean localp;
unsigned int indx;
struct ieee_modified_type *m = NULL;
localp = info->type_stack->type.localp;
indx = ieee_pop_type (info);
if (indx < 32)
return ieee_push_type (info, indx + 32, 0, TRUE, FALSE);
if (! localp)
{
m = ieee_get_modified_info (p, indx);
if (m == NULL)
return FALSE;
if (m->pointer > 0)
return ieee_push_type (info, m->pointer, 4, TRUE, FALSE);
}
if (! ieee_define_type (info, 4, TRUE, localp)
|| ! ieee_write_number (info, 'P')
|| ! ieee_write_number (info, indx))
return FALSE;
if (! localp)
m->pointer = info->type_stack->type.indx;
return TRUE;
}
static bfd_boolean
ieee_function_type (void *p, int argcount, bfd_boolean varargs)
{
struct ieee_handle *info = (struct ieee_handle *) p;
bfd_boolean localp;
unsigned int *args = NULL;
int i;
unsigned int retindx;
struct ieee_buflist fndef;
struct ieee_modified_type *m;
localp = FALSE;
if (argcount > 0)
{
args = (unsigned int *) xmalloc (argcount * sizeof *args);
for (i = argcount - 1; i >= 0; i--)
{
if (info->type_stack->type.localp)
localp = TRUE;
args[i] = ieee_pop_type (info);
}
}
else if (argcount < 0)
varargs = FALSE;
if (info->type_stack->type.localp)
localp = TRUE;
retindx = ieee_pop_type (info);
m = NULL;
if (argcount < 0 && ! localp)
{
m = ieee_get_modified_info (p, retindx);
if (m == NULL)
return FALSE;
if (m->function > 0)
return ieee_push_type (info, m->function, 0, TRUE, FALSE);
}
if (! ieee_init_buffer (info, &fndef)
|| ! ieee_define_named_type (info, (const char *) NULL,
(unsigned int) -1, 0, TRUE, localp,
&fndef)
|| ! ieee_write_number (info, 'x')
|| ! ieee_write_number (info, 0x41)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, retindx)
|| ! ieee_write_number (info, (bfd_vma) argcount + (varargs ? 1 : 0)))
return FALSE;
if (argcount > 0)
{
for (i = 0; i < argcount; i++)
if (! ieee_write_number (info, args[i]))
return FALSE;
free (args);
}
if (varargs)
{
if (! ieee_write_number (info, (bfd_vma) builtin_void + 32))
return FALSE;
}
if (! ieee_write_number (info, 0))
return FALSE;
info->type_stack->type.fndef = fndef;
if (m != NULL)
m->function = info->type_stack->type.indx;
return TRUE;
}
static bfd_boolean
ieee_reference_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
if (! ieee_pointer_type (p))
return FALSE;
info->type_stack->type.referencep = TRUE;
return TRUE;
}
static bfd_boolean
ieee_range_type (void *p, bfd_signed_vma low, bfd_signed_vma high)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
bfd_boolean unsignedp, localp;
size = info->type_stack->type.size;
unsignedp = info->type_stack->type.unsignedp;
localp = info->type_stack->type.localp;
ieee_pop_unused_type (info);
return (ieee_define_type (info, size, unsignedp, localp)
&& ieee_write_number (info, 'R')
&& ieee_write_number (info, (bfd_vma) low)
&& ieee_write_number (info, (bfd_vma) high)
&& ieee_write_number (info, unsignedp ? 0 : 1)
&& ieee_write_number (info, size));
}
static bfd_boolean
ieee_array_type (void *p, bfd_signed_vma low, bfd_signed_vma high,
bfd_boolean stringp ATTRIBUTE_UNUSED)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int eleindx;
bfd_boolean localp;
unsigned int size;
struct ieee_modified_type *m = NULL;
struct ieee_modified_array_type *a;
ieee_pop_unused_type (info);
localp = info->type_stack->type.localp;
size = info->type_stack->type.size;
eleindx = ieee_pop_type (info);
if (low < high)
size *= (high - low) + 1;
if (! localp)
{
m = ieee_get_modified_info (info, eleindx);
if (m == NULL)
return FALSE;
for (a = m->arrays; a != NULL; a = a->next)
{
if (a->low == low && a->high == high)
return ieee_push_type (info, a->indx, size, FALSE, FALSE);
}
}
if (! ieee_define_type (info, size, FALSE, localp)
|| ! ieee_write_number (info, low == 0 ? 'Z' : 'C')
|| ! ieee_write_number (info, eleindx))
return FALSE;
if (low != 0)
{
if (! ieee_write_number (info, low))
return FALSE;
}
if (! ieee_write_number (info, high + 1))
return FALSE;
if (! localp)
{
a = (struct ieee_modified_array_type *) xmalloc (sizeof *a);
memset (a, 0, sizeof *a);
a->indx = info->type_stack->type.indx;
a->low = low;
a->high = high;
a->next = m->arrays;
m->arrays = a;
}
return TRUE;
}
static bfd_boolean
ieee_set_type (void *p, bfd_boolean bitstringp ATTRIBUTE_UNUSED)
{
struct ieee_handle *info = (struct ieee_handle *) p;
bfd_boolean localp;
unsigned int eleindx;
localp = info->type_stack->type.localp;
eleindx = ieee_pop_type (info);
return (ieee_define_type (info, 0, TRUE, localp)
&& ieee_write_number (info, 's')
&& ieee_write_number (info, 4)
&& ieee_write_number (info, eleindx));
}
static bfd_boolean
ieee_offset_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int targetindx, baseindx;
targetindx = ieee_pop_type (info);
baseindx = ieee_pop_type (info);
return ieee_int_type (p, 4, TRUE);
}
static bfd_boolean
ieee_method_type (void *p, bfd_boolean domain, int argcount,
bfd_boolean varargs)
{
struct ieee_handle *info = (struct ieee_handle *) p;
if (domain)
ieee_pop_unused_type (info);
return ieee_function_type (p, argcount, varargs);
}
static bfd_boolean
ieee_const_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
bfd_boolean unsignedp, localp;
unsigned int indx;
struct ieee_modified_type *m = NULL;
size = info->type_stack->type.size;
unsignedp = info->type_stack->type.unsignedp;
localp = info->type_stack->type.localp;
indx = ieee_pop_type (info);
if (! localp)
{
m = ieee_get_modified_info (info, indx);
if (m == NULL)
return FALSE;
if (m->const_qualified > 0)
return ieee_push_type (info, m->const_qualified, size, unsignedp,
FALSE);
}
if (! ieee_define_type (info, size, unsignedp, localp)
|| ! ieee_write_number (info, 'n')
|| ! ieee_write_number (info, 1)
|| ! ieee_write_number (info, indx))
return FALSE;
if (! localp)
m->const_qualified = info->type_stack->type.indx;
return TRUE;
}
static bfd_boolean
ieee_volatile_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
bfd_boolean unsignedp, localp;
unsigned int indx;
struct ieee_modified_type *m = NULL;
size = info->type_stack->type.size;
unsignedp = info->type_stack->type.unsignedp;
localp = info->type_stack->type.localp;
indx = ieee_pop_type (info);
if (! localp)
{
m = ieee_get_modified_info (info, indx);
if (m == NULL)
return FALSE;
if (m->volatile_qualified > 0)
return ieee_push_type (info, m->volatile_qualified, size, unsignedp,
FALSE);
}
if (! ieee_define_type (info, size, unsignedp, localp)
|| ! ieee_write_number (info, 'n')
|| ! ieee_write_number (info, 2)
|| ! ieee_write_number (info, indx))
return FALSE;
if (! localp)
m->volatile_qualified = info->type_stack->type.indx;
return TRUE;
}
static unsigned int
ieee_vis_to_flags (enum debug_visibility visibility)
{
switch (visibility)
{
default:
abort ();
case DEBUG_VISIBILITY_PUBLIC:
return CXXFLAGS_VISIBILITY_PUBLIC;
case DEBUG_VISIBILITY_PRIVATE:
return CXXFLAGS_VISIBILITY_PRIVATE;
case DEBUG_VISIBILITY_PROTECTED:
return CXXFLAGS_VISIBILITY_PROTECTED;
}
}
static bfd_boolean
ieee_start_struct_type (void *p, const char *tag, unsigned int id,
bfd_boolean structp, unsigned int size)
{
struct ieee_handle *info = (struct ieee_handle *) p;
bfd_boolean localp, ignorep;
bfd_boolean copy;
char ab[20];
const char *look;
struct ieee_name_type_hash_entry *h;
struct ieee_name_type *nt, *ntlook;
struct ieee_buflist strdef;
localp = FALSE;
ignorep = FALSE;
if (tag != NULL)
{
look = tag;
copy = FALSE;
}
else
{
sprintf (ab, "__anon%u", id);
look = ab;
copy = TRUE;
}
h = ieee_name_type_hash_lookup (&info->tags, look, TRUE, copy);
if (h == NULL)
return FALSE;
nt = NULL;
for (ntlook = h->types; ntlook != NULL; ntlook = ntlook->next)
{
if (ntlook->id == id)
nt = ntlook;
else if (! ntlook->type.localp)
{
localp = TRUE;
}
}
if (nt != NULL)
{
assert (localp == nt->type.localp);
if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp)
{
ignorep = TRUE;
}
}
else
{
nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
memset (nt, 0, sizeof *nt);
nt->id = id;
nt->type.name = h->root.string;
nt->next = h->types;
h->types = nt;
nt->type.indx = info->type_indx;
++info->type_indx;
}
nt->kind = DEBUG_KIND_ILLEGAL;
if (! ieee_init_buffer (info, &strdef)
|| ! ieee_define_named_type (info, tag, nt->type.indx, size, TRUE,
localp, &strdef)
|| ! ieee_write_number (info, structp ? 'S' : 'U')
|| ! ieee_write_number (info, size))
return FALSE;
if (! ignorep)
{
const char *hold;
hold = nt->type.name;
nt->type = info->type_stack->type;
nt->type.name = hold;
}
info->type_stack->type.name = tag;
info->type_stack->type.strdef = strdef;
info->type_stack->type.ignorep = ignorep;
return TRUE;
}
static bfd_boolean
ieee_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize,
enum debug_visibility visibility)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
bfd_boolean unsignedp;
bfd_boolean referencep;
bfd_boolean localp;
unsigned int indx;
bfd_vma offset;
assert (info->type_stack != NULL
&& info->type_stack->next != NULL
&& ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
if (info->type_stack->next->type.ignorep)
{
ieee_pop_unused_type (info);
return TRUE;
}
size = info->type_stack->type.size;
unsignedp = info->type_stack->type.unsignedp;
referencep = info->type_stack->type.referencep;
localp = info->type_stack->type.localp;
indx = ieee_pop_type (info);
if (localp)
info->type_stack->type.localp = TRUE;
if (info->type_stack->type.classdef != NULL)
{
unsigned int flags;
unsigned int nindx;
flags = ieee_vis_to_flags (visibility);
nindx = info->type_stack->type.classdef->indx;
if (! ieee_change_buffer (info,
&info->type_stack->type.classdef->pmiscbuf)
|| ! ieee_write_asn (info, nindx, 'd')
|| ! ieee_write_asn (info, nindx, flags)
|| ! ieee_write_atn65 (info, nindx, name)
|| ! ieee_write_atn65 (info, nindx, name))
return FALSE;
info->type_stack->type.classdef->pmisccount += 4;
if (referencep)
{
unsigned int nindx;
nindx = info->name_indx;
++info->name_indx;
if (! ieee_change_buffer (info,
&info->type_stack->type.classdef->refs)
|| ! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_id (info, "")
|| ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 62)
|| ! ieee_write_number (info, 80)
|| ! ieee_write_number (info, 4)
|| ! ieee_write_asn (info, nindx, 'R')
|| ! ieee_write_asn (info, nindx, 3)
|| ! ieee_write_atn65 (info, nindx, info->type_stack->type.name)
|| ! ieee_write_atn65 (info, nindx, name))
return FALSE;
}
}
if (size == 0 || bitsize == 0 || bitsize == size * 8)
offset = bitpos / 8;
else
{
if (! ieee_define_type (info, 0, unsignedp,
info->type_stack->type.localp)
|| ! ieee_write_number (info, 'g')
|| ! ieee_write_number (info, unsignedp ? 0 : 1)
|| ! ieee_write_number (info, bitsize)
|| ! ieee_write_number (info, indx))
return FALSE;
indx = ieee_pop_type (info);
offset = bitpos;
}
return (ieee_change_buffer (info, &info->type_stack->type.strdef)
&& ieee_write_id (info, name)
&& ieee_write_number (info, indx)
&& ieee_write_number (info, offset));
}
static bfd_boolean
ieee_end_struct_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
struct ieee_buflist *pb;
assert (info->type_stack != NULL
&& ! ieee_buffer_emptyp (&info->type_stack->type.strdef));
if (info->type_stack->type.ignorep)
return TRUE;
if (! info->type_stack->type.localp)
{
if (ieee_buffer_emptyp (&info->global_types))
{
if (! ieee_change_buffer (info, &info->global_types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 2)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, ""))
return FALSE;
}
pb = &info->global_types;
}
else
{
if (ieee_buffer_emptyp (&info->types))
{
if (! ieee_change_buffer (info, &info->types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 1)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->modname))
return FALSE;
}
pb = &info->types;
}
if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef)
|| ! ieee_init_buffer (info, &info->type_stack->type.strdef))
return FALSE;
return TRUE;
}
static bfd_boolean
ieee_start_class_type (void *p, const char *tag, unsigned int id,
bfd_boolean structp, unsigned int size,
bfd_boolean vptr, bfd_boolean ownvptr)
{
struct ieee_handle *info = (struct ieee_handle *) p;
const char *vclass;
struct ieee_buflist pmiscbuf;
unsigned int indx;
struct ieee_type_class *classdef;
if (tag == NULL)
{
char *t;
t = (char *) xmalloc (20);
sprintf (t, "__anon%u", id);
tag = t;
}
vclass = NULL;
if (vptr && ! ownvptr)
{
vclass = info->type_stack->type.name;
assert (vclass != NULL);
(void) ieee_pop_type (info);
}
if (! ieee_start_struct_type (p, tag, id, structp, size))
return FALSE;
indx = info->name_indx;
++info->name_indx;
if (! ieee_init_buffer (info, &pmiscbuf)
|| ! ieee_change_buffer (info, &pmiscbuf)
|| ! ieee_write_asn (info, indx, 'T')
|| ! ieee_write_asn (info, indx, structp ? 'o' : 'u')
|| ! ieee_write_atn65 (info, indx, tag))
return FALSE;
classdef = (struct ieee_type_class *) xmalloc (sizeof *classdef);
memset (classdef, 0, sizeof *classdef);
classdef->indx = indx;
classdef->pmiscbuf = pmiscbuf;
classdef->pmisccount = 3;
classdef->vclass = vclass;
classdef->ownvptr = ownvptr;
info->type_stack->type.classdef = classdef;
return TRUE;
}
static bfd_boolean
ieee_class_static_member (void *p, const char *name, const char *physname,
enum debug_visibility visibility)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int flags;
unsigned int nindx;
ieee_pop_unused_type (info);
assert (info->type_stack != NULL
&& info->type_stack->type.classdef != NULL);
flags = ieee_vis_to_flags (visibility);
flags |= CXXFLAGS_STATIC;
nindx = info->type_stack->type.classdef->indx;
if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
|| ! ieee_write_asn (info, nindx, 'd')
|| ! ieee_write_asn (info, nindx, flags)
|| ! ieee_write_atn65 (info, nindx, name)
|| ! ieee_write_atn65 (info, nindx, physname))
return FALSE;
info->type_stack->type.classdef->pmisccount += 4;
return TRUE;
}
static bfd_boolean
ieee_class_baseclass (void *p, bfd_vma bitpos, bfd_boolean virtual,
enum debug_visibility visibility)
{
struct ieee_handle *info = (struct ieee_handle *) p;
const char *bname;
bfd_boolean localp;
unsigned int bindx;
char *fname;
unsigned int flags;
unsigned int nindx;
assert (info->type_stack != NULL
&& info->type_stack->type.name != NULL
&& info->type_stack->next != NULL
&& info->type_stack->next->type.classdef != NULL
&& ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
bname = info->type_stack->type.name;
localp = info->type_stack->type.localp;
bindx = ieee_pop_type (info);
if (virtual)
{
fname = (char *) xmalloc (strlen (bname) + sizeof "_vb$");
sprintf (fname, "_vb$%s", bname);
flags = BASEFLAGS_VIRTUAL;
}
else
{
if (localp)
info->type_stack->type.localp = TRUE;
fname = (char *) xmalloc (strlen (bname) + sizeof "_b$");
sprintf (fname, "_b$%s", bname);
if (! ieee_change_buffer (info, &info->type_stack->type.strdef)
|| ! ieee_write_id (info, fname)
|| ! ieee_write_number (info, bindx)
|| ! ieee_write_number (info, bitpos / 8))
return FALSE;
flags = 0;
}
if (visibility == DEBUG_VISIBILITY_PRIVATE)
flags |= BASEFLAGS_PRIVATE;
nindx = info->type_stack->type.classdef->indx;
if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
|| ! ieee_write_asn (info, nindx, 'b')
|| ! ieee_write_asn (info, nindx, flags)
|| ! ieee_write_atn65 (info, nindx, bname)
|| ! ieee_write_asn (info, nindx, 0)
|| ! ieee_write_atn65 (info, nindx, fname))
return FALSE;
info->type_stack->type.classdef->pmisccount += 5;
free (fname);
return TRUE;
}
static bfd_boolean
ieee_class_start_method (void *p, const char *name)
{
struct ieee_handle *info = (struct ieee_handle *) p;
assert (info->type_stack != NULL
&& info->type_stack->type.classdef != NULL
&& info->type_stack->type.classdef->method == NULL);
info->type_stack->type.classdef->method = name;
return TRUE;
}
static bfd_boolean
ieee_class_method_var (struct ieee_handle *info, const char *physname,
enum debug_visibility visibility,
bfd_boolean staticp, bfd_boolean constp,
bfd_boolean volatilep, bfd_vma voffset,
bfd_boolean context)
{
unsigned int flags;
unsigned int nindx;
bfd_boolean virtual;
ieee_pop_unused_type (info);
if (context)
ieee_pop_unused_type (info);
assert (info->type_stack != NULL
&& info->type_stack->type.classdef != NULL
&& info->type_stack->type.classdef->method != NULL);
flags = ieee_vis_to_flags (visibility);
if (staticp)
flags |= CXXFLAGS_STATIC;
if (constp)
flags |= CXXFLAGS_CONST;
if (volatilep)
flags |= CXXFLAGS_VOLATILE;
nindx = info->type_stack->type.classdef->indx;
virtual = context || voffset > 0;
if (! ieee_change_buffer (info,
&info->type_stack->type.classdef->pmiscbuf)
|| ! ieee_write_asn (info, nindx, virtual ? 'v' : 'm')
|| ! ieee_write_asn (info, nindx, flags)
|| ! ieee_write_atn65 (info, nindx,
info->type_stack->type.classdef->method)
|| ! ieee_write_atn65 (info, nindx, physname))
return FALSE;
if (virtual)
{
if (voffset > info->type_stack->type.classdef->voffset)
info->type_stack->type.classdef->voffset = voffset;
if (! ieee_write_asn (info, nindx, voffset))
return FALSE;
++info->type_stack->type.classdef->pmisccount;
}
if (! ieee_write_asn (info, nindx, 0))
return FALSE;
info->type_stack->type.classdef->pmisccount += 5;
return TRUE;
}
static bfd_boolean
ieee_class_method_variant (void *p, const char *physname,
enum debug_visibility visibility,
bfd_boolean constp, bfd_boolean volatilep,
bfd_vma voffset, bfd_boolean context)
{
struct ieee_handle *info = (struct ieee_handle *) p;
return ieee_class_method_var (info, physname, visibility, FALSE, constp,
volatilep, voffset, context);
}
static bfd_boolean
ieee_class_static_method_variant (void *p, const char *physname,
enum debug_visibility visibility,
bfd_boolean constp, bfd_boolean volatilep)
{
struct ieee_handle *info = (struct ieee_handle *) p;
return ieee_class_method_var (info, physname, visibility, TRUE, constp,
volatilep, 0, FALSE);
}
static bfd_boolean
ieee_class_end_method (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
assert (info->type_stack != NULL
&& info->type_stack->type.classdef != NULL
&& info->type_stack->type.classdef->method != NULL);
info->type_stack->type.classdef->method = NULL;
return TRUE;
}
static bfd_boolean
ieee_end_class_type (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int nindx;
assert (info->type_stack != NULL
&& info->type_stack->type.classdef != NULL);
if (info->type_stack->type.ignorep)
return TRUE;
nindx = info->type_stack->type.classdef->indx;
if (info->type_stack->type.classdef->vclass != NULL
|| info->type_stack->type.classdef->ownvptr)
{
if (! ieee_change_buffer (info,
&info->type_stack->type.classdef->pmiscbuf)
|| ! ieee_write_asn (info, nindx, 'z')
|| ! ieee_write_atn65 (info, nindx, "")
|| ! ieee_write_asn (info, nindx,
info->type_stack->type.classdef->voffset))
return FALSE;
if (info->type_stack->type.classdef->ownvptr)
{
if (! ieee_write_atn65 (info, nindx, ""))
return FALSE;
}
else
{
if (! ieee_write_atn65 (info, nindx,
info->type_stack->type.classdef->vclass))
return FALSE;
}
if (! ieee_write_asn (info, nindx, 0))
return FALSE;
info->type_stack->type.classdef->pmisccount += 5;
}
if (! ieee_change_buffer (info, &info->cxx)
|| ! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_id (info, "")
|| ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 62)
|| ! ieee_write_number (info, 80)
|| ! ieee_write_number (info,
info->type_stack->type.classdef->pmisccount))
return FALSE;
if (! ieee_append_buffer (info, &info->cxx,
&info->type_stack->type.classdef->pmiscbuf))
return FALSE;
if (! ieee_buffer_emptyp (&info->type_stack->type.classdef->refs))
{
if (! ieee_append_buffer (info, &info->cxx,
&info->type_stack->type.classdef->refs))
return FALSE;
}
return ieee_end_struct_type (p);
}
static bfd_boolean
ieee_typedef_type (void *p, const char *name)
{
struct ieee_handle *info = (struct ieee_handle *) p;
struct ieee_name_type_hash_entry *h;
struct ieee_name_type *nt;
h = ieee_name_type_hash_lookup (&info->typedefs, name, FALSE, FALSE);
assert (h != NULL);
nt = h->types;
if (! ieee_push_type (info, nt->type.indx, nt->type.size,
nt->type.unsignedp, nt->type.localp))
return FALSE;
info->type_stack->type = nt->type;
return TRUE;
}
static bfd_boolean
ieee_tag_type (void *p, const char *name, unsigned int id,
enum debug_type_kind kind)
{
struct ieee_handle *info = (struct ieee_handle *) p;
bfd_boolean localp;
bfd_boolean copy;
char ab[20];
struct ieee_name_type_hash_entry *h;
struct ieee_name_type *nt;
if (kind == DEBUG_KIND_ENUM)
{
struct ieee_defined_enum *e;
if (name == NULL)
abort ();
for (e = info->enums; e != NULL; e = e->next)
if (e->tag != NULL && strcmp (e->tag, name) == 0)
return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
memset (e, 0, sizeof *e);
e->indx = info->type_indx;
++info->type_indx;
e->tag = name;
e->defined = FALSE;
e->next = info->enums;
info->enums = e;
return ieee_push_type (info, e->indx, 0, TRUE, FALSE);
}
localp = FALSE;
copy = FALSE;
if (name == NULL)
{
sprintf (ab, "__anon%u", id);
name = ab;
copy = TRUE;
}
h = ieee_name_type_hash_lookup (&info->tags, name, TRUE, copy);
if (h == NULL)
return FALSE;
for (nt = h->types; nt != NULL; nt = nt->next)
{
if (nt->id == id)
{
if (! ieee_push_type (info, nt->type.indx, nt->type.size,
nt->type.unsignedp, nt->type.localp))
return FALSE;
info->type_stack->type = nt->type;
return TRUE;
}
if (! nt->type.localp)
{
localp = TRUE;
}
}
nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
memset (nt, 0, sizeof *nt);
nt->id = id;
nt->type.name = h->root.string;
nt->type.indx = info->type_indx;
nt->type.localp = localp;
++info->type_indx;
nt->kind = kind;
nt->next = h->types;
h->types = nt;
if (! ieee_push_type (info, nt->type.indx, 0, FALSE, localp))
return FALSE;
info->type_stack->type.name = h->root.string;
return TRUE;
}
static bfd_boolean
ieee_typdef (void *p, const char *name)
{
struct ieee_handle *info = (struct ieee_handle *) p;
struct ieee_write_type type;
unsigned int indx;
bfd_boolean found;
bfd_boolean localp;
struct ieee_name_type_hash_entry *h;
struct ieee_name_type *nt;
type = info->type_stack->type;
indx = type.indx;
found = FALSE;
if (indx <= (unsigned int) builtin_bcd_float)
{
switch ((enum builtin_types) indx)
{
default:
break;
case builtin_void:
if (strcmp (name, "void") == 0)
found = TRUE;
break;
case builtin_signed_char:
case builtin_char:
if (strcmp (name, "signed char") == 0)
{
indx = (unsigned int) builtin_signed_char;
found = TRUE;
}
else if (strcmp (name, "char") == 0)
{
indx = (unsigned int) builtin_char;
found = TRUE;
}
break;
case builtin_unsigned_char:
if (strcmp (name, "unsigned char") == 0)
found = TRUE;
break;
case builtin_signed_short_int:
case builtin_short:
case builtin_short_int:
case builtin_signed_short:
if (strcmp (name, "signed short int") == 0)
{
indx = (unsigned int) builtin_signed_short_int;
found = TRUE;
}
else if (strcmp (name, "short") == 0)
{
indx = (unsigned int) builtin_short;
found = TRUE;
}
else if (strcmp (name, "short int") == 0)
{
indx = (unsigned int) builtin_short_int;
found = TRUE;
}
else if (strcmp (name, "signed short") == 0)
{
indx = (unsigned int) builtin_signed_short;
found = TRUE;
}
break;
case builtin_unsigned_short_int:
case builtin_unsigned_short:
if (strcmp (name, "unsigned short int") == 0
|| strcmp (name, "short unsigned int") == 0)
{
indx = builtin_unsigned_short_int;
found = TRUE;
}
else if (strcmp (name, "unsigned short") == 0)
{
indx = builtin_unsigned_short;
found = TRUE;
}
break;
case builtin_signed_long:
case builtin_int:
case builtin_long:
if (strcmp (name, "signed long") == 0)
{
indx = builtin_signed_long;
found = TRUE;
}
else if (strcmp (name, "int") == 0)
{
indx = builtin_int;
found = TRUE;
}
else if (strcmp (name, "long") == 0
|| strcmp (name, "long int") == 0)
{
indx = builtin_long;
found = TRUE;
}
break;
case builtin_unsigned_long:
case builtin_unsigned:
case builtin_unsigned_int:
if (strcmp (name, "unsigned long") == 0
|| strcmp (name, "long unsigned int") == 0)
{
indx = builtin_unsigned_long;
found = TRUE;
}
else if (strcmp (name, "unsigned") == 0)
{
indx = builtin_unsigned;
found = TRUE;
}
else if (strcmp (name, "unsigned int") == 0)
{
indx = builtin_unsigned_int;
found = TRUE;
}
break;
case builtin_signed_long_long:
if (strcmp (name, "signed long long") == 0
|| strcmp (name, "long long int") == 0)
found = TRUE;
break;
case builtin_unsigned_long_long:
if (strcmp (name, "unsigned long long") == 0
|| strcmp (name, "long long unsigned int") == 0)
found = TRUE;
break;
case builtin_float:
if (strcmp (name, "float") == 0)
found = TRUE;
break;
case builtin_double:
if (strcmp (name, "double") == 0)
found = TRUE;
break;
case builtin_long_double:
if (strcmp (name, "long double") == 0)
found = TRUE;
break;
case builtin_long_long_double:
if (strcmp (name, "long long double") == 0)
found = TRUE;
break;
}
if (found)
type.indx = indx;
}
h = ieee_name_type_hash_lookup (&info->typedefs, name, TRUE, FALSE);
if (h == NULL)
return FALSE;
localp = type.localp;
for (nt = h->types; nt != NULL; nt = nt->next)
{
if (nt->id == indx)
{
if (! nt->type.localp)
{
ieee_pop_unused_type (info);
return TRUE;
}
}
else
{
localp = TRUE;
}
}
nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
memset (nt, 0, sizeof *nt);
nt->id = indx;
nt->type = type;
nt->type.name = name;
nt->type.localp = localp;
nt->kind = DEBUG_KIND_ILLEGAL;
nt->next = h->types;
h->types = nt;
if (found)
{
ieee_pop_unused_type (info);
return TRUE;
}
indx = ieee_pop_type (info);
if (! ieee_define_named_type (info, name, (unsigned int) -1, type.size,
type.unsignedp, localp,
(struct ieee_buflist *) NULL)
|| ! ieee_write_number (info, 'T')
|| ! ieee_write_number (info, indx))
return FALSE;
(void) ieee_pop_type (info);
return TRUE;
}
static bfd_boolean
ieee_tag (void *p, const char *name ATTRIBUTE_UNUSED)
{
struct ieee_handle *info = (struct ieee_handle *) p;
(void) ieee_pop_type (info);
return TRUE;
}
static bfd_boolean
ieee_int_constant (void *p ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED,
bfd_vma val ATTRIBUTE_UNUSED)
{
return TRUE;
}
static bfd_boolean
ieee_float_constant (void *p ATTRIBUTE_UNUSED,
const char *name ATTRIBUTE_UNUSED,
double val ATTRIBUTE_UNUSED)
{
return TRUE;
}
static bfd_boolean
ieee_typed_constant (void *p, const char *name ATTRIBUTE_UNUSED,
bfd_vma val ATTRIBUTE_UNUSED)
{
struct ieee_handle *info = (struct ieee_handle *) p;
ieee_pop_unused_type (info);
return TRUE;
}
static bfd_boolean
ieee_variable (void *p, const char *name, enum debug_var_kind kind,
bfd_vma val)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int name_indx;
unsigned int size;
bfd_boolean referencep;
unsigned int type_indx;
bfd_boolean asn;
int refflag;
size = info->type_stack->type.size;
referencep = info->type_stack->type.referencep;
type_indx = ieee_pop_type (info);
assert (! ieee_buffer_emptyp (&info->vars));
if (! ieee_change_buffer (info, &info->vars))
return FALSE;
name_indx = info->name_indx;
++info->name_indx;
if (! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, name_indx)
|| ! ieee_write_id (info, name)
|| ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
|| ! ieee_write_number (info, name_indx)
|| ! ieee_write_number (info, type_indx))
return FALSE;
switch (kind)
{
default:
abort ();
return FALSE;
case DEBUG_GLOBAL:
if (! ieee_write_number (info, 8)
|| ! ieee_add_range (info, FALSE, val, val + size))
return FALSE;
refflag = 0;
asn = TRUE;
break;
case DEBUG_STATIC:
if (! ieee_write_number (info, 3)
|| ! ieee_add_range (info, FALSE, val, val + size))
return FALSE;
refflag = 1;
asn = TRUE;
break;
case DEBUG_LOCAL_STATIC:
if (! ieee_write_number (info, 3)
|| ! ieee_add_range (info, FALSE, val, val + size))
return FALSE;
refflag = 2;
asn = TRUE;
break;
case DEBUG_LOCAL:
if (! ieee_write_number (info, 1)
|| ! ieee_write_number (info, val))
return FALSE;
refflag = 2;
asn = FALSE;
break;
case DEBUG_REGISTER:
if (! ieee_write_number (info, 2)
|| ! ieee_write_number (info,
ieee_genreg_to_regno (info->abfd, val)))
return FALSE;
refflag = 2;
asn = FALSE;
break;
}
if (asn)
{
if (! ieee_write_asn (info, name_indx, val))
return FALSE;
}
if (referencep)
{
unsigned int nindx;
nindx = info->name_indx;
++info->name_indx;
if (refflag != 2)
{
if (! ieee_change_buffer (info, &info->cxx))
return FALSE;
}
if (! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_id (info, "")
|| ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 62)
|| ! ieee_write_number (info, 80)
|| ! ieee_write_number (info, 3)
|| ! ieee_write_asn (info, nindx, 'R')
|| ! ieee_write_asn (info, nindx, refflag)
|| ! ieee_write_atn65 (info, nindx, name))
return FALSE;
}
return TRUE;
}
static bfd_boolean
ieee_start_function (void *p, const char *name, bfd_boolean global)
{
struct ieee_handle *info = (struct ieee_handle *) p;
bfd_boolean referencep;
unsigned int retindx, typeindx;
referencep = info->type_stack->type.referencep;
retindx = ieee_pop_type (info);
if (! ieee_buffer_emptyp (&info->fntype))
{
abort ();
}
info->fnname = name;
if (! ieee_define_named_type (info, name, (unsigned int) -1, 0, FALSE, TRUE,
&info->fntype)
|| ! ieee_write_number (info, 'x')
|| ! ieee_write_number (info, 0x40)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, retindx))
return FALSE;
typeindx = ieee_pop_type (info);
if (! ieee_init_buffer (info, &info->fnargs))
return FALSE;
info->fnargcount = 0;
if (referencep)
{
unsigned int nindx;
nindx = info->name_indx;
++info->name_indx;
if (! ieee_change_buffer (info, &info->cxx)
|| ! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_id (info, "")
|| ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 62)
|| ! ieee_write_number (info, 80)
|| ! ieee_write_number (info, 3)
|| ! ieee_write_asn (info, nindx, 'R')
|| ! ieee_write_asn (info, nindx, global ? 0 : 1)
|| ! ieee_write_atn65 (info, nindx, name))
return FALSE;
}
assert (! ieee_buffer_emptyp (&info->vars));
if (! ieee_change_buffer (info, &info->vars))
return FALSE;
++info->block_depth;
return (ieee_write_byte (info, (int) ieee_bb_record_enum)
&& ieee_write_byte (info, global ? 4 : 6)
&& ieee_write_number (info, 0)
&& ieee_write_id (info, name)
&& ieee_write_number (info, 0)
&& ieee_write_number (info, typeindx));
}
static bfd_boolean
ieee_function_parameter (void *p, const char *name, enum debug_parm_kind kind,
bfd_vma val)
{
struct ieee_handle *info = (struct ieee_handle *) p;
struct ieee_pending_parm *m, **pm;
assert (info->block_depth == 1);
m = (struct ieee_pending_parm *) xmalloc (sizeof *m);
memset (m, 0, sizeof *m);
m->next = NULL;
m->name = name;
m->referencep = info->type_stack->type.referencep;
m->type = ieee_pop_type (info);
m->kind = kind;
m->val = val;
for (pm = &info->pending_parms; *pm != NULL; pm = &(*pm)->next)
;
*pm = m;
if (! ieee_change_buffer (info, &info->fnargs)
|| ! ieee_write_number (info, m->type))
return FALSE;
++info->fnargcount;
return TRUE;
}
static bfd_boolean
ieee_output_pending_parms (struct ieee_handle *info)
{
struct ieee_pending_parm *m;
unsigned int refcount;
refcount = 0;
for (m = info->pending_parms; m != NULL; m = m->next)
{
enum debug_var_kind vkind;
switch (m->kind)
{
default:
abort ();
return FALSE;
case DEBUG_PARM_STACK:
case DEBUG_PARM_REFERENCE:
vkind = DEBUG_LOCAL;
break;
case DEBUG_PARM_REG:
case DEBUG_PARM_REF_REG:
vkind = DEBUG_REGISTER;
break;
}
if (! ieee_push_type (info, m->type, 0, FALSE, FALSE))
return FALSE;
info->type_stack->type.referencep = m->referencep;
if (m->referencep)
++refcount;
if (! ieee_variable ((void *) info, m->name, vkind, m->val))
return FALSE;
}
if (refcount > 0)
{
unsigned int nindx, varindx;
nindx = info->name_indx;
++info->name_indx;
if (! ieee_change_buffer (info, &info->vars)
|| ! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_id (info, "")
|| ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
|| ! ieee_write_number (info, nindx)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 62)
|| ! ieee_write_number (info, 80)
|| ! ieee_write_number (info, refcount + 3)
|| ! ieee_write_asn (info, nindx, 'B')
|| ! ieee_write_atn65 (info, nindx, info->fnname)
|| ! ieee_write_asn (info, nindx, 0))
return FALSE;
for (m = info->pending_parms, varindx = 1;
m != NULL;
m = m->next, varindx++)
{
if (m->referencep)
{
if (! ieee_write_asn (info, nindx, varindx))
return FALSE;
}
}
}
m = info->pending_parms;
while (m != NULL)
{
struct ieee_pending_parm *next;
next = m->next;
free (m);
m = next;
}
info->pending_parms = NULL;
return TRUE;
}
static bfd_boolean
ieee_start_block (void *p, bfd_vma addr)
{
struct ieee_handle *info = (struct ieee_handle *) p;
if (! ieee_change_buffer (info, &info->vars))
return FALSE;
if (info->block_depth == 1)
{
if (! ieee_write_number (info, addr)
|| ! ieee_output_pending_parms (info))
return FALSE;
}
else
{
if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 6)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, "")
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, addr))
return FALSE;
}
if (! ieee_start_range (info, addr))
return FALSE;
++info->block_depth;
return TRUE;
}
static bfd_boolean
ieee_end_block (void *p, bfd_vma addr)
{
struct ieee_handle *info = (struct ieee_handle *) p;
if (! ieee_change_buffer (info, &info->vars)
|| ! ieee_write_byte (info, (int) ieee_be_record_enum)
|| ! ieee_write_number (info, addr - 1))
return FALSE;
if (! ieee_end_range (info, addr))
return FALSE;
--info->block_depth;
if (addr > info->highaddr)
info->highaddr = addr;
return TRUE;
}
static bfd_boolean
ieee_end_function (void *p)
{
struct ieee_handle *info = (struct ieee_handle *) p;
assert (info->block_depth == 1);
--info->block_depth;
if (! ieee_change_buffer (info, &info->fntype)
|| ! ieee_write_number (info, info->fnargcount)
|| ! ieee_change_buffer (info, &info->fnargs)
|| ! ieee_write_number (info, 0))
return FALSE;
if (ieee_buffer_emptyp (&info->types))
{
if (! ieee_change_buffer (info, &info->types)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 1)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->modname))
return FALSE;
}
if (! ieee_append_buffer (info, &info->types, &info->fntype)
|| ! ieee_append_buffer (info, &info->types, &info->fnargs))
return FALSE;
info->fnname = NULL;
if (! ieee_init_buffer (info, &info->fntype)
|| ! ieee_init_buffer (info, &info->fnargs))
return FALSE;
info->fnargcount = 0;
return TRUE;
}
static bfd_boolean
ieee_lineno (void *p, const char *filename, unsigned long lineno, bfd_vma addr)
{
struct ieee_handle *info = (struct ieee_handle *) p;
assert (info->filename != NULL);
if (info->pending_lineno_filename != NULL
&& addr != info->pending_lineno_addr)
{
if (! ieee_buffer_emptyp (&info->linenos))
{
if (! ieee_change_buffer (info, &info->linenos))
return FALSE;
}
else
{
info->lineno_name_indx = info->name_indx;
++info->name_indx;
if (! ieee_change_buffer (info, &info->linenos)
|| ! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 5)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->filename)
|| ! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, info->lineno_name_indx)
|| ! ieee_write_id (info, ""))
return FALSE;
info->lineno_filename = info->filename;
}
if (strcmp (info->pending_lineno_filename, info->lineno_filename) != 0)
{
if (strcmp (info->filename, info->lineno_filename) != 0)
{
if (! ieee_write_byte (info, (int) ieee_be_record_enum))
return FALSE;
if (strcmp (info->filename, info->pending_lineno_filename) == 0)
{
info->lineno_name_indx = info->name_indx;
++info->name_indx;
if (! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, info->lineno_name_indx)
|| ! ieee_write_id (info, ""))
return FALSE;
}
}
if (strcmp (info->filename, info->pending_lineno_filename) != 0)
{
info->lineno_name_indx = info->name_indx;
++info->name_indx;
if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 5)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, info->pending_lineno_filename)
|| ! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, info->lineno_name_indx)
|| ! ieee_write_id (info, ""))
return FALSE;
}
info->lineno_filename = info->pending_lineno_filename;
}
if (! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
|| ! ieee_write_number (info, info->lineno_name_indx)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 7)
|| ! ieee_write_number (info, info->pending_lineno)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_asn (info, info->lineno_name_indx,
info->pending_lineno_addr))
return FALSE;
}
info->pending_lineno_filename = filename;
info->pending_lineno = lineno;
info->pending_lineno_addr = addr;
return TRUE;
}