perf/core improvements and fixes:

New features:
 
 - Generate comm, fork and exit events when converting perf.data files to CTF (Wang Nan)
 
 Infrastructure:
 
 - Add libbabeltrace to build-test (Wang Nan)
 
 - 'perf record' prep work to support multiple evlists (Wang Nan)
 
 - Remove unused hist_entry__annotate function (Ravi Bangoria)
 
 - Add more toolchain triplets (Ravi Bangoria)
 
 - Update message for slang devel packages on Ubuntu (Neeraj Badlani)
 
 - Generalize handling of 'ret' instructions in the annotate TUI (Naveen N. Rao)
 
 - Use proper dso name for is_regular_file, fixing device file handling (Jiri Olsa)
 
 Build Fixes:
 
 - Add missing config.h include, fixing the build with libbabeltrace (Jiri Olsa)
 
 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJXcoITAAoJENZQFvNTUqpAWxwP/j/h0hGej0/OtzmYIvkeMNXL
 Ei/G1SPjaVS1HxE2UeqcSVFN9dYXHXNwC/9D9Zhg3nTVeVqdTTtk4l2AQcBt7/0b
 5dHFD3mue5iSPFR2nh6nkidb2AyplrCd192Ovww0S/hy26HkNF/8X02aknpOm4SL
 u+S6oYo1gaKCMh7FXYqxFa4uMfzrnCQH5YmEUyuuj3S7fDyidVYVsHfa7DAvzZF9
 gyFnqHRX9H+FpWXkJtaTAaDEQtMvKqvvjLglWDm4W5z0dvyIvVpTiJwm3AtPJ17a
 7rfg+D8V/pA5rcC5HsUwzTrrwzNH0/fDwZgrn50/FImaVyR8MbowgUG+xRGctqsk
 ITmW0FQisJngBekZ7aMl8/WgZ5XfvfwtPo9sfvyTnryqbG1ZizWmnOCFg9PpfSWK
 08kNQac/t4Uo6qZmL1x3lw8T60EGsOJaVwllNKPcF5CO0ff5cXKnXTkEyCoCcS20
 RJ8mFJeqol76gmjAy5rYdK9hLMDTUlrHIB2gTE9s1woaiuAvhpnXl0QVx6q38e3L
 H0f1JFF0Ny5Nb5W+xOUFXiNmVAOKoFL9hS4GOpzDyTozVBTRazjMQf5srfskrhlb
 4dpvwJqIFHo/NaKXZcHYcT7wYFaE6gbApjw5bUaFPMvhYOJ/DefW8FSk8btcma1N
 LZ65UEGakqS5gbFX9NdU
 =rSZA
 -----END PGP SIGNATURE-----

Merge tag 'perf-core-for-mingo-20160628' 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:

New features:

 - Generate comm, fork and exit events when converting perf.data files to CTF (Wang Nan)

Infrastructure changes:

 - Add libbabeltrace to build-test (Wang Nan)

 - 'perf record' prep work to support multiple evlists (Wang Nan)

 - Remove unused hist_entry__annotate function (Ravi Bangoria)

 - Add more toolchain triplets (Ravi Bangoria)

 - Update message for slang devel packages on Ubuntu (Neeraj Badlani)

 - Generalize handling of 'ret' instructions in the annotate TUI (Naveen N. Rao)

 - Use proper dso name for is_regular_file, fixing device file handling (Jiri Olsa)

Build Fixes:

 - Add missing config.h include, fixing the build with libbabeltrace (Jiri Olsa)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2016-06-29 11:34:41 +02:00
commit d905768c9e
13 changed files with 331 additions and 59 deletions

View file

@ -34,6 +34,10 @@ OPTIONS for 'convert'
--verbose::
Be more verbose (show counter open errors, etc).
--all::
Convert all events, including non-sample events (comm, fork, ...), to output.
Default is off, only convert samples.
SEE ALSO
--------
linkperf:perf[1]

View file

@ -9,34 +9,44 @@ const char *const arm_triplets[] = {
"arm-unknown-linux-",
"arm-unknown-linux-gnu-",
"arm-unknown-linux-gnueabi-",
"arm-linux-gnu-",
"arm-linux-gnueabihf-",
"arm-none-eabi-",
NULL
};
const char *const arm64_triplets[] = {
"aarch64-linux-android-",
"aarch64-linux-gnu-",
NULL
};
const char *const powerpc_triplets[] = {
"powerpc-unknown-linux-gnu-",
"powerpc64-unknown-linux-gnu-",
"powerpc64-linux-gnu-",
"powerpc64le-linux-gnu-",
NULL
};
const char *const s390_triplets[] = {
"s390-ibm-linux-",
"s390x-linux-gnu-",
NULL
};
const char *const sh_triplets[] = {
"sh-unknown-linux-gnu-",
"sh64-unknown-linux-gnu-",
"sh-linux-gnu-",
"sh64-linux-gnu-",
NULL
};
const char *const sparc_triplets[] = {
"sparc-unknown-linux-gnu-",
"sparc64-unknown-linux-gnu-",
"sparc64-linux-gnu-",
NULL
};
@ -49,12 +59,19 @@ const char *const x86_triplets[] = {
"i386-pc-linux-gnu-",
"i686-linux-android-",
"i686-android-linux-",
"x86_64-linux-gnu-",
"i586-linux-gnu-",
NULL
};
const char *const mips_triplets[] = {
"mips-unknown-linux-gnu-",
"mipsel-linux-android-",
"mips-linux-gnu-",
"mips64-linux-gnu-",
"mips64el-linux-gnuabi64-",
"mips64-linux-gnuabi64-",
"mipsel-linux-gnu-",
NULL
};

View file

@ -3,6 +3,7 @@
#include "perf.h"
#include "debug.h"
#include <subcmd/parse-options.h>
#include "data-convert.h"
#include "data-convert-bt.h"
typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
@ -53,14 +54,18 @@ static int cmd_data_convert(int argc, const char **argv,
const char *prefix __maybe_unused)
{
const char *to_ctf = NULL;
bool force = false;
struct perf_data_convert_opts opts = {
.force = false,
.all = false,
};
const struct option options[] = {
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
OPT_STRING('i', "input", &input_name, "file", "input file name"),
#ifdef HAVE_LIBBABELTRACE_SUPPORT
OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
#endif
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_BOOLEAN('f', "force", &opts.force, "don't complain, do it"),
OPT_BOOLEAN(0, "all", &opts.all, "Convert all events"),
OPT_END()
};
@ -78,7 +83,7 @@ static int cmd_data_convert(int argc, const char **argv,
if (to_ctf) {
#ifdef HAVE_LIBBABELTRACE_SUPPORT
return bt_convert__perf2ctf(input_name, to_ctf, force);
return bt_convert__perf2ctf(input_name, to_ctf, &opts);
#else
pr_err("The libbabeltrace support is not compiled in.\n");
return -1;

View file

@ -132,9 +132,9 @@ rb_find_range(struct perf_evlist *evlist,
return backward_rb_find_range(data, mask, head, start, end);
}
static int record__mmap_read(struct record *rec, int idx)
static int record__mmap_read(struct record *rec, struct perf_evlist *evlist, int idx)
{
struct perf_mmap *md = &rec->evlist->mmap[idx];
struct perf_mmap *md = &evlist->mmap[idx];
u64 head = perf_mmap__read_head(md);
u64 old = md->prev;
u64 end = head, start = old;
@ -143,7 +143,7 @@ static int record__mmap_read(struct record *rec, int idx)
void *buf;
int rc = 0;
if (rb_find_range(rec->evlist, data, md->mask, head,
if (rb_find_range(evlist, data, md->mask, head,
old, &start, &end))
return -1;
@ -157,7 +157,7 @@ static int record__mmap_read(struct record *rec, int idx)
WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
md->prev = head;
perf_evlist__mmap_consume(rec->evlist, idx);
perf_evlist__mmap_consume(evlist, idx);
return 0;
}
@ -182,7 +182,7 @@ static int record__mmap_read(struct record *rec, int idx)
}
md->prev = head;
perf_evlist__mmap_consume(rec->evlist, idx);
perf_evlist__mmap_consume(evlist, idx);
out:
return rc;
}
@ -342,6 +342,40 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
#endif
static int record__mmap_evlist(struct record *rec,
struct perf_evlist *evlist)
{
struct record_opts *opts = &rec->opts;
char msg[512];
if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
opts->auxtrace_mmap_pages,
opts->auxtrace_snapshot_mode) < 0) {
if (errno == EPERM) {
pr_err("Permission error mapping pages.\n"
"Consider increasing "
"/proc/sys/kernel/perf_event_mlock_kb,\n"
"or try again with a smaller value of -m/--mmap_pages.\n"
"(current value: %u,%u)\n",
opts->mmap_pages, opts->auxtrace_mmap_pages);
return -errno;
} else {
pr_err("failed to mmap with %d (%s)\n", errno,
strerror_r(errno, msg, sizeof(msg)));
if (errno)
return -errno;
else
return -EINVAL;
}
}
return 0;
}
static int record__mmap(struct record *rec)
{
return record__mmap_evlist(rec, rec->evlist);
}
static int record__open(struct record *rec)
{
char msg[512];
@ -378,27 +412,9 @@ try_again:
goto out;
}
if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
opts->auxtrace_mmap_pages,
opts->auxtrace_snapshot_mode) < 0) {
if (errno == EPERM) {
pr_err("Permission error mapping pages.\n"
"Consider increasing "
"/proc/sys/kernel/perf_event_mlock_kb,\n"
"or try again with a smaller value of -m/--mmap_pages.\n"
"(current value: %u,%u)\n",
opts->mmap_pages, opts->auxtrace_mmap_pages);
rc = -errno;
} else {
pr_err("failed to mmap with %d (%s)\n", errno,
strerror_r(errno, msg, sizeof(msg)));
if (errno)
rc = -errno;
else
rc = -EINVAL;
}
rc = record__mmap(rec);
if (rc)
goto out;
}
session->evlist = evlist;
perf_session__set_id_hdr_size(session);
@ -482,17 +498,20 @@ static struct perf_event_header finished_round_event = {
.type = PERF_RECORD_FINISHED_ROUND,
};
static int record__mmap_read_all(struct record *rec)
static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist)
{
u64 bytes_written = rec->bytes_written;
int i;
int rc = 0;
for (i = 0; i < rec->evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
if (!evlist)
return 0;
if (rec->evlist->mmap[i].base) {
if (record__mmap_read(rec, i) != 0) {
for (i = 0; i < evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm = &evlist->mmap[i].auxtrace_mmap;
if (evlist->mmap[i].base) {
if (record__mmap_read(rec, evlist, i) != 0) {
rc = -1;
goto out;
}
@ -516,6 +535,17 @@ out:
return rc;
}
static int record__mmap_read_all(struct record *rec)
{
int err;
err = record__mmap_read_evlist(rec, rec->evlist);
if (err)
return err;
return err;
}
static void record__init_features(struct record *rec)
{
struct perf_session *session = rec->session;
@ -656,10 +686,21 @@ perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused
return 0;
}
static const struct perf_event_mmap_page *
perf_evlist__pick_pc(struct perf_evlist *evlist)
{
if (evlist && evlist->mmap && evlist->mmap[0].base)
return evlist->mmap[0].base;
return NULL;
}
static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
{
if (rec->evlist && rec->evlist->mmap && rec->evlist->mmap[0].base)
return rec->evlist->mmap[0].base;
const struct perf_event_mmap_page *pc;
pc = perf_evlist__pick_pc(rec->evlist);
if (pc)
return pc;
return NULL;
}

View file

@ -482,7 +482,7 @@ endif
ifndef NO_SLANG
ifneq ($(feature-libslang), 1)
msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev);
msg := $(warning slang not found, disables TUI support. Please install slang-devel, libslang-dev or libslang2-dev);
NO_SLANG := 1
else
# Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h

View file

@ -81,6 +81,7 @@ make_no_libbionic := NO_LIBBIONIC=1
make_no_auxtrace := NO_AUXTRACE=1
make_no_libbpf := NO_LIBBPF=1
make_no_libcrypto := NO_LIBCRYPTO=1
make_with_babeltrace:= LIBBABELTRACE=1
make_tags := tags
make_cscope := cscope
make_help := help
@ -136,6 +137,7 @@ run += make_no_libaudit
run += make_no_libbionic
run += make_no_auxtrace
run += make_no_libbpf
run += make_with_babeltrace
run += make_help
run += make_doc
run += make_perf_o

View file

@ -223,16 +223,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
} else if (ins__is_call(dl->ins)) {
ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
SLsmg_write_char(' ');
} else if (ins__is_ret(dl->ins)) {
ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
SLsmg_write_char(' ');
} else {
ui_browser__write_nstring(browser, " ", 2);
}
} else {
if (strcmp(dl->name, "retq")) {
ui_browser__write_nstring(browser, " ", 2);
} else {
ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
SLsmg_write_char(' ');
}
ui_browser__write_nstring(browser, " ", 2);
}
disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
@ -843,14 +841,14 @@ show_help:
ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
else if (browser->selection->offset == -1)
ui_helpline__puts("Actions are only available for assembly lines.");
else if (!browser->selection->ins) {
if (strcmp(browser->selection->name, "retq"))
goto show_sup_ins;
else if (!browser->selection->ins)
goto show_sup_ins;
else if (ins__is_ret(browser->selection->ins))
goto out;
} else if (!(annotate_browser__jump(browser) ||
else if (!(annotate_browser__jump(browser) ||
annotate_browser__callq(browser, evsel, hbt))) {
show_sup_ins:
ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");
ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
}
continue;
case 't':

View file

@ -354,6 +354,15 @@ static struct ins_ops nop_ops = {
.scnprintf = nop__scnprintf,
};
static struct ins_ops ret_ops = {
.scnprintf = ins__raw_scnprintf,
};
bool ins__is_ret(const struct ins *ins)
{
return ins->ops == &ret_ops;
}
static struct ins instructions[] = {
{ .name = "add", .ops = &mov_ops, },
{ .name = "addl", .ops = &mov_ops, },
@ -444,6 +453,7 @@ static struct ins instructions[] = {
{ .name = "xadd", .ops = &mov_ops, },
{ .name = "xbeginl", .ops = &jump_ops, },
{ .name = "xbeginq", .ops = &jump_ops, },
{ .name = "retq", .ops = &ret_ops, },
};
static int ins__key_cmp(const void *name, const void *insp)
@ -1676,11 +1686,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
return 0;
}
int hist_entry__annotate(struct hist_entry *he, size_t privsize)
{
return symbol__annotate(he->ms.sym, he->ms.map, privsize);
}
bool ui__has_annotation(void)
{
return use_browser == 1 && perf_hpp_list.sym;

View file

@ -48,6 +48,7 @@ struct ins {
bool ins__is_jump(const struct ins *ins);
bool ins__is_call(const struct ins *ins);
bool ins__is_ret(const struct ins *ins);
int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
struct annotation;
@ -156,8 +157,6 @@ void symbol__annotate_zero_histograms(struct symbol *sym);
int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
int hist_entry__annotate(struct hist_entry *he, size_t privsize);
int symbol__annotate_init(struct map *map, struct symbol *sym);
int symbol__annotate_printf(struct symbol *sym, struct map *map,
struct perf_evsel *evsel, bool full_paths,

View file

@ -26,6 +26,7 @@
#include "evlist.h"
#include "evsel.h"
#include "machine.h"
#include "config.h"
#define pr_N(n, fmt, ...) \
eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
@ -68,6 +69,9 @@ struct ctf_writer {
};
struct bt_ctf_field_type *array[6];
} data;
struct bt_ctf_event_class *comm_class;
struct bt_ctf_event_class *exit_class;
struct bt_ctf_event_class *fork_class;
};
struct convert {
@ -76,6 +80,7 @@ struct convert {
u64 events_size;
u64 events_count;
u64 non_sample_count;
/* Ordered events configured queue size. */
u64 queue_size;
@ -140,6 +145,36 @@ FUNC_VALUE_SET(s64)
FUNC_VALUE_SET(u64)
__FUNC_VALUE_SET(u64_hex, u64)
static int string_set_value(struct bt_ctf_field *field, const char *string);
static __maybe_unused int
value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event,
const char *name, const char *string)
{
struct bt_ctf_field_type *type = cw->data.string;
struct bt_ctf_field *field;
int ret = 0;
field = bt_ctf_field_create(type);
if (!field) {
pr_err("failed to create a field %s\n", name);
return -1;
}
ret = string_set_value(field, string);
if (ret) {
pr_err("failed to set value %s\n", name);
goto err_put_field;
}
ret = bt_ctf_event_set_payload(event, name, field);
if (ret)
pr_err("failed to set payload %s\n", name);
err_put_field:
bt_ctf_field_put(field);
return ret;
}
static struct bt_ctf_field_type*
get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
{
@ -731,6 +766,72 @@ static int process_sample_event(struct perf_tool *tool,
return cs ? 0 : -1;
}
#define __NON_SAMPLE_SET_FIELD(_name, _type, _field) \
do { \
ret = value_set_##_type(cw, event, #_field, _event->_name._field);\
if (ret) \
return -1; \
} while(0)
#define __FUNC_PROCESS_NON_SAMPLE(_name, body) \
static int process_##_name##_event(struct perf_tool *tool, \
union perf_event *_event, \
struct perf_sample *sample, \
struct machine *machine) \
{ \
struct convert *c = container_of(tool, struct convert, tool);\
struct ctf_writer *cw = &c->writer; \
struct bt_ctf_event_class *event_class = cw->_name##_class;\
struct bt_ctf_event *event; \
struct ctf_stream *cs; \
int ret; \
\
c->non_sample_count++; \
c->events_size += _event->header.size; \
event = bt_ctf_event_create(event_class); \
if (!event) { \
pr_err("Failed to create an CTF event\n"); \
return -1; \
} \
\
bt_ctf_clock_set_time(cw->clock, sample->time); \
body \
cs = ctf_stream(cw, 0); \
if (cs) { \
if (is_flush_needed(cs)) \
ctf_stream__flush(cs); \
\
cs->count++; \
bt_ctf_stream_append_event(cs->stream, event); \
} \
bt_ctf_event_put(event); \
\
return perf_event__process_##_name(tool, _event, sample, machine);\
}
__FUNC_PROCESS_NON_SAMPLE(comm,
__NON_SAMPLE_SET_FIELD(comm, u32, pid);
__NON_SAMPLE_SET_FIELD(comm, u32, tid);
__NON_SAMPLE_SET_FIELD(comm, string, comm);
)
__FUNC_PROCESS_NON_SAMPLE(fork,
__NON_SAMPLE_SET_FIELD(fork, u32, pid);
__NON_SAMPLE_SET_FIELD(fork, u32, ppid);
__NON_SAMPLE_SET_FIELD(fork, u32, tid);
__NON_SAMPLE_SET_FIELD(fork, u32, ptid);
__NON_SAMPLE_SET_FIELD(fork, u64, time);
)
__FUNC_PROCESS_NON_SAMPLE(exit,
__NON_SAMPLE_SET_FIELD(fork, u32, pid);
__NON_SAMPLE_SET_FIELD(fork, u32, ppid);
__NON_SAMPLE_SET_FIELD(fork, u32, tid);
__NON_SAMPLE_SET_FIELD(fork, u32, ptid);
__NON_SAMPLE_SET_FIELD(fork, u64, time);
)
#undef __NON_SAMPLE_SET_FIELD
#undef __FUNC_PROCESS_NON_SAMPLE
/* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
static char *change_name(char *name, char *orig_name, int dup)
{
@ -1005,6 +1106,80 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
return 0;
}
#define __NON_SAMPLE_ADD_FIELD(t, n) \
do { \
pr2(" field '%s'\n", #n); \
if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\
pr_err("Failed to add field '%s';\n", #n);\
return -1; \
} \
} while(0)
#define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body) \
static int add_##_name##_event(struct ctf_writer *cw) \
{ \
struct bt_ctf_event_class *event_class; \
int ret; \
\
pr("Adding "#_name" event\n"); \
event_class = bt_ctf_event_class_create("perf_" #_name);\
if (!event_class) \
return -1; \
body \
\
ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\
if (ret) { \
pr("Failed to add event class '"#_name"' into stream.\n");\
return ret; \
} \
\
cw->_name##_class = event_class; \
bt_ctf_event_class_put(event_class); \
return 0; \
}
__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm,
__NON_SAMPLE_ADD_FIELD(u32, pid);
__NON_SAMPLE_ADD_FIELD(u32, tid);
__NON_SAMPLE_ADD_FIELD(string, comm);
)
__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(fork,
__NON_SAMPLE_ADD_FIELD(u32, pid);
__NON_SAMPLE_ADD_FIELD(u32, ppid);
__NON_SAMPLE_ADD_FIELD(u32, tid);
__NON_SAMPLE_ADD_FIELD(u32, ptid);
__NON_SAMPLE_ADD_FIELD(u64, time);
)
__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit,
__NON_SAMPLE_ADD_FIELD(u32, pid);
__NON_SAMPLE_ADD_FIELD(u32, ppid);
__NON_SAMPLE_ADD_FIELD(u32, tid);
__NON_SAMPLE_ADD_FIELD(u32, ptid);
__NON_SAMPLE_ADD_FIELD(u64, time);
)
#undef __NON_SAMPLE_ADD_FIELD
#undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
static int setup_non_sample_events(struct ctf_writer *cw,
struct perf_session *session __maybe_unused)
{
int ret;
ret = add_comm_event(cw);
if (ret)
return ret;
ret = add_exit_event(cw);
if (ret)
return ret;
ret = add_fork_event(cw);
if (ret)
return ret;
return 0;
}
static void cleanup_events(struct perf_session *session)
{
struct perf_evlist *evlist = session->evlist;
@ -1273,13 +1448,14 @@ static int convert__config(const char *var, const char *value, void *cb)
return 0;
}
int bt_convert__perf2ctf(const char *input, const char *path, bool force)
int bt_convert__perf2ctf(const char *input, const char *path,
struct perf_data_convert_opts *opts)
{
struct perf_session *session;
struct perf_data_file file = {
.path = input,
.mode = PERF_DATA_MODE_READ,
.force = force,
.force = opts->force,
};
struct convert c = {
.tool = {
@ -1299,6 +1475,12 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
struct ctf_writer *cw = &c.writer;
int err = -1;
if (opts->all) {
c.tool.comm = process_comm_event;
c.tool.exit = process_exit_event;
c.tool.fork = process_fork_event;
}
perf_config(convert__config, &c);
/* CTF writer */
@ -1323,6 +1505,9 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
if (setup_events(cw, session))
goto free_session;
if (opts->all && setup_non_sample_events(cw, session))
goto free_session;
if (setup_streams(cw, session))
goto free_session;
@ -1337,10 +1522,15 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
file.path, path);
fprintf(stderr,
"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
"[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
(double) c.events_size / 1024.0 / 1024.0,
c.events_count);
if (!c.non_sample_count)
fprintf(stderr, ") ]\n");
else
fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
cleanup_events(session);
perf_session__delete(session);
ctf_writer__cleanup(cw);

View file

@ -1,8 +1,10 @@
#ifndef __DATA_CONVERT_BT_H
#define __DATA_CONVERT_BT_H
#include "data-convert.h"
#ifdef HAVE_LIBBABELTRACE_SUPPORT
int bt_convert__perf2ctf(const char *input_name, const char *to_ctf, bool force);
int bt_convert__perf2ctf(const char *input_name, const char *to_ctf,
struct perf_data_convert_opts *opts);
#endif /* HAVE_LIBBABELTRACE_SUPPORT */
#endif /* __DATA_CONVERT_BT_H */

View file

@ -0,0 +1,9 @@
#ifndef __DATA_CONVERT_H
#define __DATA_CONVERT_H
struct perf_data_convert_opts {
bool force;
bool all;
};
#endif /* __DATA_CONVERT_H */

View file

@ -1430,7 +1430,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
* Read the build id if possible. This is required for
* DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
*/
if (is_regular_file(name) &&
if (is_regular_file(dso->long_name) &&
filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0)
dso__set_build_id(dso, build_id);