summaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/evsel.c30
-rw-r--r--tools/perf/util/include/linux/kernel.h10
-rw-r--r--tools/perf/util/parse-events-test.c76
-rw-r--r--tools/perf/util/parse-events.c194
-rw-r--r--tools/perf/util/parse-events.l5
-rw-r--r--tools/perf/util/parse-events.y15
-rw-r--r--tools/perf/util/pmu.c3
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c4
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/symbol.c29
10 files changed, 275 insertions, 95 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3d1f696..e817713 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,6 +15,7 @@
#include "cpumap.h"
#include "thread_map.h"
#include "target.h"
+#include "../../../include/linux/hw_breakpoint.h"
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -152,6 +153,31 @@ static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
}
+static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
+{
+ int r;
+
+ r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
+
+ if (type & HW_BREAKPOINT_R)
+ r += scnprintf(bf + r, size - r, "r");
+
+ if (type & HW_BREAKPOINT_W)
+ r += scnprintf(bf + r, size - r, "w");
+
+ if (type & HW_BREAKPOINT_X)
+ r += scnprintf(bf + r, size - r, "x");
+
+ return r;
+}
+
+static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+ struct perf_event_attr *attr = &evsel->attr;
+ int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
+ return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
+}
+
const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
[PERF_EVSEL__MAX_ALIASES] = {
{ "L1-dcache", "l1-d", "l1d", "L1-data", },
@@ -285,6 +311,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
break;
+ case PERF_TYPE_BREAKPOINT:
+ perf_evsel__bp_name(evsel, bf, sizeof(bf));
+ break;
+
default:
scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
break;
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index 1eb804f..b6842c1 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -108,4 +108,14 @@ int eprintf(int level,
#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
#endif
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index a0f61a2..1b997d2 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
return 0;
}
+static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type",
+ PERF_TYPE_BREAKPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong bp_type",
+ (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
+ TEST_ASSERT_VAL("wrong bp_len",
+ HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+ return 0;
+}
+
static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
{
struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong name",
+ !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
return test__checkevent_breakpoint(evlist);
}
@@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong name",
+ !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
return test__checkevent_breakpoint_x(evlist);
}
@@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong name",
+ !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
return test__checkevent_breakpoint_r(evlist);
}
@@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong name",
+ !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
return test__checkevent_breakpoint_w(evlist);
}
+static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+ TEST_ASSERT_VAL("wrong name",
+ !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
+
+ return test__checkevent_breakpoint_rw(evlist);
+}
+
static int test__checkevent_pmu(struct perf_evlist *evlist)
{
@@ -585,10 +624,16 @@ static struct test__event_st test__events[] = {
.name = "instructions:H",
.check = test__checkevent_exclude_guest_modifier,
},
+ [26] = {
+ .name = "mem:0:rw",
+ .check = test__checkevent_breakpoint_rw,
+ },
+ [27] = {
+ .name = "mem:0:rw:kp",
+ .check = test__checkevent_breakpoint_rw_modifier,
+ },
};
-#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
-
static struct test__event_st test__events_pmu[] = {
[0] = {
.name = "cpu/config=10,config1,config2=3,period=1000/u",
@@ -600,9 +645,6 @@ static struct test__event_st test__events_pmu[] = {
},
};
-#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \
- sizeof(struct test__event_st))
-
struct test__term {
const char *str;
__u32 type;
@@ -718,21 +760,17 @@ int parse_events__test(void)
{
int ret;
- do {
- ret = test_events(test__events, TEST__EVENTS_CNT);
- if (ret)
- break;
-
- if (test_pmu()) {
- ret = test_events(test__events_pmu,
- TEST__EVENTS_PMU_CNT);
- if (ret)
- break;
- }
+#define TEST_EVENTS(tests) \
+do { \
+ ret = test_events(tests, ARRAY_SIZE(tests)); \
+ if (ret) \
+ return ret; \
+} while (0)
- ret = test_terms(test__terms, TEST__TERMS_CNT);
+ TEST_EVENTS(test__events);
- } while (0);
+ if (test_pmu())
+ TEST_EVENTS(test__events_pmu);
- return ret;
+ return test_terms(test__terms, ARRAY_SIZE(test__terms));
}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 0cc27da..1aa721d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -19,8 +19,6 @@
#define MAX_NAME_LEN 100
struct event_symbol {
- u8 type;
- u64 config;
const char *symbol;
const char *alias;
};
@@ -30,30 +28,86 @@ extern int parse_events_debug;
#endif
int parse_events_parse(void *data, void *scanner);
-#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
-#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
-
-static struct event_symbol event_symbols[] = {
- { CHW(CPU_CYCLES), "cpu-cycles", "cycles" },
- { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" },
- { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" },
- { CHW(INSTRUCTIONS), "instructions", "" },
- { CHW(CACHE_REFERENCES), "cache-references", "" },
- { CHW(CACHE_MISSES), "cache-misses", "" },
- { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
- { CHW(BRANCH_MISSES), "branch-misses", "" },
- { CHW(BUS_CYCLES), "bus-cycles", "" },
- { CHW(REF_CPU_CYCLES), "ref-cycles", "" },
-
- { CSW(CPU_CLOCK), "cpu-clock", "" },
- { CSW(TASK_CLOCK), "task-clock", "" },
- { CSW(PAGE_FAULTS), "page-faults", "faults" },
- { CSW(PAGE_FAULTS_MIN), "minor-faults", "" },
- { CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
- { CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
- { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
- { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" },
- { CSW(EMULATION_FAULTS), "emulation-faults", "" },
+static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = {
+ .symbol = "cpu-cycles",
+ .alias = "cycles",
+ },
+ [PERF_COUNT_HW_INSTRUCTIONS] = {
+ .symbol = "instructions",
+ .alias = "",
+ },
+ [PERF_COUNT_HW_CACHE_REFERENCES] = {
+ .symbol = "cache-references",
+ .alias = "",
+ },
+ [PERF_COUNT_HW_CACHE_MISSES] = {
+ .symbol = "cache-misses",
+ .alias = "",
+ },
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
+ .symbol = "branch-instructions",
+ .alias = "branches",
+ },
+ [PERF_COUNT_HW_BRANCH_MISSES] = {
+ .symbol = "branch-misses",
+ .alias = "",
+ },
+ [PERF_COUNT_HW_BUS_CYCLES] = {
+ .symbol = "bus-cycles",
+ .alias = "",
+ },
+ [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
+ .symbol = "stalled-cycles-frontend",
+ .alias = "idle-cycles-frontend",
+ },
+ [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
+ .symbol = "stalled-cycles-backend",
+ .alias = "idle-cycles-backend",
+ },
+ [PERF_COUNT_HW_REF_CPU_CYCLES] = {
+ .symbol = "ref-cycles",
+ .alias = "",
+ },
+};
+
+static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
+ [PERF_COUNT_SW_CPU_CLOCK] = {
+ .symbol = "cpu-clock",
+ .alias = "",
+ },
+ [PERF_COUNT_SW_TASK_CLOCK] = {
+ .symbol = "task-clock",
+ .alias = "",
+ },
+ [PERF_COUNT_SW_PAGE_FAULTS] = {
+ .symbol = "page-faults",
+ .alias = "faults",
+ },
+ [PERF_COUNT_SW_CONTEXT_SWITCHES] = {
+ .symbol = "context-switches",
+ .alias = "cs",
+ },
+ [PERF_COUNT_SW_CPU_MIGRATIONS] = {
+ .symbol = "cpu-migrations",
+ .alias = "migrations",
+ },
+ [PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
+ .symbol = "minor-faults",
+ .alias = "",
+ },
+ [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
+ .symbol = "major-faults",
+ .alias = "",
+ },
+ [PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
+ .symbol = "alignment-faults",
+ .alias = "",
+ },
+ [PERF_COUNT_SW_EMULATION_FAULTS] = {
+ .symbol = "emulation-faults",
+ .alias = "",
+ },
};
#define __PERF_EVENT_FIELD(config, name) \
@@ -383,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
if (!type || !type[i])
break;
+#define CHECK_SET_TYPE(bit) \
+do { \
+ if (attr->bp_type & bit) \
+ return -EINVAL; \
+ else \
+ attr->bp_type |= bit; \
+} while (0)
+
switch (type[i]) {
case 'r':
- attr->bp_type |= HW_BREAKPOINT_R;
+ CHECK_SET_TYPE(HW_BREAKPOINT_R);
break;
case 'w':
- attr->bp_type |= HW_BREAKPOINT_W;
+ CHECK_SET_TYPE(HW_BREAKPOINT_W);
break;
case 'x':
- attr->bp_type |= HW_BREAKPOINT_X;
+ CHECK_SET_TYPE(HW_BREAKPOINT_X);
break;
default:
return -EINVAL;
}
}
+#undef CHECK_SET_TYPE
+
if (!attr->bp_type) /* Default */
attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
@@ -408,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type)
{
struct perf_event_attr attr;
- char name[MAX_NAME_LEN];
memset(&attr, 0, sizeof(attr));
attr.bp_addr = (unsigned long) ptr;
@@ -427,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
attr.type = PERF_TYPE_BREAKPOINT;
- snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw");
- return add_event(list, idx, &attr, name);
+ return add_event(list, idx, &attr, NULL);
}
static int config_term(struct perf_event_attr *attr,
@@ -816,16 +878,13 @@ int is_valid_tracepoint(const char *event_string)
return 0;
}
-void print_events_type(u8 type)
+static void __print_events_type(u8 type, struct event_symbol *syms,
+ unsigned max)
{
- struct event_symbol *syms = event_symbols;
- unsigned int i;
char name[64];
+ unsigned i;
- for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
- if (type != syms->type)
- continue;
-
+ for (i = 0; i < max ; i++, syms++) {
if (strlen(syms->alias))
snprintf(name, sizeof(name), "%s OR %s",
syms->symbol, syms->alias);
@@ -837,6 +896,14 @@ void print_events_type(u8 type)
}
}
+void print_events_type(u8 type)
+{
+ if (type == PERF_TYPE_SOFTWARE)
+ __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
+ else
+ __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
+}
+
int print_hwcache_events(const char *event_glob)
{
unsigned int type, op, i, printed = 0;
@@ -864,26 +931,13 @@ int print_hwcache_events(const char *event_glob)
return printed;
}
-/*
- * Print the help text for the event symbols:
- */
-void print_events(const char *event_glob)
+static void print_symbol_events(const char *event_glob, unsigned type,
+ struct event_symbol *syms, unsigned max)
{
- unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
- struct event_symbol *syms = event_symbols;
+ unsigned i, printed = 0;
char name[MAX_NAME_LEN];
- printf("\n");
- printf("List of pre-defined events (to be used in -e):\n");
-
- for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
- type = syms->type;
-
- if (type != prev_type && printed) {
- printf("\n");
- printed = 0;
- ntypes_printed++;
- }
+ for (i = 0; i < max; i++, syms++) {
if (event_glob != NULL &&
!(strglobmatch(syms->symbol, event_glob) ||
@@ -894,17 +948,31 @@ void print_events(const char *event_glob)
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
else
strncpy(name, syms->symbol, MAX_NAME_LEN);
- printf(" %-50s [%s]\n", name,
- event_type_descriptors[type]);
- prev_type = type;
- ++printed;
+ printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
+
+ printed++;
}
- if (ntypes_printed) {
- printed = 0;
+ if (printed)
printf("\n");
- }
+}
+
+/*
+ * Print the help text for the event symbols:
+ */
+void print_events(const char *event_glob)
+{
+
+ printf("\n");
+ printf("List of pre-defined events (to be used in -e):\n");
+
+ print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
+ event_symbols_hw, PERF_COUNT_HW_MAX);
+
+ print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
+ event_symbols_sw, PERF_COUNT_SW_MAX);
+
print_hwcache_events(event_glob);
if (event_glob != NULL)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 488362e..384ca74 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -56,7 +56,7 @@ static int sym(yyscan_t scanner, int type, int config)
YYSTYPE *yylval = parse_events_get_lval(scanner);
yylval->num = (type << 16) + config;
- return PE_VALUE_SYM;
+ return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
}
static int term(yyscan_t scanner, int type)
@@ -76,7 +76,7 @@ num_hex 0x[a-fA-F0-9]+
num_raw_hex [a-fA-F0-9]+
name [a-zA-Z_*?][a-zA-Z0-9_*?]*
modifier_event [ukhpGH]{1,8}
-modifier_bp [rwx]
+modifier_bp [rwx]{1,3}
%%
@@ -152,6 +152,7 @@ r{num_raw_hex} { return raw(yyscanner); }
, { return ','; }
: { return ':'; }
= { return '='; }
+\n { }
<mem>{
{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 9525c45..2bc5fbf 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -26,14 +26,15 @@ do { \
%}
%token PE_START_EVENTS PE_START_TERMS
-%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM
+%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
%token PE_NAME
%token PE_MODIFIER_EVENT PE_MODIFIER_BP
%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
%token PE_PREFIX_MEM PE_PREFIX_RAW
%token PE_ERROR
%type <num> PE_VALUE
-%type <num> PE_VALUE_SYM
+%type <num> PE_VALUE_SYM_HW
+%type <num> PE_VALUE_SYM_SW
%type <num> PE_RAW
%type <num> PE_TERM
%type <str> PE_NAME
@@ -41,6 +42,7 @@ do { \
%type <str> PE_NAME_CACHE_OP_RESULT
%type <str> PE_MODIFIER_EVENT
%type <str> PE_MODIFIER_BP
+%type <num> value_sym
%type <head> event_config
%type <term> event_term
%type <head> event_pmu
@@ -109,8 +111,13 @@ PE_NAME '/' event_config '/'
$$ = list;
}
+value_sym:
+PE_VALUE_SYM_HW
+|
+PE_VALUE_SYM_SW
+
event_legacy_symbol:
-PE_VALUE_SYM '/' event_config '/'
+value_sym '/' event_config '/'
{
struct parse_events_data__events *data = _data;
struct list_head *list = NULL;
@@ -123,7 +130,7 @@ PE_VALUE_SYM '/' event_config '/'
$$ = list;
}
|
-PE_VALUE_SYM sep_slash_dc
+value_sym sep_slash_dc
{
struct parse_events_data__events *data = _data;
struct list_head *list = NULL;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 74d0948e..67715a4 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
"%s/bus/event_source/devices/%s/format", sysfs, name);
if (stat(path, &st) < 0)
- return -1;
+ return 0; /* no error if format does not exist */
if (pmu_format_parse(path, format))
return -1;
@@ -252,6 +252,7 @@ static struct perf_pmu *pmu_lookup(char *name)
list_splice(&aliases, &pmu->aliases);
pmu->name = strdup(name);
pmu->type = type;
+ list_add_tail(&pmu->list, &pmus);
return pmu;
}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b3620fe..02dfa19 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -209,6 +209,10 @@ static void define_event_symbols(struct event_format *event,
define_symbolic_values(args->symbol.symbols, ev_name,
cur_field_name);
break;
+ case PRINT_HEX:
+ define_event_symbols(event, ev_name, args->hex.field);
+ define_event_symbols(event, ev_name, args->hex.size);
+ break;
case PRINT_BSTRING:
case PRINT_DYNAMIC_ARRAY:
case PRINT_STRING:
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index a8ca2f8..ce4d1b0 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -166,6 +166,10 @@ static void define_event_symbols(struct event_format *event,
define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
cur_field_name);
break;
+ case PRINT_HEX:
+ define_event_symbols(event, ev_name, args->hex.field);
+ define_event_symbols(event, ev_name, args->hex.size);
+ break;
case PRINT_STRING:
break;
case PRINT_TYPE:
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 994f4ff..50958bb 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1478,14 +1478,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
goto out;
}
- sec = elf_section_by_name(elf, &ehdr, &shdr,
- ".note.gnu.build-id", NULL);
- if (sec == NULL) {
+ /*
+ * Check following sections for notes:
+ * '.note.gnu.build-id'
+ * '.notes'
+ * '.note' (VDSO specific)
+ */
+ do {
+ sec = elf_section_by_name(elf, &ehdr, &shdr,
+ ".note.gnu.build-id", NULL);
+ if (sec)
+ break;
+
sec = elf_section_by_name(elf, &ehdr, &shdr,
".notes", NULL);
- if (sec == NULL)
- goto out;
- }
+ if (sec)
+ break;
+
+ sec = elf_section_by_name(elf, &ehdr, &shdr,
+ ".note", NULL);
+ if (sec)
+ break;
+
+ return err;
+
+ } while (0);
data = elf_getdata(sec, NULL);
if (data == NULL)
OpenPOWER on IntegriCloud