Skip to content
Merged
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
10 changes: 10 additions & 0 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
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
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);
}