Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

User visible changes:

- Improve support of compressed kernel modules (Jiri Olsa)

- Add --kallsyms option to 'perf diff' (David Ahern)

- Add pid/tid filtering to 'report' and 'script' commands (David Ahern)

- Add support for __print_array() in libtraceevent (Javi Merino)

- Save DSO loading errno to better report errors (Arnaldo Carvalho de Melo)

- Fix 'probe' to get ummapped symbol address on kernel (Masami Hiramatsu)

- Print big numbers using thousands' group in 'kmem' (Namhyung Kim)

- Remove (null) value of "Sort order" for perf mem report (Yunlong Song)

Infrastructure changes:

- Handle NULL comm name in libtracevent (Josef Bacik)

- Libtraceevent synchronization with trace-cmd repo (Steven Rostedt)

- Work around lack of sched_getcpu() in glibc < 2.6. (Vinson Lee)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

+624 -134
+233 -34
tools/lib/traceevent/event-parse.c
··· 304 304 if (!item) 305 305 return -1; 306 306 307 - item->comm = strdup(comm); 307 + if (comm) 308 + item->comm = strdup(comm); 309 + else 310 + item->comm = strdup("<...>"); 308 311 if (!item->comm) { 309 312 free(item); 310 313 return -1; ··· 321 318 return 0; 322 319 } 323 320 324 - void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock) 321 + int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock) 325 322 { 326 - pevent->trace_clock = trace_clock; 323 + pevent->trace_clock = strdup(trace_clock); 324 + if (!pevent->trace_clock) { 325 + errno = ENOMEM; 326 + return -1; 327 + } 328 + return 0; 327 329 } 328 330 329 331 struct func_map { ··· 765 757 case PRINT_HEX: 766 758 free_arg(arg->hex.field); 767 759 free_arg(arg->hex.size); 760 + break; 761 + case PRINT_INT_ARRAY: 762 + free_arg(arg->int_array.field); 763 + free_arg(arg->int_array.count); 764 + free_arg(arg->int_array.el_size); 768 765 break; 769 766 case PRINT_TYPE: 770 767 free(arg->typecast.type); ··· 2027 2014 return EVENT_ERROR; 2028 2015 } 2029 2016 2017 + static int alloc_and_process_delim(struct event_format *event, char *next_token, 2018 + struct print_arg **print_arg) 2019 + { 2020 + struct print_arg *field; 2021 + enum event_type type; 2022 + char *token; 2023 + int ret = 0; 2024 + 2025 + field = alloc_arg(); 2026 + if (!field) { 2027 + do_warning_event(event, "%s: not enough memory!", __func__); 2028 + errno = ENOMEM; 2029 + return -1; 2030 + } 2031 + 2032 + type = process_arg(event, field, &token); 2033 + 2034 + if (test_type_token(type, token, EVENT_DELIM, next_token)) { 2035 + errno = EINVAL; 2036 + ret = -1; 2037 + free_arg(field); 2038 + goto out_free_token; 2039 + } 2040 + 2041 + *print_arg = field; 2042 + 2043 + out_free_token: 2044 + free_token(token); 2045 + 2046 + return ret; 2047 + } 2048 + 2030 2049 static char *arg_eval (struct print_arg *arg); 2031 2050 2032 2051 static unsigned long long ··· 2531 2486 static enum event_type 2532 2487 process_hex(struct event_format *event, struct print_arg *arg, char **tok) 2533 2488 { 2534 - struct print_arg *field; 2535 - enum event_type type; 2536 - char *token = NULL; 2537 - 2538 2489 memset(arg, 0, sizeof(*arg)); 2539 2490 arg->type = PRINT_HEX; 2540 2491 2541 - field = alloc_arg(); 2542 - if (!field) { 2543 - do_warning_event(event, "%s: not enough memory!", __func__); 2544 - goto out_free; 2545 - } 2492 + if (alloc_and_process_delim(event, ",", &arg->hex.field)) 2493 + goto out; 2546 2494 2547 - type = process_arg(event, field, &token); 2495 + if (alloc_and_process_delim(event, ")", &arg->hex.size)) 2496 + goto free_field; 2548 2497 2549 - if (test_type_token(type, token, EVENT_DELIM, ",")) 2550 - goto out_free; 2498 + return read_token_item(tok); 2551 2499 2552 - arg->hex.field = field; 2500 + free_field: 2501 + free_arg(arg->hex.field); 2502 + out: 2503 + *tok = NULL; 2504 + return EVENT_ERROR; 2505 + } 2553 2506 2554 - free_token(token); 2507 + static enum event_type 2508 + process_int_array(struct event_format *event, struct print_arg *arg, char **tok) 2509 + { 2510 + memset(arg, 0, sizeof(*arg)); 2511 + arg->type = PRINT_INT_ARRAY; 2555 2512 2556 - field = alloc_arg(); 2557 - if (!field) { 2558 - do_warning_event(event, "%s: not enough memory!", __func__); 2559 - *tok = NULL; 2560 - return EVENT_ERROR; 2561 - } 2513 + if (alloc_and_process_delim(event, ",", &arg->int_array.field)) 2514 + goto out; 2562 2515 2563 - type = process_arg(event, field, &token); 2516 + if (alloc_and_process_delim(event, ",", &arg->int_array.count)) 2517 + goto free_field; 2564 2518 2565 - if (test_type_token(type, token, EVENT_DELIM, ")")) 2566 - goto out_free; 2519 + if (alloc_and_process_delim(event, ")", &arg->int_array.el_size)) 2520 + goto free_size; 2567 2521 2568 - arg->hex.size = field; 2522 + return read_token_item(tok); 2569 2523 2570 - free_token(token); 2571 - type = read_token_item(tok); 2572 - return type; 2573 - 2574 - out_free: 2575 - free_arg(field); 2576 - free_token(token); 2524 + free_size: 2525 + free_arg(arg->int_array.count); 2526 + free_field: 2527 + free_arg(arg->int_array.field); 2528 + out: 2577 2529 *tok = NULL; 2578 2530 return EVENT_ERROR; 2579 2531 } ··· 2869 2827 if (strcmp(token, "__print_hex") == 0) { 2870 2828 free_token(token); 2871 2829 return process_hex(event, arg, tok); 2830 + } 2831 + if (strcmp(token, "__print_array") == 0) { 2832 + free_token(token); 2833 + return process_int_array(event, arg, tok); 2872 2834 } 2873 2835 if (strcmp(token, "__get_str") == 0) { 2874 2836 free_token(token); ··· 3402 3356 break; 3403 3357 case PRINT_FLAGS: 3404 3358 case PRINT_SYMBOL: 3359 + case PRINT_INT_ARRAY: 3405 3360 case PRINT_HEX: 3406 3361 break; 3407 3362 case PRINT_TYPE: ··· 3813 3766 } 3814 3767 break; 3815 3768 3769 + case PRINT_INT_ARRAY: { 3770 + void *num; 3771 + int el_size; 3772 + 3773 + if (arg->int_array.field->type == PRINT_DYNAMIC_ARRAY) { 3774 + unsigned long offset; 3775 + struct format_field *field = 3776 + arg->int_array.field->dynarray.field; 3777 + offset = pevent_read_number(pevent, 3778 + data + field->offset, 3779 + field->size); 3780 + num = data + (offset & 0xffff); 3781 + } else { 3782 + field = arg->int_array.field->field.field; 3783 + if (!field) { 3784 + str = arg->int_array.field->field.name; 3785 + field = pevent_find_any_field(event, str); 3786 + if (!field) 3787 + goto out_warning_field; 3788 + arg->int_array.field->field.field = field; 3789 + } 3790 + num = data + field->offset; 3791 + } 3792 + len = eval_num_arg(data, size, event, arg->int_array.count); 3793 + el_size = eval_num_arg(data, size, event, 3794 + arg->int_array.el_size); 3795 + for (i = 0; i < len; i++) { 3796 + if (i) 3797 + trace_seq_putc(s, ' '); 3798 + 3799 + if (el_size == 1) { 3800 + trace_seq_printf(s, "%u", *(uint8_t *)num); 3801 + } else if (el_size == 2) { 3802 + trace_seq_printf(s, "%u", *(uint16_t *)num); 3803 + } else if (el_size == 4) { 3804 + trace_seq_printf(s, "%u", *(uint32_t *)num); 3805 + } else if (el_size == 8) { 3806 + trace_seq_printf(s, "%lu", *(uint64_t *)num); 3807 + } else { 3808 + trace_seq_printf(s, "BAD SIZE:%d 0x%x", 3809 + el_size, *(uint8_t *)num); 3810 + el_size = 1; 3811 + } 3812 + 3813 + num += el_size; 3814 + } 3815 + break; 3816 + } 3816 3817 case PRINT_TYPE: 3817 3818 break; 3818 3819 case PRINT_STRING: { ··· 4091 3996 case '0' ... '9': 4092 3997 goto process_again; 4093 3998 case '.': 3999 + goto process_again; 4000 + case 'z': 4001 + case 'Z': 4002 + ls = 1; 4094 4003 goto process_again; 4095 4004 case 'p': 4096 4005 ls = 1; ··· 5038 4939 return comm; 5039 4940 } 5040 4941 4942 + static struct cmdline * 4943 + pid_from_cmdlist(struct pevent *pevent, const char *comm, struct cmdline *next) 4944 + { 4945 + struct cmdline_list *cmdlist = (struct cmdline_list *)next; 4946 + 4947 + if (cmdlist) 4948 + cmdlist = cmdlist->next; 4949 + else 4950 + cmdlist = pevent->cmdlist; 4951 + 4952 + while (cmdlist && strcmp(cmdlist->comm, comm) != 0) 4953 + cmdlist = cmdlist->next; 4954 + 4955 + return (struct cmdline *)cmdlist; 4956 + } 4957 + 4958 + /** 4959 + * pevent_data_pid_from_comm - return the pid from a given comm 4960 + * @pevent: a handle to the pevent 4961 + * @comm: the cmdline to find the pid from 4962 + * @next: the cmdline structure to find the next comm 4963 + * 4964 + * This returns the cmdline structure that holds a pid for a given 4965 + * comm, or NULL if none found. As there may be more than one pid for 4966 + * a given comm, the result of this call can be passed back into 4967 + * a recurring call in the @next paramater, and then it will find the 4968 + * next pid. 4969 + * Also, it does a linear seach, so it may be slow. 4970 + */ 4971 + struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm, 4972 + struct cmdline *next) 4973 + { 4974 + struct cmdline *cmdline; 4975 + 4976 + /* 4977 + * If the cmdlines have not been converted yet, then use 4978 + * the list. 4979 + */ 4980 + if (!pevent->cmdlines) 4981 + return pid_from_cmdlist(pevent, comm, next); 4982 + 4983 + if (next) { 4984 + /* 4985 + * The next pointer could have been still from 4986 + * a previous call before cmdlines were created 4987 + */ 4988 + if (next < pevent->cmdlines || 4989 + next >= pevent->cmdlines + pevent->cmdline_count) 4990 + next = NULL; 4991 + else 4992 + cmdline = next++; 4993 + } 4994 + 4995 + if (!next) 4996 + cmdline = pevent->cmdlines; 4997 + 4998 + while (cmdline < pevent->cmdlines + pevent->cmdline_count) { 4999 + if (strcmp(cmdline->comm, comm) == 0) 5000 + return cmdline; 5001 + cmdline++; 5002 + } 5003 + return NULL; 5004 + } 5005 + 5006 + /** 5007 + * pevent_cmdline_pid - return the pid associated to a given cmdline 5008 + * @cmdline: The cmdline structure to get the pid from 5009 + * 5010 + * Returns the pid for a give cmdline. If @cmdline is NULL, then 5011 + * -1 is returned. 5012 + */ 5013 + int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline) 5014 + { 5015 + struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline; 5016 + 5017 + if (!cmdline) 5018 + return -1; 5019 + 5020 + /* 5021 + * If cmdlines have not been created yet, or cmdline is 5022 + * not part of the array, then treat it as a cmdlist instead. 5023 + */ 5024 + if (!pevent->cmdlines || 5025 + cmdline < pevent->cmdlines || 5026 + cmdline >= pevent->cmdlines + pevent->cmdline_count) 5027 + return cmdlist->pid; 5028 + 5029 + return cmdline->pid; 5030 + } 5031 + 5041 5032 /** 5042 5033 * pevent_data_comm_from_pid - parse the data into the print format 5043 5034 * @s: the trace_seq to write to ··· 5443 5254 print_args(args->hex.field); 5444 5255 printf(", "); 5445 5256 print_args(args->hex.size); 5257 + printf(")"); 5258 + break; 5259 + case PRINT_INT_ARRAY: 5260 + printf("__print_array("); 5261 + print_args(args->int_array.field); 5262 + printf(", "); 5263 + print_args(args->int_array.count); 5264 + printf(", "); 5265 + print_args(args->int_array.el_size); 5446 5266 printf(")"); 5447 5267 break; 5448 5268 case PRINT_STRING: ··· 6544 6346 free_handler(handle); 6545 6347 } 6546 6348 6349 + free(pevent->trace_clock); 6547 6350 free(pevent->events); 6548 6351 free(pevent->sort_events); 6549 6352
+19 -2
tools/lib/traceevent/event-parse.h
··· 116 116 char *name; 117 117 char *plugin_alias; 118 118 char *description; 119 - char *value; 119 + const char *value; 120 120 void *priv; 121 121 int set; 122 122 }; ··· 153 153 * 154 154 * .plugin_alias is used to give a shorter name to access 155 155 * the vairable. Useful if a plugin handles more than one event. 156 + * 157 + * If .value is not set, then it is considered a boolean and only 158 + * .set will be processed. If .value is defined, then it is considered 159 + * a string option and .set will be ignored. 156 160 * 157 161 * PEVENT_PLUGIN_ALIAS: (optional) 158 162 * The name to use for finding options (uses filename if not defined) ··· 251 247 struct print_arg *size; 252 248 }; 253 249 250 + struct print_arg_int_array { 251 + struct print_arg *field; 252 + struct print_arg *count; 253 + struct print_arg *el_size; 254 + }; 255 + 254 256 struct print_arg_dynarray { 255 257 struct format_field *field; 256 258 struct print_arg *index; ··· 285 275 PRINT_FLAGS, 286 276 PRINT_SYMBOL, 287 277 PRINT_HEX, 278 + PRINT_INT_ARRAY, 288 279 PRINT_TYPE, 289 280 PRINT_STRING, 290 281 PRINT_BSTRING, ··· 305 294 struct print_arg_flags flags; 306 295 struct print_arg_symbol symbol; 307 296 struct print_arg_hex hex; 297 + struct print_arg_int_array int_array; 308 298 struct print_arg_func func; 309 299 struct print_arg_string string; 310 300 struct print_arg_bitmask bitmask; ··· 611 599 }; 612 600 613 601 int pevent_register_comm(struct pevent *pevent, const char *comm, int pid); 614 - void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock); 602 + int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock); 615 603 int pevent_register_function(struct pevent *pevent, char *name, 616 604 unsigned long long addr, char *mod); 617 605 int pevent_register_print_string(struct pevent *pevent, const char *fmt, ··· 690 678 struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type); 691 679 int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec); 692 680 const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid); 681 + struct cmdline; 682 + struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm, 683 + struct cmdline *next); 684 + int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline); 685 + 693 686 void pevent_event_info(struct trace_seq *s, struct event_format *event, 694 687 struct pevent_record *record); 695 688 int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
+54 -6
tools/lib/traceevent/event-plugin.c
··· 18 18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 19 */ 20 20 21 + #include <ctype.h> 21 22 #include <stdio.h> 22 23 #include <string.h> 23 24 #include <dlfcn.h> ··· 49 48 char *name; 50 49 void *handle; 51 50 }; 51 + 52 + static void lower_case(char *str) 53 + { 54 + if (!str) 55 + return; 56 + for (; *str; str++) 57 + *str = tolower(*str); 58 + } 59 + 60 + static int update_option_value(struct pevent_plugin_option *op, const char *val) 61 + { 62 + char *op_val; 63 + 64 + if (!val) { 65 + /* toggle, only if option is boolean */ 66 + if (op->value) 67 + /* Warn? */ 68 + return 0; 69 + op->set ^= 1; 70 + return 0; 71 + } 72 + 73 + /* 74 + * If the option has a value then it takes a string 75 + * otherwise the option is a boolean. 76 + */ 77 + if (op->value) { 78 + op->value = val; 79 + return 0; 80 + } 81 + 82 + /* Option is boolean, must be either "1", "0", "true" or "false" */ 83 + 84 + op_val = strdup(val); 85 + if (!op_val) 86 + return -1; 87 + lower_case(op_val); 88 + 89 + if (strcmp(val, "1") == 0 || strcmp(val, "true") == 0) 90 + op->set = 1; 91 + else if (strcmp(val, "0") == 0 || strcmp(val, "false") == 0) 92 + op->set = 0; 93 + free(op_val); 94 + 95 + return 0; 96 + } 52 97 53 98 /** 54 99 * traceevent_plugin_list_options - get list of plugin options ··· 167 120 { 168 121 struct trace_plugin_options *op; 169 122 char *plugin; 123 + int ret = 0; 170 124 171 125 if (option->plugin_alias) { 172 126 plugin = strdup(option->plugin_alias); ··· 192 144 if (strcmp(op->option, option->name) != 0) 193 145 continue; 194 146 195 - option->value = op->value; 196 - option->set ^= 1; 197 - goto out; 147 + ret = update_option_value(option, op->value); 148 + if (ret) 149 + goto out; 150 + break; 198 151 } 199 152 200 153 /* first look for unnamed options */ ··· 205 156 if (strcmp(op->option, option->name) != 0) 206 157 continue; 207 158 208 - option->value = op->value; 209 - option->set ^= 1; 159 + ret = update_option_value(option, op->value); 210 160 break; 211 161 } 212 162 213 163 out: 214 164 free(plugin); 215 - return 0; 165 + return ret; 216 166 } 217 167 218 168 /**
+11 -1
tools/lib/traceevent/kbuffer-parse.c
··· 372 372 switch (type_len) { 373 373 case KBUFFER_TYPE_PADDING: 374 374 *length = read_4(kbuf, data); 375 - data += *length; 376 375 break; 377 376 378 377 case KBUFFER_TYPE_TIME_EXTEND: ··· 728 729 kbuf->flags |= KBUFFER_FL_OLD_FORMAT; 729 730 730 731 kbuf->next_event = __old_next_event; 732 + } 733 + 734 + /** 735 + * kbuffer_start_of_data - return offset of where data starts on subbuffer 736 + * @kbuf: The kbuffer 737 + * 738 + * Returns the location on the subbuffer where the data starts. 739 + */ 740 + int kbuffer_start_of_data(struct kbuffer *kbuf) 741 + { 742 + return kbuf->start; 731 743 }
+1
tools/lib/traceevent/kbuffer.h
··· 63 63 int kbuffer_subbuffer_size(struct kbuffer *kbuf); 64 64 65 65 void kbuffer_set_old_format(struct kbuffer *kbuf); 66 + int kbuffer_start_of_data(struct kbuffer *kbuf); 66 67 67 68 #endif /* _K_BUFFER_H */
+2
tools/lib/traceevent/parse-filter.c
··· 1058 1058 *parg = current_op; 1059 1059 else 1060 1060 *parg = current_exp; 1061 + free(token); 1061 1062 return PEVENT_ERRNO__UNBALANCED_PAREN; 1062 1063 } 1063 1064 break; ··· 1169 1168 1170 1169 *parg = current_op; 1171 1170 1171 + free(token); 1172 1172 return 0; 1173 1173 1174 1174 fail_alloc:
+3
tools/perf/Documentation/perf-diff.txt
··· 31 31 --dump-raw-trace:: 32 32 Dump raw trace in ASCII. 33 33 34 + --kallsyms=<file>:: 35 + kallsyms pathname 36 + 34 37 -m:: 35 38 --modules:: 36 39 Load module symbols. WARNING: use only with -k and LIVE kernel
+5
tools/perf/Documentation/perf-report.txt
··· 40 40 Only consider symbols in these comms. CSV that understands 41 41 file://filename entries. This option will affect the percentage of 42 42 the overhead column. See --percentage for more info. 43 + --pid=:: 44 + Only show events for given process ID (comma separated list). 45 + 46 + --tid=:: 47 + Only show events for given thread ID (comma separated list). 43 48 -d:: 44 49 --dsos=:: 45 50 Only consider symbols in these dsos. CSV that understands
+6
tools/perf/Documentation/perf-script.txt
··· 193 193 Only display events for these comms. CSV that understands 194 194 file://filename entries. 195 195 196 + --pid=:: 197 + Only show events for given process ID (comma separated list). 198 + 199 + --tid=:: 200 + Only show events for given thread ID (comma separated list). 201 + 196 202 -I:: 197 203 --show-info:: 198 204 Display extended information about the perf.data file. This adds
+2
tools/perf/builtin-diff.c
··· 791 791 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 792 792 "dump raw trace in ASCII"), 793 793 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 794 + OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 795 + "file", "kallsyms pathname"), 794 796 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 795 797 "load module symbols - WARNING: use only with -k and LIVE kernel"), 796 798 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
+7 -4
tools/perf/builtin-kmem.c
··· 20 20 21 21 #include <linux/rbtree.h> 22 22 #include <linux/string.h> 23 + #include <locale.h> 23 24 24 25 struct alloc_stat; 25 26 typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); ··· 326 325 static void print_summary(void) 327 326 { 328 327 printf("\nSUMMARY\n=======\n"); 329 - printf("Total bytes requested: %lu\n", total_requested); 330 - printf("Total bytes allocated: %lu\n", total_allocated); 331 - printf("Total bytes wasted on internal fragmentation: %lu\n", 328 + printf("Total bytes requested: %'lu\n", total_requested); 329 + printf("Total bytes allocated: %'lu\n", total_allocated); 330 + printf("Total bytes wasted on internal fragmentation: %'lu\n", 332 331 total_allocated - total_requested); 333 332 printf("Internal fragmentation: %f%%\n", 334 333 fragmentation(total_requested, total_allocated)); 335 - printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs); 334 + printf("Cross CPU allocations: %'lu/%'lu\n", nr_cross_allocs, nr_allocs); 336 335 } 337 336 338 337 static void print_result(struct perf_session *session) ··· 707 706 symbol__init(&session->header.env); 708 707 709 708 if (!strcmp(argv[0], "stat")) { 709 + setlocale(LC_ALL, ""); 710 + 710 711 if (cpu__setup_cpunode_map()) 711 712 goto out_delete; 712 713
+5 -1
tools/perf/builtin-report.c
··· 304 304 305 305 if (rep->mem_mode) { 306 306 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events); 307 - ret += fprintf(fp, "\n# Sort order : %s", sort_order); 307 + ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order); 308 308 } else 309 309 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); 310 310 return ret + fprintf(fp, "\n#\n"); ··· 669 669 "only consider symbols in these dsos"), 670 670 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 671 671 "only consider symbols in these comms"), 672 + OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]", 673 + "only consider symbols in these pids"), 674 + OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", 675 + "only consider symbols in these tids"), 672 676 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 673 677 "only consider these symbols"), 674 678 OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
+4
tools/perf/builtin-script.c
··· 1562 1562 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1563 1563 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 1564 1564 "only display events for these comms"), 1565 + OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]", 1566 + "only consider symbols in these pids"), 1567 + OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", 1568 + "only consider symbols in these tids"), 1565 1569 OPT_BOOLEAN('I', "show-info", &show_full_info, 1566 1570 "display extended information from perf.data file"), 1567 1571 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
+4 -2
tools/perf/builtin-top.c
··· 757 757 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 758 758 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 759 759 if (symbol_conf.vmlinux_name) { 760 - ui__warning("The %s file can't be used.\n%s", 761 - symbol_conf.vmlinux_name, msg); 760 + char serr[256]; 761 + dso__strerror_load(al.map->dso, serr, sizeof(serr)); 762 + ui__warning("The %s file can't be used: %s\n%s", 763 + symbol_conf.vmlinux_name, serr, msg); 762 764 } else { 763 765 ui__warning("A vmlinux file was not found.\n%s", 764 766 msg);
+31 -1
tools/perf/util/annotate.c
··· 1008 1008 } 1009 1009 filename = symfs_filename; 1010 1010 } 1011 + } else if (dso__needs_decompress(dso)) { 1012 + char tmp[PATH_MAX]; 1013 + struct kmod_path m; 1014 + int fd; 1015 + bool ret; 1016 + 1017 + if (kmod_path__parse_ext(&m, symfs_filename)) 1018 + goto out_free_filename; 1019 + 1020 + snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX"); 1021 + 1022 + fd = mkstemp(tmp); 1023 + if (fd < 0) { 1024 + free(m.ext); 1025 + goto out_free_filename; 1026 + } 1027 + 1028 + ret = decompress_to_file(m.ext, symfs_filename, fd); 1029 + 1030 + free(m.ext); 1031 + close(fd); 1032 + 1033 + if (!ret) 1034 + goto out_free_filename; 1035 + 1036 + strcpy(symfs_filename, tmp); 1011 1037 } 1012 1038 1013 1039 snprintf(command, sizeof(command), ··· 1053 1027 1054 1028 file = popen(command, "r"); 1055 1029 if (!file) 1056 - goto out_free_filename; 1030 + goto out_remove_tmp; 1057 1031 1058 1032 while (!feof(file)) 1059 1033 if (symbol__parse_objdump_line(sym, map, file, privsize, ··· 1068 1042 delete_last_nop(sym); 1069 1043 1070 1044 pclose(file); 1045 + 1046 + out_remove_tmp: 1047 + if (dso__needs_decompress(dso)) 1048 + unlink(symfs_filename); 1071 1049 out_free_filename: 1072 1050 if (delete_extract) 1073 1051 kcore_extract__delete(&kce);
+6
tools/perf/util/cloexec.c
··· 7 7 8 8 static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 9 9 10 + int __weak sched_getcpu(void) 11 + { 12 + errno = ENOSYS; 13 + return -1; 14 + } 15 + 10 16 static int perf_flag_probe(void) 11 17 { 12 18 /* use 'safest' configuration as used in perf_evsel__fallback() */
+6
tools/perf/util/cloexec.h
··· 3 3 4 4 unsigned long perf_event_open_cloexec_flag(void); 5 5 6 + #ifdef __GLIBC_PREREQ 7 + #if !__GLIBC_PREREQ(2, 6) 8 + extern int sched_getcpu(void) __THROW; 9 + #endif 10 + #endif 11 + 6 12 #endif /* __PERF_CLOEXEC_H */
+38 -23
tools/perf/util/dso.c
··· 165 165 return false; 166 166 } 167 167 168 - bool is_kmodule_extension(const char *ext) 168 + bool is_kernel_module(const char *pathname) 169 169 { 170 - if (strncmp(ext, "ko", 2)) 171 - return false; 170 + struct kmod_path m; 172 171 173 - if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3))) 174 - return true; 172 + if (kmod_path__parse(&m, pathname)) 173 + return NULL; 175 174 176 - return false; 177 - } 178 - 179 - bool is_kernel_module(const char *pathname, bool *compressed) 180 - { 181 - const char *ext = strrchr(pathname, '.'); 182 - 183 - if (ext == NULL) 184 - return false; 185 - 186 - if (is_supported_compression(ext + 1)) { 187 - if (compressed) 188 - *compressed = true; 189 - ext -= 3; 190 - } else if (compressed) 191 - *compressed = false; 192 - 193 - return is_kmodule_extension(ext + 1); 175 + return m.kmod; 194 176 } 195 177 196 178 bool decompress_to_file(const char *ext, const char *filename, int output_fd) ··· 1136 1154 return DSO__TYPE_UNKNOWN; 1137 1155 1138 1156 return dso__type_fd(fd); 1157 + } 1158 + 1159 + int dso__strerror_load(struct dso *dso, char *buf, size_t buflen) 1160 + { 1161 + int idx, errnum = dso->load_errno; 1162 + /* 1163 + * This must have a same ordering as the enum dso_load_errno. 1164 + */ 1165 + static const char *dso_load__error_str[] = { 1166 + "Internal tools/perf/ library error", 1167 + "Invalid ELF file", 1168 + "Can not read build id", 1169 + "Mismatching build id", 1170 + "Decompression failure", 1171 + }; 1172 + 1173 + BUG_ON(buflen == 0); 1174 + 1175 + if (errnum >= 0) { 1176 + const char *err = strerror_r(errnum, buf, buflen); 1177 + 1178 + if (err != buf) 1179 + scnprintf(buf, buflen, "%s", err); 1180 + 1181 + return 0; 1182 + } 1183 + 1184 + if (errnum < __DSO_LOAD_ERRNO__START || errnum >= __DSO_LOAD_ERRNO__END) 1185 + return -1; 1186 + 1187 + idx = errnum - __DSO_LOAD_ERRNO__START; 1188 + scnprintf(buf, buflen, "%s", dso_load__error_str[idx]); 1189 + return 0; 1139 1190 }
+29 -2
tools/perf/util/dso.h
··· 60 60 DSO__TYPE_X32BIT, 61 61 }; 62 62 63 + enum dso_load_errno { 64 + DSO_LOAD_ERRNO__SUCCESS = 0, 65 + 66 + /* 67 + * Choose an arbitrary negative big number not to clash with standard 68 + * errno since SUS requires the errno has distinct positive values. 69 + * See 'Issue 6' in the link below. 70 + * 71 + * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html 72 + */ 73 + __DSO_LOAD_ERRNO__START = -10000, 74 + 75 + DSO_LOAD_ERRNO__INTERNAL_ERROR = __DSO_LOAD_ERRNO__START, 76 + 77 + /* for symsrc__init() */ 78 + DSO_LOAD_ERRNO__INVALID_ELF, 79 + DSO_LOAD_ERRNO__CANNOT_READ_BUILDID, 80 + DSO_LOAD_ERRNO__MISMATCHING_BUILDID, 81 + 82 + /* for decompress_kmodule */ 83 + DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE, 84 + 85 + __DSO_LOAD_ERRNO__END, 86 + }; 87 + 63 88 #define DSO__SWAP(dso, type, val) \ 64 89 ({ \ 65 90 type ____r = val; \ ··· 138 113 enum dso_swap_type needs_swap; 139 114 enum dso_binary_type symtab_type; 140 115 enum dso_binary_type binary_type; 116 + enum dso_load_errno load_errno; 141 117 u8 adjust_symbols:1; 142 118 u8 has_build_id:1; 143 119 u8 has_srcline:1; ··· 216 190 int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 217 191 char *root_dir, char *filename, size_t size); 218 192 bool is_supported_compression(const char *ext); 219 - bool is_kmodule_extension(const char *ext); 220 - bool is_kernel_module(const char *pathname, bool *compressed); 193 + bool is_kernel_module(const char *pathname); 221 194 bool decompress_to_file(const char *ext, const char *filename, int output_fd); 222 195 bool dso__needs_decompress(struct dso *dso); 223 196 ··· 319 294 void dso__free_a2l(struct dso *dso); 320 295 321 296 enum dso_type dso__type(struct dso *dso, struct machine *machine); 297 + 298 + int dso__strerror_load(struct dso *dso, char *buf, size_t buflen); 322 299 323 300 #endif /* __PERF_DSO */
+1 -1
tools/perf/util/header.c
··· 1266 1266 1267 1267 dso__set_build_id(dso, &bev->build_id); 1268 1268 1269 - if (!is_kernel_module(filename, NULL)) 1269 + if (!is_kernel_module(filename)) 1270 1270 dso->kernel = dso_type; 1271 1271 1272 1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
+50 -28
tools/perf/util/machine.c
··· 498 498 if (kmod_path__parse_name(&m, filename)) 499 499 return NULL; 500 500 501 + map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION, 502 + m.name); 503 + if (map) 504 + goto out; 505 + 501 506 dso = machine__module_dso(machine, &m, filename); 502 507 if (dso == NULL) 503 508 goto out; ··· 856 851 return strdup(name); 857 852 } 858 853 854 + static bool is_kmod_dso(struct dso *dso) 855 + { 856 + return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || 857 + dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE; 858 + } 859 + 860 + static int map_groups__set_module_path(struct map_groups *mg, const char *path, 861 + struct kmod_path *m) 862 + { 863 + struct map *map; 864 + char *long_name; 865 + 866 + map = map_groups__find_by_name(mg, MAP__FUNCTION, m->name); 867 + if (map == NULL) 868 + return 0; 869 + 870 + long_name = strdup(path); 871 + if (long_name == NULL) 872 + return -ENOMEM; 873 + 874 + dso__set_long_name(map->dso, long_name, true); 875 + dso__kernel_module_get_build_id(map->dso, ""); 876 + 877 + /* 878 + * Full name could reveal us kmod compression, so 879 + * we need to update the symtab_type if needed. 880 + */ 881 + if (m->comp && is_kmod_dso(map->dso)) 882 + map->dso->symtab_type++; 883 + 884 + return 0; 885 + } 886 + 859 887 static int map_groups__set_modules_path_dir(struct map_groups *mg, 860 888 const char *dir_name, int depth) 861 889 { ··· 927 889 if (ret < 0) 928 890 goto out; 929 891 } else { 930 - char *dot = strrchr(dent->d_name, '.'), 931 - dso_name[PATH_MAX]; 932 - struct map *map; 933 - char *long_name; 892 + struct kmod_path m; 934 893 935 - if (dot == NULL) 936 - continue; 937 - 938 - /* On some system, modules are compressed like .ko.gz */ 939 - if (is_supported_compression(dot + 1) && 940 - is_kmodule_extension(dot - 2)) 941 - dot -= 3; 942 - 943 - snprintf(dso_name, sizeof(dso_name), "[%.*s]", 944 - (int)(dot - dent->d_name), dent->d_name); 945 - 946 - strxfrchar(dso_name, '-', '_'); 947 - map = map_groups__find_by_name(mg, MAP__FUNCTION, 948 - dso_name); 949 - if (map == NULL) 950 - continue; 951 - 952 - long_name = strdup(path); 953 - if (long_name == NULL) { 954 - ret = -1; 894 + ret = kmod_path__parse_name(&m, dent->d_name); 895 + if (ret) 955 896 goto out; 956 - } 957 - dso__set_long_name(map->dso, long_name, true); 958 - dso__kernel_module_get_build_id(map->dso, ""); 897 + 898 + if (m.kmod) 899 + ret = map_groups__set_module_path(mg, path, &m); 900 + 901 + free(m.name); 902 + 903 + if (ret) 904 + goto out; 959 905 } 960 906 } 961 907 ··· 1109 1087 struct dso *dso; 1110 1088 1111 1089 list_for_each_entry(dso, &machine->kernel_dsos.head, node) { 1112 - if (is_kernel_module(dso->long_name, NULL)) 1090 + if (is_kernel_module(dso->long_name)) 1113 1091 continue; 1114 1092 1115 1093 kernel = dso;
+4 -1
tools/perf/util/probe-event.c
··· 310 310 311 311 /* Find the address of given function */ 312 312 map__for_each_symbol_by_name(map, pp->function, sym) { 313 - address = sym->start; 313 + if (uprobes) 314 + address = sym->start; 315 + else 316 + address = map->unmap_ip(map, sym->start); 314 317 break; 315 318 } 316 319 if (!address) {
+5
tools/perf/util/scripting-engines/trace-event-perl.c
··· 214 214 define_event_symbols(event, ev_name, args->hex.field); 215 215 define_event_symbols(event, ev_name, args->hex.size); 216 216 break; 217 + case PRINT_INT_ARRAY: 218 + define_event_symbols(event, ev_name, args->int_array.field); 219 + define_event_symbols(event, ev_name, args->int_array.count); 220 + define_event_symbols(event, ev_name, args->int_array.el_size); 221 + break; 217 222 case PRINT_BSTRING: 218 223 case PRINT_DYNAMIC_ARRAY: 219 224 case PRINT_STRING:
+5
tools/perf/util/scripting-engines/trace-event-python.c
··· 231 231 define_event_symbols(event, ev_name, args->hex.field); 232 232 define_event_symbols(event, ev_name, args->hex.size); 233 233 break; 234 + case PRINT_INT_ARRAY: 235 + define_event_symbols(event, ev_name, args->int_array.field); 236 + define_event_symbols(event, ev_name, args->int_array.count); 237 + define_event_symbols(event, ev_name, args->int_array.el_size); 238 + break; 234 239 case PRINT_STRING: 235 240 break; 236 241 case PRINT_TYPE:
+1
tools/perf/util/sort.h
··· 44 44 extern struct sort_entry sort_sym_from; 45 45 extern struct sort_entry sort_sym_to; 46 46 extern enum sort_type sort__first_dimension; 47 + extern const char default_mem_sort_order[]; 47 48 48 49 struct he_stat { 49 50 u64 period;
+38 -19
tools/perf/util/symbol-elf.c
··· 579 579 static int decompress_kmodule(struct dso *dso, const char *name, 580 580 enum dso_binary_type type) 581 581 { 582 - int fd; 583 - const char *ext = strrchr(name, '.'); 582 + int fd = -1; 584 583 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; 584 + struct kmod_path m; 585 585 586 586 if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && 587 587 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP && 588 588 type != DSO_BINARY_TYPE__BUILD_ID_CACHE) 589 589 return -1; 590 590 591 - if (!ext || !is_supported_compression(ext + 1)) { 592 - ext = strrchr(dso->name, '.'); 593 - if (!ext || !is_supported_compression(ext + 1)) 594 - return -1; 595 - } 591 + if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE) 592 + name = dso->long_name; 596 593 597 - fd = mkstemp(tmpbuf); 598 - if (fd < 0) 594 + if (kmod_path__parse_ext(&m, name) || !m.comp) 599 595 return -1; 600 596 601 - if (!decompress_to_file(ext + 1, name, fd)) { 597 + fd = mkstemp(tmpbuf); 598 + if (fd < 0) { 599 + dso->load_errno = errno; 600 + goto out; 601 + } 602 + 603 + if (!decompress_to_file(m.ext, name, fd)) { 604 + dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE; 602 605 close(fd); 603 606 fd = -1; 604 607 } 605 608 606 609 unlink(tmpbuf); 607 610 611 + out: 612 + free(m.ext); 608 613 return fd; 609 614 } 610 615 ··· 638 633 Elf *elf; 639 634 int fd; 640 635 641 - if (dso__needs_decompress(dso)) 636 + if (dso__needs_decompress(dso)) { 642 637 fd = decompress_kmodule(dso, name, type); 643 - else 638 + if (fd < 0) 639 + return -1; 640 + } else { 644 641 fd = open(name, O_RDONLY); 645 - 646 - if (fd < 0) 647 - return -1; 642 + if (fd < 0) { 643 + dso->load_errno = errno; 644 + return -1; 645 + } 646 + } 648 647 649 648 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 650 649 if (elf == NULL) { 651 650 pr_debug("%s: cannot read %s ELF file.\n", __func__, name); 651 + dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF; 652 652 goto out_close; 653 653 } 654 654 655 655 if (gelf_getehdr(elf, &ehdr) == NULL) { 656 + dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF; 656 657 pr_debug("%s: cannot get elf header.\n", __func__); 657 658 goto out_elf_end; 658 659 } 659 660 660 - if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) 661 + if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) { 662 + dso->load_errno = DSO_LOAD_ERRNO__INTERNAL_ERROR; 661 663 goto out_elf_end; 664 + } 662 665 663 666 /* Always reject images with a mismatched build-id: */ 664 667 if (dso->has_build_id) { 665 668 u8 build_id[BUILD_ID_SIZE]; 666 669 667 - if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) 670 + if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) { 671 + dso->load_errno = DSO_LOAD_ERRNO__CANNOT_READ_BUILDID; 668 672 goto out_elf_end; 673 + } 669 674 670 - if (!dso__build_id_equal(dso, build_id)) 675 + if (!dso__build_id_equal(dso, build_id)) { 676 + dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID; 671 677 goto out_elf_end; 678 + } 672 679 } 673 680 674 681 ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64); ··· 716 699 } 717 700 718 701 ss->name = strdup(name); 719 - if (!ss->name) 702 + if (!ss->name) { 703 + dso->load_errno = errno; 720 704 goto out_elf_end; 705 + } 721 706 722 707 ss->elf = elf; 723 708 ss->fd = fd;
+4 -3
tools/perf/util/symbol-minimal.c
··· 246 246 return ret; 247 247 } 248 248 249 - int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused, 250 - const char *name, 249 + int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, 251 250 enum dso_binary_type type) 252 251 { 253 252 int fd = open(name, O_RDONLY); 254 253 if (fd < 0) 255 - return -1; 254 + goto out_errno; 256 255 257 256 ss->name = strdup(name); 258 257 if (!ss->name) ··· 263 264 return 0; 264 265 out_close: 265 266 close(fd); 267 + out_errno: 268 + dso->load_errno = errno; 266 269 return -1; 267 270 } 268 271
+30 -1
tools/perf/util/symbol.c
··· 15 15 #include "machine.h" 16 16 #include "symbol.h" 17 17 #include "strlist.h" 18 + #include "intlist.h" 18 19 #include "header.h" 19 20 20 21 #include <elf.h> ··· 1860 1859 return 0; 1861 1860 } 1862 1861 1862 + int setup_intlist(struct intlist **list, const char *list_str, 1863 + const char *list_name) 1864 + { 1865 + if (list_str == NULL) 1866 + return 0; 1867 + 1868 + *list = intlist__new(list_str); 1869 + if (!*list) { 1870 + pr_err("problems parsing %s list\n", list_name); 1871 + return -1; 1872 + } 1873 + return 0; 1874 + } 1875 + 1863 1876 static bool symbol__read_kptr_restrict(void) 1864 1877 { 1865 1878 bool value = false; ··· 1924 1909 symbol_conf.comm_list_str, "comm") < 0) 1925 1910 goto out_free_dso_list; 1926 1911 1912 + if (setup_intlist(&symbol_conf.pid_list, 1913 + symbol_conf.pid_list_str, "pid") < 0) 1914 + goto out_free_comm_list; 1915 + 1916 + if (setup_intlist(&symbol_conf.tid_list, 1917 + symbol_conf.tid_list_str, "tid") < 0) 1918 + goto out_free_pid_list; 1919 + 1927 1920 if (setup_list(&symbol_conf.sym_list, 1928 1921 symbol_conf.sym_list_str, "symbol") < 0) 1929 - goto out_free_comm_list; 1922 + goto out_free_tid_list; 1930 1923 1931 1924 /* 1932 1925 * A path to symbols of "/" is identical to "" ··· 1953 1930 symbol_conf.initialized = true; 1954 1931 return 0; 1955 1932 1933 + out_free_tid_list: 1934 + intlist__delete(symbol_conf.tid_list); 1935 + out_free_pid_list: 1936 + intlist__delete(symbol_conf.pid_list); 1956 1937 out_free_comm_list: 1957 1938 strlist__delete(symbol_conf.comm_list); 1958 1939 out_free_dso_list: ··· 1971 1944 strlist__delete(symbol_conf.sym_list); 1972 1945 strlist__delete(symbol_conf.dso_list); 1973 1946 strlist__delete(symbol_conf.comm_list); 1947 + intlist__delete(symbol_conf.tid_list); 1948 + intlist__delete(symbol_conf.pid_list); 1974 1949 vmlinux_path__exit(); 1975 1950 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 1976 1951 symbol_conf.initialized = false;
+7
tools/perf/util/symbol.h
··· 78 78 } 79 79 80 80 struct strlist; 81 + struct intlist; 81 82 82 83 struct symbol_conf { 83 84 unsigned short priv_size; ··· 116 115 const char *guestmount; 117 116 const char *dso_list_str, 118 117 *comm_list_str, 118 + *pid_list_str, 119 + *tid_list_str, 119 120 *sym_list_str, 120 121 *col_width_list_str; 121 122 struct strlist *dso_list, ··· 127 124 *dso_to_list, 128 125 *sym_from_list, 129 126 *sym_to_list; 127 + struct intlist *pid_list, 128 + *tid_list; 130 129 const char *symfs; 131 130 }; 132 131 ··· 300 295 301 296 int setup_list(struct strlist **list, const char *list_str, 302 297 const char *list_name); 298 + int setup_intlist(struct intlist **list, const char *list_str, 299 + const char *list_name); 303 300 304 301 #endif /* __PERF_SYMBOL */
+2 -5
tools/perf/util/target.c
··· 123 123 if (errnum >= 0) { 124 124 const char *err = strerror_r(errnum, buf, buflen); 125 125 126 - if (err != buf) { 127 - size_t len = strlen(err); 128 - memcpy(buf, err, min(buflen - 1, len)); 129 - *(buf + min(buflen - 1, len)) = '\0'; 130 - } 126 + if (err != buf) 127 + scnprintf(buf, buflen, "%s", err); 131 128 132 129 return 0; 133 130 }
+11
tools/perf/util/thread.h
··· 7 7 #include <sys/types.h> 8 8 #include "symbol.h" 9 9 #include <strlist.h> 10 + #include <intlist.h> 10 11 11 12 struct thread_stack; 12 13 ··· 98 97 { 99 98 if (symbol_conf.comm_list && 100 99 !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) { 100 + return true; 101 + } 102 + 103 + if (symbol_conf.pid_list && 104 + !intlist__has_entry(symbol_conf.pid_list, thread->pid_)) { 105 + return true; 106 + } 107 + 108 + if (symbol_conf.tid_list && 109 + !intlist__has_entry(symbol_conf.tid_list, thread->tid)) { 101 110 return true; 102 111 } 103 112