* ieee.c: Various changes to handle C++ reference types.
This commit is contained in:
parent
084ae26cf5
commit
3d2d462907
579
binutils/ieee.c
579
binutils/ieee.c
@ -39,6 +39,8 @@ struct ieee_block
|
||||
int kind;
|
||||
/* The source file name, for a BB5 block. */
|
||||
const char *filename;
|
||||
/* The index of the function type, for a BB4 or BB6 block. */
|
||||
unsigned int fnindx;
|
||||
};
|
||||
|
||||
/* This structure is the block stack. */
|
||||
@ -63,6 +65,10 @@ struct ieee_var
|
||||
unsigned long namlen;
|
||||
/* Type. */
|
||||
debug_type type;
|
||||
/* Slot if we make an indirect type. */
|
||||
debug_type *pslot;
|
||||
/* Kind of variable (DEBUG_VAR_ILLEGAL if not a variable). */
|
||||
enum debug_var_kind variable;
|
||||
};
|
||||
|
||||
/* This structure holds all the variables. */
|
||||
@ -84,6 +90,8 @@ struct ieee_type
|
||||
debug_type type;
|
||||
/* Slot if this is type is referenced before it is defined. */
|
||||
debug_type *pslot;
|
||||
/* Slots for arguments if we make indirect types for them. */
|
||||
debug_type *arg_slots;
|
||||
/* If this is a bitfield, this is the size in bits. If this is not
|
||||
a bitfield, this is zero. */
|
||||
unsigned long bitsize;
|
||||
@ -115,19 +123,10 @@ struct ieee_tag
|
||||
debug_type type;
|
||||
/* The tagged type is an indirect type pointing at this slot. */
|
||||
debug_type slot;
|
||||
};
|
||||
|
||||
/* This structure holds a linked list of functions with their argument
|
||||
types, so that we can convert them to C++ methods if necessary. */
|
||||
|
||||
struct ieee_function
|
||||
{
|
||||
/* Next function. */
|
||||
struct ieee_function *next;
|
||||
/* This function name. */
|
||||
const char *name;
|
||||
/* The function type. */
|
||||
debug_type type;
|
||||
/* This is an array of slots used when a field type is converted
|
||||
into a indirect type, in case it needs to be later converted into
|
||||
a reference type. */
|
||||
debug_type *fslots;
|
||||
};
|
||||
|
||||
/* This structure holds the information we pass around to the parsing
|
||||
@ -151,8 +150,6 @@ struct ieee_info
|
||||
struct ieee_types types;
|
||||
/* The list of tagged structs. */
|
||||
struct ieee_tag *tags;
|
||||
/* The list of functions. */
|
||||
struct ieee_function *functions;
|
||||
};
|
||||
|
||||
/* Basic builtin types, not including the pointers. */
|
||||
@ -268,6 +265,10 @@ static boolean ieee_read_cxx_misc
|
||||
PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
|
||||
static boolean ieee_read_cxx_class
|
||||
PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
|
||||
static boolean ieee_read_cxx_defaults
|
||||
PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
|
||||
static boolean ieee_read_reference
|
||||
PARAMS ((struct ieee_info *, const bfd_byte **));
|
||||
static boolean ieee_require_asn
|
||||
PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
|
||||
static boolean ieee_require_atn65
|
||||
@ -885,7 +886,6 @@ parse_ieee (dhandle, abfd, bytes, len)
|
||||
info.types.alloc = 0;
|
||||
info.types.types = NULL;
|
||||
info.tags = NULL;
|
||||
info.functions = NULL;
|
||||
for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
|
||||
info.types.builtins[i] = DEBUG_TYPE_NULL;
|
||||
|
||||
@ -965,7 +965,8 @@ parse_ieee_bb (info, pp)
|
||||
const char *name;
|
||||
unsigned long namlen;
|
||||
char *namcopy;
|
||||
|
||||
unsigned int fnindx;
|
||||
|
||||
block_start = *pp;
|
||||
|
||||
b = **pp;
|
||||
@ -975,6 +976,8 @@ parse_ieee_bb (info, pp)
|
||||
|| ! ieee_read_id (info, pp, &name, &namlen))
|
||||
return false;
|
||||
|
||||
fnindx = (unsigned int) -1;
|
||||
|
||||
switch (b)
|
||||
{
|
||||
case 1:
|
||||
@ -1003,8 +1006,7 @@ parse_ieee_bb (info, pp)
|
||||
/* BB4: Global function. */
|
||||
{
|
||||
bfd_vma stackspace, typindx, offset;
|
||||
debug_type type, return_type;
|
||||
struct ieee_function *func;
|
||||
debug_type return_type;
|
||||
|
||||
if (! ieee_read_number (info, pp, &stackspace)
|
||||
|| ! ieee_read_number (info, pp, &typindx)
|
||||
@ -1015,22 +1017,21 @@ parse_ieee_bb (info, pp)
|
||||
|
||||
if (typindx < 256)
|
||||
{
|
||||
type = ieee_builtin_type (info, block_start, typindx);
|
||||
if (type == NULL)
|
||||
return_type = ieee_builtin_type (info, block_start, typindx);
|
||||
if (return_type == DEBUG_TYPE_NULL)
|
||||
return false;
|
||||
return_type = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
typindx -= 256;
|
||||
if (! ieee_alloc_type (info, typindx, true))
|
||||
return false;
|
||||
type = info->types.types[typindx].type;
|
||||
if (debug_get_type_kind (info->dhandle, type)
|
||||
!= DEBUG_KIND_FUNCTION)
|
||||
return_type = type;
|
||||
else
|
||||
return_type = debug_get_return_type (info->dhandle, type);
|
||||
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);
|
||||
@ -1039,13 +1040,6 @@ parse_ieee_bb (info, pp)
|
||||
if (! debug_record_function (info->dhandle, namcopy, return_type,
|
||||
true, offset))
|
||||
return false;
|
||||
|
||||
func = (struct ieee_function *) xmalloc (sizeof *func);
|
||||
memset (func, 0, sizeof *func);
|
||||
func->next = info->functions;
|
||||
info->functions = func;
|
||||
func->name = namcopy;
|
||||
func->type = type;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1109,6 +1103,7 @@ parse_ieee_bb (info, pp)
|
||||
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)
|
||||
@ -1184,6 +1179,7 @@ parse_ieee_bb (info, pp)
|
||||
info->blockstack.bsp->kind = b;
|
||||
if (b == 5)
|
||||
info->blockstack.bsp->filename = namcopy;
|
||||
info->blockstack.bsp->fnindx = fnindx;
|
||||
++info->blockstack.bsp;
|
||||
|
||||
return true;
|
||||
@ -1319,6 +1315,7 @@ parse_ieee_ty (info, pp)
|
||||
bfd_vma typeindx, varindx, tc;
|
||||
PTR dhandle;
|
||||
boolean tag, typdef;
|
||||
debug_type *arg_slots;
|
||||
unsigned long type_bitsize;
|
||||
debug_type type;
|
||||
|
||||
@ -1371,6 +1368,7 @@ parse_ieee_ty (info, pp)
|
||||
|
||||
tag = false;
|
||||
typdef = false;
|
||||
arg_slots = NULL;
|
||||
type_bitsize = 0;
|
||||
switch (tc)
|
||||
{
|
||||
@ -1691,6 +1689,7 @@ parse_ieee_ty (info, pp)
|
||||
debug_type rtype;
|
||||
bfd_vma nargs;
|
||||
boolean present;
|
||||
struct ieee_var *pv;
|
||||
|
||||
/* FIXME: We ignore the attribute and the argument names. */
|
||||
|
||||
@ -1708,6 +1707,19 @@ parse_ieee_ty (info, pp)
|
||||
}
|
||||
while (present);
|
||||
|
||||
pv = info->vars.vars + varindx;
|
||||
if (pv->namlen > 0
|
||||
&& debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
|
||||
{
|
||||
/* Set up the return type as an indirect type pointing to
|
||||
the variable slot, so that we can change it to a
|
||||
reference later if appropriate. */
|
||||
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);
|
||||
}
|
||||
@ -1815,6 +1827,7 @@ parse_ieee_ty (info, pp)
|
||||
/* Procedure with compiler dependencies. FIXME: This is an
|
||||
extern declaration, which we have no way of representing. */
|
||||
{
|
||||
struct ieee_var *pv;
|
||||
bfd_vma attr, frame_type, push_mask, nargs, level, father;
|
||||
debug_type rtype;
|
||||
debug_type *arg_types;
|
||||
@ -1823,6 +1836,8 @@ parse_ieee_ty (info, pp)
|
||||
|
||||
/* FIXME: We ignore almost all this information. */
|
||||
|
||||
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)
|
||||
@ -1863,12 +1878,46 @@ parse_ieee_ty (info, pp)
|
||||
}
|
||||
}
|
||||
|
||||
/* If there are any pointer arguments, turn them into
|
||||
indirect types in case we later need to convert them to
|
||||
reference types. */
|
||||
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;
|
||||
|
||||
if (pv->namlen > 0
|
||||
&& debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
|
||||
{
|
||||
/* Set up the return type as an indirect type pointing to
|
||||
the variable slot, so that we can change it to a
|
||||
reference later if appropriate. */
|
||||
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;
|
||||
@ -1877,9 +1926,11 @@ parse_ieee_ty (info, pp)
|
||||
/* Record the type in the table. If the corresponding NN record has
|
||||
a name, name it. FIXME: Is this always correct? */
|
||||
|
||||
if (type == NULL)
|
||||
if (type == DEBUG_TYPE_NULL)
|
||||
return false;
|
||||
|
||||
info->vars.vars[varindx].type = type;
|
||||
|
||||
if ((tag || typdef)
|
||||
&& info->vars.vars[varindx].namlen > 0)
|
||||
{
|
||||
@ -1916,6 +1967,7 @@ parse_ieee_ty (info, pp)
|
||||
}
|
||||
|
||||
info->types.types[typeindx].type = type;
|
||||
info->types.types[typeindx].arg_slots = arg_slots;
|
||||
info->types.types[typeindx].bitsize = type_bitsize;
|
||||
|
||||
/* We may have already allocated type as an indirect type pointing
|
||||
@ -1937,7 +1989,7 @@ parse_ieee_atn (info, pp)
|
||||
{
|
||||
const bfd_byte *atn_start, *atn_code_start;
|
||||
bfd_vma varindx;
|
||||
boolean zeroindx;
|
||||
struct ieee_var *pvar;
|
||||
debug_type type;
|
||||
bfd_vma atn_code;
|
||||
PTR dhandle;
|
||||
@ -1961,7 +2013,7 @@ parse_ieee_atn (info, pp)
|
||||
|
||||
if (varindx == 0)
|
||||
{
|
||||
zeroindx = true;
|
||||
pvar = NULL;
|
||||
name = "";
|
||||
namlen = 0;
|
||||
}
|
||||
@ -1973,7 +2025,6 @@ parse_ieee_atn (info, pp)
|
||||
else
|
||||
{
|
||||
varindx -= 32;
|
||||
zeroindx = false;
|
||||
if (varindx >= info->vars.alloc
|
||||
|| info->vars.vars[varindx].name == NULL)
|
||||
{
|
||||
@ -1981,14 +2032,40 @@ parse_ieee_atn (info, pp)
|
||||
return false;
|
||||
}
|
||||
|
||||
info->vars.vars[varindx].type = type;
|
||||
pvar = info->vars.vars + varindx;
|
||||
|
||||
name = info->vars.vars[varindx].name;
|
||||
namlen = info->vars.vars[varindx].namlen;
|
||||
pvar->type = type;
|
||||
|
||||
name = pvar->name;
|
||||
namlen = pvar->namlen;
|
||||
}
|
||||
|
||||
dhandle = info->dhandle;
|
||||
|
||||
/* If we are going to call debug_record_variable with a pointer
|
||||
type, change the type to an indirect type so that we can later
|
||||
change it to a reference type if we encounter a C++ pmisc 'R'
|
||||
record. */
|
||||
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 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:
|
||||
@ -2002,6 +2079,8 @@ parse_ieee_atn (info, pp)
|
||||
namcopy = savestring (name, namlen);
|
||||
if (type == NULL)
|
||||
type = debug_make_void_type (dhandle);
|
||||
if (pvar != NULL)
|
||||
pvar->variable = DEBUG_LOCAL;
|
||||
return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v);
|
||||
|
||||
case 2:
|
||||
@ -2011,6 +2090,8 @@ parse_ieee_atn (info, pp)
|
||||
namcopy = savestring (name, namlen);
|
||||
if (type == NULL)
|
||||
type = debug_make_void_type (dhandle);
|
||||
if (pvar != NULL)
|
||||
pvar->variable = DEBUG_REGISTER;
|
||||
return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER,
|
||||
ieee_regno_to_genreg (info->abfd, v));
|
||||
|
||||
@ -2025,6 +2106,13 @@ parse_ieee_atn (info, pp)
|
||||
blocktype = 0;
|
||||
else
|
||||
blocktype = info->blockstack.bsp[-1].kind;
|
||||
if (pvar != NULL)
|
||||
{
|
||||
if (blocktype == 4 || blocktype == 6)
|
||||
pvar->variable = DEBUG_LOCAL_STATIC;
|
||||
else
|
||||
pvar->variable = DEBUG_STATIC;
|
||||
}
|
||||
return debug_record_variable (dhandle, namcopy, type,
|
||||
(blocktype == 4 || blocktype == 6
|
||||
? DEBUG_LOCAL_STATIC
|
||||
@ -2067,6 +2155,8 @@ parse_ieee_atn (info, pp)
|
||||
namcopy = savestring (name, namlen);
|
||||
if (type == NULL)
|
||||
type = debug_make_void_type (dhandle);
|
||||
if (pvar != NULL)
|
||||
pvar->variable = DEBUG_GLOBAL;
|
||||
return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v);
|
||||
|
||||
case 9:
|
||||
@ -2089,6 +2179,8 @@ parse_ieee_atn (info, pp)
|
||||
namcopy = savestring (name, namlen);
|
||||
if (type == NULL)
|
||||
type = debug_make_void_type (dhandle);
|
||||
if (pvar != NULL)
|
||||
pvar->variable = DEBUG_REGISTER;
|
||||
return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v);
|
||||
|
||||
case 11:
|
||||
@ -2271,52 +2363,8 @@ ieee_read_cxx_misc (info, pp, count)
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
{
|
||||
const char *fnname, *strval;
|
||||
unsigned long fnlen, strvallen;
|
||||
bfd_vma count, type, val;
|
||||
|
||||
/* Specify default argument values. We have no way to store
|
||||
these, so we just ignore them. FIXME. */
|
||||
|
||||
/* Giving the function name before the argument count is an
|
||||
addendum to the spec. */
|
||||
if (! ieee_require_atn65 (info, pp, &fnname, &fnlen)
|
||||
|| ! ieee_require_asn (info, pp, &count)
|
||||
|| ! ieee_require_asn (info, pp, &type))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
case 4:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
if (! ieee_require_asn (info, pp, &val))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 7:
|
||||
if (! ieee_require_atn65 (info, pp, &strval, &strvallen))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
ieee_error (info, start, "unrecognized C++ B type");
|
||||
return false;
|
||||
}
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
bfd_vma pos;
|
||||
|
||||
if (! ieee_require_asn (info, pp, &pos))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (! ieee_read_cxx_defaults (info, pp, count))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
@ -2338,31 +2386,8 @@ ieee_read_cxx_misc (info, pp, count)
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
{
|
||||
bfd_vma flags;
|
||||
const char *class, *name;
|
||||
unsigned long classlen, namlen;
|
||||
|
||||
/* Indicates that an object actually has reference type. */
|
||||
|
||||
if (! ieee_require_asn (info, pp, &flags))
|
||||
return false;
|
||||
|
||||
/* Giving the class name before the member name is in an
|
||||
addendum to the spec. */
|
||||
if (flags == 3)
|
||||
{
|
||||
if (! ieee_require_atn65 (info, pp, &class, &classlen))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! ieee_require_atn65 (info, pp, &name, &namlen))
|
||||
return false;
|
||||
|
||||
/* FIXME: Now we are supposed to track down the variable or
|
||||
function or class member and convert the type into a
|
||||
reference type. */
|
||||
}
|
||||
if (! ieee_read_reference (info, pp))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2603,13 +2628,17 @@ ieee_read_cxx_class (info, pp, count)
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int findx;
|
||||
|
||||
if (structfields == NULL)
|
||||
{
|
||||
ieee_error (info, start, "C++ object has no fields");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++)
|
||||
for (pf = structfields, findx = 0;
|
||||
*pf != DEBUG_FIELD_NULL;
|
||||
pf++, findx++)
|
||||
{
|
||||
const char *fname;
|
||||
|
||||
@ -2629,6 +2658,35 @@ ieee_read_cxx_class (info, pp, count)
|
||||
}
|
||||
|
||||
ftype = debug_get_field_type (dhandle, *pf);
|
||||
|
||||
if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER)
|
||||
{
|
||||
/* We might need to convert this field into a
|
||||
reference type later on, so make it an indirect
|
||||
type. */
|
||||
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;
|
||||
@ -2699,7 +2757,7 @@ ieee_read_cxx_class (info, pp, count)
|
||||
bfd_vma flags, virtindex, control;
|
||||
const char *name, *mangled;
|
||||
unsigned long namlen, mangledlen;
|
||||
struct ieee_function *func;
|
||||
struct ieee_var *pv, *pvend;
|
||||
debug_type type;
|
||||
enum debug_visibility visibility;
|
||||
boolean constp, volatilep;
|
||||
@ -2730,15 +2788,15 @@ ieee_read_cxx_class (info, pp, count)
|
||||
if ((flags & CXXFLAGS_FRIEND) != 0)
|
||||
break;
|
||||
|
||||
/* We should already have seen debugging information for
|
||||
the function itself, which will include type
|
||||
information. */
|
||||
for (func = info->functions; func != NULL; func = func->next)
|
||||
if (func->name[0] == mangled[0]
|
||||
&& strncmp (func->name, mangled, mangledlen)
|
||||
&& strlen (func->name) == mangledlen)
|
||||
/* We should already have seen a type for the function. */
|
||||
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 (func == NULL)
|
||||
|
||||
if (pv >= pvend)
|
||||
{
|
||||
/* We won't have type information for this function if
|
||||
it is not included in this file. We don't try to
|
||||
@ -2756,7 +2814,7 @@ ieee_read_cxx_class (info, pp, count)
|
||||
const debug_type *arg_types;
|
||||
boolean varargs;
|
||||
|
||||
if (debug_get_type_kind (dhandle, func->type)
|
||||
if (debug_get_type_kind (dhandle, pv->type)
|
||||
!= DEBUG_KIND_FUNCTION)
|
||||
{
|
||||
ieee_error (info, start,
|
||||
@ -2764,8 +2822,8 @@ ieee_read_cxx_class (info, pp, count)
|
||||
return false;
|
||||
}
|
||||
|
||||
return_type = debug_get_return_type (dhandle, func->type);
|
||||
arg_types = debug_get_parameter_types (dhandle, func->type,
|
||||
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)
|
||||
{
|
||||
@ -2980,6 +3038,7 @@ ieee_read_cxx_class (info, pp, count)
|
||||
if (dmethods[i] == DEBUG_METHOD_NULL)
|
||||
return false;
|
||||
}
|
||||
dmethods[i] = DEBUG_METHOD_NULL;
|
||||
free (methods);
|
||||
}
|
||||
|
||||
@ -2998,6 +3057,274 @@ ieee_read_cxx_class (info, pp, count)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Read C++ default argument value and reference type information. */
|
||||
|
||||
static boolean
|
||||
ieee_read_cxx_defaults (info, pp, count)
|
||||
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;
|
||||
|
||||
/* Giving the function name before the argument count is an addendum
|
||||
to the spec. The function name is demangled, though, so this
|
||||
record must always refer to the current function. */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* We have no way to record the default argument values, so we
|
||||
just ignore them. FIXME. */
|
||||
}
|
||||
|
||||
/* Any remaining arguments are indices of parameters that are really
|
||||
reference type. */
|
||||
if (count > 0)
|
||||
{
|
||||
PTR 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;
|
||||
/* The index is 1 based. */
|
||||
--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;
|
||||
}
|
||||
|
||||
/* Read a C++ reference definition. */
|
||||
|
||||
static boolean
|
||||
ieee_read_reference (info, pp)
|
||||
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;
|
||||
|
||||
/* Giving the class name before the member name is in an addendum to
|
||||
the spec. */
|
||||
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 i;
|
||||
struct ieee_var *pv = NULL;
|
||||
|
||||
/* We search from the last variable indices to the first in
|
||||
hopes of finding local variables correctly. FIXME: This
|
||||
probably won't work in all cases. On the other hand, I don't
|
||||
know what will. */
|
||||
for (i = (int) info->vars.alloc - 1; i >= 0; i--)
|
||||
{
|
||||
boolean found;
|
||||
|
||||
pv = info->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:
|
||||
/* Global variable or function. */
|
||||
if (pv->variable == DEBUG_GLOBAL)
|
||||
found = true;
|
||||
else if (pv->type != DEBUG_TYPE_NULL
|
||||
&& (debug_get_type_kind (info->dhandle, pv->type)
|
||||
== DEBUG_KIND_FUNCTION))
|
||||
found = true;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* Global static variable or function. */
|
||||
if (pv->variable == DEBUG_STATIC)
|
||||
found = true;
|
||||
else if (pv->type != DEBUG_TYPE_NULL
|
||||
&& (debug_get_type_kind (info->dhandle, pv->type)
|
||||
== DEBUG_KIND_FUNCTION))
|
||||
found = true;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Local variable. */
|
||||
if (pv->variable == DEBUG_LOCAL_STATIC
|
||||
|| pv->variable == DEBUG_LOCAL
|
||||
|| pv->variable == DEBUG_REGISTER)
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= 0)
|
||||
pslot = pv->pslot;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* We allocated the type of the object as an indirect type pointing
|
||||
to *pslot, which we can now update to be a reference type. */
|
||||
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;
|
||||
}
|
||||
|
||||
/* Require an ASN record. */
|
||||
|
||||
static boolean
|
||||
|
Loading…
Reference in New Issue
Block a user