perf probe: Fix mis-estimation for shortening filename
[safe/jmp/linux-2.6] / tools / perf / util / parse-events.c
index 9e5dbd6..435781e 100644 (file)
@@ -5,6 +5,7 @@
 #include "parse-events.h"
 #include "exec_cmd.h"
 #include "string.h"
+#include "symbol.h"
 #include "cache.h"
 #include "header.h"
 #include "debugfs.h"
@@ -197,7 +198,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
                        if (id == config) {
                                closedir(evt_dir);
                                closedir(sys_dir);
-                               path = zalloc(sizeof(path));
+                               path = zalloc(sizeof(*path));
                                path->system = malloc(MAX_EVENT_LENGTH);
                                if (!path->system) {
                                        free(path);
@@ -450,7 +451,8 @@ parse_single_tracepoint_event(char *sys_name,
 /* sys + ':' + event + ':' + flags*/
 #define MAX_EVOPT_LEN  (MAX_EVENT_LENGTH * 2 + 2 + 128)
 static enum event_result
-parse_subsystem_tracepoint_event(char *sys_name, char *flags)
+parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
+                               char *flags)
 {
        char evt_path[MAXPATHLEN];
        struct dirent *evt_ent;
@@ -467,7 +469,6 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags)
        while ((evt_ent = readdir(evt_dir))) {
                char event_opt[MAX_EVOPT_LEN + 1];
                int len;
-               unsigned int rem = MAX_EVOPT_LEN;
 
                if (!strcmp(evt_ent->d_name, ".")
                    || !strcmp(evt_ent->d_name, "..")
@@ -475,20 +476,15 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags)
                    || !strcmp(evt_ent->d_name, "filter"))
                        continue;
 
-               len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
-                              evt_ent->d_name);
+               if (!strglobmatch(evt_ent->d_name, evt_exp))
+                       continue;
+
+               len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name,
+                              evt_ent->d_name, flags ? ":" : "",
+                              flags ?: "");
                if (len < 0)
                        return EVT_FAILED;
 
-               rem -= len;
-               if (flags) {
-                       if (rem < strlen(flags) + 1)
-                               return EVT_FAILED;
-
-                       strcat(event_opt, ":");
-                       strcat(event_opt, flags);
-               }
-
                if (parse_events(NULL, event_opt, 0))
                        return EVT_FAILED;
        }
@@ -531,9 +527,10 @@ static enum event_result parse_tracepoint_event(const char **strp,
        if (evt_length >= MAX_EVENT_LENGTH)
                return EVT_FAILED;
 
-       if (!strcmp(evt_name, "*")) {
+       if (strpbrk(evt_name, "*?")) {
                *strp = evt_name + evt_length;
-               return parse_subsystem_tracepoint_event(sys_name, flags);
+               return parse_multiple_tracepoint_event(sys_name, evt_name,
+                                                      flags);
        } else
                return parse_single_tracepoint_event(sys_name, evt_name,
                                                     evt_length, flags,
@@ -660,6 +657,10 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr)
                return EVT_FAILED;
        n = hex2u64(str + 1, &config);
        if (n > 0) {
+               if (str[n+1] == 'p') {
+                       attr->precise = 1;
+                       n++;
+               }
                *strp = str + n + 1;
                attr->type = PERF_TYPE_RAW;
                attr->config = config;
@@ -762,11 +763,11 @@ modifier:
        return ret;
 }
 
-static void store_event_type(const char *orgname)
+static int store_event_type(const char *orgname)
 {
        char filename[PATH_MAX], *c;
        FILE *file;
-       int id;
+       int id, n;
 
        sprintf(filename, "%s/", debugfs_path);
        strncat(filename, orgname, strlen(orgname));
@@ -778,11 +779,14 @@ static void store_event_type(const char *orgname)
 
        file = fopen(filename, "r");
        if (!file)
-               return;
-       if (fscanf(file, "%i", &id) < 1)
-               die("cannot store event ID");
+               return 0;
+       n = fscanf(file, "%i", &id);
        fclose(file);
-       perf_header__push_event(id, orgname);
+       if (n < 1) {
+               pr_err("cannot store event ID\n");
+               return -EINVAL;
+       }
+       return perf_header__push_event(id, orgname);
 }
 
 int parse_events(const struct option *opt __used, const char *str, int unset __used)
@@ -791,7 +795,8 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
        enum event_result ret;
 
        if (strchr(str, ':'))
-               store_event_type(str);
+               if (store_event_type(str) < 0)
+                       return -1;
 
        for (;;) {
                if (nr_counters == MAX_COUNTERS)
@@ -844,11 +849,12 @@ int parse_filter(const struct option *opt __used, const char *str,
 }
 
 static const char * const event_type_descriptors[] = {
-       "",
        "Hardware event",
        "Software event",
        "Tracepoint event",
        "Hardware cache event",
+       "Raw hardware event descriptor",
+       "Hardware breakpoint",
 };
 
 /*
@@ -881,7 +887,7 @@ static void print_tracepoint_events(void)
                        snprintf(evt_path, MAXPATHLEN, "%s:%s",
                                 sys_dirent.d_name, evt_dirent.d_name);
                        printf("  %-42s [%s]\n", evt_path,
-                               event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
+                               event_type_descriptors[PERF_TYPE_TRACEPOINT]);
                }
                closedir(evt_dir);
        }
@@ -901,9 +907,7 @@ void print_events(void)
        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 + 1;
-               if (type >= ARRAY_SIZE(event_type_descriptors))
-                       type = 0;
+               type = syms->type;
 
                if (type != prev_type)
                        printf("\n");
@@ -928,17 +932,19 @@ void print_events(void)
                        for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
                                printf("  %-42s [%s]\n",
                                        event_cache_name(type, op, i),
-                                       event_type_descriptors[4]);
+                                       event_type_descriptors[PERF_TYPE_HW_CACHE]);
                        }
                }
        }
 
        printf("\n");
-       printf("  %-42s [raw hardware event descriptor]\n",
-               "rNNN");
+       printf("  %-42s [%s]\n",
+               "rNNN", event_type_descriptors[PERF_TYPE_RAW]);
        printf("\n");
 
-       printf("  %-42s [hardware breakpoint]\n", "mem:<addr>[:access]");
+       printf("  %-42s [%s]\n",
+                       "mem:<addr>[:access]",
+                       event_type_descriptors[PERF_TYPE_BREAKPOINT]);
        printf("\n");
 
        print_tracepoint_events();