diff options
Diffstat (limited to 'tools/perf/util/dwarf-aux.c')
| -rw-r--r-- | tools/perf/util/dwarf-aux.c | 28 | 
1 files changed, 26 insertions, 2 deletions
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index aa898014ad12..7b2d471a6419 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -356,9 +356,25 @@ bool die_is_signed_type(Dwarf_Die *tp_die)  bool die_is_func_def(Dwarf_Die *dw_die)  {  	Dwarf_Attribute attr; +	Dwarf_Addr addr = 0; + +	if (dwarf_tag(dw_die) != DW_TAG_subprogram) +		return false; + +	if (dwarf_attr(dw_die, DW_AT_declaration, &attr)) +		return false; -	return (dwarf_tag(dw_die) == DW_TAG_subprogram && -		dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL); +	/* +	 * DW_AT_declaration can be lost from function declaration +	 * by gcc's bug #97060. +	 * So we need to check this subprogram DIE has DW_AT_inline +	 * or an entry address. +	 */ +	if (!dwarf_attr(dw_die, DW_AT_inline, &attr) && +	    die_entrypc(dw_die, &addr) < 0) +		return false; + +	return true;  }  /** @@ -373,6 +389,7 @@ bool die_is_func_def(Dwarf_Die *dw_die)  int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)  {  	Dwarf_Addr base, end; +	Dwarf_Attribute attr;  	if (!addr)  		return -EINVAL; @@ -380,6 +397,13 @@ int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)  	if (dwarf_entrypc(dw_die, addr) == 0)  		return 0; +	/* +	 *  Since the dwarf_ranges() will return 0 if there is no +	 * DW_AT_ranges attribute, we should check it first. +	 */ +	if (!dwarf_attr(dw_die, DW_AT_ranges, &attr)) +		return -ENOENT; +  	return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0;  }  | 
