Follow DW_AT_specification when looking up DW_AT_type attributes.

dwarf_attrval_*() will search the parent DIE referenced by a
DW_AT_abstract_origin attribute for the value of the DW_AT_type attribute.
Do the same thing for the DW_AT_specification attributes in variable
definitions emitted by GCC 6.2, and ensure that we return an error rather
than crashing if neither DW_AT_abstract_origin or DW_AT_specification is
found when looking for the value of the DW_AT_type attribute.

PR:		215350, 215395
Reviewed by:	emaste
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D8920
This commit is contained in:
Mark Johnston 2016-12-28 21:54:33 +00:00
parent 47abdb10a0
commit 2ef476c9a2
2 changed files with 29 additions and 14 deletions

View File

@ -145,6 +145,7 @@ dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwa
Dwarf_Die die1;
Dwarf_Unsigned val;
Dwarf_Debug dbg;
int first;
dbg = die != NULL ? die->die_dbg : NULL;
@ -155,14 +156,16 @@ dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwa
*valp = 0;
if ((at = _dwarf_attr_find(die, attr)) == NULL && attr != DW_AT_type) {
DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
return (DW_DLV_NO_ENTRY);
}
die1 = NULL;
if (at == NULL &&
(at = _dwarf_attr_find(die, DW_AT_abstract_origin)) != NULL) {
for (;;) {
if ((at = _dwarf_attr_find(die, attr)) != NULL ||
attr != DW_AT_type)
break;
if ((at = _dwarf_attr_find(die, DW_AT_abstract_origin)) ==
NULL &&
(at = _dwarf_attr_find(die, DW_AT_specification)) == NULL)
break;
switch (at->at_form) {
case DW_FORM_ref1:
case DW_FORM_ref2:
@ -170,13 +173,15 @@ dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwa
case DW_FORM_ref8:
case DW_FORM_ref_udata:
val = at->u[0].u64;
if ((die1 = _dwarf_die_find(die, val)) == NULL ||
(at = _dwarf_attr_find(die1, attr)) == NULL) {
if (die1 != NULL)
dwarf_dealloc(dbg, die1, DW_DLA_DIE);
first = (die1 == NULL);
die1 = _dwarf_die_find(die, val);
if (!first)
dwarf_dealloc(dbg, die, DW_DLA_DIE);
if (die1 == NULL) {
DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
return (DW_DLV_NO_ENTRY);
}
die = die1;
break;
default:
DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
@ -184,6 +189,11 @@ dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwa
}
}
if (at == NULL) {
DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
return (DW_DLV_NO_ENTRY);
}
switch (at->at_form) {
case DW_FORM_addr:
case DW_FORM_data1:

View File

@ -24,7 +24,7 @@
.\"
.\" $Id: dwarf_attrval_signed.3 2980 2014-01-21 20:15:54Z kaiwang27 $
.\"
.Dd January 18, 2014
.Dd December 26, 2016
.Os
.Dt DWARF_ATTRVAL_SIGNED 3
.Sh NAME
@ -168,17 +168,22 @@ or
.Pp
If the attribute named by argument
.Ar attr
is not present in the debugging information entry referenced by
argument
is
.Dv DW_AT_type
and is not present in the debugging information entry referenced by argument
.Ar die ,
and if a
.Dv DW_AT_abstract_origin
or
.Dv DW_AT_specification
attribute is present in the debugging information entry,
function
.Fn dwarf_attrval_unsigned
will search for the named attribute in the debugging information entry
referenced by the
.Dv DW_AT_abstract_origin
or
.Dv DW_AT_specification
attribute.
.Sh RETURN VALUES
On success, these functions returns