Skip to content

Granulate changes to perf #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tools/build/feature/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ $(OUTPUT)test-libopencsd.bin:

DWARFLIBS := -ldw
ifeq ($(findstring -static,${LDFLAGS}),-static)
DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
DWARFLIBS += -lelf -lz -llzma -lbz2 -lpthread
endif

$(OUTPUT)test-dwarf.bin:
Expand Down
39 changes: 39 additions & 0 deletions tools/perf/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
FROM ubuntu:xenial-20200619

WORKDIR /code
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
build-essential \
git \
curl \
autoconf \
asciidoc \
libssl-dev \
zlib1g-dev \
libaudit-dev \
binutils-dev \
libiberty-dev \
libcap-dev \
libdwarf-dev \
liblzma-dev \
libnuma-dev \
libbabeltrace-ctf-dev \
systemtap-sdt-dev \
libslang2-dev \
libzstd-dev \
libbz2-dev \
flex \
bison \
;

# Installing a new version of elfutils and libunwind
RUN curl -L ftp://sourceware.org/pub/elfutils/0.179/elfutils-0.179.tar.bz2 -o /tmp/elfutils-0.179.tar.bz2
RUN cd /tmp && tar -xf elfutils-0.179.tar.bz2
RUN cd /tmp/elfutils-0.179 && ./configure --disable-debuginfod --prefix=/usr && make && make install

RUN curl -L http://download.savannah.nongnu.org/releases/libunwind/libunwind-1.4.0.tar.gz -o /tmp/libunwind-1.4.0.tar.gz
RUN cd /tmp && tar -xf libunwind-1.4.0.tar.gz
RUN cd /tmp/libunwind-1.4.0 && ./configure --prefix=/usr && make install

CMD bash
2 changes: 1 addition & 1 deletion tools/perf/Makefile.config
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ ifdef LIBDW_DIR
endif
DWARFLIBS := -ldw
ifeq ($(findstring -static,${LDFLAGS}),-static)
DWARFLIBS += -lelf -lebl -ldl -lz -llzma -lbz2
DWARFLIBS += -lelf -ldl -lz -llzma -lbz2 -lpthread
endif
FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) $(DWARFLIBS)
Expand Down
8 changes: 5 additions & 3 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -3212,25 +3212,27 @@ static int switch_output_setup(struct record *rec)
return 0;
}

if (!strcmp(s->str, "signal")) {
// strstr, not strcmp, to allow it to be used with size/time.
if (strstr(s->str, "signal")) {
do_signal:
s->signal = true;
pr_debug("switch-output with SIGUSR2 signal\n");
goto enabled;
}

val = parse_tag_value(s->str, tags_size);
if (val != (unsigned long) -1) {
s->size = val;
pr_debug("switch-output with %s size threshold\n", s->str);
goto enabled;
}

val = parse_tag_value(s->str, tags_time);
if (val != (unsigned long) -1) {
s->time = val;
pr_debug("switch-output with %s time threshold (%lu seconds)\n",
s->str, s->time);
}

if (s->size || s->time || s->signal) {
goto enabled;
}

Expand Down
18 changes: 13 additions & 5 deletions tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ enum perf_output_field {
PERF_OUTPUT_CGROUP = 1ULL << 39,
PERF_OUTPUT_RETIRE_LAT = 1ULL << 40,
PERF_OUTPUT_DSOFF = 1ULL << 41,
PERF_OUTPUT_SYMLINE = 1ULL << 42,
};

struct perf_script {
Expand Down Expand Up @@ -178,6 +179,7 @@ struct output_option {
{.str = "dsoff", .field = PERF_OUTPUT_DSOFF},
{.str = "addr", .field = PERF_OUTPUT_ADDR},
{.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
{.str = "symline", .field = PERF_OUTPUT_SYMLINE},
{.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
{.str = "period", .field = PERF_OUTPUT_PERIOD},
{.str = "iregs", .field = PERF_OUTPUT_IREGS},
Expand Down Expand Up @@ -497,6 +499,11 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
"selected.\n");
return -EINVAL;
}
if (PRINT_FIELD(SYMLINE) && !PRINT_FIELD(SYM)) {
pr_err("Display of line offsets requested but symbol is not"
"selected.\n");
return -EINVAL;
}
if (PRINT_FIELD(DSO) &&
!(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
pr_err("Display of DSO requested but no address to convert.\n");
Expand Down Expand Up @@ -582,6 +589,9 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
if (PRINT_FIELD(SYMOFFSET))
output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;

if (PRINT_FIELD(SYMLINE))
output[type].print_ip_opts |= EVSEL__PRINT_SYMLINE;

if (PRINT_FIELD(SRCLINE))
output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
}
Expand Down Expand Up @@ -790,14 +800,12 @@ static int perf_sample__fprintf_start(struct perf_script *script,
printed += fprintf(fp, "VCPU:%03d ", sample->vcpu);

if (PRINT_FIELD(COMM)) {
const char *comm = thread ? thread__comm_str(thread) : ":-1";

if (latency_format)
printed += fprintf(fp, "%8.8s ", comm);
printed += fprintf(fp, "%8.8s ", thread__exec_comm_str(thread));
else if (PRINT_FIELD(IP) && evsel__has_callchain(evsel) && symbol_conf.use_callchain)
printed += fprintf(fp, "%s ", comm);
printed += fprintf(fp, "%s ", thread__exec_comm_str(thread));
else
printed += fprintf(fp, "%16s ", comm);
printed += fprintf(fp, "%16s ", thread__exec_comm_str(thread));
}

if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
Expand Down
5 changes: 4 additions & 1 deletion tools/perf/util/evsel_fprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
int print_dso = print_opts & EVSEL__PRINT_DSO;
int print_dsoff = print_opts & EVSEL__PRINT_DSOFF;
int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
int print_symline = print_opts & EVSEL__PRINT_SYMLINE;
int print_oneline = print_opts & EVSEL__PRINT_ONELINE;
int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
Expand Down Expand Up @@ -167,7 +168,9 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
node_al.addr = addr;
node_al.map = map__get(map);

if (print_symoffset) {
if (print_symline) {
printed += symbol__fprintf_symline_offs(sym, &node_al, fp);
} else if (print_symoffset) {
printed += __symbol__fprintf_symname_offs(sym, &node_al,
print_unknown_as_addr,
true, fp);
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/evsel_fprintf.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ int evsel__fprintf(struct evsel *evsel, struct perf_attr_details *details, FILE
#define EVSEL__PRINT_CALLCHAIN_ARROW (1<<7)
#define EVSEL__PRINT_SKIP_IGNORED (1<<8)
#define EVSEL__PRINT_DSOFF (1<<9)
#define EVSEL__PRINT_SYMLINE (1<<10)

struct addr_location;
struct perf_event_attr;
Expand Down
5 changes: 5 additions & 0 deletions tools/perf/util/probe-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
*/
clear_perf_probe_point(&pev->point);
memcpy(&pev->point, &tmp, sizeof(tmp));
} else {
if (need_dwarf)
return -ENOENT;
pr_debug("Failed to use debug info. Try to use symbols.\n");
return 0;
}
}

Expand Down
23 changes: 18 additions & 5 deletions tools/perf/util/probe-finder.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,23 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
}

/* If this is based on frame buffer, set the offset */
if (op->atom == DW_OP_fbreg) {
if (op->atom == DW_OP_fbreg || op->atom == DW_OP_call_frame_cfa) {
if (fb_ops == NULL)
return -ENOTSUP;
ref = true;
offs = op->number;
if (op->atom == DW_OP_fbreg) {
offs = op->number;
} else if (nops == 3) {
/*
* In the case of DW_OP_call_frame_cfa, we either have
* an offset of 0 or we have two more expressions that
* add a const
*/
if ((op + 1)->atom != DW_OP_consts ||
(op + 2)->atom != DW_OP_plus)
return -ENOTSUP;
offs = (op + 1)->number;
}
op = &fb_ops[0];
}

Expand Down Expand Up @@ -376,10 +388,11 @@ static int convert_variable_type(Dwarf_Die *vr_die,
(*ref_ptr)->user_access = user_access;
}
if (!die_compare_name(&type, "char") &&
!die_compare_name(&type, "unsigned char")) {
!die_compare_name(&type, "unsigned char") &&
!die_compare_name(&type, "uint8")) {
pr_warning("Failed to cast into string: "
"%s is not (unsigned) char *.\n",
dwarf_diename(vr_die));
"%s is not (unsigned) char * or uint8 *, it is %s *.\n",
dwarf_diename(vr_die), dwarf_diename(&type));
return -EINVAL;
}
tvar->type = strdup(cast);
Expand Down
6 changes: 6 additions & 0 deletions tools/perf/util/symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ void symbol__elf_init(void);
int symbol__annotation_init(void);

struct symbol *symbol__new(u64 start, u64 len, u8 binding, u8 type, const char *name);
size_t __symbol__fprintf_sym_offs(const struct symbol *sym,
const struct addr_location *al,
bool unknown_as_addr, bool print_offsets,
bool print_line, FILE *fp);
size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al,
bool unknown_as_addr,
Expand All @@ -171,6 +175,8 @@ bool symbol__restricted_filename(const char *filename,
const char *restricted_filename);
int symbol__config_symfs(const struct option *opt __maybe_unused,
const char *dir, int unset __maybe_unused);
size_t symbol__fprintf_symline_offs(const struct symbol *sym,
const struct addr_location *al, FILE *fp);

struct symsrc;

Expand Down
54 changes: 44 additions & 10 deletions tools/perf/util/symbol_fprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "dso.h"
#include "map.h"
#include "symbol.h"
#include "srcline.h"

size_t symbol__fprintf(struct symbol *sym, FILE *fp)
{
Expand All @@ -16,22 +17,40 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp)
sym->name);
}

size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al,
bool unknown_as_addr,
bool print_offsets, FILE *fp)
size_t __symbol__fprintf_sym_offs(const struct symbol *sym,
const struct addr_location *al,
bool unknown_as_addr, bool print_offsets,
bool print_line, FILE *fp)
{
unsigned long offset;
size_t length;

if (sym) {
length = fprintf(fp, "%s", sym->name);
if (al && print_offsets) {
if (al->addr < sym->end)
offset = al->addr - sym->start;
else
offset = al->addr - map__start(al->map) - sym->start;
length += fprintf(fp, "+0x%lx", offset);
if (al && (print_offsets || print_line)) {
if (print_line) {
int ret = 0;
char *srcline = map__srcline(al->map, al->addr, NULL);
if (srcline != SRCLINE_UNKNOWN) {
ret = fprintf(fp, "+%s", srcline);
if (ret > 0)
length += (size_t)ret;
}
zfree_srcline(&srcline);
srcline = map__srcline(al->map, sym->start, NULL);
if (srcline != SRCLINE_UNKNOWN) {
ret = fprintf(fp, "+%s", srcline);
if (ret > 0)
length += (size_t)ret;
}
zfree_srcline(&srcline);
} else {
if (al->addr < sym->end)
offset = al->addr - sym->start;
else
offset = al->addr - map__start(al->map) - sym->start;
length += fprintf(fp, "+0x%lx", offset);
}
}
return length;
} else if (al && unknown_as_addr)
Expand All @@ -40,6 +59,15 @@ size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
return fprintf(fp, "[unknown]");
}

size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al,
bool unknown_as_addr, bool print_offsets,
FILE *fp)
{
return __symbol__fprintf_sym_offs(sym, al, unknown_as_addr,
print_offsets, false, fp);
}

size_t symbol__fprintf_symname_offs(const struct symbol *sym,
const struct addr_location *al,
FILE *fp)
Expand Down Expand Up @@ -71,3 +99,9 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
}
return ret;
}

size_t symbol__fprintf_symline_offs(const struct symbol *sym,
const struct addr_location *al, FILE *fp)
{
return __symbol__fprintf_sym_offs(sym, al, false, false, true, fp);
}
23 changes: 22 additions & 1 deletion tools/perf/util/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,27 @@ const char *thread__comm_str(struct thread *thread)
return str;
}

static const char *__thread__exec_comm_str(struct thread *thread)
{
const struct comm *comm = thread__exec_comm(thread);

if (!comm)
return NULL;

return comm__str(comm);
}

const char *thread__exec_comm_str(struct thread *thread)
{
const char *str;

down_read(&thread->comm_lock);
str = __thread__exec_comm_str(thread);
up_read(&thread->comm_lock);

return str;
}

static int __thread__comm_len(struct thread *thread, const char *comm)
{
if (!comm)
Expand Down Expand Up @@ -398,7 +419,7 @@ static int thread__clone_maps(struct thread *thread, struct thread *parent, bool
int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone)
{
if (thread__comm_set(parent)) {
const char *comm = thread__comm_str(parent);
const char *comm = thread__exec_comm_str(parent);
int err;
if (!comm)
return -ENOMEM;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ int thread__comm_len(struct thread *thread);
struct comm *thread__comm(struct thread *thread);
struct comm *thread__exec_comm(struct thread *thread);
const char *thread__comm_str(struct thread *thread);
const char *thread__exec_comm_str(struct thread *thread);
int thread__insert_map(struct thread *thread, struct map *map);
int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone);
size_t thread__fprintf(struct thread *thread, FILE *fp);
Expand Down