From d110162cafc80dad0622cfd40f3113aebb77e1bb Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Mon, 14 Sep 2020 19:53:09 +0800 Subject: perf tsc: Support cap_user_time_short for event TIME_CONV The synthesized event TIME_CONV doesn't contain the complete parameters for counters, this will lead to wrong conversion between counter cycles and timestamp. This patch extends event TIME_CONV to record flags 'cap_user_time_zero' which is used to indicate the counter parameters are valid or not, if not will directly return 0 for timestamp calculation. And record the flag 'cap_user_time_short' and its relevant fields 'time_cycles' and 'time_mask' for cycle calibration. Signed-off-by: Leo Yan Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Gustavo A. R. Silva Cc: Ian Rogers Cc: Jiri Olsa Cc: John Garry Cc: Kemeng Shi Cc: Mark Rutland Cc: Mathieu Poirier Cc: Namhyung Kim Cc: Nick Gasson Cc: Peter Zijlstra Cc: Remi Bernon Cc: Stephane Eranian Cc: Steve Maclean Cc: Will Deacon Cc: Zou Wei Cc: linux-arm-kernel@lists.infradead.org Link: http://lore.kernel.org/lkml/20200914115311.2201-5-leo.yan@linaro.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/include/perf/event.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h index 842028858d66..a6dbba6b9073 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -324,6 +324,10 @@ struct perf_record_time_conv { __u64 time_shift; __u64 time_mult; __u64 time_zero; + __u64 time_cycles; + __u64 time_mask; + bool cap_user_time_zero; + bool cap_user_time_short; }; struct perf_record_header_feature { -- cgit v1.2.3 From bef69bd7cfc363ab94b84ea29102f3e913ed3c6c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 7 Oct 2020 17:13:11 +0900 Subject: perf stat: Fix out of bounds CPU map access when handling armv8_pmu events It was reported that 'perf stat' crashed when using with armv8_pmu (CPU) events with the task mode. As 'perf stat' uses an empty cpu map for task mode but armv8_pmu has its own cpu mask, it has confused which map it should use when accessing file descriptors and this causes segfaults: (gdb) bt #0 0x0000000000603fc8 in perf_evsel__close_fd_cpu (evsel=, cpu=) at evsel.c:122 #1 perf_evsel__close_cpu (evsel=evsel@entry=0x716e950, cpu=7) at evsel.c:156 #2 0x00000000004d4718 in evlist__close (evlist=0x70a7cb0) at util/evlist.c:1242 #3 0x0000000000453404 in __run_perf_stat (argc=3, argc@entry=1, argv=0x30, argv@entry=0xfffffaea2f90, run_idx=119, run_idx@entry=1701998435) at builtin-stat.c:929 #4 0x0000000000455058 in run_perf_stat (run_idx=1701998435, argv=0xfffffaea2f90, argc=1) at builtin-stat.c:947 #5 cmd_stat (argc=1, argv=0xfffffaea2f90) at builtin-stat.c:2357 #6 0x00000000004bb888 in run_builtin (p=p@entry=0x9764b8 , argc=argc@entry=4, argv=argv@entry=0xfffffaea2f90) at perf.c:312 #7 0x00000000004bbb54 in handle_internal_command (argc=argc@entry=4, argv=argv@entry=0xfffffaea2f90) at perf.c:364 #8 0x0000000000435378 in run_argv (argcp=, argv=) at perf.c:408 #9 main (argc=4, argv=0xfffffaea2f90) at perf.c:538 To fix this, I simply used the given cpu map unless the evsel actually is not a system-wide event (like uncore events). Fixes: 7736627b865d ("perf stat: Use affinity for closing file descriptors") Reported-by: Wei Li Signed-off-by: Namhyung Kim Tested-by: Barry Song Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Mark Rutland Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20201007081311.1831003-1-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/evlist.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c index 2208444ecb44..cfcdbd7be066 100644 --- a/tools/lib/perf/evlist.c +++ b/tools/lib/perf/evlist.c @@ -45,6 +45,9 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, if (!evsel->own_cpus || evlist->has_user_cpus) { perf_cpu_map__put(evsel->cpus); evsel->cpus = perf_cpu_map__get(evlist->cpus); + } else if (!evsel->system_wide && perf_cpu_map__empty(evlist->cpus)) { + perf_cpu_map__put(evsel->cpus); + evsel->cpus = perf_cpu_map__get(evlist->cpus); } else if (evsel->cpus != evsel->own_cpus) { perf_cpu_map__put(evsel->cpus); evsel->cpus = perf_cpu_map__get(evsel->own_cpus); -- cgit v1.2.3 From a41c32105cc12a7d2ae11a591929a6add98987cd Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Wed, 30 Sep 2020 14:07:33 +0300 Subject: tools lib traceevent: Hide non API functions There are internal library functions, which are not declared as a static. They are used inside the library from different files. Hide them from the library users, as they are not part of the API. These functions are made hidden and are renamed without the prefix "tep_": tep_free_plugin_paths tep_peek_char tep_buffer_init tep_get_input_buf_ptr tep_get_input_buf tep_read_token tep_free_token tep_free_event tep_free_format_field __tep_parse_format Link: https://lore.kernel.org/linux-trace-devel/e4afdd82deb5e023d53231bb13e08dca78085fb0.camel@decadent.org.uk/ Reported-by: Ben Hutchings Signed-off-by: Tzvetomir Stoyanov (VMware) Reviewed-by: Steven Rostedt (VMware) Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200930110733.280534-1-tz.stoyanov@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse-api.c | 8 +- tools/lib/traceevent/event-parse-local.h | 24 ++++-- tools/lib/traceevent/event-parse.c | 125 +++++++++++++------------------ tools/lib/traceevent/event-parse.h | 8 -- tools/lib/traceevent/event-plugin.c | 2 +- tools/lib/traceevent/parse-filter.c | 23 +++--- 6 files changed, 83 insertions(+), 107 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse-api.c b/tools/lib/traceevent/event-parse-api.c index 4faf52a65791..f8361e45d446 100644 --- a/tools/lib/traceevent/event-parse-api.c +++ b/tools/lib/traceevent/event-parse-api.c @@ -92,7 +92,7 @@ bool tep_test_flag(struct tep_handle *tep, enum tep_flag flag) return false; } -unsigned short tep_data2host2(struct tep_handle *tep, unsigned short data) +__hidden unsigned short data2host2(struct tep_handle *tep, unsigned short data) { unsigned short swap; @@ -105,7 +105,7 @@ unsigned short tep_data2host2(struct tep_handle *tep, unsigned short data) return swap; } -unsigned int tep_data2host4(struct tep_handle *tep, unsigned int data) +__hidden unsigned int data2host4(struct tep_handle *tep, unsigned int data) { unsigned int swap; @@ -120,8 +120,8 @@ unsigned int tep_data2host4(struct tep_handle *tep, unsigned int data) return swap; } -unsigned long long -tep_data2host8(struct tep_handle *tep, unsigned long long data) +__hidden unsigned long long +data2host8(struct tep_handle *tep, unsigned long long data) { unsigned long long swap; diff --git a/tools/lib/traceevent/event-parse-local.h b/tools/lib/traceevent/event-parse-local.h index d805a920af6f..fd4bbcfbb849 100644 --- a/tools/lib/traceevent/event-parse-local.h +++ b/tools/lib/traceevent/event-parse-local.h @@ -15,6 +15,8 @@ struct event_handler; struct func_resolver; struct tep_plugins_dir; +#define __hidden __attribute__((visibility ("hidden"))) + struct tep_handle { int ref_count; @@ -102,12 +104,20 @@ struct tep_print_parse { struct tep_print_arg *len_as_arg; }; -void tep_free_event(struct tep_event *event); -void tep_free_format_field(struct tep_format_field *field); -void tep_free_plugin_paths(struct tep_handle *tep); - -unsigned short tep_data2host2(struct tep_handle *tep, unsigned short data); -unsigned int tep_data2host4(struct tep_handle *tep, unsigned int data); -unsigned long long tep_data2host8(struct tep_handle *tep, unsigned long long data); +void free_tep_event(struct tep_event *event); +void free_tep_format_field(struct tep_format_field *field); +void free_tep_plugin_paths(struct tep_handle *tep); + +unsigned short data2host2(struct tep_handle *tep, unsigned short data); +unsigned int data2host4(struct tep_handle *tep, unsigned int data); +unsigned long long data2host8(struct tep_handle *tep, unsigned long long data); + +/* access to the internal parser */ +int peek_char(void); +void init_input_buf(const char *buf, unsigned long long size); +unsigned long long get_input_buf_ptr(void); +const char *get_input_buf(void); +enum tep_event_type read_token(char **tok); +void free_token(char *tok); #endif /* _PARSE_EVENTS_INT_H */ diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 5acc18b32606..fe58843d047c 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -54,19 +54,26 @@ static int show_warning = 1; warning(fmt, ##__VA_ARGS__); \ } while (0) -static void init_input_buf(const char *buf, unsigned long long size) +/** + * init_input_buf - init buffer for parsing + * @buf: buffer to parse + * @size: the size of the buffer + * + * Initializes the internal buffer that tep_read_token() will parse. + */ +__hidden void init_input_buf(const char *buf, unsigned long long size) { input_buf = buf; input_buf_siz = size; input_buf_ptr = 0; } -const char *tep_get_input_buf(void) +__hidden const char *get_input_buf(void) { return input_buf; } -unsigned long long tep_get_input_buf_ptr(void) +__hidden unsigned long long get_input_buf_ptr(void) { return input_buf_ptr; } @@ -100,26 +107,13 @@ process_defined_func(struct trace_seq *s, void *data, int size, static void free_func_handle(struct tep_function_handler *func); -/** - * tep_buffer_init - init buffer for parsing - * @buf: buffer to parse - * @size: the size of the buffer - * - * For use with tep_read_token(), this initializes the internal - * buffer that tep_read_token() will parse. - */ -void tep_buffer_init(const char *buf, unsigned long long size) -{ - init_input_buf(buf, size); -} - void breakpoint(void) { static int x; x++; } -struct tep_print_arg *alloc_arg(void) +static struct tep_print_arg *alloc_arg(void) { return calloc(1, sizeof(struct tep_print_arg)); } @@ -962,22 +956,17 @@ static int __read_char(void) return input_buf[input_buf_ptr++]; } -static int __peek_char(void) -{ - if (input_buf_ptr >= input_buf_siz) - return -1; - - return input_buf[input_buf_ptr]; -} - /** - * tep_peek_char - peek at the next character that will be read + * peek_char - peek at the next character that will be read * * Returns the next character read, or -1 if end of buffer. */ -int tep_peek_char(void) +__hidden int peek_char(void) { - return __peek_char(); + if (input_buf_ptr >= input_buf_siz) + return -1; + + return input_buf[input_buf_ptr]; } static int extend_token(char **tok, char *buf, int size) @@ -1033,7 +1022,7 @@ static enum tep_event_type __read_token(char **tok) case TEP_EVENT_OP: switch (ch) { case '-': - next_ch = __peek_char(); + next_ch = peek_char(); if (next_ch == '>') { buf[i++] = __read_char(); break; @@ -1045,7 +1034,7 @@ static enum tep_event_type __read_token(char **tok) case '>': case '<': last_ch = ch; - ch = __peek_char(); + ch = peek_char(); if (ch != last_ch) goto test_equal; buf[i++] = __read_char(); @@ -1068,7 +1057,7 @@ static enum tep_event_type __read_token(char **tok) return type; test_equal: - ch = __peek_char(); + ch = peek_char(); if (ch == '=') buf[i++] = __read_char(); goto out; @@ -1122,7 +1111,7 @@ static enum tep_event_type __read_token(char **tok) break; } - while (get_type(__peek_char()) == type) { + while (get_type(peek_char()) == type) { if (i == (BUFSIZ - 1)) { buf[i] = 0; tok_size += BUFSIZ; @@ -1191,13 +1180,26 @@ static enum tep_event_type force_token(const char *str, char **tok) return type; } -static void free_token(char *tok) +/** + * free_token - free a token returned by tep_read_token + * @token: the token to free + */ +__hidden void free_token(char *tok) { if (tok) free(tok); } -static enum tep_event_type read_token(char **tok) +/** + * read_token - access to utilities to use the tep parser + * @tok: The token to return + * + * This will parse tokens from the string given by + * tep_init_data(). + * + * Returns the token type. + */ +__hidden enum tep_event_type read_token(char **tok) { enum tep_event_type type; @@ -1214,29 +1216,6 @@ static enum tep_event_type read_token(char **tok) return TEP_EVENT_NONE; } -/** - * tep_read_token - access to utilities to use the tep parser - * @tok: The token to return - * - * This will parse tokens from the string given by - * tep_init_data(). - * - * Returns the token type. - */ -enum tep_event_type tep_read_token(char **tok) -{ - return read_token(tok); -} - -/** - * tep_free_token - free a token returned by tep_read_token - * @token: the token to free - */ -void tep_free_token(char *token) -{ - free_token(token); -} - /* no newline */ static enum tep_event_type read_token_item(char **tok) { @@ -3459,12 +3438,12 @@ unsigned long long tep_read_number(struct tep_handle *tep, case 1: return *(unsigned char *)ptr; case 2: - return tep_data2host2(tep, *(unsigned short *)ptr); + return data2host2(tep, *(unsigned short *)ptr); case 4: - return tep_data2host4(tep, *(unsigned int *)ptr); + return data2host4(tep, *(unsigned int *)ptr); case 8: memcpy(&val, (ptr), sizeof(unsigned long long)); - return tep_data2host8(tep, val); + return data2host8(tep, val); default: /* BUG! */ return 0; @@ -4190,7 +4169,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, f = tep_find_any_field(event, arg->string.string); arg->string.offset = f->offset; } - str_offset = tep_data2host4(tep, *(unsigned int *)(data + arg->string.offset)); + str_offset = data2host4(tep, *(unsigned int *)(data + arg->string.offset)); str_offset &= 0xffff; print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset); break; @@ -4208,7 +4187,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, f = tep_find_any_field(event, arg->bitmask.bitmask); arg->bitmask.offset = f->offset; } - bitmask_offset = tep_data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset)); + bitmask_offset = data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset)); bitmask_size = bitmask_offset >> 16; bitmask_offset &= 0xffff; print_bitmask_to_seq(tep, s, format, len_arg, @@ -6750,7 +6729,7 @@ static int find_event_handle(struct tep_handle *tep, struct tep_event *event) } /** - * __tep_parse_format - parse the event format + * parse_format - parse the event format * @buf: the buffer storing the event format string * @size: the size of @buf * @sys: the system the event belongs to @@ -6762,9 +6741,9 @@ static int find_event_handle(struct tep_handle *tep, struct tep_event *event) * * /sys/kernel/debug/tracing/events/.../.../format */ -enum tep_errno __tep_parse_format(struct tep_event **eventp, - struct tep_handle *tep, const char *buf, - unsigned long size, const char *sys) +static enum tep_errno parse_format(struct tep_event **eventp, + struct tep_handle *tep, const char *buf, + unsigned long size, const char *sys) { struct tep_event *event; int ret; @@ -6879,7 +6858,7 @@ __parse_event(struct tep_handle *tep, const char *buf, unsigned long size, const char *sys) { - int ret = __tep_parse_format(eventp, tep, buf, size, sys); + int ret = parse_format(eventp, tep, buf, size, sys); struct tep_event *event = *eventp; if (event == NULL) @@ -6897,7 +6876,7 @@ __parse_event(struct tep_handle *tep, return 0; event_add_failed: - tep_free_event(event); + free_tep_event(event); return ret; } @@ -7490,7 +7469,7 @@ int tep_get_ref(struct tep_handle *tep) return 0; } -void tep_free_format_field(struct tep_format_field *field) +__hidden void free_tep_format_field(struct tep_format_field *field) { free(field->type); if (field->alias != field->name) @@ -7505,7 +7484,7 @@ static void free_format_fields(struct tep_format_field *field) while (field) { next = field->next; - tep_free_format_field(field); + free_tep_format_field(field); field = next; } } @@ -7516,7 +7495,7 @@ static void free_formats(struct tep_format *format) free_format_fields(format->fields); } -void tep_free_event(struct tep_event *event) +__hidden void free_tep_event(struct tep_event *event) { free(event->name); free(event->system); @@ -7602,7 +7581,7 @@ void tep_free(struct tep_handle *tep) } for (i = 0; i < tep->nr_events; i++) - tep_free_event(tep->events[i]); + free_tep_event(tep->events[i]); while (tep->handlers) { handle = tep->handlers; @@ -7613,7 +7592,7 @@ void tep_free(struct tep_handle *tep) free(tep->events); free(tep->sort_events); free(tep->func_resolver); - tep_free_plugin_paths(tep); + free_tep_plugin_paths(tep); free(tep); } diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index c29b693e31ee..a67ad9a5b835 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -578,14 +578,6 @@ void tep_ref(struct tep_handle *tep); void tep_unref(struct tep_handle *tep); int tep_get_ref(struct tep_handle *tep); -/* access to the internal parser */ -void tep_buffer_init(const char *buf, unsigned long long size); -enum tep_event_type tep_read_token(char **tok); -void tep_free_token(char *token); -int tep_peek_char(void); -const char *tep_get_input_buf(void); -unsigned long long tep_get_input_buf_ptr(void); - /* for debugging */ void tep_print_funcs(struct tep_handle *tep); void tep_print_printk(struct tep_handle *tep); diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index e7c2acb8680f..e7f93d5fe4fd 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -676,7 +676,7 @@ int tep_add_plugin_path(struct tep_handle *tep, char *path, return 0; } -void tep_free_plugin_paths(struct tep_handle *tep) +__hidden void free_tep_plugin_paths(struct tep_handle *tep) { struct tep_plugins_dir *dir; diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index c271aeeb227d..368826bb5a57 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -38,8 +38,8 @@ static void show_error(char *error_buf, const char *fmt, ...) int len; int i; - input = tep_get_input_buf(); - index = tep_get_input_buf_ptr(); + input = get_input_buf(); + index = get_input_buf_ptr(); len = input ? strlen(input) : 0; if (len) { @@ -57,25 +57,20 @@ static void show_error(char *error_buf, const char *fmt, ...) va_end(ap); } -static void free_token(char *token) -{ - tep_free_token(token); -} - -static enum tep_event_type read_token(char **tok) +static enum tep_event_type filter_read_token(char **tok) { enum tep_event_type type; char *token = NULL; do { free_token(token); - type = tep_read_token(&token); + type = read_token(&token); } while (type == TEP_EVENT_NEWLINE || type == TEP_EVENT_SPACE); /* If token is = or ! check to see if the next char is ~ */ if (token && (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && - tep_peek_char() == '~') { + peek_char() == '~') { /* append it */ *tok = malloc(3); if (*tok == NULL) { @@ -85,7 +80,7 @@ static enum tep_event_type read_token(char **tok) sprintf(*tok, "%c%c", *token, '~'); free_token(token); /* Now remove the '~' from the buffer */ - tep_read_token(&token); + read_token(&token); free_token(token); } else *tok = token; @@ -959,7 +954,7 @@ process_filter(struct tep_event *event, struct tep_filter_arg **parg, do { free(token); - type = read_token(&token); + type = filter_read_token(&token); switch (type) { case TEP_EVENT_SQUOTE: case TEP_EVENT_DQUOTE: @@ -1185,7 +1180,7 @@ process_event(struct tep_event *event, const char *filter_str, { int ret; - tep_buffer_init(filter_str, strlen(filter_str)); + init_input_buf(filter_str, strlen(filter_str)); ret = process_filter(event, parg, error_str, 0); if (ret < 0) @@ -1243,7 +1238,7 @@ filter_event(struct tep_event_filter *filter, struct tep_event *event, static void filter_init_error_buf(struct tep_event_filter *filter) { /* clear buffer to reset show error */ - tep_buffer_init("", 0); + init_input_buf("", 0); filter->error_buffer[0] = '\0'; } -- cgit v1.2.3 From b0a323c7f0ece5dd76a5dc296ecd9175851a4283 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 13 Oct 2020 21:24:39 +0200 Subject: perf tools: Add size to 'struct perf_record_header_build_id' We do not store size with build ids in perf data, but there's enough space to do it. Adding misc bit PERF_RECORD_MISC_BUILD_ID_SIZE to mark build id event with size. With this fix the dso with md5 build id will have correct build id data and will be usable for debuginfod processing if needed (coming in following patches). Committer notes: Use %zu with size_t to fix this error on 32-bit arches: util/header.c: In function '__event_process_build_id': util/header.c:2105:3: error: format '%lu' expects argument of type 'long unsigned int', but argument 6 has type 'size_t' [-Werror=format=] pr_debug("build id event received for %s: %s [%lu]\n", ^ Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Link: https://lore.kernel.org/r/20201013192441.1299447-8-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/include/perf/event.h | 12 +++++++++++- tools/perf/util/build-id.c | 8 +++++--- tools/perf/util/header.c | 10 +++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h index a6dbba6b9073..988c539bedb6 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -201,10 +201,20 @@ struct perf_record_header_tracing_data { __u32 size; }; +#define PERF_RECORD_MISC_BUILD_ID_SIZE (1 << 15) + struct perf_record_header_build_id { struct perf_event_header header; pid_t pid; - __u8 build_id[24]; + union { + __u8 build_id[24]; + struct { + __u8 data[20]; + __u8 size; + __u8 reserved1__; + __u16 reserved2__; + }; + }; char filename[]; }; diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index b5648735f01f..8763772f1095 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -296,7 +296,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size, continue; \ else -static int write_buildid(const char *name, size_t name_len, u8 *build_id, +static int write_buildid(const char *name, size_t name_len, struct build_id *bid, pid_t pid, u16 misc, struct feat_fd *fd) { int err; @@ -307,7 +307,9 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id, len = PERF_ALIGN(len, NAME_ALIGN); memset(&b, 0, sizeof(b)); - memcpy(&b.build_id, build_id, BUILD_ID_SIZE); + memcpy(&b.data, bid->data, bid->size); + b.size = (u8) bid->size; + misc |= PERF_RECORD_MISC_BUILD_ID_SIZE; b.pid = pid; b.header.misc = misc; b.header.size = sizeof(b) + len; @@ -354,7 +356,7 @@ static int machine__write_buildid_table(struct machine *machine, in_kernel = pos->kernel || is_kernel_module(name, PERF_RECORD_MISC_CPUMODE_UNKNOWN); - err = write_buildid(name, name_len, pos->bid.data, machine->pid, + err = write_buildid(name, name_len, &pos->bid, machine->pid, in_kernel ? kmisc : umisc, fd); if (err) break; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 21243adbb9fd..be850e9f8852 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2083,8 +2083,12 @@ static int __event_process_build_id(struct perf_record_header_build_id *bev, if (dso != NULL) { char sbuild_id[SBUILD_ID_SIZE]; struct build_id bid; + size_t size = BUILD_ID_SIZE; - build_id__init(&bid, bev->build_id, BUILD_ID_SIZE); + if (bev->header.misc & PERF_RECORD_MISC_BUILD_ID_SIZE) + size = bev->size; + + build_id__init(&bid, bev->data, size); dso__set_build_id(dso, &bid); if (dso_space != DSO_SPACE__USER) { @@ -2098,8 +2102,8 @@ static int __event_process_build_id(struct perf_record_header_build_id *bev, } build_id__sprintf(&dso->bid, sbuild_id); - pr_debug("build id event received for %s: %s\n", - dso->long_name, sbuild_id); + pr_debug("build id event received for %s: %s [%zu]\n", + dso->long_name, sbuild_id, size); dso__put(dso); } -- cgit v1.2.3