Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 323670
b: refs/heads/master
c: 71ad0f5
h: refs/heads/master
v: v3
  • Loading branch information
Jiri Olsa authored and Arnaldo Carvalho de Melo committed Aug 11, 2012
1 parent 5253ba9 commit ba89a98
Show file tree
Hide file tree
Showing 14 changed files with 796 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0f6a30150ca2e0cf4f893e7173d61434a3c02e0e
refs/heads/master: 71ad0f5e4e361c8bca864c7d09d14b64af6bc2fc
2 changes: 2 additions & 0 deletions trunk/tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ LIB_H += util/target.h
LIB_H += util/rblist.h
LIB_H += util/intlist.h
LIB_H += util/perf_regs.h
LIB_H += util/unwind.h

LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
Expand Down Expand Up @@ -547,6 +548,7 @@ else
EXTLIBS += $(LIBUNWIND_LIBS)
BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS)
BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS)
LIB_OBJS += $(OUTPUT)util/unwind.o
endif

ifdef NO_NEWT
Expand Down
3 changes: 3 additions & 0 deletions trunk/tools/perf/arch/x86/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif
ifndef NO_LIBUNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
endif
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
111 changes: 111 additions & 0 deletions trunk/tools/perf/arch/x86/util/unwind.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@

#include <errno.h>
#include <libunwind.h>
#include "perf_regs.h"
#include "../../util/unwind.h"

#ifdef ARCH_X86_64
int unwind__arch_reg_id(int regnum)
{
int id;

switch (regnum) {
case UNW_X86_64_RAX:
id = PERF_REG_X86_AX;
break;
case UNW_X86_64_RDX:
id = PERF_REG_X86_DX;
break;
case UNW_X86_64_RCX:
id = PERF_REG_X86_CX;
break;
case UNW_X86_64_RBX:
id = PERF_REG_X86_BX;
break;
case UNW_X86_64_RSI:
id = PERF_REG_X86_SI;
break;
case UNW_X86_64_RDI:
id = PERF_REG_X86_DI;
break;
case UNW_X86_64_RBP:
id = PERF_REG_X86_BP;
break;
case UNW_X86_64_RSP:
id = PERF_REG_X86_SP;
break;
case UNW_X86_64_R8:
id = PERF_REG_X86_R8;
break;
case UNW_X86_64_R9:
id = PERF_REG_X86_R9;
break;
case UNW_X86_64_R10:
id = PERF_REG_X86_R10;
break;
case UNW_X86_64_R11:
id = PERF_REG_X86_R11;
break;
case UNW_X86_64_R12:
id = PERF_REG_X86_R12;
break;
case UNW_X86_64_R13:
id = PERF_REG_X86_R13;
break;
case UNW_X86_64_R14:
id = PERF_REG_X86_R14;
break;
case UNW_X86_64_R15:
id = PERF_REG_X86_R15;
break;
case UNW_X86_64_RIP:
id = PERF_REG_X86_IP;
break;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}

return id;
}
#else
int unwind__arch_reg_id(int regnum)
{
int id;

switch (regnum) {
case UNW_X86_EAX:
id = PERF_REG_X86_AX;
break;
case UNW_X86_EDX:
id = PERF_REG_X86_DX;
break;
case UNW_X86_ECX:
id = PERF_REG_X86_CX;
break;
case UNW_X86_EBX:
id = PERF_REG_X86_BX;
break;
case UNW_X86_ESI:
id = PERF_REG_X86_SI;
break;
case UNW_X86_EDI:
id = PERF_REG_X86_DI;
break;
case UNW_X86_EBP:
id = PERF_REG_X86_BP;
break;
case UNW_X86_ESP:
id = PERF_REG_X86_SP;
break;
case UNW_X86_EIP:
id = PERF_REG_X86_IP;
break;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}

return id;
}
#endif /* ARCH_X86_64 */
18 changes: 9 additions & 9 deletions trunk/tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,

if ((sort__has_parent || symbol_conf.use_callchain)
&& sample->callchain) {
err = machine__resolve_callchain(machine, al->thread,
sample->callchain, &parent);
err = machine__resolve_callchain(machine, evsel, al->thread,
sample, &parent);
if (err)
return err;
}
Expand Down Expand Up @@ -140,8 +140,8 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
struct hist_entry *he;

if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
err = machine__resolve_callchain(machine, al->thread,
sample->callchain, &parent);
err = machine__resolve_callchain(machine, evsel, al->thread,
sample, &parent);
if (err)
return err;
}
Expand Down Expand Up @@ -397,17 +397,17 @@ static int __cmd_report(struct perf_report *rep)
desc);
}

if (dump_trace) {
perf_session__fprintf_nr_events(session, stdout);
goto out_delete;
}

if (verbose > 3)
perf_session__fprintf(session, stdout);

if (verbose > 2)
perf_session__fprintf_dsos(session, stdout);

if (dump_trace) {
perf_session__fprintf_nr_events(session, stdout);
goto out_delete;
}

nr_samples = 0;
list_for_each_entry(pos, &session->evlist->entries, node) {
struct hists *hists = &pos->hists;
Expand Down
4 changes: 2 additions & 2 deletions trunk/tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ static void print_sample_bts(union perf_event *event,
printf(" ");
else
printf("\n");
perf_event__print_ip(event, sample, machine,
perf_evsel__print_ip(evsel, event, sample, machine,
PRINT_FIELD(SYM), PRINT_FIELD(DSO),
PRINT_FIELD(SYMOFFSET));
}
Expand Down Expand Up @@ -422,7 +422,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
printf(" ");
else
printf("\n");
perf_event__print_ip(event, sample, machine,
perf_evsel__print_ip(evsel, event, sample, machine,
PRINT_FIELD(SYM), PRINT_FIELD(DSO),
PRINT_FIELD(SYMOFFSET));
}
Expand Down
6 changes: 4 additions & 2 deletions trunk/tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,8 +783,10 @@ static void perf_event__process_sample(struct perf_tool *tool,

if ((sort__has_parent || symbol_conf.use_callchain) &&
sample->callchain) {
err = machine__resolve_callchain(machine, al.thread,
sample->callchain, &parent);
err = machine__resolve_callchain(machine, evsel,
al.thread, sample,
&parent);

if (err)
return;
}
Expand Down
1 change: 1 addition & 0 deletions trunk/tools/perf/util/include/linux/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
#endif

#define __used __attribute__((__unused__))
#define __packed __attribute__((__packed__))

#endif
5 changes: 4 additions & 1 deletion trunk/tools/perf/util/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,12 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid);
void machine__exit(struct machine *self);
void machine__delete(struct machine *self);

struct perf_evsel;
struct perf_sample;
int machine__resolve_callchain(struct machine *machine,
struct perf_evsel *evsel,
struct thread *thread,
struct ip_callchain *chain,
struct perf_sample *sample,
struct symbol **parent);
int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
u64 addr);
Expand Down
66 changes: 53 additions & 13 deletions trunk/tools/perf/util/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "cpumap.h"
#include "event-parse.h"
#include "perf_regs.h"
#include "unwind.h"

static int perf_session__open(struct perf_session *self, bool force)
{
Expand Down Expand Up @@ -289,10 +290,11 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
return bi;
}

int machine__resolve_callchain(struct machine *self,
struct thread *thread,
struct ip_callchain *chain,
struct symbol **parent)
static int machine__resolve_callchain_sample(struct machine *machine,
struct thread *thread,
struct ip_callchain *chain,
struct symbol **parent)

{
u8 cpumode = PERF_RECORD_MISC_USER;
unsigned int i;
Expand All @@ -317,11 +319,14 @@ int machine__resolve_callchain(struct machine *self,
if (ip >= PERF_CONTEXT_MAX) {
switch (ip) {
case PERF_CONTEXT_HV:
cpumode = PERF_RECORD_MISC_HYPERVISOR; break;
cpumode = PERF_RECORD_MISC_HYPERVISOR;
break;
case PERF_CONTEXT_KERNEL:
cpumode = PERF_RECORD_MISC_KERNEL; break;
cpumode = PERF_RECORD_MISC_KERNEL;
break;
case PERF_CONTEXT_USER:
cpumode = PERF_RECORD_MISC_USER; break;
cpumode = PERF_RECORD_MISC_USER;
break;
default:
pr_debug("invalid callchain context: "
"%"PRId64"\n", (s64) ip);
Expand All @@ -336,7 +341,7 @@ int machine__resolve_callchain(struct machine *self,
}

al.filtered = false;
thread__find_addr_location(thread, self, cpumode,
thread__find_addr_location(thread, machine, cpumode,
MAP__FUNCTION, ip, &al, NULL);
if (al.sym != NULL) {
if (sort__has_parent && !*parent &&
Expand All @@ -355,6 +360,40 @@ int machine__resolve_callchain(struct machine *self,
return 0;
}

static int unwind_entry(struct unwind_entry *entry, void *arg)
{
struct callchain_cursor *cursor = arg;
return callchain_cursor_append(cursor, entry->ip,
entry->map, entry->sym);
}

int machine__resolve_callchain(struct machine *machine,
struct perf_evsel *evsel,
struct thread *thread,
struct perf_sample *sample,
struct symbol **parent)

{
int ret;

callchain_cursor_reset(&callchain_cursor);

ret = machine__resolve_callchain_sample(machine, thread,
sample->callchain, parent);
if (ret)
return ret;

/* Can we do dwarf post unwind? */
if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
(evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
return 0;

return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
thread, evsel->attr.sample_regs_user,
sample);

}

static int process_event_synth_tracing_data_stub(union perf_event *event __used,
struct perf_session *session __used)
{
Expand Down Expand Up @@ -1533,9 +1572,9 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
return NULL;
}

void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
struct machine *machine, int print_sym,
int print_dso, int print_symoffset)
void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
struct perf_sample *sample, struct machine *machine,
int print_sym, int print_dso, int print_symoffset)
{
struct addr_location al;
struct callchain_cursor_node *node;
Expand All @@ -1549,8 +1588,9 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,

if (symbol_conf.use_callchain && sample->callchain) {

if (machine__resolve_callchain(machine, al.thread,
sample->callchain, NULL) != 0) {

if (machine__resolve_callchain(machine, evsel, al.thread,
sample, NULL) != 0) {
if (verbose)
error("Failed to resolve callchain. Skipping\n");
return;
Expand Down
6 changes: 3 additions & 3 deletions trunk/tools/perf/util/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
unsigned int type);

void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
struct machine *machine, int print_sym,
int print_dso, int print_symoffset);
void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
struct perf_sample *sample, struct machine *machine,
int print_sym, int print_dso, int print_symoffset);

int perf_session__cpu_bitmap(struct perf_session *session,
const char *cpu_list, unsigned long *cpu_bitmap);
Expand Down
2 changes: 2 additions & 0 deletions trunk/tools/perf/util/trace-event.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ void tracing_data_put(struct tracing_data *tdata);

struct addr_location;

struct perf_session;

struct scripting_ops {
const char *name;
int (*start_script) (const char *script, int argc, const char **argv);
Expand Down
Loading

0 comments on commit ba89a98

Please sign in to comment.