perf probe: Change function definition check due to broken DWARF
[linux-2.6-microblaze.git] / tools / perf / util / dwarf-aux.c
index aa89801..7b2d471 100644 (file)
@@ -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;
 }