📄 stabs.c
字号:
(debug_type *) NULL, false);
dtype = debug_make_pointer_type (dhandle, ftype);
}
}
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
value))
return false;
/* FIXME: At this point gdb considers rearranging the parameter
address on a big endian machine if it is smaller than an int.
We have no way to do that, since we don't really know much
about the target. */
break;
case 'P':
if (stabtype == N_FUN)
{
/* Prototype of a function referenced by this file. */
while (*p == ';')
{
++p;
if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL)
== DEBUG_TYPE_NULL)
return false;
}
break;
}
/* Fall through. */
case 'R':
/* Parameter which is in a register. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
value))
return false;
break;
case 'r':
/* Register variable (either global or local). */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
value))
return false;
/* FIXME: At this point gdb checks to combine pairs of 'p' and
'r' stabs into a single 'P' stab. */
break;
case 'S':
/* Static symbol at top level of file */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
value))
return false;
break;
case 't':
/* A typedef. */
dtype = parse_stab_type (dhandle, info, name, &p, &slot);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (name == NULL)
{
/* A nameless type. Nothing to do. */
return true;
}
dtype = debug_name_type (dhandle, name, dtype);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (slot != NULL)
*slot = dtype;
break;
case 'T':
/* Struct, union, or enum tag. For GNU C++, this can be be followed
by 't' which means we are typedef'ing it as well. */
if (*p != 't')
{
synonym = false;
/* FIXME: gdb sets synonym to true if the current language
is C++. */
}
else
{
synonym = true;
++p;
}
dtype = parse_stab_type (dhandle, info, name, &p, &slot);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (name == NULL)
return true;
/* INFO->SELF_CROSSREF is set by parse_stab_type if this type is
a cross reference to itself. These are generated by some
versions of g++. */
self_crossref = info->self_crossref;
dtype = debug_tag_type (dhandle, name, dtype);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (slot != NULL)
*slot = dtype;
/* See if we have a cross reference to this tag which we can now
fill in. Avoid filling in a cross reference to ourselves,
because that would lead to circular debugging information. */
if (! self_crossref)
{
register struct stab_tag **pst;
for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
{
if ((*pst)->name[0] == name[0]
&& strcmp ((*pst)->name, name) == 0)
{
(*pst)->slot = dtype;
*pst = (*pst)->next;
break;
}
}
}
if (synonym)
{
dtype = debug_name_type (dhandle, name, dtype);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (slot != NULL)
*slot = dtype;
}
break;
case 'V':
/* Static symbol of local scope */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
/* FIXME: gdb checks os9k_stabs here. */
if (! stab_record_variable (dhandle, info, name, dtype,
DEBUG_LOCAL_STATIC, value))
return false;
break;
case 'v':
/* Reference parameter. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
value))
return false;
break;
case 'a':
/* Reference parameter which is in a register. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
value))
return false;
break;
case 'X':
/* This is used by Sun FORTRAN for "function result value".
Sun claims ("dbx and dbxtool interfaces", 2nd ed)
that Pascal uses it too, but when I tried it Pascal used
"x:3" (local symbol) instead. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return false;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
value))
return false;
break;
default:
bad_stab (string);
return false;
}
/* FIXME: gdb converts structure values to structure pointers in a
couple of cases, depending upon the target. */
return true;
}
/* Parse a stabs type. The typename argument is non-NULL if this is a
typedef or a tag definition. The pp argument points to the stab
string, and is updated. The slotp argument points to a place to
store the slot used if the type is being defined. */
static debug_type
parse_stab_type (dhandle, info, typename, pp, slotp)
PTR dhandle;
struct stab_handle *info;
const char *typename;
const char **pp;
debug_type **slotp;
{
const char *orig;
int typenums[2];
int size;
bfd_boolean stringp;
int descriptor;
debug_type dtype;
if (slotp != NULL)
*slotp = NULL;
orig = *pp;
size = -1;
stringp = false;
info->self_crossref = false;
/* Read type number if present. The type number may be omitted.
for instance in a two-dimensional array declared with type
"ar1;1;10;ar1;1;10;4". */
if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-')
{
/* 'typenums=' not present, type is anonymous. Read and return
the definition, but don't put it in the type vector. */
typenums[0] = typenums[1] = -1;
}
else
{
if (! parse_stab_type_number (pp, typenums))
return DEBUG_TYPE_NULL;
if (**pp != '=')
{
/* Type is not being defined here. Either it already
exists, or this is a forward reference to it. */
return stab_find_type (dhandle, info, typenums);
}
/* Only set the slot if the type is being defined. This means
that the mapping from type numbers to types will only record
the name of the typedef which defines a type. If we don't do
this, then something like
typedef int foo;
int i;
will record that i is of type foo. Unfortunately, stabs
information is ambiguous about variable types. For this code,
typedef int foo;
int i;
foo j;
the stabs information records both i and j as having the same
type. This could be fixed by patching the compiler. */
if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0)
*slotp = stab_find_slot (info, typenums);
/* Type is being defined here. */
/* Skip the '='. */
++*pp;
while (**pp == '@')
{
const char *p = *pp + 1;
const char *attr;
if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
{
/* Member type. */
break;
}
/* Type attributes. */
attr = p;
for (; *p != ';'; ++p)
{
if (*p == '\0')
{
bad_stab (orig);
return DEBUG_TYPE_NULL;
}
}
*pp = p + 1;
switch (*attr)
{
case 's':
size = atoi (attr + 1);
size /= 8; /* Size is in bits. We store it in bytes. */
if (size <= 0)
size = -1;
break;
case 'S':
stringp = true;
break;
default:
/* Ignore unrecognized type attributes, so future
compilers can invent new ones. */
break;
}
}
}
descriptor = **pp;
++*pp;
switch (descriptor)
{
case 'x':
{
enum debug_type_kind code;
const char *q1, *q2, *p;
/* A cross reference to another type. */
switch (**pp)
{
case 's':
code = DEBUG_KIND_STRUCT;
break;
case 'u':
code = DEBUG_KIND_UNION;
break;
case 'e':
code = DEBUG_KIND_ENUM;
break;
default:
/* Complain and keep going, so compilers can invent new
cross-reference types. */
warn_stab (orig, _("unrecognized cross reference type"));
code = DEBUG_KIND_STRUCT;
break;
}
++*pp;
q1 = strchr (*pp, '<');
p = strchr (*pp, ':');
if (p == NULL)
{
bad_stab (orig);
return DEBUG_TYPE_NULL;
}
if (q1 != NULL && p > q1 && p[1] == ':')
{
int nest = 0;
for (q2 = q1; *q2 != '\0'; ++q2)
{
if (*q2 == '<')
++nest;
else if (*q2 == '>')
--nest;
else if (*q2 == ':' && nest == 0)
break;
}
p = q2;
if (*p != ':')
{
bad_stab (orig);
return DEBUG_TYPE_NULL;
}
}
/* Some versions of g++ can emit stabs like
fleep:T20=xsfleep:
which define structures in terms of themselves. We need to
tell the caller to avoid building a circular structure. */
if (typename != NULL
&& strncmp (typename, *pp, p - *pp) == 0
&& typename[p - *pp] == '\0')
info->self_crossref = true;
dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
*pp = p + 1;
}
break;
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '(':
{
const char *hold;
int xtypenums[2];
/* This type is defined as another type. */
(*pp)--;
hold = *pp;
/* Peek ahead at the number to detect void. */
if (! parse_stab_type_number (pp, xtypenums))
return DEBUG_TYPE_NULL;
if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
{
/* This type is being defined as itself, which means that
it is void. */
dtype = debug_make_void_type (dhandle);
}
else
{
*pp = hold;
/* Go back to the number and have parse_stab_type get it.
This means that we can deal with something like
t(1,2)=(3,4)=... which the Lucid compiler uses. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL,
pp, (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
}
if (typenums[0] != -1)
{
if (! stab_record_type (dhandle, info, typenums, dtype))
return DEBUG_TYPE_NULL;
}
break;
}
case '*':
dtype = debug_make_pointer_type (dhandle,
parse_stab_type (dhandle, info,
(const char *) NULL,
pp,
(debug_type **) NULL));
break;
case '&':
/* Reference to another type. */
dtype = (debug_make_reference_type
(dhandle,
parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL)));
break;
case 'f':
/* Function returning another type. */
/* FIXME: gdb checks os9k_stabs here. */
dtype = (debug_make_function_type
(dhandle,
parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL),
(debug_type *) NULL, false));
break;
case 'k':
/* Const qualifier on some type (Sun). */
/* FIXME: gdb accepts 'c' here if os9k_stabs. */
dtype = debug_make_const_type (dhandle,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -