perf probe: Support "string" type
Support string type casting to event argument. If perf-probe finds an argument casted as string, it ensures the target variable is "(unsigned/signed) char *(or []). perf-probe also adds dereference if the target is a pointer. So, both of 'char buf[10];' and 'char *buf;' can be accessed by 'buf:string' Cc: Ingo Molnar <mingo@elte.hu> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20100519195734.2885.1666.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
e09c8614b3
commit
73317b9540
@@ -464,18 +464,61 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf)
|
||||
}
|
||||
|
||||
static int convert_variable_type(Dwarf_Die *vr_die,
|
||||
struct kprobe_trace_arg *targ)
|
||||
struct kprobe_trace_arg *tvar,
|
||||
const char *cast)
|
||||
{
|
||||
struct kprobe_trace_arg_ref **ref_ptr = &tvar->ref;
|
||||
Dwarf_Die type;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
/* TODO: check all types */
|
||||
if (cast && strcmp(cast, "string") != 0) {
|
||||
/* Non string type is OK */
|
||||
tvar->type = strdup(cast);
|
||||
return (tvar->type == NULL) ? -ENOMEM : 0;
|
||||
}
|
||||
|
||||
if (die_get_real_type(vr_die, &type) == NULL) {
|
||||
pr_warning("Failed to get a type information of %s.\n",
|
||||
dwarf_diename(vr_die));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (cast && strcmp(cast, "string") == 0) { /* String type */
|
||||
ret = dwarf_tag(&type);
|
||||
if (ret != DW_TAG_pointer_type &&
|
||||
ret != DW_TAG_array_type) {
|
||||
pr_warning("Failed to cast into string: "
|
||||
"%s(%s) is not a pointer nor array.",
|
||||
dwarf_diename(vr_die), dwarf_diename(&type));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ret == DW_TAG_pointer_type) {
|
||||
if (die_get_real_type(&type, &type) == NULL) {
|
||||
pr_warning("Failed to get a type information.");
|
||||
return -ENOENT;
|
||||
}
|
||||
while (*ref_ptr)
|
||||
ref_ptr = &(*ref_ptr)->next;
|
||||
/* Add new reference with offset +0 */
|
||||
*ref_ptr = zalloc(sizeof(struct kprobe_trace_arg_ref));
|
||||
if (*ref_ptr == NULL) {
|
||||
pr_warning("Out of memory error\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
if (die_compare_name(&type, "char") != 0 &&
|
||||
die_compare_name(&type, "unsigned char") != 0) {
|
||||
pr_warning("Failed to cast into string: "
|
||||
"%s is not (unsigned) char *.",
|
||||
dwarf_diename(vr_die));
|
||||
return -EINVAL;
|
||||
}
|
||||
tvar->type = strdup(cast);
|
||||
return (tvar->type == NULL) ? -ENOMEM : 0;
|
||||
}
|
||||
|
||||
ret = die_get_byte_size(&type) * 8;
|
||||
if (ret) {
|
||||
/* Check the bitwidth */
|
||||
@@ -495,8 +538,8 @@ static int convert_variable_type(Dwarf_Die *vr_die,
|
||||
strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
targ->type = strdup(buf);
|
||||
if (targ->type == NULL)
|
||||
tvar->type = strdup(buf);
|
||||
if (tvar->type == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
@@ -606,14 +649,8 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
|
||||
&die_mem);
|
||||
vr_die = &die_mem;
|
||||
}
|
||||
if (ret == 0) {
|
||||
if (pf->pvar->type) {
|
||||
pf->tvar->type = strdup(pf->pvar->type);
|
||||
if (pf->tvar->type == NULL)
|
||||
ret = -ENOMEM;
|
||||
} else
|
||||
ret = convert_variable_type(vr_die, pf->tvar);
|
||||
}
|
||||
if (ret == 0)
|
||||
ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
|
||||
/* *expr will be cached in libdw. Don't free it. */
|
||||
return ret;
|
||||
error:
|
||||
|
Reference in New Issue
Block a user