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. */
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. */
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;
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
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. */
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
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;
const char *name;
unsigned long namlen;
char *namcopy;
-
+ unsigned int fnindx;
+
block_start = *pp;
b = **pp;
|| ! ieee_read_id (info, pp, &name, &namlen))
return false;
+ fnindx = (unsigned int) -1;
+
switch (b)
{
case 1:
/* 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)
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);
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;
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)
info->blockstack.bsp->kind = b;
if (b == 5)
info->blockstack.bsp->filename = namcopy;
+ info->blockstack.bsp->fnindx = fnindx;
++info->blockstack.bsp;
return true;
bfd_vma typeindx, varindx, tc;
PTR dhandle;
boolean tag, typdef;
+ debug_type *arg_slots;
unsigned long type_bitsize;
debug_type type;
tag = false;
typdef = false;
+ arg_slots = NULL;
type_bitsize = 0;
switch (tc)
{
debug_type rtype;
bfd_vma nargs;
boolean present;
+ struct ieee_var *pv;
/* FIXME: We ignore the attribute and the argument names. */
}
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);
}
/* 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;
/* 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)
}
}
+ /* 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;
/* 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)
{
}
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
{
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;
if (varindx == 0)
{
- zeroindx = true;
+ pvar = NULL;
name = "";
namlen = 0;
}
else
{
varindx -= 32;
- zeroindx = false;
if (varindx >= info->vars.alloc
|| info->vars.vars[varindx].name == NULL)
{
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:
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:
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));
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
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:
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:
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':
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;
}
}
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;
}
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;
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;
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
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,
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)
{
if (dmethods[i] == DEBUG_METHOD_NULL)
return false;
}
+ dmethods[i] = DEBUG_METHOD_NULL;
free (methods);
}
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