tools lib traceevent: Let function symbols be used in operations
The preemptirq events records only 32 bits for the locations of where the
events occur. It records the offset from _stext to do so. But the
libtraceevent does not handle function names in operations to add offsets
to.
Have the eval_num_arg() check if the value found is zero and then check if
it is a string. If it is a string value, check if that string matches any
function. If it does, then evaluate the function symbol and replace the
value with the actual number to complete the calculation.
Link: http://lore.kernel.org/linux-trace-devel/20200708203017.319177062@goodmis.org
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=205953
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
diff --git a/lib/traceevent/event-parse.c b/lib/traceevent/event-parse.c
index ee16be9..77c3249 100644
--- a/lib/traceevent/event-parse.c
+++ b/lib/traceevent/event-parse.c
@@ -3649,6 +3649,50 @@
return event;
}
+static unsigned long long test_for_symbol(struct tep_handle *tep,
+ struct tep_print_arg *arg)
+{
+ unsigned long long val = 0;
+ struct func_list *item = tep->funclist;
+ char *func;
+ int i;
+
+ if (isdigit(arg->atom.atom[0]))
+ return 0;
+
+ /* Linear search but only happens once (see after the loop) */
+ for (i = 0; i < (int)tep->func_count; i++) {
+ unsigned long long addr;
+ const char *name;
+
+ if (tep->func_map) {
+ addr = tep->func_map[i].addr;
+ name = tep->func_map[i].func;
+ } else if (item) {
+ addr = item->addr;
+ name = item->func;
+ item = item->next;
+ } else
+ break;
+
+ if (strcmp(arg->atom.atom, name) == 0) {
+ val = addr;
+ break;
+ }
+ }
+
+ /*
+ * This modifies the arg to hardcode the value
+ * and will not loop again.
+ */
+ func = realloc(arg->atom.atom, 32);
+ if (func) {
+ snprintf(func, 32, "%lld", val);
+ arg->atom.atom = func;
+ }
+ return val;
+}
+
static unsigned long long
eval_num_arg(void *data, int size, struct tep_event *event, struct tep_print_arg *arg)
{
@@ -3665,7 +3709,10 @@
/* ?? */
return 0;
case TEP_PRINT_ATOM:
- return strtoull(arg->atom.atom, NULL, 0);
+ val = strtoull(arg->atom.atom, NULL, 0);
+ if (!val)
+ val = test_for_symbol(tep, arg);
+ return val;
case TEP_PRINT_FIELD:
if (!arg->field.field) {
arg->field.field = tep_find_any_field(event, arg->field.name);