diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-30 11:15:14 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-30 11:15:14 -0800 |
commit | d8b91dde38f4c43bd0bbbf17a90f735b16aaff2c (patch) | |
tree | bd72dabf6e4b23e060fce429c87e60504f69de54 /tools/lib | |
parent | 5e7481a25e90b661d1dbbba18be3fd3dfe12ec6f (diff) | |
parent | e4c1091cb495d9cbec8956d642644a71a1689958 (diff) |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar:
"Kernel side changes:
- Clean up the x86 instruction decoder (Masami Hiramatsu)
- Add new uprobes optimization for PUSH instructions on x86 (Yonghong
Song)
- Add MSR_IA32_THERM_STATUS to the MSR events (Stephane Eranian)
- Fix misc bugs, update documentation, plus various cleanups (Jiri
Olsa)
There's a large number of tooling side improvements:
- Intel-PT/BTS improvements (Adrian Hunter)
- Numerous 'perf trace' improvements (Arnaldo Carvalho de Melo)
- Introduce an errno code to string facility (Hendrik Brueckner)
- Various build system improvements (Jiri Olsa)
- Add support for CoreSight trace decoding by making the perf tools
use the external openCSD (Mathieu Poirier, Tor Jeremiassen)
- Add ARM Statistical Profiling Extensions (SPE) support (Kim
Phillips)
- libtraceevent updates (Steven Rostedt)
- Intel vendor event JSON updates (Andi Kleen)
- Introduce 'perf report --mmaps' and 'perf report --tasks' to show
info present in 'perf.data' (Jiri Olsa, Arnaldo Carvalho de Melo)
- Add infrastructure to record first and last sample time to the
perf.data file header, so that when processing all samples in a
'perf record' session, such as when doing build-id processing, or
when specifically requesting that that info be recorded, use that
in 'perf report --time', that also got support for percent slices
in addition to absolute ones.
I.e. now it is possible to ask for the samples in the 10%-20% time
slice of a perf.data file (Jin Yao)
- Allow system wide 'perf stat --per-thread', sorting the result (Jin
Yao)
E.g.:
[root@jouet ~]# perf stat --per-thread --metrics IPC
^C
Performance counter stats for 'system wide':
make-22229 23,012,094,032 inst_retired.any # 0.8 IPC
cc1-22419 692,027,497 inst_retired.any # 0.8 IPC
gcc-22418 328,231,855 inst_retired.any # 0.9 IPC
cc1-22509 220,853,647 inst_retired.any # 0.8 IPC
gcc-22486 199,874,810 inst_retired.any # 1.0 IPC
as-22466 177,896,365 inst_retired.any # 0.9 IPC
cc1-22465 150,732,374 inst_retired.any # 0.8 IPC
gcc-22508 112,555,593 inst_retired.any # 0.9 IPC
cc1-22487 108,964,079 inst_retired.any # 0.7 IPC
qemu-system-x86-2697 21,330,550 inst_retired.any # 0.3 IPC
systemd-journal-551 20,642,951 inst_retired.any # 0.4 IPC
docker-containe-17651 9,552,892 inst_retired.any # 0.5 IPC
dockerd-current-9809 7,528,586 inst_retired.any # 0.5 IPC
make-22153 12,504,194,380 inst_retired.any # 0.8 IPC
python2-22429 12,081,290,954 inst_retired.any # 0.8 IPC
<SNIP>
python2-22429 15,026,328,103 cpu_clk_unhalted.thread
cc1-22419 826,660,193 cpu_clk_unhalted.thread
gcc-22418 365,321,295 cpu_clk_unhalted.thread
cc1-22509 279,169,362 cpu_clk_unhalted.thread
gcc-22486 210,156,950 cpu_clk_unhalted.thread
<SNIP>
5.638075538 seconds time elapsed
[root@jouet ~]#
- Improve shell auto-completion of perf events (Jin Yao)
- 'perf probe' improvements (Masami Hiramatsu)
- Improve PMU infrastructure to support amp64's ThunderX2
implementation defined core events (Ganapatrao Kulkarni)
- Various annotation related improvements and fixes (Thomas Richter)
- Clarify usage of 'overwrite' and 'backward' in the evlist/mmap
code, removing the 'overwrite' parameter from several functions as
it was always used it as 'false' (Wang Nan)
- Fix/improve 'perf record' reverse recording support (Wang Nan)
- Improve command line options documentation (Sihyeon Jang)
- Optimize sample parsing for ordering events, where we don't need to
parse all the PERF_SAMPLE_ bits, just the ones leading to the
timestamp needed to reorder events (Jiri Olsa)
- Generalize the annotation code to support other source information
besides objdump/DWARF obtained ones, starting with python scripts,
that will is slated to be merged soon (Jiri Olsa)
- ... and a lot more that I failed to list, see the shortlog and
changelog for details"
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (262 commits)
perf trace beauty flock: Move to separate object file
perf evlist: Remove fcntl.h from evlist.h
perf trace beauty futex: Beautify FUTEX_BITSET_MATCH_ANY
perf trace: Do not print from time delta for interrupted syscall lines
perf trace: Add --print-sample
perf bpf: Remove misplaced __maybe_unused attribute
MAINTAINERS: Adding entry for CoreSight trace decoding
perf tools: Add mechanic to synthesise CoreSight trace packets
perf tools: Add full support for CoreSight trace decoding
pert tools: Add queue management functionality
perf tools: Add functionality to communicate with the openCSD decoder
perf tools: Add support for decoding CoreSight trace data
perf tools: Add decoder mechanic to support dumping trace data
perf tools: Add processing of coresight metadata
perf tools: Add initial entry point for decoder CoreSight traces
perf tools: Integrating the CoreSight decoding library
perf vendor events intel: Update IvyTown files to V20
perf vendor events intel: Update IvyBridge files to V20
perf vendor events intel: Update BroadwellDE events to V7
perf vendor events intel: Update SkylakeX events to V1.06
...
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/traceevent/event-parse.c | 62 | ||||
-rw-r--r-- | tools/lib/traceevent/event-plugin.c | 24 | ||||
-rw-r--r-- | tools/lib/traceevent/kbuffer-parse.c | 4 | ||||
-rw-r--r-- | tools/lib/traceevent/parse-filter.c | 22 |
4 files changed, 76 insertions, 36 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 7ce724fc0544..e5f2acbb70cc 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -1094,7 +1094,7 @@ static enum event_type __read_token(char **tok) if (strcmp(*tok, "LOCAL_PR_FMT") == 0) { free(*tok); *tok = NULL; - return force_token("\"\%s\" ", tok); + return force_token("\"%s\" ", tok); } else if (strcmp(*tok, "STA_PR_FMT") == 0) { free(*tok); *tok = NULL; @@ -3970,6 +3970,11 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, val &= ~fval; } } + if (val) { + if (print && arg->flags.delim) + trace_seq_puts(s, arg->flags.delim); + trace_seq_printf(s, "0x%llx", val); + } break; case PRINT_SYMBOL: val = eval_num_arg(data, size, event, arg->symbol.field); @@ -3980,6 +3985,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, break; } } + if (!flag) + trace_seq_printf(s, "0x%llx", val); break; case PRINT_HEX: case PRINT_HEX_STR: @@ -4293,6 +4300,26 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc goto process_again; case 'p': ls = 1; + if (isalnum(ptr[1])) { + ptr++; + /* Check for special pointers */ + switch (*ptr) { + case 's': + case 'S': + case 'f': + case 'F': + break; + default: + /* + * Older kernels do not process + * dereferenced pointers. + * Only process if the pointer + * value is a printable. + */ + if (isprint(*(char *)bptr)) + goto process_string; + } + } /* fall through */ case 'd': case 'u': @@ -4345,6 +4372,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc break; case 's': + process_string: arg = alloc_arg(); if (!arg) { do_warning_event(event, "%s(%d): not enough memory!", @@ -4949,21 +4977,27 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event else ls = 2; - if (*(ptr+1) == 'F' || *(ptr+1) == 'f' || - *(ptr+1) == 'S' || *(ptr+1) == 's') { + if (isalnum(ptr[1])) ptr++; + + if (arg->type == PRINT_BSTRING) { + trace_seq_puts(s, arg->string.string); + break; + } + + if (*ptr == 'F' || *ptr == 'f' || + *ptr == 'S' || *ptr == 's') { show_func = *ptr; - } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') { - print_mac_arg(s, *(ptr+1), data, size, event, arg); - ptr++; + } else if (*ptr == 'M' || *ptr == 'm') { + print_mac_arg(s, *ptr, data, size, event, arg); arg = arg->next; break; - } else if (*(ptr+1) == 'I' || *(ptr+1) == 'i') { + } else if (*ptr == 'I' || *ptr == 'i') { int n; - n = print_ip_arg(s, ptr+1, data, size, event, arg); + n = print_ip_arg(s, ptr, data, size, event, arg); if (n > 0) { - ptr += n; + ptr += n - 1; arg = arg->next; break; } @@ -5532,8 +5566,14 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s, event = pevent_find_event_by_record(pevent, record); if (!event) { - do_warning("ug! no event found for type %d", - trace_parse_common_type(pevent, record->data)); + int i; + int type = trace_parse_common_type(pevent, record->data); + + do_warning("ug! no event found for type %d", type); + trace_seq_printf(s, "[UNKNOWN TYPE %d]", type); + for (i = 0; i < record->size; i++) + trace_seq_printf(s, " %02x", + ((unsigned char *)record->data)[i]); return; } diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index a16756ae3526..d542cb60ca1a 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -120,12 +120,12 @@ char **traceevent_plugin_list_options(void) for (op = reg->options; op->name; op++) { char *alias = op->plugin_alias ? op->plugin_alias : op->file; char **temp = list; + int ret; - name = malloc(strlen(op->name) + strlen(alias) + 2); - if (!name) + ret = asprintf(&name, "%s:%s", alias, op->name); + if (ret < 0) goto err; - sprintf(name, "%s:%s", alias, op->name); list = realloc(list, count + 2); if (!list) { list = temp; @@ -290,17 +290,14 @@ load_plugin(struct pevent *pevent, const char *path, const char *alias; char *plugin; void *handle; + int ret; - plugin = malloc(strlen(path) + strlen(file) + 2); - if (!plugin) { + ret = asprintf(&plugin, "%s/%s", path, file); + if (ret < 0) { warning("could not allocate plugin memory\n"); return; } - strcpy(plugin, path); - strcat(plugin, "/"); - strcat(plugin, file); - handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL); if (!handle) { warning("could not load plugin '%s'\n%s\n", @@ -391,6 +388,7 @@ load_plugins(struct pevent *pevent, const char *suffix, char *home; char *path; char *envdir; + int ret; if (pevent->flags & PEVENT_DISABLE_PLUGINS) return; @@ -421,16 +419,12 @@ load_plugins(struct pevent *pevent, const char *suffix, if (!home) return; - path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2); - if (!path) { + ret = asprintf(&path, "%s/%s", home, LOCAL_PLUGIN_DIR); + if (ret < 0) { warning("could not allocate plugin memory\n"); return; } - strcpy(path, home); - strcat(path, "/"); - strcat(path, LOCAL_PLUGIN_DIR); - load_plugins_dir(pevent, suffix, path, load_plugin, data); free(path); diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c index c94e3641b046..ca424b157e46 100644 --- a/tools/lib/traceevent/kbuffer-parse.c +++ b/tools/lib/traceevent/kbuffer-parse.c @@ -24,8 +24,8 @@ #include "kbuffer.h" -#define MISSING_EVENTS (1 << 31) -#define MISSING_STORED (1 << 30) +#define MISSING_EVENTS (1UL << 31) +#define MISSING_STORED (1UL << 30) #define COMMIT_MASK ((1 << 27) - 1) diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 315df0a70265..431e8b309f6e 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -287,12 +287,10 @@ find_event(struct pevent *pevent, struct event_list **events, sys_name = NULL; } - reg = malloc(strlen(event_name) + 3); - if (reg == NULL) + ret = asprintf(®, "^%s$", event_name); + if (ret < 0) return PEVENT_ERRNO__MEM_ALLOC_FAILED; - sprintf(reg, "^%s$", event_name); - ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB); free(reg); @@ -300,13 +298,12 @@ find_event(struct pevent *pevent, struct event_list **events, return PEVENT_ERRNO__INVALID_EVENT_NAME; if (sys_name) { - reg = malloc(strlen(sys_name) + 3); - if (reg == NULL) { + ret = asprintf(®, "^%s$", sys_name); + if (ret < 0) { regfree(&ereg); return PEVENT_ERRNO__MEM_ALLOC_FAILED; } - sprintf(reg, "^%s$", sys_name); ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB); free(reg); if (ret) { @@ -1634,6 +1631,7 @@ int pevent_filter_clear_trivial(struct event_filter *filter, case FILTER_TRIVIAL_FALSE: if (filter_type->filter->boolean.value) continue; + break; case FILTER_TRIVIAL_TRUE: if (!filter_type->filter->boolean.value) continue; @@ -1879,17 +1877,25 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r struct pevent *pevent; unsigned long long addr; const char *val = NULL; + unsigned int size; char hex[64]; /* If the field is not a string convert it */ if (arg->str.field->flags & FIELD_IS_STRING) { val = record->data + arg->str.field->offset; + size = arg->str.field->size; + + if (arg->str.field->flags & FIELD_IS_DYNAMIC) { + addr = *(unsigned int *)val; + val = record->data + (addr & 0xffff); + size = addr >> 16; + } /* * We need to copy the data since we can't be sure the field * is null terminated. */ - if (*(val + arg->str.field->size - 1)) { + if (*(val + size - 1)) { /* copy it */ memcpy(arg->str.buffer, val, arg->str.field->size); /* the buffer is already NULL terminated */ |