|
|
|
@ -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; |
|
|
|
|
|
|
|
pvar->type = type; |
|
|
|
|
|
|
|
name = info->vars.vars[varindx].name; |
|
|
|
namlen = info->vars.vars[varindx].namlen; |
|
|
|
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 |
|
|
|
|