When a type is defined as "typedef const struct foo foo_t", dwarf_peel_type() for foo_t loops infinitely. 38 int 39 dwarf_peel_type (Dwarf_Die *die, Dwarf_Die *result) 40 { 41 int tag; 42 43 /* Ignore previous errors. */ 44 if (die == NULL) 45 return -1; 46 47 *result = *die; 48 tag = INTUSE (dwarf_tag) (result); 49 while (tag == DW_TAG_typedef 50 || tag == DW_TAG_const_type 51 || tag == DW_TAG_volatile_type 52 || tag == DW_TAG_restrict_type 53 || tag == DW_TAG_atomic_type) 54 { 55 Dwarf_Attribute attr_mem; 56 Dwarf_Attribute *attr = INTUSE (dwarf_attr_integrate) (die, DW_AT_type, 57 &attr_mem); 58 if (attr == NULL) 59 return 1; 60 61 if (INTUSE (dwarf_formref_die) (attr, result) == NULL) 62 return -1; 63 64 tag = INTUSE (dwarf_tag) (result); 65 } ... dwarf_tag() at line 48 returns DW_TAG_typedef. dwarf_attr_integrate() and dwarf_formref_die() sets DW_AT_type of die to result. dwarf_tag() at line 64 returns DW_TAG_const. dwarf_attr_integrate() and dwarf_formref_die() sets same value to result because the first argument of dwarf_attr_integrate() is unchanged. dwarf_tag() at line 64 returns same value forever.
Oops. That die argument at line 56 to dwarf_attr_integrate () should obviously have been result instead. This looks like it could never have worked. But there are various testcases that should have caught this. Unfortunately all usages in elfutils itself do dwarf_peel_type (die, die). And that invocation works just fine...
Posted a patch: https://sourceware.org/ml/elfutils-devel/2017-q1/msg00149.html
commit f339da994fda25b51cddc3d88182f249b75f89ff Author: Mark Wielaard <mark@klomp.org> Date: Thu Mar 30 12:19:53 2017 +0200 libdw: Fix dwarf_peel_type infinite loop. We were calling dwarf_attr_integrate () in the die in the loop instead of on the result. Which would cause an infinite loop when die != result. Add a testcase that explicitly checks this case. https://sourceware.org/bugzilla/show_bug.cgi?id=21330 Signed-off-by: Mark Wielaard <mark@klomp.org>