perf/core improvements and fixes:
User visible: - 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: - 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: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWwjpTAAoJENZQFvNTUqpAmAUP/0mXztM6ynrRNXMhRd/No0OF YfjNlsoLSv6S43jv+DZi5LU7M1/59J+vMwPTNybiq2aOXIN6O5QCOEjczpUE6Ud1 CwNwE2wzCioRl+KdyYQ0BMNtOYlPwBVXaVO+ymeWzmpEElaTJs/l3SMP+w8v3Sgq mMG4QsWDyoVFbmOsdolM63+1a4UySW2dLYNSEyO+6NuqtvJMmDNkJD6pW0uemhf+ DtgcB+gC6M+vT4qyiE4Ki9JvSWUolWhovBnyQGD61/g0umMXjOC7r6Ybk2ezRqzN SJR/TxeLK5SSsxNS6mtn2T/zUmi0LcEbBmohJ545EpEFCjLT6uFj9DEv034HU8XC LHxQmOlXiyi2nErLB61dx4vu9EQJCBZFK5gg6KwGE/JJG1ESoTAZP07dS8CB26CA QI14H0kjA93WMDldvUC6FZAU27pGbaqz+eq3mSF+bHb9hzpvED1gk1OoSk9L7zQS jRCEje7kTisxAk9hsYTbwluDO24O0aKj9gHUgBkY82YGO1AX7tU6HoFt4zGkBwXA uHLfnNXXYJMcSb9Rhk2ObT0Z6M6ioCNBZyhrfRrHD96OZWshV370gZVaQvOlaSoA gjIdIziea/Fc1Z2VUSCzIflyHEDwI/rQtFCOKSHfxUvr/XF3KcgXtv54hvoGdhQw Je32m3XtQkWp+bumvM4H =+W8V -----END PGP SIGNATURE----- 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: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
fe7a2eaa71
|
@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file.
|
|||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'perf config' -l | --list
|
||||
'perf config' [<file-option>] -l | --list
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
@ -21,6 +21,14 @@ OPTIONS
|
|||
--list::
|
||||
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
|
||||
------------------
|
||||
|
||||
|
@ -30,6 +38,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration.
|
|||
The file '$(sysconfdir)/perfconfig' can be used to
|
||||
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
|
||||
~~~~~~
|
||||
|
||||
|
|
|
@ -139,6 +139,8 @@ $(call allow-override,CC,$(CROSS_COMPILE)gcc)
|
|||
$(call allow-override,AR,$(CROSS_COMPILE)ar)
|
||||
$(call allow-override,LD,$(CROSS_COMPILE)ld)
|
||||
|
||||
LD += $(EXTRA_LDFLAGS)
|
||||
|
||||
PKG_CONFIG = $(CROSS_COMPILE)pkg-config
|
||||
|
||||
RM = rm -f
|
||||
|
|
|
@ -89,7 +89,7 @@ static int intel_pt_parse_terms_with_default(struct list_head *formats,
|
|||
|
||||
*config = attr.config;
|
||||
out_free:
|
||||
parse_events__free_terms(terms);
|
||||
parse_events_terms__delete(terms);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
#include "util/util.h"
|
||||
#include "util/debug.h"
|
||||
|
||||
static bool use_system_config, use_user_config;
|
||||
|
||||
static const char * const config_usage[] = {
|
||||
"perf config [options]",
|
||||
"perf config [<file-option>] [options]",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -25,6 +27,8 @@ enum actions {
|
|||
static struct option config_options[] = {
|
||||
OPT_SET_UINT('l', "list", &actions,
|
||||
"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()
|
||||
};
|
||||
|
||||
|
@ -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 ret = 0;
|
||||
char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
|
||||
|
||||
argc = parse_options(argc, argv, config_options, config_usage,
|
||||
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) {
|
||||
case ACTION_LIST:
|
||||
if (argc) {
|
||||
|
@ -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);
|
||||
} else {
|
||||
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, "
|
||||
"please check your ~/.perfconfig file\n");
|
||||
"please check your %s \n", config_filename);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -71,7 +71,10 @@ try:
|
|||
except:
|
||||
if not audit_package_warned:
|
||||
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):
|
||||
try:
|
||||
|
|
|
@ -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;
|
||||
int fd;
|
||||
|
@ -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_SETSIG, signal);
|
||||
fcntl(fd, F_SETSIG, sig);
|
||||
fcntl(fd, F_SETOWN, getpid());
|
||||
|
||||
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
|
||||
|
@ -141,14 +141,14 @@ static int __event(bool is_x, void *addr, int signal)
|
|||
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)
|
||||
|
|
|
@ -1666,7 +1666,7 @@ static int test_term(struct terms_test *t)
|
|||
}
|
||||
|
||||
ret = t->check(&terms);
|
||||
parse_events__free_terms(&terms);
|
||||
parse_events_terms__purge(&terms);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1061,7 +1061,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
|
|||
struct hist_entry *entry,
|
||||
unsigned short row)
|
||||
{
|
||||
char s[256];
|
||||
int printed = 0;
|
||||
int width = browser->b.width;
|
||||
char folded_sign = ' ';
|
||||
|
@ -1086,16 +1085,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
|
|||
.folded_sign = folded_sign,
|
||||
.current_entry = current_entry,
|
||||
};
|
||||
struct perf_hpp hpp = {
|
||||
.buf = s,
|
||||
.size = sizeof(s),
|
||||
.ptr = &arg,
|
||||
};
|
||||
int column = 0;
|
||||
|
||||
hist_browser__gotorc(browser, row, 0);
|
||||
|
||||
hists__for_each_format(browser->hists, fmt) {
|
||||
char s[2048];
|
||||
struct perf_hpp hpp = {
|
||||
.buf = s,
|
||||
.size = sizeof(s),
|
||||
.ptr = &arg,
|
||||
};
|
||||
|
||||
if (perf_hpp__should_skip(fmt, entry->hists) ||
|
||||
column++ < browser->b.horiz_scroll)
|
||||
continue;
|
||||
|
@ -1120,11 +1121,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
|
|||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
width -= hpp.buf - s;
|
||||
}
|
||||
|
||||
/* The scroll bar isn't being used */
|
||||
|
@ -1452,9 +1460,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
|
|||
first = false;
|
||||
|
||||
ret = fmt->entry(fmt, &hpp, he);
|
||||
ret = hist_entry__snprintf_alignment(he, &hpp, fmt, ret);
|
||||
advance_hpp(&hpp, ret);
|
||||
}
|
||||
printed += fprintf(fp, "%s\n", rtrim(s));
|
||||
printed += fprintf(fp, "%s\n", s);
|
||||
|
||||
if (folded_sign == '-')
|
||||
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)
|
|||
else
|
||||
ret = fmt->entry(fmt, hpp, he);
|
||||
|
||||
ret = hist_entry__snprintf_alignment(he, hpp, fmt, ret);
|
||||
advance_hpp(hpp, ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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) \
|
||||
list_for_each_entry(pos, head, node) \
|
||||
if (!pos->has_build_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);
|
||||
|
||||
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,
|
||||
struct perf_sample *sample, struct perf_evsel *evsel,
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
|
||||
#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
|
||||
|
||||
extern const char *config_exclusive_filename;
|
||||
|
||||
typedef int (*config_fn_t)(const char *, const char *, void *);
|
||||
extern int perf_default_config(const char *, const char *, void *);
|
||||
extern int perf_config(config_fn_t fn, void *);
|
||||
|
@ -31,6 +33,7 @@ extern u64 perf_config_u64(const char *, const char *);
|
|||
extern int perf_config_bool(const char *, const char *);
|
||||
extern int config_error_nonbool(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);
|
||||
int split_cmdline(char *cmdline, const char ***argv);
|
||||
|
|
|
@ -26,7 +26,7 @@ static const char *config_file_name;
|
|||
static int config_linenr;
|
||||
static int config_file_eof;
|
||||
|
||||
static const char *config_exclusive_filename;
|
||||
const char *config_exclusive_filename;
|
||||
|
||||
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
|
|||
return ret;
|
||||
}
|
||||
|
||||
static const char *perf_etc_perfconfig(void)
|
||||
const char *perf_etc_perfconfig(void)
|
||||
{
|
||||
static const char *system_wide;
|
||||
if (!system_wide)
|
||||
|
|
|
@ -858,6 +858,23 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
|
|||
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)
|
||||
{
|
||||
struct ctf_stream **stream;
|
||||
|
@ -1171,6 +1188,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
|
|||
(double) c.events_size / 1024.0 / 1024.0,
|
||||
c.events_count);
|
||||
|
||||
cleanup_events(session);
|
||||
perf_session__delete(session);
|
||||
ctf_writer__cleanup(cw);
|
||||
|
||||
|
|
|
@ -1014,6 +1014,27 @@ void hist_entry__delete(struct hist_entry *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
|
||||
*/
|
||||
|
|
|
@ -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 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__collapse(struct hist_entry *left, struct hist_entry *right);
|
||||
int hist_entry__transaction_len(void);
|
||||
int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
|
||||
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 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)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (data.terms)
|
||||
parse_events__free_terms(data.terms);
|
||||
parse_events_terms__delete(data.terms);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2068,12 +2067,22 @@ int parse_events_term__clone(struct parse_events_term **new,
|
|||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -115,7 +115,8 @@ int parse_events_term__sym_hw(struct parse_events_term **term,
|
|||
char *config, unsigned idx);
|
||||
int parse_events_term__clone(struct parse_events_term **new,
|
||||
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_group(struct list_head *list, char *event_mod);
|
||||
int parse_events_name(struct list_head *list, char *name);
|
||||
|
|
|
@ -218,7 +218,7 @@ PE_NAME '/' event_config '/'
|
|||
|
||||
ALLOC_LIST(list);
|
||||
ABORT_ON(parse_events_add_pmu(data, list, $1, $3));
|
||||
parse_events__free_terms($3);
|
||||
parse_events_terms__delete($3);
|
||||
$$ = list;
|
||||
}
|
||||
|
|
||||
|
@ -246,7 +246,7 @@ PE_KERNEL_PMU_EVENT sep_dc
|
|||
|
||||
ALLOC_LIST(list);
|
||||
ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
|
||||
parse_events__free_terms(head);
|
||||
parse_events_terms__delete(head);
|
||||
$$ = list;
|
||||
}
|
||||
|
|
||||
|
@ -266,7 +266,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
|
|||
|
||||
ALLOC_LIST(list);
|
||||
ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
|
||||
parse_events__free_terms(head);
|
||||
parse_events_terms__delete(head);
|
||||
$$ = list;
|
||||
}
|
||||
|
||||
|
@ -285,7 +285,7 @@ value_sym '/' event_config '/'
|
|||
|
||||
ALLOC_LIST(list);
|
||||
ABORT_ON(parse_events_add_numeric(data, list, type, config, $3));
|
||||
parse_events__free_terms($3);
|
||||
parse_events_terms__delete($3);
|
||||
$$ = list;
|
||||
}
|
||||
|
|
||||
|
|
|
@ -354,7 +354,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias,
|
|||
list_for_each_entry(term, &alias->terms, list) {
|
||||
ret = parse_events_term__clone(&cloned, term);
|
||||
if (ret) {
|
||||
parse_events__free_terms(&list);
|
||||
parse_events_terms__purge(&list);
|
||||
return ret;
|
||||
}
|
||||
list_add_tail(&cloned->list, &list);
|
||||
|
|
|
@ -28,7 +28,15 @@ int sort__has_socket = 0;
|
|||
int sort__has_thread = 0;
|
||||
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, ...)
|
||||
{
|
||||
int n;
|
||||
|
@ -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, "+0x%llx",
|
||||
ip - map->unmap_ip(map, sym->start));
|
||||
ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
|
||||
width - ret, "");
|
||||
} else {
|
||||
ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
|
||||
ret += repsep_snprintf(bf + ret, size - ret, "%.*s",
|
||||
width - ret,
|
||||
sym->name);
|
||||
}
|
||||
|
@ -258,14 +264,9 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
|
|||
size_t len = BITS_PER_LONG / 4;
|
||||
ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
|
||||
len, ip);
|
||||
ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
|
||||
width - ret, "");
|
||||
}
|
||||
|
||||
if (ret > width)
|
||||
bf[width] = '\0';
|
||||
|
||||
return width;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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,
|
|||
else
|
||||
out = "No";
|
||||
|
||||
return repsep_snprintf(bf, size, "%-*s", width, out);
|
||||
return repsep_snprintf(bf, size, "%.*s", width, out);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
|
|
|
@ -1529,6 +1529,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
|
|||
if (!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)
|
||||
ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod);
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue