Commit fe7a2eaa authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

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:

  - Do not print trailing spaces in the hists browser (top, report) to
    avoid line wrapping issues when long C++ demangled functions are
    sampled (Arnaldo Carvalho de Melo)

  - Allow 'perf config' to show --system or --user settings (Taeung Song)

  - Add better warning about the need to install the audit-lib-python
    package when using perf python scripts (Taeung Song)

  - Fix symbol resolution when kernel modules files are only in the
    build id cache (~/.debug) (Wang Nan)

Build fixes:

  - Fix 'perf test' build on older systems where 'signal' is reserved (Arnaldo Carvalho de Melo)

Infrastructure changes:

  - Free the terms list_head in parse_events__free_terms(), also unlink the entries
    when deleting them (Wang Nan)

  - Fix releasing event_class in 'perf data' fixing integration with
    libbabeltrace (Wang Nan)

  - Add EXTRA_LDFLAGS option to Makefile (Zubair Lutfullah Kakakhel)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents a7636d9e 1ad826ba
...@@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file. ...@@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file.
SYNOPSIS SYNOPSIS
-------- --------
[verse] [verse]
'perf config' -l | --list 'perf config' [<file-option>] -l | --list
DESCRIPTION DESCRIPTION
----------- -----------
...@@ -21,6 +21,14 @@ OPTIONS ...@@ -21,6 +21,14 @@ OPTIONS
--list:: --list::
Show current config variables, name and value, for all sections. Show current config variables, name and value, for all sections.
--user::
For writing and reading options: write to user
'$HOME/.perfconfig' file or read it.
--system::
For writing and reading options: write to system-wide
'$(sysconfdir)/perfconfig' or read it.
CONFIGURATION FILE CONFIGURATION FILE
------------------ ------------------
...@@ -30,6 +38,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration. ...@@ -30,6 +38,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration.
The file '$(sysconfdir)/perfconfig' can be used to The file '$(sysconfdir)/perfconfig' can be used to
store a system-wide default configuration. store a system-wide default configuration.
When reading or writing, the values are read from the system and user
configuration files by default, and options '--system' and '--user'
can be used to tell the command to read from or write to only that location.
Syntax Syntax
~~~~~~ ~~~~~~
......
...@@ -139,6 +139,8 @@ $(call allow-override,CC,$(CROSS_COMPILE)gcc) ...@@ -139,6 +139,8 @@ $(call allow-override,CC,$(CROSS_COMPILE)gcc)
$(call allow-override,AR,$(CROSS_COMPILE)ar) $(call allow-override,AR,$(CROSS_COMPILE)ar)
$(call allow-override,LD,$(CROSS_COMPILE)ld) $(call allow-override,LD,$(CROSS_COMPILE)ld)
LD += $(EXTRA_LDFLAGS)
PKG_CONFIG = $(CROSS_COMPILE)pkg-config PKG_CONFIG = $(CROSS_COMPILE)pkg-config
RM = rm -f RM = rm -f
......
...@@ -89,7 +89,7 @@ static int intel_pt_parse_terms_with_default(struct list_head *formats, ...@@ -89,7 +89,7 @@ static int intel_pt_parse_terms_with_default(struct list_head *formats,
*config = attr.config; *config = attr.config;
out_free: out_free:
parse_events__free_terms(terms); parse_events_terms__delete(terms);
return err; return err;
} }
......
...@@ -13,8 +13,10 @@ ...@@ -13,8 +13,10 @@
#include "util/util.h" #include "util/util.h"
#include "util/debug.h" #include "util/debug.h"
static bool use_system_config, use_user_config;
static const char * const config_usage[] = { static const char * const config_usage[] = {
"perf config [options]", "perf config [<file-option>] [options]",
NULL NULL
}; };
...@@ -25,6 +27,8 @@ enum actions { ...@@ -25,6 +27,8 @@ enum actions {
static struct option config_options[] = { static struct option config_options[] = {
OPT_SET_UINT('l', "list", &actions, OPT_SET_UINT('l', "list", &actions,
"show current config variables", ACTION_LIST), "show current config variables", ACTION_LIST),
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
OPT_END() OPT_END()
}; };
...@@ -42,10 +46,23 @@ static int show_config(const char *key, const char *value, ...@@ -42,10 +46,23 @@ static int show_config(const char *key, const char *value,
int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{ {
int ret = 0; int ret = 0;
char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
argc = parse_options(argc, argv, config_options, config_usage, argc = parse_options(argc, argv, config_options, config_usage,
PARSE_OPT_STOP_AT_NON_OPTION); PARSE_OPT_STOP_AT_NON_OPTION);
if (use_system_config && use_user_config) {
pr_err("Error: only one config file at a time\n");
parse_options_usage(config_usage, config_options, "user", 0);
parse_options_usage(NULL, config_options, "system", 0);
return -1;
}
if (use_system_config)
config_exclusive_filename = perf_etc_perfconfig();
else if (use_user_config)
config_exclusive_filename = user_config;
switch (actions) { switch (actions) {
case ACTION_LIST: case ACTION_LIST:
if (argc) { if (argc) {
...@@ -53,9 +70,13 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -53,9 +70,13 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
parse_options_usage(config_usage, config_options, "l", 1); parse_options_usage(config_usage, config_options, "l", 1);
} else { } else {
ret = perf_config(show_config, NULL); ret = perf_config(show_config, NULL);
if (ret < 0) if (ret < 0) {
const char * config_filename = config_exclusive_filename;
if (!config_exclusive_filename)
config_filename = user_config;
pr_err("Nothing configured, " pr_err("Nothing configured, "
"please check your ~/.perfconfig file\n"); "please check your %s \n", config_filename);
}
} }
break; break;
default: default:
......
...@@ -71,7 +71,10 @@ try: ...@@ -71,7 +71,10 @@ try:
except: except:
if not audit_package_warned: if not audit_package_warned:
audit_package_warned = True audit_package_warned = True
print "Install the audit-libs-python package to get syscall names" print "Install the audit-libs-python package to get syscall names.\n" \
"For example:\n # apt-get install python-audit (Ubuntu)" \
"\n # yum install audit-libs-python (Fedora)" \
"\n etc.\n"
def syscall_name(id): def syscall_name(id):
try: try:
......
...@@ -103,7 +103,7 @@ static void sig_handler(int signum __maybe_unused, ...@@ -103,7 +103,7 @@ static void sig_handler(int signum __maybe_unused,
} }
} }
static int __event(bool is_x, void *addr, int signal) static int __event(bool is_x, void *addr, int sig)
{ {
struct perf_event_attr pe; struct perf_event_attr pe;
int fd; int fd;
...@@ -133,7 +133,7 @@ static int __event(bool is_x, void *addr, int signal) ...@@ -133,7 +133,7 @@ static int __event(bool is_x, void *addr, int signal)
} }
fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
fcntl(fd, F_SETSIG, signal); fcntl(fd, F_SETSIG, sig);
fcntl(fd, F_SETOWN, getpid()); fcntl(fd, F_SETOWN, getpid());
ioctl(fd, PERF_EVENT_IOC_RESET, 0); ioctl(fd, PERF_EVENT_IOC_RESET, 0);
...@@ -141,14 +141,14 @@ static int __event(bool is_x, void *addr, int signal) ...@@ -141,14 +141,14 @@ static int __event(bool is_x, void *addr, int signal)
return fd; return fd;
} }
static int bp_event(void *addr, int signal) static int bp_event(void *addr, int sig)
{ {
return __event(true, addr, signal); return __event(true, addr, sig);
} }
static int wp_event(void *addr, int signal) static int wp_event(void *addr, int sig)
{ {
return __event(false, addr, signal); return __event(false, addr, sig);
} }
static long long bp_count(int fd) static long long bp_count(int fd)
......
...@@ -1666,7 +1666,7 @@ static int test_term(struct terms_test *t) ...@@ -1666,7 +1666,7 @@ static int test_term(struct terms_test *t)
} }
ret = t->check(&terms); ret = t->check(&terms);
parse_events__free_terms(&terms); parse_events_terms__purge(&terms);
return ret; return ret;
} }
......
...@@ -1061,7 +1061,6 @@ static int hist_browser__show_entry(struct hist_browser *browser, ...@@ -1061,7 +1061,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
struct hist_entry *entry, struct hist_entry *entry,
unsigned short row) unsigned short row)
{ {
char s[256];
int printed = 0; int printed = 0;
int width = browser->b.width; int width = browser->b.width;
char folded_sign = ' '; char folded_sign = ' ';
...@@ -1086,16 +1085,18 @@ static int hist_browser__show_entry(struct hist_browser *browser, ...@@ -1086,16 +1085,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
.folded_sign = folded_sign, .folded_sign = folded_sign,
.current_entry = current_entry, .current_entry = current_entry,
}; };
int column = 0;
hist_browser__gotorc(browser, row, 0);
hists__for_each_format(browser->hists, fmt) {
char s[2048];
struct perf_hpp hpp = { struct perf_hpp hpp = {
.buf = s, .buf = s,
.size = sizeof(s), .size = sizeof(s),
.ptr = &arg, .ptr = &arg,
}; };
int column = 0;
hist_browser__gotorc(browser, row, 0);
hists__for_each_format(browser->hists, fmt) {
if (perf_hpp__should_skip(fmt, entry->hists) || if (perf_hpp__should_skip(fmt, entry->hists) ||
column++ < browser->b.horiz_scroll) column++ < browser->b.horiz_scroll)
continue; continue;
...@@ -1120,11 +1121,18 @@ static int hist_browser__show_entry(struct hist_browser *browser, ...@@ -1120,11 +1121,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
} }
if (fmt->color) { if (fmt->color) {
width -= fmt->color(fmt, &hpp, entry); int ret = fmt->color(fmt, &hpp, entry);
hist_entry__snprintf_alignment(entry, &hpp, fmt, ret);
/*
* fmt->color() already used ui_browser to
* print the non alignment bits, skip it (+ret):
*/
ui_browser__printf(&browser->b, "%s", s + ret);
} else { } else {
width -= fmt->entry(fmt, &hpp, entry); hist_entry__snprintf_alignment(entry, &hpp, fmt, fmt->entry(fmt, &hpp, entry));
ui_browser__printf(&browser->b, "%s", s); ui_browser__printf(&browser->b, "%s", s);
} }
width -= hpp.buf - s;
} }
/* The scroll bar isn't being used */ /* The scroll bar isn't being used */
...@@ -1452,9 +1460,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, ...@@ -1452,9 +1460,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
first = false; first = false;
ret = fmt->entry(fmt, &hpp, he); ret = fmt->entry(fmt, &hpp, he);
ret = hist_entry__snprintf_alignment(he, &hpp, fmt, ret);
advance_hpp(&hpp, ret); advance_hpp(&hpp, ret);
} }
printed += fprintf(fp, "%s\n", rtrim(s)); printed += fprintf(fp, "%s\n", s);
if (folded_sign == '-') if (folded_sign == '-')
printed += hist_browser__fprintf_callchain(browser, he, fp); printed += hist_browser__fprintf_callchain(browser, he, fp);
......
...@@ -403,6 +403,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) ...@@ -403,6 +403,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
else else
ret = fmt->entry(fmt, hpp, he); ret = fmt->entry(fmt, hpp, he);
ret = hist_entry__snprintf_alignment(he, hpp, fmt, ret);
advance_hpp(hpp, ret); advance_hpp(hpp, ret);
} }
......
...@@ -166,6 +166,50 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) ...@@ -166,6 +166,50 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
return build_id__filename(build_id_hex, bf, size); return build_id__filename(build_id_hex, bf, size);
} }
bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
{
char *id_name, *ch;
struct stat sb;
id_name = dso__build_id_filename(dso, bf, size);
if (!id_name)
goto err;
if (access(id_name, F_OK))
goto err;
if (lstat(id_name, &sb) == -1)
goto err;
if ((size_t)sb.st_size > size - 1)
goto err;
if (readlink(id_name, bf, size - 1) < 0)
goto err;
bf[sb.st_size] = '\0';
/*
* link should be:
* ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92
*/
ch = strrchr(bf, '/');
if (!ch)
goto err;
if (ch - 3 < bf)
goto err;
return strncmp(".ko", ch - 3, 3) == 0;
err:
/*
* If dso__build_id_filename work, get id_name again,
* because id_name points to bf and is broken.
*/
if (id_name)
id_name = dso__build_id_filename(dso, bf, size);
pr_err("Invalid build id: %s\n", id_name ? :
dso->long_name ? :
dso->short_name ? :
"[unknown]");
return false;
}
#define dsos__for_each_with_build_id(pos, head) \ #define dsos__for_each_with_build_id(pos, head) \
list_for_each_entry(pos, head, node) \ list_for_each_entry(pos, head, node) \
if (!pos->has_build_id) \ if (!pos->has_build_id) \
......
...@@ -16,6 +16,7 @@ int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id); ...@@ -16,6 +16,7 @@ int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
int filename__sprintf_build_id(const char *pathname, char *sbuild_id); int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size);
int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
struct perf_sample *sample, struct perf_evsel *evsel, struct perf_sample *sample, struct perf_evsel *evsel,
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
#define PERF_PAGER_ENVIRONMENT "PERF_PAGER" #define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
extern const char *config_exclusive_filename;
typedef int (*config_fn_t)(const char *, const char *, void *); typedef int (*config_fn_t)(const char *, const char *, void *);
extern int perf_default_config(const char *, const char *, void *); extern int perf_default_config(const char *, const char *, void *);
extern int perf_config(config_fn_t fn, void *); extern int perf_config(config_fn_t fn, void *);
...@@ -31,6 +33,7 @@ extern u64 perf_config_u64(const char *, const char *); ...@@ -31,6 +33,7 @@ extern u64 perf_config_u64(const char *, const char *);
extern int perf_config_bool(const char *, const char *); extern int perf_config_bool(const char *, const char *);
extern int config_error_nonbool(const char *); extern int config_error_nonbool(const char *);
extern const char *perf_config_dirname(const char *, const char *); extern const char *perf_config_dirname(const char *, const char *);
extern const char *perf_etc_perfconfig(void);
char *alias_lookup(const char *alias); char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv); int split_cmdline(char *cmdline, const char ***argv);
......
...@@ -26,7 +26,7 @@ static const char *config_file_name; ...@@ -26,7 +26,7 @@ static const char *config_file_name;
static int config_linenr; static int config_linenr;
static int config_file_eof; static int config_file_eof;
static const char *config_exclusive_filename; const char *config_exclusive_filename;
static int get_next_char(void) static int get_next_char(void)
{ {
...@@ -434,7 +434,7 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat ...@@ -434,7 +434,7 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat
return ret; return ret;
} }
static const char *perf_etc_perfconfig(void) const char *perf_etc_perfconfig(void)
{ {
static const char *system_wide; static const char *system_wide;
if (!system_wide) if (!system_wide)
......
...@@ -858,6 +858,23 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session) ...@@ -858,6 +858,23 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
return 0; return 0;
} }
static void cleanup_events(struct perf_session *session)
{
struct perf_evlist *evlist = session->evlist;
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
struct evsel_priv *priv;
priv = evsel->priv;
bt_ctf_event_class_put(priv->event_class);
zfree(&evsel->priv);
}
perf_evlist__delete(evlist);
session->evlist = NULL;
}
static int setup_streams(struct ctf_writer *cw, struct perf_session *session) static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
{ {
struct ctf_stream **stream; struct ctf_stream **stream;
...@@ -1171,6 +1188,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force) ...@@ -1171,6 +1188,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
(double) c.events_size / 1024.0 / 1024.0, (double) c.events_size / 1024.0 / 1024.0,
c.events_count); c.events_count);
cleanup_events(session);
perf_session__delete(session); perf_session__delete(session);
ctf_writer__cleanup(cw); ctf_writer__cleanup(cw);
......
...@@ -1014,6 +1014,27 @@ void hist_entry__delete(struct hist_entry *he) ...@@ -1014,6 +1014,27 @@ void hist_entry__delete(struct hist_entry *he)
free(he); free(he);
} }
/*
* If this is not the last column, then we need to pad it according to the
* pre-calculated max lenght for this column, otherwise don't bother adding
* spaces because that would break viewing this with, for instance, 'less',
* that would show tons of trailing spaces when a long C++ demangled method
* names is sampled.
*/
int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
struct perf_hpp_fmt *fmt, int printed)
{
if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) {
const int width = fmt->width(fmt, hpp, hists_to_evsel(he->hists));
if (printed < width) {
advance_hpp(hpp, printed);
printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " ");
}
}
return printed;
}
/* /*
* collapse the histogram * collapse the histogram
*/ */
......
...@@ -122,11 +122,16 @@ struct hist_entry *__hists__add_entry(struct hists *hists, ...@@ -122,11 +122,16 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
int max_stack_depth, void *arg); int max_stack_depth, void *arg);
struct perf_hpp;
struct perf_hpp_fmt;
int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
int hist_entry__transaction_len(void); int hist_entry__transaction_len(void);
int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
struct hists *hists); struct hists *hists);
int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
struct perf_hpp_fmt *fmt, int printed);
void hist_entry__delete(struct hist_entry *he); void hist_entry__delete(struct hist_entry *he);
void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog);
......
...@@ -1386,8 +1386,7 @@ int parse_events_terms(struct list_head *terms, const char *str) ...@@ -1386,8 +1386,7 @@ int parse_events_terms(struct list_head *terms, const char *str)
return 0; return 0;
} }
if (data.terms) parse_events_terms__delete(data.terms);
parse_events__free_terms(data.terms);
return ret; return ret;
} }
...@@ -2068,12 +2067,22 @@ int parse_events_term__clone(struct parse_events_term **new, ...@@ -2068,12 +2067,22 @@ int parse_events_term__clone(struct parse_events_term **new,
term->err_term, term->err_val); term->err_term, term->err_val);
} }
void parse_events__free_terms(struct list_head *terms) void parse_events_terms__purge(struct list_head *terms)
{ {
struct parse_events_term *term, *h; struct parse_events_term *term, *h;
list_for_each_entry_safe(term, h, terms, list) list_for_each_entry_safe(term, h, terms, list) {
list_del_init(&term->list);
free(term); free(term);
}
}
void parse_events_terms__delete(struct list_head *terms)
{
if (!terms)
return;
parse_events_terms__purge(terms);
free(terms);
} }
void parse_events_evlist_error(struct parse_events_evlist *data, void parse_events_evlist_error(struct parse_events_evlist *data,
......
...@@ -115,7 +115,8 @@ int parse_events_term__sym_hw(struct parse_events_term **term, ...@@ -115,7 +115,8 @@ int parse_events_term__sym_hw(struct parse_events_term **term,
char *config, unsigned idx); char *config, unsigned idx);
int parse_events_term__clone(struct parse_events_term **new, int parse_events_term__clone(struct parse_events_term **new,
struct parse_events_term *term); struct parse_events_term *term);
void parse_events__free_terms(struct list_head *terms); void parse_events_terms__delete(struct list_head *terms);
void parse_events_terms__purge(struct list_head *terms);
int parse_events__modifier_event(struct list_head *list, char *str, bool add); int parse_events__modifier_event(struct list_head *list, char *str, bool add);
int parse_events__modifier_group(struct list_head *list, char *event_mod); int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_name(struct list_head *list, char *name); int parse_events_name(struct list_head *list, char *name);
......
...@@ -218,7 +218,7 @@ PE_NAME '/' event_config '/' ...@@ -218,7 +218,7 @@ PE_NAME '/' event_config '/'
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_add_pmu(data, list, $1, $3)); ABORT_ON(parse_events_add_pmu(data, list, $1, $3));
parse_events__free_terms($3); parse_events_terms__delete($3);
$$ = list; $$ = list;
} }
| |
...@@ -246,7 +246,7 @@ PE_KERNEL_PMU_EVENT sep_dc ...@@ -246,7 +246,7 @@ PE_KERNEL_PMU_EVENT sep_dc
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
parse_events__free_terms(head); parse_events_terms__delete(head);
$$ = list; $$ = list;
} }
| |
...@@ -266,7 +266,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc ...@@ -266,7 +266,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
parse_events__free_terms(head); parse_events_terms__delete(head);
$$ = list; $$ = list;
} }
...@@ -285,7 +285,7 @@ value_sym '/' event_config '/' ...@@ -285,7 +285,7 @@ value_sym '/' event_config '/'
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_add_numeric(data, list, type, config, $3)); ABORT_ON(parse_events_add_numeric(data, list, type, config, $3));
parse_events__free_terms($3); parse_events_terms__delete($3);
$$ = list; $$ = list;
} }
| |
......
...@@ -354,7 +354,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias, ...@@ -354,7 +354,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias,
list_for_each_entry(term, &alias->terms, list) { list_for_each_entry(term, &alias->terms, list) {
ret = parse_events_term__clone(&cloned, term); ret = parse_events_term__clone(&cloned, term);
if (ret) { if (ret) {
parse_events__free_terms(&list); parse_events_terms__purge(&list);
return ret; return ret;
} }
list_add_tail(&cloned->list, &list); list_add_tail(&cloned->list, &list);
......
...@@ -28,7 +28,15 @@ int sort__has_socket = 0; ...@@ -28,7 +28,15 @@ int sort__has_socket = 0;
int sort__has_thread = 0; int sort__has_thread = 0;
enum sort_mode sort__mode = SORT_MODE__NORMAL; enum sort_mode sort__mode = SORT_MODE__NORMAL;
/*
* Replaces all occurrences of a char used with the:
*
* -t, --field-separator
*
* option, that uses a special separator character and don't pad with spaces,
* replacing all occurances of this separator in symbol names (and other
* output) with a '.' character, that thus it's the only non valid separator.
*/
static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
{ {
int n; int n;
...@@ -247,10 +255,8 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, ...@@ -247,10 +255,8 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
ip - map->unmap_ip(map, sym->start)); ip - map->unmap_ip(map, sym->start));
ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
width - ret, "");
} else { } else {
ret += repsep_snprintf(bf + ret, size - ret, "%-*s", ret += repsep_snprintf(bf + ret, size - ret, "%.*s",
width - ret, width - ret,
sym->name); sym->name);
} }
...@@ -258,14 +264,9 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, ...@@ -258,14 +264,9 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
size_t len = BITS_PER_LONG / 4; size_t len = BITS_PER_LONG / 4;
ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
len, ip); len, ip);
ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
width - ret, "");
} }
if (ret > width) return ret;
bf[width] = '\0';
return width;
} }
static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
...@@ -811,7 +812,7 @@ static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf, ...@@ -811,7 +812,7 @@ static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
else else
out = "No"; out = "No";
return repsep_snprintf(bf, size, "%-*s", width, out); return repsep_snprintf(bf, size, "%.*s", width, out);
} }
static int64_t static int64_t
......
...@@ -1529,6 +1529,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) ...@@ -1529,6 +1529,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
if (!runtime_ss && syms_ss) if (!runtime_ss && syms_ss)
runtime_ss = syms_ss; runtime_ss = syms_ss;
if (syms_ss && syms_ss->type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
if (dso__build_id_is_kmod(dso, name, PATH_MAX))
kmod = true;
if (syms_ss) if (syms_ss)
ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod); ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod);
else else
......
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