Skip to contentSkip to conversation

perf-probe: Fix to convert array type collectly

PATCH New Masami Hiramatsu 1 participant 1 message Mar 16, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 perf-probe: Fix to convert array type collectly

Fix to convert array element type collectly. Current perf-probe converts the type of array-elements incorrectly. It always converts the types as a pointer of array. This passes the "array" type DIE to the type converter so that it can get correct "element of array" type DIE from it.

E.g.
====

  $ cat hello.c
  #include <stdio.h>

void foo(int a[])

  {
	  printf("%d\n", a[1]);

}

void main()

  {
	  int a[3] = {4, 5, 6};
	  printf("%d\n", a[0]);
	  foo(a);

}

  $ gcc -g hello.c -o hello
  $ perf probe -x ./hello -D "foo a[1]"
  ====

Without this fix, above outputs
====
p:probe_hello/foo /tmp/hello:0x4d3 a=+4(-8(%bp)):u64
====
The "u64" means "int *", but a[1] is "int".

With this,
====
p:probe_hello/foo /tmp/hello:0x4d3 a=+4(-8(%bp)):s32
====
So, "int" correctly converted to "s32"

Fixes b2a3c12b7442 ("perf probe: Support tracing an entry of array")
---
 tools/perf/util/probe-finder.c |   13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)
tools/perf/util/probe-finder.c +5 -8
index a5731de0e5eb..c37fbef1711d 100644
@@ -423,20 +423,20 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
 		pr_warning("Failed to get the type of %s.\n", varname);
 		return -ENOENT;
 	}
-	pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
+	pr_debug2("Var real type: %s (%x)\n", dwarf_diename(&type),
+		  (unsigned)dwarf_dieoffset(&type));
 	tag = dwarf_tag(&type);
 
 	if (field->name[0] == '[' &&
 	    (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
-		if (field->next)
-			/* Save original type for next field */
-			memcpy(die_mem, &type, sizeof(*die_mem));
+		/* Save original type for next field or type */
+		memcpy(die_mem, &type, sizeof(*die_mem));
 		/* Get the type of this array */
 		if (die_get_real_type(&type, &type) == NULL) {
 			pr_warning("Failed to get the type of %s.\n", varname);
 			return -ENOENT;
 		}
-		pr_debug2("Array real type: (%x)\n",
+		pr_debug2("Array real type: %s (%x)\n", dwarf_diename(&type),
 			 (unsigned)dwarf_dieoffset(&type));
 		if (tag == DW_TAG_pointer_type) {
 			ref = zalloc(sizeof(struct probe_trace_arg_ref));
@@ -448,9 +448,6 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
 				*ref_ptr = ref;
 		}
 		ref->offset += dwarf_bytesize(&type) * field->index;
-		if (!field->next)
-			/* Save vr_die for converting types */
-			memcpy(die_mem, vr_die, sizeof(*die_mem));
 		goto next;
 	} else if (tag == DW_TAG_pointer_type) {
 		/* Check the pointer and dereference */