Commit 7977fed9 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-urgent-for-mingo-5.6-20200228' of...

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

Pull perf/urgent fixes from Arnaldo Carvalho de Melo:

perf annotate:

  Ravi Bangoria:

  - Fix segfault with source toggle.

  - Fix --show-total-period and --show-nr-samples for tui/stdio2.

  - Fix handling of settings in ~/.perfconfig versus the ones passed
    in the command line

  - Re-render title bar after switching back from script browser.

  - Fix options man page, document some missing ones.

perf probe:

  He Zhe:

  - Check return value of strlist__add() for -ENOMEM.

tools UAPI:

  Arnaldo Carvalho de Melo:

  - Sync x86's msr-index.h copy with the kernel sources.

  - Update tools's copy of x86's kvm.h headers.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 4c45945a e0560ba6
...@@ -512,6 +512,8 @@ ...@@ -512,6 +512,8 @@
#define MSR_K7_HWCR 0xc0010015 #define MSR_K7_HWCR 0xc0010015
#define MSR_K7_HWCR_SMMLOCK_BIT 0 #define MSR_K7_HWCR_SMMLOCK_BIT 0
#define MSR_K7_HWCR_SMMLOCK BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT) #define MSR_K7_HWCR_SMMLOCK BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
#define MSR_K7_HWCR_IRPERF_EN_BIT 30
#define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
#define MSR_K7_FID_VID_CTL 0xc0010041 #define MSR_K7_FID_VID_CTL 0xc0010041
#define MSR_K7_FID_VID_STATUS 0xc0010042 #define MSR_K7_FID_VID_STATUS 0xc0010042
......
...@@ -390,6 +390,7 @@ struct kvm_sync_regs { ...@@ -390,6 +390,7 @@ struct kvm_sync_regs {
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_RUN_PENDING 0x00000002 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002
#define KVM_STATE_NESTED_EVMCS 0x00000004 #define KVM_STATE_NESTED_EVMCS 0x00000004
#define KVM_STATE_NESTED_MTF_PENDING 0x00000008
#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_SMM_VMXON 0x00000002 #define KVM_STATE_NESTED_SMM_VMXON 0x00000002
......
...@@ -239,7 +239,6 @@ buildid.*:: ...@@ -239,7 +239,6 @@ buildid.*::
set buildid.dir to /dev/null. The default is $HOME/.debug set buildid.dir to /dev/null. The default is $HOME/.debug
annotate.*:: annotate.*::
These options work only for TUI.
These are in control of addresses, jump function, source code These are in control of addresses, jump function, source code
in lines of assembly code from a specific program. in lines of assembly code from a specific program.
...@@ -269,6 +268,8 @@ annotate.*:: ...@@ -269,6 +268,8 @@ annotate.*::
│ mov (%rdi),%rdx │ mov (%rdi),%rdx
│ return n; │ return n;
This option works with tui, stdio2 browsers.
annotate.use_offset:: annotate.use_offset::
Basing on a first address of a loaded function, offset can be used. Basing on a first address of a loaded function, offset can be used.
Instead of using original addresses of assembly code, Instead of using original addresses of assembly code,
...@@ -287,6 +288,8 @@ annotate.*:: ...@@ -287,6 +288,8 @@ annotate.*::
368:│ mov 0x8(%r14),%rdi 368:│ mov 0x8(%r14),%rdi
This option works with tui, stdio2 browsers.
annotate.jump_arrows:: annotate.jump_arrows::
There can be jump instruction among assembly code. There can be jump instruction among assembly code.
Depending on a boolean value of jump_arrows, Depending on a boolean value of jump_arrows,
...@@ -306,6 +309,8 @@ annotate.*:: ...@@ -306,6 +309,8 @@ annotate.*::
│1330: mov %r15,%r10 │1330: mov %r15,%r10
│1333: cmp %r15,%r14 │1333: cmp %r15,%r14
This option works with tui browser.
annotate.show_linenr:: annotate.show_linenr::
When showing source code if this option is 'true', When showing source code if this option is 'true',
line numbers are printed as below. line numbers are printed as below.
...@@ -325,6 +330,8 @@ annotate.*:: ...@@ -325,6 +330,8 @@ annotate.*::
│ array++; │ array++;
│ } │ }
This option works with tui, stdio2 browsers.
annotate.show_nr_jumps:: annotate.show_nr_jumps::
Let's see a part of assembly code. Let's see a part of assembly code.
...@@ -335,6 +342,8 @@ annotate.*:: ...@@ -335,6 +342,8 @@ annotate.*::
│1 1382: movb $0x1,-0x270(%rbp) │1 1382: movb $0x1,-0x270(%rbp)
This option works with tui, stdio2 browsers.
annotate.show_total_period:: annotate.show_total_period::
To compare two records on an instruction base, with this option To compare two records on an instruction base, with this option
provided, display total number of samples that belong to a line provided, display total number of samples that belong to a line
...@@ -348,11 +357,30 @@ annotate.*:: ...@@ -348,11 +357,30 @@ annotate.*::
99.93 │ mov %eax,%eax 99.93 │ mov %eax,%eax
This option works with tui, stdio2, stdio browsers.
annotate.show_nr_samples::
By default perf annotate shows percentage of samples. This option
can be used to print absolute number of samples. Ex, when set as
false:
Percent│
74.03 │ mov %fs:0x28,%rax
When set as true:
Samples│
6 │ mov %fs:0x28,%rax
This option works with tui, stdio2, stdio browsers.
annotate.offset_level:: annotate.offset_level::
Default is '1', meaning just jump targets will have offsets show right beside Default is '1', meaning just jump targets will have offsets show right beside
the instruction. When set to '2' 'call' instructions will also have its offsets the instruction. When set to '2' 'call' instructions will also have its offsets
shown, 3 or higher will show offsets for all instructions. shown, 3 or higher will show offsets for all instructions.
This option works with tui, stdio2 browsers.
hist.*:: hist.*::
hist.percentage:: hist.percentage::
This option control the way to calculate overhead of filtered entries - This option control the way to calculate overhead of filtered entries -
...@@ -490,6 +518,12 @@ top.*:: ...@@ -490,6 +518,12 @@ top.*::
column by default. column by default.
The default is 'true'. The default is 'true'.
top.call-graph::
This is identical to 'call-graph.record-mode', except it is
applicable only for 'top' subcommand. This option ONLY setup
the unwind method. To enable 'perf top' to actually use it,
the command line option -g must be specified.
man.*:: man.*::
man.viewer:: man.viewer::
This option can assign a tool to view manual pages when 'help' This option can assign a tool to view manual pages when 'help'
...@@ -517,6 +551,16 @@ record.*:: ...@@ -517,6 +551,16 @@ record.*::
But if this option is 'no-cache', it will not update the build-id cache. But if this option is 'no-cache', it will not update the build-id cache.
'skip' skips post-processing and does not update the cache. 'skip' skips post-processing and does not update the cache.
record.call-graph::
This is identical to 'call-graph.record-mode', except it is
applicable only for 'record' subcommand. This option ONLY setup
the unwind method. To enable 'perf record' to actually use it,
the command line option -g must be specified.
record.aio::
Use 'n' control blocks in asynchronous (Posix AIO) trace writing
mode ('n' default: 1, max: 4).
diff.*:: diff.*::
diff.order:: diff.order::
This option sets the number of columns to sort the result. This option sets the number of columns to sort the result.
...@@ -566,6 +610,11 @@ trace.*:: ...@@ -566,6 +610,11 @@ trace.*::
"libbeauty", the default, to use the same argument beautifiers used in the "libbeauty", the default, to use the same argument beautifiers used in the
strace-like sys_enter+sys_exit lines. strace-like sys_enter+sys_exit lines.
ftrace.*::
ftrace.tracer::
Can be used to select the default tracer. Possible values are
'function' and 'function_graph'.
llvm.*:: llvm.*::
llvm.clang-path:: llvm.clang-path::
Path to clang. If omit, search it from $PATH. Path to clang. If omit, search it from $PATH.
...@@ -610,6 +659,29 @@ scripts.*:: ...@@ -610,6 +659,29 @@ scripts.*::
The script gets the same options passed as a full perf script, The script gets the same options passed as a full perf script,
in particular -i perfdata file, --cpu, --tid in particular -i perfdata file, --cpu, --tid
convert.*::
convert.queue-size::
Limit the size of ordered_events queue, so we could control
allocation size of perf data files without proper finished
round events.
intel-pt.*::
intel-pt.cache-divisor::
intel-pt.mispred-all::
If set, Intel PT decoder will set the mispred flag on all
branches.
auxtrace.*::
auxtrace.dumpdir::
s390 only. The directory to save the auxiliary trace buffer
can be changed using this option. Ex, auxtrace.dumpdir=/tmp.
If the directory does not exist or has the wrong file type,
the current directory is used.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf[1] linkperf:perf[1]
...@@ -566,6 +566,8 @@ int cmd_annotate(int argc, const char **argv) ...@@ -566,6 +566,8 @@ int cmd_annotate(int argc, const char **argv)
if (ret < 0) if (ret < 0)
return ret; return ret;
annotation_config__init(&annotate.opts);
argc = parse_options(argc, argv, options, annotate_usage, 0); argc = parse_options(argc, argv, options, annotate_usage, 0);
if (argc) { if (argc) {
/* /*
...@@ -605,8 +607,6 @@ int cmd_annotate(int argc, const char **argv) ...@@ -605,8 +607,6 @@ int cmd_annotate(int argc, const char **argv)
if (ret < 0) if (ret < 0)
goto out_delete; goto out_delete;
annotation_config__init();
symbol_conf.try_vmlinux_path = true; symbol_conf.try_vmlinux_path = true;
ret = symbol__init(&annotate.session->header.env); ret = symbol__init(&annotate.session->header.env);
......
...@@ -449,7 +449,8 @@ static int perf_del_probe_events(struct strfilter *filter) ...@@ -449,7 +449,8 @@ static int perf_del_probe_events(struct strfilter *filter)
ret = probe_file__del_strlist(kfd, klist); ret = probe_file__del_strlist(kfd, klist);
if (ret < 0) if (ret < 0)
goto error; goto error;
} } else if (ret == -ENOMEM)
goto error;
ret2 = probe_file__get_events(ufd, filter, ulist); ret2 = probe_file__get_events(ufd, filter, ulist);
if (ret2 == 0) { if (ret2 == 0) {
...@@ -459,7 +460,8 @@ static int perf_del_probe_events(struct strfilter *filter) ...@@ -459,7 +460,8 @@ static int perf_del_probe_events(struct strfilter *filter)
ret2 = probe_file__del_strlist(ufd, ulist); ret2 = probe_file__del_strlist(ufd, ulist);
if (ret2 < 0) if (ret2 < 0)
goto error; goto error;
} } else if (ret2 == -ENOMEM)
goto error;
if (ret == -ENOENT && ret2 == -ENOENT) if (ret == -ENOENT && ret2 == -ENOENT)
pr_warning("\"%s\" does not hit any event.\n", str); pr_warning("\"%s\" does not hit any event.\n", str);
......
...@@ -1507,7 +1507,7 @@ int cmd_report(int argc, const char **argv) ...@@ -1507,7 +1507,7 @@ int cmd_report(int argc, const char **argv)
symbol_conf.priv_size += sizeof(u32); symbol_conf.priv_size += sizeof(u32);
symbol_conf.sort_by_name = true; symbol_conf.sort_by_name = true;
} }
annotation_config__init(); annotation_config__init(&report.annotation_opts);
} }
if (symbol__init(&session->header.env) < 0) if (symbol__init(&session->header.env) < 0)
......
...@@ -143,7 +143,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) ...@@ -143,7 +143,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
return err; return err;
} }
err = symbol__annotate(&he->ms, evsel, 0, &top->annotation_opts, NULL); err = symbol__annotate(&he->ms, evsel, &top->annotation_opts, NULL);
if (err == 0) { if (err == 0) {
top->sym_filter_entry = he; top->sym_filter_entry = he;
} else { } else {
...@@ -1683,7 +1683,7 @@ int cmd_top(int argc, const char **argv) ...@@ -1683,7 +1683,7 @@ int cmd_top(int argc, const char **argv)
if (status < 0) if (status < 0)
goto out_delete_evlist; goto out_delete_evlist;
annotation_config__init(); annotation_config__init(&top.annotation_opts);
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
status = symbol__init(NULL); status = symbol__init(NULL);
......
...@@ -754,10 +754,9 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -754,10 +754,9 @@ static int annotate_browser__run(struct annotate_browser *browser,
"? Search string backwards\n"); "? Search string backwards\n");
continue; continue;
case 'r': case 'r':
{ script_browse(NULL, NULL);
script_browse(NULL, NULL); annotate_browser__show(&browser->b, title, help);
continue; continue;
}
case 'k': case 'k':
notes->options->show_linenr = !notes->options->show_linenr; notes->options->show_linenr = !notes->options->show_linenr;
break; break;
...@@ -834,13 +833,13 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -834,13 +833,13 @@ static int annotate_browser__run(struct annotate_browser *browser,
map_symbol__annotation_dump(ms, evsel, browser->opts); map_symbol__annotation_dump(ms, evsel, browser->opts);
continue; continue;
case 't': case 't':
if (notes->options->show_total_period) { if (symbol_conf.show_total_period) {
notes->options->show_total_period = false; symbol_conf.show_total_period = false;
notes->options->show_nr_samples = true; symbol_conf.show_nr_samples = true;
} else if (notes->options->show_nr_samples) } else if (symbol_conf.show_nr_samples)
notes->options->show_nr_samples = false; symbol_conf.show_nr_samples = false;
else else
notes->options->show_total_period = true; symbol_conf.show_total_period = true;
annotation__update_column_widths(notes); annotation__update_column_widths(notes);
continue; continue;
case 'c': case 'c':
......
...@@ -174,7 +174,7 @@ static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel, ...@@ -174,7 +174,7 @@ static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel,
if (ms->map->dso->annotate_warned) if (ms->map->dso->annotate_warned)
return -1; return -1;
err = symbol__annotate(ms, evsel, 0, &annotation__default_options, NULL); err = symbol__annotate(ms, evsel, &annotation__default_options, NULL);
if (err) { if (err) {
char msg[BUFSIZ]; char msg[BUFSIZ];
symbol__strerror_disassemble(ms, err, msg, sizeof(msg)); symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
......
...@@ -1143,93 +1143,70 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp) ...@@ -1143,93 +1143,70 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)
} }
struct annotate_args { struct annotate_args {
size_t privsize; struct arch *arch;
struct arch *arch; struct map_symbol ms;
struct map_symbol ms; struct evsel *evsel;
struct evsel *evsel;
struct annotation_options *options; struct annotation_options *options;
s64 offset; s64 offset;
char *line; char *line;
int line_nr; int line_nr;
}; };
static void annotation_line__delete(struct annotation_line *al) static void annotation_line__init(struct annotation_line *al,
struct annotate_args *args,
int nr)
{ {
void *ptr = (void *) al - al->privsize; al->offset = args->offset;
al->line = strdup(args->line);
al->line_nr = args->line_nr;
al->data_nr = nr;
}
static void annotation_line__exit(struct annotation_line *al)
{
free_srcline(al->path); free_srcline(al->path);
zfree(&al->line); zfree(&al->line);
free(ptr);
} }
/* static size_t disasm_line_size(int nr)
* Allocating the annotation line data with following
* structure:
*
* --------------------------------------
* private space | struct annotation_line
* --------------------------------------
*
* Size of the private space is stored in 'struct annotation_line'.
*
*/
static struct annotation_line *
annotation_line__new(struct annotate_args *args, size_t privsize)
{ {
struct annotation_line *al; struct annotation_line *al;
struct evsel *evsel = args->evsel;
size_t size = privsize + sizeof(*al);
int nr = 1;
if (perf_evsel__is_group_event(evsel))
nr = evsel->core.nr_members;
size += sizeof(al->data[0]) * nr; return (sizeof(struct disasm_line) + (sizeof(al->data[0]) * nr));
al = zalloc(size);
if (al) {
al = (void *) al + privsize;
al->privsize = privsize;
al->offset = args->offset;
al->line = strdup(args->line);
al->line_nr = args->line_nr;
al->data_nr = nr;
}
return al;
} }
/* /*
* Allocating the disasm annotation line data with * Allocating the disasm annotation line data with
* following structure: * following structure:
* *
* ------------------------------------------------------------ * -------------------------------------------
* privsize space | struct disasm_line | struct annotation_line * struct disasm_line | struct annotation_line
* ------------------------------------------------------------ * -------------------------------------------
* *
* We have 'struct annotation_line' member as last member * We have 'struct annotation_line' member as last member
* of 'struct disasm_line' to have an easy access. * of 'struct disasm_line' to have an easy access.
*
*/ */
static struct disasm_line *disasm_line__new(struct annotate_args *args) static struct disasm_line *disasm_line__new(struct annotate_args *args)
{ {
struct disasm_line *dl = NULL; struct disasm_line *dl = NULL;
struct annotation_line *al; int nr = 1;
size_t privsize = args->privsize + offsetof(struct disasm_line, al);
al = annotation_line__new(args, privsize); if (perf_evsel__is_group_event(args->evsel))
if (al != NULL) { nr = args->evsel->core.nr_members;
dl = disasm_line(al);
if (dl->al.line == NULL) dl = zalloc(disasm_line_size(nr));
goto out_delete; if (!dl)
return NULL;
if (args->offset != -1) { annotation_line__init(&dl->al, args, nr);
if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0) if (dl->al.line == NULL)
goto out_free_line; goto out_delete;
disasm_line__init_ins(dl, args->arch, &args->ms); if (args->offset != -1) {
} if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
goto out_free_line;
disasm_line__init_ins(dl, args->arch, &args->ms);
} }
return dl; return dl;
...@@ -1248,7 +1225,8 @@ void disasm_line__free(struct disasm_line *dl) ...@@ -1248,7 +1225,8 @@ void disasm_line__free(struct disasm_line *dl)
else else
ins__delete(&dl->ops); ins__delete(&dl->ops);
zfree(&dl->ins.name); zfree(&dl->ins.name);
annotation_line__delete(&dl->al); annotation_line__exit(&dl->al);
free(dl);
} }
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name) int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name)
...@@ -2149,13 +2127,12 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel) ...@@ -2149,13 +2127,12 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
annotation__calc_percent(notes, evsel, symbol__size(sym)); annotation__calc_percent(notes, evsel, symbol__size(sym));
} }
int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, size_t privsize, int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
struct annotation_options *options, struct arch **parch) struct annotation_options *options, struct arch **parch)
{ {
struct symbol *sym = ms->sym; struct symbol *sym = ms->sym;
struct annotation *notes = symbol__annotation(sym); struct annotation *notes = symbol__annotation(sym);
struct annotate_args args = { struct annotate_args args = {
.privsize = privsize,
.evsel = evsel, .evsel = evsel,
.options = options, .options = options,
}; };
...@@ -2644,6 +2621,8 @@ void annotation__set_offsets(struct annotation *notes, s64 size) ...@@ -2644,6 +2621,8 @@ void annotation__set_offsets(struct annotation *notes, s64 size)
struct annotation_line *al; struct annotation_line *al;
notes->max_line_len = 0; notes->max_line_len = 0;
notes->nr_entries = 0;
notes->nr_asm_entries = 0;
list_for_each_entry(al, &notes->src->source, node) { list_for_each_entry(al, &notes->src->source, node) {
size_t line_len = strlen(al->line); size_t line_len = strlen(al->line);
...@@ -2790,7 +2769,7 @@ int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel, ...@@ -2790,7 +2769,7 @@ int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
struct symbol *sym = ms->sym; struct symbol *sym = ms->sym;
struct rb_root source_line = RB_ROOT; struct rb_root source_line = RB_ROOT;
if (symbol__annotate(ms, evsel, 0, opts, NULL) < 0) if (symbol__annotate(ms, evsel, opts, NULL) < 0)
return -1; return -1;
symbol__calc_percent(sym, evsel); symbol__calc_percent(sym, evsel);
...@@ -2915,9 +2894,9 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati ...@@ -2915,9 +2894,9 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
percent = annotation_data__percent(&al->data[i], percent_type); percent = annotation_data__percent(&al->data[i], percent_type);
obj__set_percent_color(obj, percent, current_entry); obj__set_percent_color(obj, percent, current_entry);
if (notes->options->show_total_period) { if (symbol_conf.show_total_period) {
obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period); obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
} else if (notes->options->show_nr_samples) { } else if (symbol_conf.show_nr_samples) {
obj__printf(obj, "%6" PRIu64 " ", obj__printf(obj, "%6" PRIu64 " ",
al->data[i].he.nr_samples); al->data[i].he.nr_samples);
} else { } else {
...@@ -2931,8 +2910,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati ...@@ -2931,8 +2910,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
obj__printf(obj, "%-*s", pcnt_width, " "); obj__printf(obj, "%-*s", pcnt_width, " ");
else { else {
obj__printf(obj, "%-*s", pcnt_width, obj__printf(obj, "%-*s", pcnt_width,
notes->options->show_total_period ? "Period" : symbol_conf.show_total_period ? "Period" :
notes->options->show_nr_samples ? "Samples" : "Percent"); symbol_conf.show_nr_samples ? "Samples" : "Percent");
} }
} }
...@@ -3070,7 +3049,7 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel, ...@@ -3070,7 +3049,7 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
if (perf_evsel__is_group_event(evsel)) if (perf_evsel__is_group_event(evsel))
nr_pcnt = evsel->core.nr_members; nr_pcnt = evsel->core.nr_members;
err = symbol__annotate(ms, evsel, 0, options, parch); err = symbol__annotate(ms, evsel, options, parch);
if (err) if (err)
goto out_free_offsets; goto out_free_offsets;
...@@ -3094,69 +3073,46 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel, ...@@ -3094,69 +3073,46 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
return err; return err;
} }
#define ANNOTATION__CFG(n) \ static int annotation__config(const char *var, const char *value, void *data)
{ .name = #n, .value = &annotation__default_options.n, }
/*
* Keep the entries sorted, they are bsearch'ed
*/
static struct annotation_config {
const char *name;
void *value;
} annotation__configs[] = {
ANNOTATION__CFG(hide_src_code),
ANNOTATION__CFG(jump_arrows),
ANNOTATION__CFG(offset_level),
ANNOTATION__CFG(show_linenr),
ANNOTATION__CFG(show_nr_jumps),
ANNOTATION__CFG(show_nr_samples),
ANNOTATION__CFG(show_total_period),
ANNOTATION__CFG(use_offset),
};
#undef ANNOTATION__CFG
static int annotation_config__cmp(const void *name, const void *cfgp)
{
const struct annotation_config *cfg = cfgp;
return strcmp(name, cfg->name);
}
static int annotation__config(const char *var, const char *value,
void *data __maybe_unused)
{ {
struct annotation_config *cfg; struct annotation_options *opt = data;
const char *name;
if (!strstarts(var, "annotate.")) if (!strstarts(var, "annotate."))
return 0; return 0;
name = var + 9; if (!strcmp(var, "annotate.offset_level")) {
cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs), perf_config_u8(&opt->offset_level, "offset_level", value);
sizeof(struct annotation_config), annotation_config__cmp);
if (opt->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
if (cfg == NULL) opt->offset_level = ANNOTATION__MAX_OFFSET_LEVEL;
pr_debug("%s variable unknown, ignoring...", var); else if (opt->offset_level < ANNOTATION__MIN_OFFSET_LEVEL)
else if (strcmp(var, "annotate.offset_level") == 0) { opt->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
perf_config_int(cfg->value, name, value); } else if (!strcmp(var, "annotate.hide_src_code")) {
opt->hide_src_code = perf_config_bool("hide_src_code", value);
if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL) } else if (!strcmp(var, "annotate.jump_arrows")) {
*(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL; opt->jump_arrows = perf_config_bool("jump_arrows", value);
else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL) } else if (!strcmp(var, "annotate.show_linenr")) {
*(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL; opt->show_linenr = perf_config_bool("show_linenr", value);
} else if (!strcmp(var, "annotate.show_nr_jumps")) {
opt->show_nr_jumps = perf_config_bool("show_nr_jumps", value);
} else if (!strcmp(var, "annotate.show_nr_samples")) {
symbol_conf.show_nr_samples = perf_config_bool("show_nr_samples",
value);
} else if (!strcmp(var, "annotate.show_total_period")) {
symbol_conf.show_total_period = perf_config_bool("show_total_period",
value);
} else if (!strcmp(var, "annotate.use_offset")) {
opt->use_offset = perf_config_bool("use_offset", value);
} else { } else {
*(bool *)cfg->value = perf_config_bool(name, value); pr_debug("%s variable unknown, ignoring...", var);
} }
return 0; return 0;
} }
void annotation_config__init(void) void annotation_config__init(struct annotation_options *opt)
{ {
perf_config(annotation__config, NULL); perf_config(annotation__config, opt);
annotation__default_options.show_total_period = symbol_conf.show_total_period;
annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
} }
static unsigned int parse_percent_type(char *str1, char *str2) static unsigned int parse_percent_type(char *str1, char *str2)
......
...@@ -83,8 +83,6 @@ struct annotation_options { ...@@ -83,8 +83,6 @@ struct annotation_options {
full_path, full_path,
show_linenr, show_linenr,
show_nr_jumps, show_nr_jumps,
show_nr_samples,
show_total_period,
show_minmax_cycle, show_minmax_cycle,
show_asm_raw, show_asm_raw,
annotate_src; annotate_src;
...@@ -141,7 +139,6 @@ struct annotation_line { ...@@ -141,7 +139,6 @@ struct annotation_line {
u64 cycles; u64 cycles;
u64 cycles_max; u64 cycles_max;
u64 cycles_min; u64 cycles_min;
size_t privsize;
char *path; char *path;
u32 idx; u32 idx;
int idx_asm; int idx_asm;
...@@ -309,7 +306,7 @@ static inline int annotation__cycles_width(struct annotation *notes) ...@@ -309,7 +306,7 @@ static inline int annotation__cycles_width(struct annotation *notes)
static inline int annotation__pcnt_width(struct annotation *notes) static inline int annotation__pcnt_width(struct annotation *notes)
{ {
return (notes->options->show_total_period ? 12 : 7) * notes->nr_events; return (symbol_conf.show_total_period ? 12 : 7) * notes->nr_events;
} }
static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes) static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes)
...@@ -352,7 +349,7 @@ struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists); ...@@ -352,7 +349,7 @@ struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
void symbol__annotate_zero_histograms(struct symbol *sym); void symbol__annotate_zero_histograms(struct symbol *sym);
int symbol__annotate(struct map_symbol *ms, int symbol__annotate(struct map_symbol *ms,
struct evsel *evsel, size_t privsize, struct evsel *evsel,
struct annotation_options *options, struct annotation_options *options,
struct arch **parch); struct arch **parch);
int symbol__annotate2(struct map_symbol *ms, int symbol__annotate2(struct map_symbol *ms,
...@@ -413,7 +410,7 @@ static inline int symbol__tui_annotate(struct map_symbol *ms __maybe_unused, ...@@ -413,7 +410,7 @@ static inline int symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
} }
#endif #endif
void annotation_config__init(void); void annotation_config__init(struct annotation_options *opt);
int annotate_parse_percent_type(const struct option *opt, const char *_str, int annotate_parse_percent_type(const struct option *opt, const char *_str,
int unset); int unset);
......
...@@ -374,6 +374,18 @@ int perf_config_int(int *dest, const char *name, const char *value) ...@@ -374,6 +374,18 @@ int perf_config_int(int *dest, const char *name, const char *value)
return 0; return 0;
} }
int perf_config_u8(u8 *dest, const char *name, const char *value)
{
long ret = 0;
if (!perf_parse_long(value, &ret)) {
bad_config(name);
return -1;
}
*dest = ret;
return 0;
}
static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
{ {
int ret; int ret;
......
...@@ -29,6 +29,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *); ...@@ -29,6 +29,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
int perf_default_config(const char *, const char *, void *); int perf_default_config(const char *, const char *, void *);
int perf_config(config_fn_t fn, void *); int perf_config(config_fn_t fn, void *);
int perf_config_int(int *dest, const char *, const char *); int perf_config_int(int *dest, const char *, const char *);
int perf_config_u8(u8 *dest, const char *name, const char *value);
int perf_config_u64(u64 *dest, const char *, const char *); int perf_config_u64(u64 *dest, const char *, const char *);
int perf_config_bool(const char *, const char *); int perf_config_bool(const char *, const char *);
int config_error_nonbool(const char *); int config_error_nonbool(const char *);
......
...@@ -301,10 +301,15 @@ int probe_file__get_events(int fd, struct strfilter *filter, ...@@ -301,10 +301,15 @@ int probe_file__get_events(int fd, struct strfilter *filter,
p = strchr(ent->s, ':'); p = strchr(ent->s, ':');
if ((p && strfilter__compare(filter, p + 1)) || if ((p && strfilter__compare(filter, p + 1)) ||
strfilter__compare(filter, ent->s)) { strfilter__compare(filter, ent->s)) {
strlist__add(plist, ent->s); ret = strlist__add(plist, ent->s);
if (ret == -ENOMEM) {
pr_err("strlist__add failed with -ENOMEM\n");
goto out;
}
ret = 0; ret = 0;
} }
} }
out:
strlist__delete(namelist); strlist__delete(namelist);
return ret; return ret;
...@@ -511,7 +516,11 @@ static int probe_cache__load(struct probe_cache *pcache) ...@@ -511,7 +516,11 @@ static int probe_cache__load(struct probe_cache *pcache)
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
strlist__add(entry->tevlist, buf); ret = strlist__add(entry->tevlist, buf);
if (ret == -ENOMEM) {
pr_err("strlist__add failed with -ENOMEM\n");
goto out;
}
} }
} }
out: out:
...@@ -672,7 +681,12 @@ int probe_cache__add_entry(struct probe_cache *pcache, ...@@ -672,7 +681,12 @@ int probe_cache__add_entry(struct probe_cache *pcache,
command = synthesize_probe_trace_command(&tevs[i]); command = synthesize_probe_trace_command(&tevs[i]);
if (!command) if (!command)
goto out_err; goto out_err;
strlist__add(entry->tevlist, command); ret = strlist__add(entry->tevlist, command);
if (ret == -ENOMEM) {
pr_err("strlist__add failed with -ENOMEM\n");
goto out_err;
}
free(command); free(command);
} }
list_add_tail(&entry->node, &pcache->entries); list_add_tail(&entry->node, &pcache->entries);
...@@ -853,9 +867,15 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname) ...@@ -853,9 +867,15 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
break; break;
} }
strlist__add(entry->tevlist, buf); ret = strlist__add(entry->tevlist, buf);
free(buf); free(buf);
entry = NULL; entry = NULL;
if (ret == -ENOMEM) {
pr_err("strlist__add failed with -ENOMEM\n");
break;
}
} }
if (entry) { if (entry) {
list_del_init(&entry->node); list_del_init(&entry->node);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment