-/* ieee.c -- Write out IEEE-695 debugging information.
+/* ieee.c -- Read and write IEEE-695 debugging information.
Copyright (C) 1996 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>.
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 or function. */
+ enum
+ {
+ IEEE_UNKNOWN,
+ IEEE_EXTERNAL,
+ IEEE_GLOBAL,
+ IEEE_STATIC,
+ IEEE_LOCAL,
+ IEEE_FUNCTION
+ } kind;
};
/* 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;
+ pv->kind = IEEE_EXTERNAL;
+ 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);
}
break;
case 'x':
- /* Procedure with compiler dependencies. FIXME: This is an
- extern declaration, which we have no way of representing. */
+ /* Procedure with compiler dependencies. */
{
+ struct ieee_var *pv;
bfd_vma attr, frame_type, push_mask, nargs, level, father;
debug_type rtype;
debug_type *arg_types;
boolean varargs;
boolean present;
- /* FIXME: We ignore almost all this information. */
+ /* FIXME: We ignore some of this information. */
+
+ pv = info->vars.vars + varindx;
if (! ieee_read_number (info, pp, &attr)
|| ! ieee_read_number (info, pp, &frame_type)
}
}
+ /* 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;
+ /* We can't distinguish between a global function and a static
+ function. */
+ pv->kind = IEEE_FUNCTION;
+
+ 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;
- 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 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:
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:
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));
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
case 4:
/* External function. We don't currently record these. FIXME. */
+ if (pvar != NULL)
+ pvar->kind = IEEE_EXTERNAL;
return true;
case 5:
/* External variable. We don't currently record these. FIXME. */
+ if (pvar != NULL)
+ pvar->kind = IEEE_EXTERNAL;
return true;
case 7:
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:
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:
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;
}
if (staticp)
{
- /* We can only figure out the type here if mangledname
- happens to have already been defined, but that is
- not necessarily the case. In fact, it may never be
- defined. For now, we don't even try. FIXME. */
- pf = NULL;
- ftype = ieee_builtin_type (info, start,
- (unsigned int) builtin_void);
+ struct ieee_var *pv, *pvend;
+
+ /* See if we can find a definition for this variable. */
+ 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
+ {
+ /* This can happen if the variable is never used. */
+ 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; *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;
break;
}
- if ((flags & CXXFLAGS_STATIC) != 0)
+ if (staticp)
{
char *mangledcopy;
case 'm':
case 'v':
{
- bfd_vma flags, virtindex, control;
+ bfd_vma flags, voffset, 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;
|| ! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
return false;
count -= 3;
- if (id == 'v')
+ if (id != 'v')
+ voffset = 0;
+ else
{
- if (! ieee_require_asn (info, pp, &virtindex))
+ if (! ieee_require_asn (info, pp, &voffset))
return false;
--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
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)
{
}
else
{
- bfd_vma voffset;
debug_type vcontext;
if (id != 'v')
- {
- voffset = 0;
- vcontext = DEBUG_TYPE_NULL;
- }
+ vcontext = DEBUG_TYPE_NULL;
else
{
- /* FIXME: This should depend upon the pointer
- size. */
- voffset = virtindex * 4;
/* FIXME: How can we calculate this correctly? */
vcontext = it->type;
}
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->kind == IEEE_GLOBAL
+ || pv->kind == IEEE_EXTERNAL
+ || pv->kind == IEEE_FUNCTION)
+ found = true;
+ break;
+
+ case 1:
+ /* Global static variable or function. */
+ if (pv->kind == IEEE_STATIC
+ || pv->kind == IEEE_FUNCTION)
+ found = true;
+ break;
+
+ case 2:
+ /* Local variable. */
+ if (pv->kind == IEEE_LOCAL)
+ 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
bfd_byte buf[IEEE_BUFSIZE];
};
+/* A list of buffers. */
+
+struct ieee_buflist
+{
+ /* Head of list. */
+ struct ieee_buf *head;
+ /* Tail--last buffer on list. */
+ struct ieee_buf *tail;
+};
+
/* In order to generate the BB11 blocks required by the HP emulator,
we keep track of ranges of addresses which correspond to a given
compilation unit. */
bfd_vma high;
};
+/* This structure holds information for a class on the type stack. */
+
+struct ieee_type_class
+{
+ /* The name index in the debugging information. */
+ unsigned int indx;
+ /* The pmisc records for the class. */
+ struct ieee_buflist pmiscbuf;
+ /* The number of pmisc records. */
+ unsigned int pmisccount;
+ /* The name of the class holding the virtual table, if not this
+ class. */
+ const char *vclass;
+ /* Whether this class holds its own virtual table. */
+ boolean ownvptr;
+ /* The largest virtual table offset seen so far. */
+ bfd_vma voffset;
+ /* The current method. */
+ const char *method;
+ /* Additional pmisc records used to record fields of reference type. */
+ struct ieee_buflist refs;
+};
+
/* This is how we store types for the writing routines. Most types
are simply represented by a type index. */
unsigned int indx;
/* The size of the type, if known. */
unsigned int size;
+ /* The name of the type, if any. */
+ const char *name;
+ /* If this is a function or method type, we build the type here, and
+ only add it to the output buffers if we need it. */
+ struct ieee_buflist fndef;
/* If this is a struct, this is where the struct definition is
built. */
- struct ieee_buf *strdef;
+ struct ieee_buflist strdef;
+ /* If this is a class, this is where the class information is built. */
+ struct ieee_type_class *classdef;
/* Whether the type is unsigned. */
unsigned int unsignedp : 1;
/* Whether this is a reference type. */
unsigned int referencep : 1;
+ /* Whether this is in the local type block. */
+ unsigned int localp : 1;
+ /* Whether this is a duplicate struct definition which we are
+ ignoring. */
+ unsigned int ignorep : 1;
};
/* This is the type stack used by the debug writing routines. FIXME:
struct ieee_write_type type;
};
-/* This is a list of associations between names and types. This could
- be more efficiently implemented as a hash table. */
+/* This is a list of associations between a name and some types.
+ These are used for typedefs and tags. */
struct ieee_name_type
{
- /* Next name/type assocation. */
+ /* Next type for this name. */
struct ieee_name_type *next;
- /* Name. */
- const char *name;
+ /* ID number. For a typedef, this is the index of the type to which
+ this name is typedefed. */
+ unsigned int id;
/* Type. */
struct ieee_write_type type;
/* If this is a tag which has not yet been defined, this is the
enum debug_type_kind kind;
};
+/* We use a hash table to associate names and types. */
+
+struct ieee_name_type_hash_table
+{
+ struct bfd_hash_table root;
+};
+
+struct ieee_name_type_hash_entry
+{
+ struct bfd_hash_entry root;
+ /* Information for this name. */
+ struct ieee_name_type *types;
+};
+
+/* This is a list of enums. */
+
+struct ieee_defined_enum
+{
+ /* Next enum. */
+ struct ieee_defined_enum *next;
+ /* Type index. */
+ unsigned int indx;
+ /* Tag. */
+ const char *tag;
+ /* Names. */
+ const char **names;
+ /* Values. */
+ bfd_signed_vma *vals;
+};
+
+/* We keep a list of modified versions of types, so that we don't
+ output them more than once. */
+
+struct ieee_modified_type
+{
+ /* Pointer to this type. */
+ unsigned int pointer;
+ /* Function with unknown arguments returning this type. */
+ unsigned int function;
+ /* Const version of this type. */
+ unsigned int const_qualified;
+ /* Volatile version of this type. */
+ unsigned int volatile_qualified;
+ /* List of arrays of this type of various bounds. */
+ struct ieee_modified_array_type *arrays;
+};
+
+/* A list of arrays bounds. */
+
+struct ieee_modified_array_type
+{
+ /* Next array bounds. */
+ struct ieee_modified_array_type *next;
+ /* Type index with these bounds. */
+ unsigned int indx;
+ /* Low bound. */
+ bfd_signed_vma low;
+ /* High bound. */
+ bfd_signed_vma high;
+};
+
/* This is a list of pending function parameter information. We don't
output them until we see the first block. */
const char *name;
/* Type index. */
unsigned int type;
+ /* Whether the type is a reference. */
+ boolean referencep;
/* Kind. */
enum debug_parm_kind kind;
/* Value. */
{
/* BFD we are writing to. */
bfd *abfd;
+ /* Whether we got an error in a subroutine called via traverse or
+ map_over_sections. */
+ boolean error;
+ /* Current data buffer list. */
+ struct ieee_buflist *current;
/* Current data buffer. */
- struct ieee_buf *current;
+ struct ieee_buf *curbuf;
/* Filename of current compilation unit. */
const char *filename;
/* Module name of current compilation unit. */
const char *modname;
+ /* List of buffer for global types. */
+ struct ieee_buflist global_types;
/* List of finished data buffers. */
- struct ieee_buf *data;
+ struct ieee_buflist data;
/* List of buffers for typedefs in the current compilation unit. */
- struct ieee_buf *types;
+ struct ieee_buflist types;
/* List of buffers for variables and functions in the current
compilation unit. */
- struct ieee_buf *vars;
+ struct ieee_buflist vars;
+ /* List of buffers for C++ class definitions in the current
+ compilation unit. */
+ struct ieee_buflist cxx;
/* List of buffers for line numbers in the current compilation unit. */
- struct ieee_buf *linenos;
+ struct ieee_buflist linenos;
/* Ranges for the current compilation unit. */
struct ieee_range *ranges;
+ /* Ranges for all debugging information. */
+ struct ieee_range *global_ranges;
/* Nested pending ranges. */
struct ieee_range *pending_ranges;
/* Type stack. */
/* Next unallocated name index. */
unsigned int name_indx;
/* Typedefs. */
- struct ieee_name_type *typedefs;
+ struct ieee_name_type_hash_table typedefs;
/* Tags. */
- struct ieee_name_type *tags;
+ struct ieee_name_type_hash_table tags;
+ /* Enums. */
+ struct ieee_defined_enum *enums;
+ /* Modified versions of types. */
+ struct ieee_modified_type *modified;
+ /* Number of entries allocated in modified. */
+ unsigned int modified_alloc;
/* The depth of block nesting. This is 0 outside a function, and 1
just after start_function is called. */
unsigned int block_depth;
+ /* The name of the current function. */
+ const char *fnname;
+ /* List of buffers for the type of the function we are currently
+ writing out. */
+ struct ieee_buflist fntype;
+ /* List of buffers for the parameters of the function we are
+ currently writing out. */
+ struct ieee_buflist fnargs;
+ /* Number of arguments written to fnargs. */
+ unsigned int fnargcount;
/* Pending function parameters. */
struct ieee_pending_parm *pending_parms;
/* Current line number filename. */
const char *lineno_filename;
/* Line number name index. */
unsigned int lineno_name_indx;
+ /* Filename of pending line number. */
+ const char *pending_lineno_filename;
+ /* Pending line number. */
+ unsigned long pending_lineno;
+ /* Address of pending line number. */
+ bfd_vma pending_lineno_addr;
+ /* Highest address seen at end of procedure. */
+ bfd_vma highaddr;
};
+static boolean ieee_init_buffer
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *));
static boolean ieee_change_buffer
- PARAMS ((struct ieee_handle *, struct ieee_buf **));
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *));
+static boolean ieee_append_buffer
+ PARAMS ((struct ieee_handle *, struct ieee_buflist *,
+ struct ieee_buflist *));
+static boolean ieee_real_write_byte PARAMS ((struct ieee_handle *, int));
+static boolean ieee_write_2bytes PARAMS ((struct ieee_handle *, int));
+static boolean ieee_write_number PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_write_id PARAMS ((struct ieee_handle *, const char *));
+static boolean ieee_write_asn
+ PARAMS ((struct ieee_handle *, unsigned int, bfd_vma));
+static boolean ieee_write_atn65
+ PARAMS ((struct ieee_handle *, unsigned int, const char *));
static boolean ieee_push_type
- PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean));
+ PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean,
+ boolean));
static unsigned int ieee_pop_type PARAMS ((struct ieee_handle *));
+static void ieee_pop_unused_type PARAMS ((struct ieee_handle *));
+static unsigned int ieee_pop_type_used
+ PARAMS ((struct ieee_handle *, boolean));
static boolean ieee_add_range
- PARAMS ((struct ieee_handle *, bfd_vma, bfd_vma));
+ PARAMS ((struct ieee_handle *, boolean, bfd_vma, bfd_vma));
static boolean ieee_start_range PARAMS ((struct ieee_handle *, bfd_vma));
static boolean ieee_end_range PARAMS ((struct ieee_handle *, bfd_vma));
-static boolean ieee_real_write_byte PARAMS ((struct ieee_handle *, int));
-static boolean ieee_write_2bytes PARAMS ((struct ieee_handle *, int));
-static boolean ieee_write_number PARAMS ((struct ieee_handle *, bfd_vma));
-static boolean ieee_write_id PARAMS ((struct ieee_handle *, const char *));
static boolean ieee_define_type
- PARAMS ((struct ieee_handle *, unsigned int, boolean));
+ PARAMS ((struct ieee_handle *, unsigned int, boolean, boolean));
static boolean ieee_define_named_type
- PARAMS ((struct ieee_handle *, const char *, boolean, unsigned int, boolean,
- struct ieee_buf **));
+ PARAMS ((struct ieee_handle *, const char *, unsigned int, unsigned int,
+ boolean, boolean, struct ieee_buflist *));
+static struct ieee_modified_type *ieee_get_modified_info
+ PARAMS ((struct ieee_handle *, unsigned int));
+static struct bfd_hash_entry *ieee_name_type_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean ieee_write_undefined_tag
+ PARAMS ((struct ieee_name_type_hash_entry *, PTR));
static boolean ieee_finish_compilation_unit PARAMS ((struct ieee_handle *));
+static void ieee_add_bb11_blocks PARAMS ((bfd *, asection *, PTR));
+static boolean ieee_add_bb11
+ PARAMS ((struct ieee_handle *, asection *, bfd_vma, bfd_vma));
static boolean ieee_output_pending_parms PARAMS ((struct ieee_handle *));
+static unsigned int ieee_vis_to_flags PARAMS ((enum debug_visibility));
+static boolean ieee_class_method_var
+ PARAMS ((struct ieee_handle *, const char *, enum debug_visibility, boolean,
+ boolean, boolean, bfd_vma, boolean));
static boolean ieee_start_compilation_unit PARAMS ((PTR, const char *));
static boolean ieee_start_source PARAMS ((PTR, const char *));
ieee_lineno
};
-/* Change the current buffer to a specified buffer chain. */
-
-static boolean
-ieee_change_buffer (info, ppbuf)
- struct ieee_handle *info;
- struct ieee_buf **ppbuf;
-{
- struct ieee_buf *buf;
-
- if (*ppbuf != NULL)
- {
- for (buf = *ppbuf; buf->next != NULL; buf = buf->next)
- ;
- }
- else
- {
- buf = (struct ieee_buf *) xmalloc (sizeof *buf);
- buf->next = NULL;
- buf->c = 0;
- *ppbuf = buf;
- }
-
- info->current = buf;
- return true;
-}
-
-/* Push a type index onto the type stack. */
+/* Initialize a buffer to be empty. */
+/*ARGSUSED*/
static boolean
-ieee_push_type (info, indx, size, unsignedp)
+ieee_init_buffer (info, buflist)
struct ieee_handle *info;
- unsigned int indx;
- unsigned int size;
- boolean unsignedp;
+ struct ieee_buflist *buflist;
{
- 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->next = info->type_stack;
- info->type_stack = ts;
-
+ buflist->head = NULL;
+ buflist->tail = NULL;
return true;
}
-/* Pop a type index off the type stack. */
-
-static unsigned int
-ieee_pop_type (info)
- struct ieee_handle *info;
-{
- struct ieee_type_stack *ts;
- unsigned int ret;
+/* See whether a buffer list has any data. */
- ts = info->type_stack;
- assert (ts != NULL);
- ret = ts->type.indx;
- info->type_stack = ts->next;
- free (ts);
- return ret;
-}
+#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL)
-/* Add a range of bytes included in the current compilation unit. */
+/* Change the current buffer to a specified buffer chain. */
static boolean
-ieee_add_range (info, low, high)
+ieee_change_buffer (info, buflist)
struct ieee_handle *info;
- bfd_vma low;
- bfd_vma high;
+ struct ieee_buflist *buflist;
{
- struct ieee_range *r, **pr;
-
- if (low == (bfd_vma) -1 || high == (bfd_vma) -1)
- return true;
-
- for (r = info->ranges; r != NULL; r = r->next)
+ if (buflist->head == NULL)
{
- if (high >= r->low && low <= r->high)
- {
- /* The new range overlaps r. */
- 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;
+ struct ieee_buf *buf;
- if ((*pr)->high > r->high)
- r->high = (*pr)->high;
- n = (*pr)->next;
- free (*pr);
- *pr = n;
- }
- return true;
- }
+ buf = (struct ieee_buf *) xmalloc (sizeof *buf);
+ buf->next = NULL;
+ buf->c = 0;
+ buflist->head = buf;
+ buflist->tail = buf;
}
- r = (struct ieee_range *) xmalloc (sizeof *r);
- memset (r, 0, sizeof *r);
-
- r->low = low;
- r->high = high;
-
- /* Store the ranges sorted by address. */
- for (pr = &info->ranges; *pr != NULL; pr = &(*pr)->next)
- if ((*pr)->next != NULL && (*pr)->next->low > high)
- break;
- r->next = *pr;
- *pr = r;
+ info->current = buflist;
+ info->curbuf = buflist->tail;
return true;
}
-/* Start a new range for which we only have the low address. */
+/* Append a buffer chain. */
+/*ARGSUSED*/
static boolean
-ieee_start_range (info, low)
+ieee_append_buffer (info, mainbuf, newbuf)
struct ieee_handle *info;
- bfd_vma low;
+ struct ieee_buflist *mainbuf;
+ struct ieee_buflist *newbuf;
{
- 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;
+ if (newbuf->head != NULL)
+ {
+ if (mainbuf->head == NULL)
+ mainbuf->head = newbuf->head;
+ else
+ mainbuf->tail->next = newbuf->head;
+ mainbuf->tail = newbuf->tail;
+ }
return true;
-}
-
-/* Finish a range started by ieee_start_range. */
-
-static boolean
-ieee_end_range (info, high)
- 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, low, high);
}
/* Write a byte into the buffer. We use a macro for speed and a
function for the complex cases. */
#define ieee_write_byte(info, b) \
- ((info)->current->c < IEEE_BUFSIZE \
- ? ((info)->current->buf[(info)->current->c++] = (b), true) \
+ ((info)->curbuf->c < IEEE_BUFSIZE \
+ ? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), true) \
: ieee_real_write_byte ((info), (b)))
static boolean
struct ieee_handle *info;
int b;
{
- if (info->current->c >= IEEE_BUFSIZE)
+ if (info->curbuf->c >= IEEE_BUFSIZE)
{
struct ieee_buf *n;
n = (struct ieee_buf *) xmalloc (sizeof *n);
n->next = NULL;
n->c = 0;
- info->current->next = n;
- info->current = n;
+ if (info->current->head == NULL)
+ info->current->head = n;
+ else
+ info->current->tail->next = n;
+ info->current->tail = n;
+ info->curbuf = n;
}
- info->current->buf[info->current->c] = b;
- ++info->current->c;
+ info->curbuf->buf[info->curbuf->c] = b;
+ ++info->curbuf->c;
return true;
}
return true;
}
-/* Start defining a type. */
+/* Write out an ASN record. */
static boolean
-ieee_define_type (info, size, unsignedp)
+ieee_write_asn (info, indx, val)
struct ieee_handle *info;
- unsigned int size;
- boolean unsignedp;
+ unsigned int indx;
+ bfd_vma val;
{
- return ieee_define_named_type (info, (const char *) NULL, false, size,
- unsignedp, (struct ieee_buf **) NULL);
+ return (ieee_write_2bytes (info, (int) ieee_asn_record_enum)
+ && ieee_write_number (info, indx)
+ && ieee_write_number (info, val));
}
-/* Start defining a named type. */
+/* Write out an ATN65 record. */
static boolean
-ieee_define_named_type (info, name, tagp, size, unsignedp, ppbuf)
+ieee_write_atn65 (info, indx, s)
struct ieee_handle *info;
- const char *name;
- boolean tagp;
- unsigned int size;
- boolean unsignedp;
- struct ieee_buf **ppbuf;
+ unsigned int indx;
+ const char *s;
{
- unsigned int type_indx;
- unsigned int name_indx;
-
- if (! tagp || name == NULL || *name == '\0')
- {
- type_indx = info->type_indx;
- ++info->type_indx;
- }
- else
- {
- struct ieee_name_type *nt;
+ 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));
+}
- /* The name is a tag. If we have already defined the tag, we
- must use the existing type index. */
- for (nt = info->tags; nt != NULL; nt = nt->next)
- if (nt->name[0] == name[0]
- && strcmp (nt->name, name) == 0)
- break;
+/* Push a type index onto the type stack. */
- if (nt == NULL)
- {
- nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
- memset (nt, 0, sizeof *nt);
- nt->name = name;
- nt->next = info->tags;
- info->tags = nt;
- nt->type.indx = info->type_indx;
- ++info->type_indx;
- }
+static boolean
+ieee_push_type (info, indx, size, unsignedp, localp)
+ struct ieee_handle *info;
+ unsigned int indx;
+ unsigned int size;
+ boolean unsignedp;
+ boolean localp;
+{
+ struct ieee_type_stack *ts;
- nt->type.size = size;
- nt->type.unsignedp = unsignedp;
- nt->kind = DEBUG_KIND_ILLEGAL;
+ ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
+ memset (ts, 0, sizeof *ts);
- type_indx = nt->type.indx;
- }
+ ts->type.indx = indx;
+ ts->type.size = size;
+ ts->type.unsignedp = unsignedp;
+ ts->type.localp = localp;
- name_indx = info->name_indx;
- ++info->name_indx;
+ ts->next = info->type_stack;
+ info->type_stack = ts;
- if (name == NULL)
- name = "";
+ return true;
+}
- /* If we were given a buffer, use it; otherwise, use the general
- type information, and make sure that the type block is started. */
- if (ppbuf != NULL)
- {
- if (! ieee_change_buffer (info, ppbuf))
- return false;
- }
- else if (info->types != NULL)
- {
- 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;
- }
+/* Pop a type index off the type stack. */
- /* Push the new type on the type stack, write out an NN record, and
- write out the start of a TY record. The caller will then finish
- the TY record. */
- return (ieee_push_type (info, type_indx, size, unsignedp)
- && 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 unsigned int
+ieee_pop_type (info)
+ struct ieee_handle *info;
+{
+ return ieee_pop_type_used (info, true);
}
-\f
-/* The general routine to write out IEEE debugging information. */
-boolean
-write_ieee_debugging_info (abfd, dhandle)
- bfd *abfd;
- PTR dhandle;
+/* Pop an unused type index off the type stack. */
+
+static void
+ieee_pop_unused_type (info)
+ struct ieee_handle *info;
{
- struct ieee_handle info;
- struct ieee_buf *tags;
- struct ieee_name_type *nt;
- asection *s;
- const char *err;
- struct ieee_buf *b;
+ (void) ieee_pop_type_used (info, false);
+}
- memset (&info, 0, sizeof info);
- info.abfd = abfd;
- info.type_indx = 256;
- info.name_indx = 32;
+/* Pop a used or unused type index off the type stack. */
- if (! debug_write (dhandle, &ieee_fns, (PTR) &info))
- return false;
+static unsigned int
+ieee_pop_type_used (info, used)
+ struct ieee_handle *info;
+ boolean used;
+{
+ struct ieee_type_stack *ts;
+ unsigned int ret;
- if (info.filename != NULL)
- {
- if (! ieee_finish_compilation_unit (&info))
- return false;
- }
+ ts = info->type_stack;
+ assert (ts != NULL);
- /* Put any undefined tags in the global typedef information. */
- tags = NULL;
- for (nt = info.tags; nt != NULL; nt = nt->next)
+ /* If this is a function type, and we need it, we need to append the
+ actual definition to the typedef block now. */
+ if (used && ! ieee_buffer_emptyp (&ts->type.fndef))
{
- unsigned int name_indx;
- char code;
+ struct ieee_buflist *buflist;
- if (nt->kind == DEBUG_KIND_ILLEGAL)
- continue;
- if (tags == NULL)
+ if (ts->type.localp)
{
- if (! ieee_change_buffer (&info, &tags)
- || ! 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;
+ /* Make sure we have started the types block. */
+ 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;
}
- 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->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))
- return false;
- switch (nt->kind)
+ else
{
- default:
- abort ();
- 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;
+ /* Make sure we started the global type block. */
+ 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_write_number (&info, code)
- || ! ieee_write_number (&info, 0))
+
+ if (! ieee_append_buffer (info, buflist, &ts->type.fndef))
return false;
}
- if (tags != NULL)
+
+ ret = ts->type.indx;
+ info->type_stack = ts->next;
+ free (ts);
+ return ret;
+}
+
+/* Add a range of bytes included in the current compilation unit. */
+
+static boolean
+ieee_add_range (info, global, low, high)
+ struct ieee_handle *info;
+ 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)
{
- struct ieee_buf **pb;
+ if (high >= r->low && low <= r->high)
+ {
+ /* The new range overlaps r. */
+ 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 (! ieee_write_byte (&info, (int) ieee_be_record_enum))
+ 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;
+
+ /* Store the ranges sorted by address. */
+ for (pr = plist; *pr != NULL; pr = &(*pr)->next)
+ if ((*pr)->low > high)
+ break;
+ r->next = *pr;
+ *pr = r;
+
+ return true;
+}
+
+/* Start a new range for which we only have the low address. */
+
+static boolean
+ieee_start_range (info, low)
+ 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;
+}
+
+/* Finish a range started by ieee_start_range. */
+
+static boolean
+ieee_end_range (info, high)
+ 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);
+}
+
+/* Start defining a type. */
+
+static boolean
+ieee_define_type (info, size, unsignedp, localp)
+ struct ieee_handle *info;
+ unsigned int size;
+ boolean unsignedp;
+ boolean localp;
+{
+ return ieee_define_named_type (info, (const char *) NULL,
+ (unsigned int) -1, size, unsignedp,
+ localp, (struct ieee_buflist *) NULL);
+}
+
+/* Start defining a named type. */
+
+static boolean
+ieee_define_named_type (info, name, indx, size, unsignedp, localp, buflist)
+ struct ieee_handle *info;
+ const char *name;
+ unsigned int indx;
+ unsigned int size;
+ boolean unsignedp;
+ 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 we were given a buffer, use it; otherwise, use either the
+ local or the global type information, and make sure that the type
+ block is started. */
+ 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;
+ }
+ }
+
+ /* Push the new type on the type stack, write out an NN record, and
+ write out the start of a TY record. The caller will then finish
+ the TY record. */
+ 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));
+}
- for (pb = &tags; *pb != NULL; pb = &(*pb)->next)
- ;
- *pb = info.data;
- info.data = tags;
+/* Get an entry to the list of modified versions of a type. */
+
+static struct ieee_modified_type *
+ieee_get_modified_info (info, indx)
+ 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;
+}
+\f
+/* Routines for the hash table mapping names to types. */
+
+/* Initialize an entry in the hash table. */
+
+static struct bfd_hash_entry *
+ieee_name_type_newfunc (entry, table, string)
+ 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;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == NULL)
+ ret = ((struct ieee_name_type_hash_entry *)
+ bfd_hash_allocate (table, sizeof *ret));
+ if (ret == NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct ieee_name_type_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->types = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Look up an entry in the hash table. */
+
+#define ieee_name_type_hash_lookup(table, string, create, copy) \
+ ((struct ieee_name_type_hash_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+/* Traverse the hash table. */
+
+#define ieee_name_type_hash_traverse(table, func, info) \
+ (bfd_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
+ (info)))
+\f
+/* The general routine to write out IEEE debugging information. */
+
+boolean
+write_ieee_debugging_info (abfd, dhandle)
+ bfd *abfd;
+ PTR 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, (PTR) &info))
+ return false;
+
+ if (info.filename != NULL)
+ {
+ if (! ieee_finish_compilation_unit (&info))
+ return false;
+ }
+
+ /* Put any undefined tags in the global typedef information. */
+ info.error = false;
+ ieee_name_type_hash_traverse (&info.tags,
+ ieee_write_undefined_tag,
+ (PTR) &info);
+ if (info.error)
+ return false;
+
+ /* Prepend the global typedef information to the other data. */
+ if (! ieee_buffer_emptyp (&info.global_types))
+ {
+ if (! ieee_change_buffer (&info, &info.global_types)
+ || ! 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;
+ }
+
+ /* Make sure that we have declare BB11 blocks for each range in the
+ file. They are added to info->vars. */
+ info.error = false;
+ if (! ieee_init_buffer (&info, &info.vars))
+ return false;
+ bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (PTR) &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;
}
/* Now all the data is in info.data. Write it out to the BFD. We
normally would need to worry about whether all the other sections
are set up yet, but the IEEE backend will handle this particular
case correctly regardless. */
- if (info.data == NULL)
+ if (ieee_buffer_emptyp (&info.data))
{
/* There is no debugging information. */
return true;
bfd_size_type size;
size = 0;
- for (b = info.data; b != NULL; b = b->next)
+ 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";
file_ptr offset;
offset = 0;
- for (b = info.data; b != NULL; b = b->next)
+ for (b = info.data.head; b != NULL; b = b->next)
{
if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c))
{
return false;
}
+ bfd_hash_table_free (&info.typedefs.root);
+ bfd_hash_table_free (&info.tags.root);
+
+ return true;
+}
+
+/* Write out information for an undefined tag. This is called via
+ ieee_name_type_hash_traverse. */
+
+static boolean
+ieee_write_undefined_tag (h, p)
+ struct ieee_name_type_hash_entry *h;
+ PTR 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;
+ }
+ }
+
+ 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;
}
struct ieee_handle *info = (struct ieee_handle *) p;
const char *modname;
char *c, *s;
+ unsigned int nindx;
if (info->filename != NULL)
{
*s = '\0';
info->modname = c;
- info->types = NULL;
- info->vars = NULL;
- info->linenos = NULL;
+ 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;
+ /* Always include a BB1 and a BB3 block. That is what the output of
+ the MRI linker seems to look like. */
+ 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;
}
ieee_finish_compilation_unit (info)
struct ieee_handle *info;
{
- struct ieee_buf **pp;
struct ieee_range *r;
- if (info->types != NULL)
+ 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 (info->vars != NULL)
+ if (! ieee_buffer_emptyp (&info->cxx))
+ {
+ /* Append any C++ information to the global function and
+ variable information. */
+ assert (! ieee_buffer_emptyp (&info->vars));
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
+
+ /* We put the pmisc records in a dummy procedure, just as the
+ MRI compiler does. */
+ 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->linenos != NULL)
+ if (info->pending_lineno_filename != NULL)
+ {
+ /* Force out the pending line number. */
+ if (! ieee_lineno ((PTR) 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)
+ {
+ /* We were not in the main file. We just closed the
+ included line number block, and now we must close the
+ main line number block. */
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ }
}
- for (pp = &info->data; *pp != NULL; pp = &(*pp)->next)
- ;
- *pp = info->types;
- for (; *pp != NULL; pp = &(*pp)->next)
- ;
- *pp = info->vars;
- for (; *pp != NULL; pp = &(*pp)->next)
- ;
- *pp = info->linenos;
+ 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;
/* Build BB10/BB11 blocks based on the ranges we recorded. */
if (! ieee_change_buffer (info, &info->data))
+ bfd_section_size (info->abfd, s))))
{
r = r->next;
- high = r->next->high;
+ high = r->high;
}
if ((s->flags & SEC_CODE) != 0)
|| ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, "")
|| ! ieee_write_number (info, kind)
- || ! ieee_write_number (info, s->index)
+ || ! 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;
+
+ /* Add this range to the list of global ranges. */
+ if (! ieee_add_range (info, true, low, high))
+ return false;
+ }
+
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+
+ return true;
+}
+
+/* Add BB11 blocks describing each range that we have not already
+ described. */
+
+static void
+ieee_add_bb11_blocks (abfd, sec, data)
+ bfd *abfd;
+ asection *sec;
+ PTR 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);
+
+ /* Find the first range at or after this section. The ranges are
+ sorted by address. */
+ 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)
+ {
+ if (! ieee_add_bb11 (info, sec, low, r->low))
+ {
+ info->error = true;
+ return;
+ }
+ }
+ low = r->high;
+
+ r = r->next;
+ }
+}
+
+/* Add a single BB11 block for a range. We add it to info->vars. */
+
+static boolean
+ieee_add_bb11 (info, sec, low, high)
+ 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;
+ char *c, *s;
+
+ /* Start the enclosing BB10 block. */
+ filename = bfd_get_filename (info->abfd);
+ modname = strrchr (filename, '/');
+ if (modname != NULL)
+ ++modname;
+ else
+ {
+ modname = strrchr (filename, '\\');
+ if (modname != NULL)
+ ++modname;
+ 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 (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ 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;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- return ieee_push_type (info, 0, 0, false);
+ return ieee_push_type (info, 0, 0, false, false);
}
/* Make a void type. */
{
struct ieee_handle *info = (struct ieee_handle *) p;
- return ieee_push_type (info, 1, 0, false);
+ return ieee_push_type (info, 1, 0, false, false);
}
/* Make an integer type. */
if (unsignedp)
++indx;
- return ieee_push_type (info, indx, size, unsignedp);
+ return ieee_push_type (info, indx, size, unsignedp, false);
}
/* Make a floating point type. */
return false;
}
- return ieee_push_type (info, indx, size, false);
+ return ieee_push_type (info, indx, size, false, false);
}
/* Make a complex type. */
}
/* FIXME: I don't know what the string is for. */
- return (ieee_define_type (info, size, false)
+ return (ieee_define_type (info, size, false, false)
&& ieee_write_number (info, code)
&& ieee_write_id (info, ""));
}
bfd_signed_vma *vals;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- boolean simple;
+ struct ieee_defined_enum *e;
+ boolean localp, simple;
int i;
+ localp = false;
+ 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 (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[i] == NULL && e->names[i] == NULL))
+ {
+ /* We've seen this enum before. */
+ return ieee_push_type (info, e->indx, 0, true, false);
+ }
+
+ if (tag != NULL)
+ {
+ /* We've already seen an enum of the same name, so we must make
+ sure to output this one locally. */
+ localp = true;
+ break;
+ }
+ }
+
/* If this is a simple enumeration, in which the values start at 0
and always increment by 1, we can use type E. Otherwise we must
use type N. */
}
}
- if (! ieee_define_named_type (info, tag, true, 0, true,
- (struct ieee_buf **) NULL)
+ if (! ieee_define_named_type (info, tag, (unsigned int) -1, 0,
+ true, localp, (struct ieee_buflist *) NULL)
|| ! ieee_write_number (info, simple ? 'E' : 'N'))
return false;
if (simple)
}
}
+ if (! localp)
+ {
+ e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
+ memset (e, 0, sizeof *e);
+
+ e->indx = info->type_stack->type.indx;
+ e->tag = tag;
+ e->names = names;
+ e->vals = vals;
+
+ e->next = info->enums;
+ info->enums = e;
+ }
+
return true;
}
PTR p;
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
unsigned int indx;
+ struct ieee_modified_type *m = NULL;
+ localp = info->type_stack->type.localp;
indx = ieee_pop_type (info);
- /* A pointer to a simple builtin type can be obtained by adding 32. */
+ /* A pointer to a simple builtin type can be obtained by adding 32.
+ FIXME: Will this be a short pointer, and will that matter? */
if (indx < 32)
- return ieee_push_type (info, indx + 32, 0, true);
+ return ieee_push_type (info, indx + 32, 0, true, false);
+
+ if (! localp)
+ {
+ m = ieee_get_modified_info (p, indx);
+ if (m == NULL)
+ return false;
+
+ /* FIXME: The size should depend upon the architecture. */
+ 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 (ieee_define_type (info, 0, true)
- && ieee_write_number (info, 'P')
- && ieee_write_number (info, indx));
+ return true;
}
-/* Make a function type. */
+/* Make a function type. This will be called for a method, but we
+ don't want to actually add it to the type table in that case. We
+ handle this by defining the type in a private buffer, and only
+ adding that buffer to the typedef block if we are going to use it. */
static boolean
ieee_function_type (p, argcount, varargs)
boolean varargs;
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ 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--)
- args[i] = ieee_pop_type (info);
+ {
+ 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);
+ }
+
/* An attribute of 0x41 means that the frame and push mask are
unknown. */
- if (! ieee_define_type (info, 0, true)
+ 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)
return false;
}
- return ieee_write_number (info, 0);
+ if (! ieee_write_number (info, 0))
+ return false;
+
+ /* We wrote the information into fndef, in case we don't need it.
+ It will be appended to info->types by ieee_pop_type. */
+ info->type_stack->type.fndef = fndef;
+
+ if (m != NULL)
+ m->function = info->type_stack->type.indx;
+
+ return true;
}
/* Make a reference type. */
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
- boolean unsignedp;
+ boolean unsignedp, localp;
size = info->type_stack->type.size;
unsignedp = info->type_stack->type.unsignedp;
- (void) ieee_pop_type (info);
- return (ieee_define_type (info, size, 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)
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int eleindx;
+ boolean localp;
+ struct ieee_modified_type *m = NULL;
+ struct ieee_modified_array_type *a;
/* IEEE does not store the range, so we just ignore it. */
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
+ localp = info->type_stack->type.localp;
eleindx = ieee_pop_type (info);
- if (! ieee_define_type (info, 0, false)
+ 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, 0, false, false);
+ }
+ }
+
+ if (! ieee_define_type (info, 0, false, localp)
|| ! ieee_write_number (info, low == 0 ? 'Z' : 'C')
|| ! ieee_write_number (info, eleindx))
return false;
return false;
}
- return ieee_write_number (info, high);
+ 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;
}
/* Make a set type. */
boolean bitstringp;
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ boolean localp;
unsigned int eleindx;
+ localp = info->type_stack->type.localp;
eleindx = ieee_pop_type (info);
/* FIXME: We don't know the size, so we just use 4. */
- return (ieee_define_type (info, 0, true)
+ return (ieee_define_type (info, 0, true, localp)
&& ieee_write_number (info, 's')
&& ieee_write_number (info, 4)
&& ieee_write_number (info, eleindx));
type. */
if (domain)
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
return ieee_function_type (p, argcount, varargs);
}
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
- boolean unsignedp;
+ 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);
- return (ieee_define_type (info, size, unsignedp)
- && ieee_write_number (info, 'n')
- && ieee_write_number (info, 1)
- && ieee_write_number (info, indx));
+
+ 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;
}
/* Make a volatile qualified type. */
{
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
- boolean unsignedp;
+ 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);
- return (ieee_define_type (info, size, unsignedp)
- && ieee_write_number (info, 'n')
- && ieee_write_number (info, 2)
- && ieee_write_number (info, indx));
+
+ 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;
+}
+
+/* Convert an enum debug_visibility into a CXXFLAGS value. */
+
+static unsigned int
+ieee_vis_to_flags (visibility)
+ 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;
+ }
+ /*NOTREACHED*/
}
/* Start defining a struct type. We build it in the strdef field on
unsigned int size;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- struct ieee_buf *strdef;
+ boolean localp, ignorep;
+ 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;
+
+ /* We need to create a tag for internal use even if we don't want
+ one for external use. This will let us refer to an anonymous
+ struct. */
+ if (tag != NULL)
+ {
+ look = tag;
+ copy = false;
+ }
+ else
+ {
+ sprintf (ab, "__anon%u", id);
+ look = ab;
+ copy = true;
+ }
+
+ /* If we already have references to the tag, we must use the
+ existing type index. */
+ 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)
+ {
+ /* We are creating a duplicate definition of a globally
+ defined tag. Force it to be local to avoid
+ confusion. */
+ localp = true;
+ }
+ }
+
+ if (nt != NULL)
+ {
+ assert (localp == nt->type.localp);
+ if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp)
+ {
+ /* We've already seen a global definition of the type.
+ Ignore this new definition. */
+ 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;
- strdef = NULL;
- if (! ieee_define_named_type (info, tag, true, size, true, &strdef)
+ 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;
+
+ /* We never want nt->type.name to be NULL. We want the rest of
+ the type to be the object set up on the type stack; it will
+ have a NULL name if tag is NULL. */
+ 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;
}
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
boolean unsignedp;
+ boolean referencep;
+ 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 we are ignoring this struct definition, just pop and ignore
+ the type. */
+ 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);
- assert (info->type_stack != NULL && info->type_stack->type.strdef != NULL);
+ if (localp)
+ info->type_stack->type.localp = true;
+
+ if (info->type_stack->type.classdef != NULL)
+ {
+ unsigned int flags;
+ unsigned int nindx;
+
+ /* This is a class. We must add a description of this field to
+ the class records we are building. */
+
+ 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;
+
+ /* We need to output a record recording that this field is
+ really of reference type. We put this on the refs field
+ of classdef, so that it can be appended to the C++
+ records after the class is defined. */
+
+ 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 the bitsize doesn't match the expected size, we need to output
a bitfield type. */
- if (size == 0 || bitsize == size * 8)
+ if (size == 0 || bitsize == 0 || bitsize == size * 8)
offset = bitpos / 8;
else
{
- if (! ieee_define_type (info, 0, unsignedp)
+ 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);
PTR p;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- struct ieee_buf **pb;
+ struct ieee_buflist *pb;
+
+ assert (info->type_stack != NULL
+ && ! ieee_buffer_emptyp (&info->type_stack->type.strdef));
- assert (info->type_stack != NULL && info->type_stack->type.strdef != NULL);
+ /* If we were ignoring this struct definition because it was a
+ duplicate defintion, just through away whatever bytes we have
+ accumulated. Leave the type on the stack. */
+ if (info->type_stack->type.ignorep)
+ return true;
- /* Make sure we have started the types block. */
- if (info->types == NULL)
+ /* If this is not a duplicate definition of this tag, then localp
+ will be false, and we can put it in the global type block.
+ FIXME: We should avoid outputting duplicate definitions which are
+ the same. */
+ if (! info->type_stack->type.localp)
{
- 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;
+ /* Make sure we have started the global type block. */
+ 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
+ {
+ /* Make sure we have started the types block. */
+ 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;
}
/* Append the struct definition to the types. */
- for (pb = &info->types; *pb != NULL; pb = &(*pb)->next)
- ;
- *pb = info->type_stack->type.strdef;
- info->type_stack->type.strdef = NULL;
+ if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef)
+ || ! ieee_init_buffer (info, &info->type_stack->type.strdef))
+ return false;
/* Leave the struct on the type stack. */
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;
- /* FIXME. */
+ /* A C++ class is output as a C++ struct along with a set of pmisc
+ records describing the class. */
+
+ /* We need to have a name so that we can associate the struct and
+ the class. */
+ if (tag == NULL)
+ {
+ char *t;
+
+ t = (char *) xmalloc (20);
+ sprintf (t, "__anon%u", id);
+ tag = t;
+ }
+
+ /* We can't write out the virtual table information until we have
+ finished the class, because we don't know the virtual table size.
+ We get the size from the largest voffset we see. */
+ vclass = NULL;
if (vptr && ! ownvptr)
- (void) ieee_pop_type (info);
- return ieee_start_struct_type (p, tag, id, structp, size);
+ {
+ vclass = info->type_stack->type.name;
+ assert (vclass != NULL);
+ /* We don't call ieee_pop_unused_type, since the class should
+ get defined. */
+ (void) ieee_pop_type (info);
+ }
+
+ if (! ieee_start_struct_type (p, tag, id, structp, size))
+ return false;
+
+ indx = info->name_indx;
+ ++info->name_indx;
+
+ /* We write out pmisc records into the classdef field. We will
+ write out the pmisc start after we know the number of records we
+ need. */
+ 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;
}
/* Add a static member to a class. */
enum debug_visibility visibility;
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int flags;
+ unsigned int nindx;
+
+ /* We don't care about the type. Hopefully there will be a call to
+ ieee_variable declaring the physical name and the type, since
+ that is where an IEEE consumer must get the type. */
+ 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;
- /* FIXME. */
- (void) ieee_pop_type (info);
return true;
}
enum debug_visibility visibility;
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ const char *bname;
+ 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);
+
+ /* We are currently defining both a struct and a class. We must
+ write out a field definition in the struct which holds the base
+ class. The stabs debugging reader will create a field named
+ _vb$CLASS for a virtual base class, so we just use that. FIXME:
+ we should not depend upon a detail of stabs debugging. */
+ 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);
- /* FIXME. */
- (void) ieee_pop_type (info);
return true;
}
PTR p;
const char *name;
{
- /* FIXME. */
+ 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;
+}
+
+/* Define a new method variant, either static or not. */
+
+static boolean
+ieee_class_method_var (info, physname, visibility, staticp, constp,
+ volatilep, voffset, context)
+ struct ieee_handle *info;
+ const char *physname;
+ enum debug_visibility visibility;
+ boolean staticp;
+ boolean constp;
+ boolean volatilep;
+ bfd_vma voffset;
+ boolean context;
+{
+ unsigned int flags;
+ unsigned int nindx;
+ boolean virtual;
+
+ /* We don't need the type of the method. An IEEE consumer which
+ wants the type must track down the function by the physical name
+ and get the type from that. */
+ ieee_pop_unused_type (info);
+
+ /* We don't use the context. FIXME: We probably ought to use it to
+ adjust the voffset somehow, but I don't really know how. */
+ 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);
+
+ /* FIXME: We never set CXXFLAGS_OVERRIDE, CXXFLAGS_OPERATOR,
+ CXXFLAGS_CTORDTOR, CXXFLAGS_CTOR, or CXXFLAGS_INLINE. */
+
+ 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;
}
bfd_vma voffset;
boolean context;
{
- struct ieee_handle *info = (struct ieee_handle *) p;
-
- /* FIXME. */
- (void) ieee_pop_type (info);
- if (context)
- (void) ieee_pop_type (info);
- return true;
+ struct ieee_handle *info = (struct ieee_handle *) p;
+
+ return ieee_class_method_var (info, physname, visibility, false, constp,
+ volatilep, voffset, context);
}
/* Define a new static method variant. */
{
struct ieee_handle *info = (struct ieee_handle *) p;
- /* FIXME. */
- (void) ieee_pop_type (info);
- return true;
+ return ieee_class_method_var (info, physname, visibility, true, constp,
+ volatilep, 0, false);
}
/* Finish up a method. */
ieee_class_end_method (p)
PTR p;
{
- /* FIXME. */
+ 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;
}
ieee_end_class_type (p)
PTR p;
{
+ struct ieee_handle *info = (struct ieee_handle *) p;
+ unsigned int nindx;
+
+ assert (info->type_stack != NULL
+ && info->type_stack->type.classdef != NULL);
+
+ /* If we were ignoring this class definition because it was a
+ duplicate definition, just through away whatever bytes we have
+ accumulated. Leave the type on the stack. */
+ if (info->type_stack->type.ignorep)
+ return true;
+
+ nindx = info->type_stack->type.classdef->indx;
+
+ /* If we have a virtual table, we can write out the information now. */
+ 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;
+ }
+
+ /* Now that we know the number of pmisc records, we can write out
+ the atn62 which starts the pmisc records, and append them to the
+ C++ buffers. */
+
+ 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);
}
const char *name;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- register struct ieee_name_type *nt;
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
- for (nt = info->typedefs; nt != NULL; nt = nt->next)
- {
- if (nt->name[0] == name[0]
- && strcmp (nt->name, name) == 0)
- {
- if (! ieee_push_type (info, nt->type.indx, nt->type.size,
- nt->type.unsignedp))
- return false;
- /* Copy over any other type information we may have. */
- info->type_stack->type = nt->type;
- return true;
- }
- }
+ h = ieee_name_type_hash_lookup (&info->typedefs, name, false, false);
+
+ /* h should never be NULL, since that would imply that the generic
+ debugging code has asked for a typedef which it has not yet
+ defined. */
+ assert (h != NULL);
+
+ /* We always use the most recently defined type for this name, which
+ will be the first one on the list. */
+
+ nt = h->types;
+ if (! ieee_push_type (info, nt->type.indx, nt->type.size,
+ nt->type.unsignedp, nt->type.localp))
+ return false;
+
+ /* Copy over any other type information we may have. */
+ info->type_stack->type = nt->type;
- abort ();
+ return true;
}
/* Push a tagged type onto the type stack. */
enum debug_type_kind kind;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- register struct ieee_name_type *nt;
+ boolean localp;
+ boolean copy;
+ char ab[20];
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
+ localp = false;
+
+ copy = false;
if (name == NULL)
- return true;
+ {
+ sprintf (ab, "__anon%u", id);
+ name = ab;
+ copy = true;
+ }
- for (nt = info->tags; nt != NULL; nt = nt->next)
+ 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->name[0] == name[0]
- && strcmp (nt->name, name) == 0)
+ if (nt->id == id)
{
if (! ieee_push_type (info, nt->type.indx, nt->type.size,
- nt->type.unsignedp))
+ nt->type.unsignedp, nt->type.localp))
return false;
/* Copy over any other type information we may have. */
info->type_stack->type = nt->type;
return true;
}
+
+ if (! nt->type.localp)
+ {
+ /* This is a duplicate of a global type, so it must be
+ local. */
+ localp = true;
+ }
}
nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
memset (nt, 0, sizeof *nt);
- nt->name = name;
+ 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 = info->tags;
- info->tags = nt;
+ 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 ieee_push_type (info, nt->type.indx, 0, false);
+ return true;
}
/* Output a typedef. */
const char *name;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- struct ieee_name_type *nt;
- unsigned int size;
- boolean unsignedp;
+ struct ieee_write_type type;
unsigned int indx;
+ boolean found;
+ boolean localp;
+ struct ieee_name_type_hash_entry *h;
+ struct ieee_name_type *nt;
- nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
- memset (nt, 0, sizeof *nt);
- nt->name = name;
- nt->type = info->type_stack->type;
- nt->kind = DEBUG_KIND_ILLEGAL;
-
- nt->next = info->typedefs;
- info->typedefs = nt;
-
- size = info->type_stack->type.size;
- unsignedp = info->type_stack->type.unsignedp;
- indx = ieee_pop_type (info);
+ type = info->type_stack->type;
+ indx = type.indx;
/* If this is a simple builtin type using a builtin name, we don't
want to output the typedef itself. We also want to change the
type index to correspond to the name being used. We recognize
names used in stabs debugging output even if they don't exactly
correspond to the names used for the IEEE builtin types. */
+ found = false;
if (indx <= (unsigned int) builtin_bcd_float)
{
- boolean found;
-
- found = false;
switch ((enum builtin_types) indx)
{
default:
}
if (found)
+ type.indx = indx;
+ }
+
+ h = ieee_name_type_hash_lookup (&info->typedefs, name, true, false);
+ if (h == NULL)
+ return false;
+
+ /* See if we have already defined this type with this name. */
+ localp = type.localp;
+ for (nt = h->types; nt != NULL; nt = nt->next)
+ {
+ if (nt->id == indx)
{
- nt->type.indx = indx;
- return true;
+ /* If this is a global definition, then we don't need to
+ do anything here. */
+ if (! nt->type.localp)
+ {
+ ieee_pop_unused_type (info);
+ return true;
+ }
+ }
+ else
+ {
+ /* This is a duplicate definition, so make this one local. */
+ localp = true;
}
}
- if (! ieee_define_named_type (info, name, false, size, unsignedp,
- (struct ieee_buf **) NULL)
+ /* We need to add a new typedef for this type. */
+
+ 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)
+ {
+ /* This is one of the builtin typedefs, so we don't need to
+ actually define it. */
+ 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;
- /* Remove the type we just added to the type stack. */
+ /* Remove the type we just added to the type stack. This should not
+ be ieee_pop_unused_type, since the type is used, we just don't
+ need it now. */
(void) ieee_pop_type (info);
return true;
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ /* This should not be ieee_pop_unused_type, since we want the type
+ to be defined. */
(void) ieee_pop_type (info);
return true;
}
struct ieee_handle *info = (struct ieee_handle *) p;
/* FIXME. */
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
return true;
}
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int name_indx;
unsigned int size;
+ boolean referencep;
unsigned int type_indx;
boolean asn;
+ int refflag;
- /* Make sure the variable section is started. */
- if (info->vars != NULL)
- {
- if (! ieee_change_buffer (info, &info->vars))
- return false;
- }
- else
- {
- 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;
- }
+ 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;
- size = info->type_stack->type.size;
- type_indx = ieee_pop_type (info);
-
/* Write out an NN and an ATN record for this variable. */
if (! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, name_indx)
return false;
case DEBUG_GLOBAL:
if (! ieee_write_number (info, 8)
- || ! ieee_add_range (info, val, val + size))
+ || ! 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, val, val + size))
+ || ! 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:
|| ! ieee_write_number (info,
ieee_genreg_to_regno (info->abfd, val)))
return false;
+ refflag = 2;
asn = false;
break;
}
if (asn)
{
- if (! ieee_write_2bytes (info, (int) ieee_asn_record_enum)
- || ! ieee_write_number (info, name_indx)
- || ! ieee_write_number (info, val))
+ if (! ieee_write_asn (info, name_indx, val))
+ return false;
+ }
+
+ /* If this is really a reference type, then we just output it with
+ pointer type, and must now output a C++ record indicating that it
+ is really reference type. */
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+
+ /* If this is a global variable, we want to output the misc
+ record in the C++ misc record block. Otherwise, we want to
+ output it just after the variable definition, which is where
+ the current buffer is. */
+ 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;
}
boolean global;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- unsigned int indx;
+ boolean referencep;
+ unsigned int retindx, typeindx;
+
+ referencep = info->type_stack->type.referencep;
+ retindx = ieee_pop_type (info);
- /* Make sure the variable section is started. */
- if (info->vars != NULL)
+ /* Besides recording a BB4 or BB6 block, we record the type of the
+ function in the BB1 typedef block. We can't write out the full
+ type until we have seen all the parameters, so we accumulate it
+ in info->fntype and info->fnargs. */
+ if (! ieee_buffer_emptyp (&info->fntype))
{
- if (! ieee_change_buffer (info, &info->vars))
- return false;
+ /* FIXME: This might happen someday if we support nested
+ functions. */
+ abort ();
}
- else
+
+ info->fnname = name;
+
+ /* An attribute of 0x40 means that the push mask is unknown. */
+ 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 the function return value is actually a reference type, we
+ must add a record indicating that. */
+ if (referencep)
{
- if (! ieee_change_buffer (info, &info->vars)
- || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
- || ! ieee_write_byte (info, 3)
+ 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_id (info, info->modname))
+ || ! 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;
}
- indx = ieee_pop_type (info);
+ assert (! ieee_buffer_emptyp (&info->vars));
+ if (! ieee_change_buffer (info, &info->vars))
+ return false;
/* The address is written out as the first block. */
&& ieee_write_number (info, 0)
&& ieee_write_id (info, name)
&& ieee_write_number (info, 0)
- && ieee_write_number (info, indx));
+ && ieee_write_number (info, typeindx));
}
/* Add a function parameter. This will normally be called before the
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;
;
*pm = m;
+ /* Add the type to the fnargs list. */
+ if (! ieee_change_buffer (info, &info->fnargs)
+ || ! ieee_write_number (info, m->type))
+ return false;
+ ++info->fnargcount;
+
return true;
}
struct ieee_handle *info;
{
struct ieee_pending_parm *m;
+ unsigned int refcount;
- m = info->pending_parms;
- while (m != NULL)
+ refcount = 0;
+ for (m = info->pending_parms; m != NULL; m = m->next)
{
- struct ieee_pending_parm *next;
enum debug_var_kind vkind;
switch (m->kind)
break;
}
- if (! ieee_push_type (info, m->type, 0, false)
- || ! ieee_variable ((PTR) info, m->name, vkind, m->val))
+ 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 ((PTR) info, m->name, vkind, m->val))
+ return false;
+ }
+
+ /* If there are any reference parameters, we need to output a
+ miscellaneous record indicating them. */
+ if (refcount > 0)
+ {
+ unsigned int nindx, varindx;
+
+ /* FIXME: The MRI compiler outputs the demangled function name
+ here, but we are outputting the mangled name. */
+ 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;
+ }
+ }
+ }
- /* FIXME: We should output a pmisc note here for reference
- parameters. */
+ 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;
{
if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
|| ! ieee_write_byte (info, 6)
- || ! ieee_write_byte (info, 0)
+ || ! ieee_write_number (info, 0)
|| ! ieee_write_id (info, "")
|| ! ieee_write_number (info, 0)
|| ! ieee_write_number (info, 0)
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ /* The address we are given is the end of the block, but IEEE seems
+ to want to the address of the last byte in the block, so we
+ subtract one. */
if (! ieee_change_buffer (info, &info->vars)
|| ! ieee_write_byte (info, (int) ieee_be_record_enum)
- || ! ieee_write_number (info, addr))
+ || ! ieee_write_number (info, addr - 1))
return false;
if (! ieee_end_range (info, addr))
--info->block_depth;
+ if (addr > info->highaddr)
+ info->highaddr = addr;
+
return true;
}
--info->block_depth;
+ /* Now we can finish up fntype, and add it to the typdef section.
+ At this point, fntype is the 'x' type up to the argument count,
+ and fnargs is the argument types. We must add the argument
+ count, and we must add the level. FIXME: We don't record varargs
+ functions correctly. In fact, stabs debugging does not give us
+ enough information to do so. */
+ 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;
+
+ /* Make sure the typdef block has been started. */
+ 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;
}
assert (info->filename != NULL);
- /* Make sure we have a line number block. */
- if (info->linenos != NULL)
- {
- 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 (filename, info->lineno_filename) != 0)
+ /* The HP simulator seems to get confused when more than one line is
+ listed for the same address, at least if they are in different
+ files. We handle this by always listing the last line for a
+ given address, since that seems to be the one that gdb uses. */
+ if (info->pending_lineno_filename != NULL
+ && addr != info->pending_lineno_addr)
{
- if (strcmp (info->filename, info->lineno_filename) != 0)
+ /* Make sure we have a line number block. */
+ if (! ieee_buffer_emptyp (&info->linenos))
{
- /* We were not in the main file. Close the block for the
- included file. */
- if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ if (! ieee_change_buffer (info, &info->linenos))
return false;
}
- if (strcmp (info->filename, filename) != 0)
+ else
{
- /* We are not changing to the main file. Open a block for
- the new included file. */
- if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ 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, filename))
+ || ! 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)
+ {
+ /* We were not in the main file. Close the block for the
+ included file. */
+ if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+ return false;
+ if (strcmp (info->filename, info->pending_lineno_filename) == 0)
+ {
+ /* We need a new NN record, and we aren't output to
+ output one. */
+ 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)
+ {
+ /* We are not changing to the main file. Open a block for
+ the new included file. */
+ 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;
}
- info->lineno_filename = 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;
}
- return (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, lineno)
- && ieee_write_number (info, 0)
- && ieee_write_2bytes (info, (int) ieee_asn_record_enum)
- && ieee_write_number (info, info->lineno_name_indx)
- && ieee_write_number (info, addr));
+ info->pending_lineno_filename = filename;
+ info->pending_lineno = lineno;
+ info->pending_lineno_addr = addr;
+
+ return true;
}