From 0680ee7db16de9c02d1d4b1a935a5daf754fe8a1 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 12 May 2014 20:19:46 +0200 Subject: [PATCH 1/8] perf tools: Remove usage of trace_sched_wakeup(.success) trace_sched_wakeup(.success) is a dead argument and has been for ages, the only reason its still there is because of brain dead software, which apparently includes perf tools There's a few more instances in pearly snake shit, but that's not supported as far as I care anyhow, so let that bitrot. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20140512181946.GG13467@laptop.programming.kicks-ass.net Signed-off-by: Jiri Olsa --- tools/perf/builtin-sched.c | 7 +------ tools/perf/tests/evsel-tp-sched.c | 3 --- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 2579215f5743..a3320f1cda69 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1007,17 +1007,12 @@ static int latency_wakeup_event(struct perf_sched *sched, struct perf_sample *sample, struct machine *machine) { - const u32 pid = perf_evsel__intval(evsel, sample, "pid"), - success = perf_evsel__intval(evsel, sample, "success"); + const u32 pid = perf_evsel__intval(evsel, sample, "pid"); struct work_atoms *atoms; struct work_atom *atom; struct thread *wakee; u64 timestamp = sample->time; - /* Note for later, it may be interesting to observe the failing cases */ - if (!success) - return 0; - wakee = machine__findnew_thread(machine, 0, pid); atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); if (!atoms) { diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 4774f7fbb758..35d7fdb2328d 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -74,9 +74,6 @@ int test__perf_evsel__tp_sched_test(void) if (perf_evsel__test_field(evsel, "prio", 4, true)) ret = -1; - if (perf_evsel__test_field(evsel, "success", 4, true)) - ret = -1; - if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) ret = -1; From 67d6259dd021006ade25d67b045ad2089b5aba96 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Tue, 13 May 2014 10:38:21 +0900 Subject: [PATCH 2/8] perf sched: Remove nr_state_machine_bugs in perf latency As we do not use .success in sched_wakeup event any more, then we can not guarantee that the task when wakeup event happen is out of run queue. So the message of nr_state_machine_bugs is not correct. Signed-off-by: Dongsheng Yang Link: http://lkml.kernel.org/r/1399945101-21736-1-git-send-email-yangds.fnst@cn.fujitsu.com Signed-off-by: Jiri Olsa --- tools/perf/builtin-sched.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index a3320f1cda69..0b4fe533e1a1 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -149,7 +149,6 @@ struct perf_sched { unsigned long nr_runs; unsigned long nr_timestamps; unsigned long nr_unordered_timestamps; - unsigned long nr_state_machine_bugs; unsigned long nr_context_switch_bugs; unsigned long nr_events; unsigned long nr_lost_chunks; @@ -1032,12 +1031,18 @@ static int latency_wakeup_event(struct perf_sched *sched, atom = list_entry(atoms->work_list.prev, struct work_atom, list); /* + * As we do not guarantee the wakeup event happens when + * task is out of run queue, also may happen when task is + * on run queue and wakeup only change ->state to TASK_RUNNING, + * then we should not set the ->wake_up_time when wake up a + * task which is on run queue. + * * You WILL be missing events if you've recorded only * one CPU, or are only looking at only one, so don't - * make useless noise. + * skip in this case. */ if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING) - sched->nr_state_machine_bugs++; + return 0; sched->nr_timestamps++; if (atom->sched_out_time > timestamp) { @@ -1496,14 +1501,6 @@ static void print_bad_events(struct perf_sched *sched) (double)sched->nr_lost_events/(double)sched->nr_events * 100.0, sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks); } - if (sched->nr_state_machine_bugs && sched->nr_timestamps) { - printf(" INFO: %.3f%% state machine bugs (%ld out of %ld)", - (double)sched->nr_state_machine_bugs/(double)sched->nr_timestamps*100.0, - sched->nr_state_machine_bugs, sched->nr_timestamps); - if (sched->nr_lost_events) - printf(" (due to lost events?)"); - printf("\n"); - } if (sched->nr_context_switch_bugs && sched->nr_timestamps) { printf(" INFO: %.3f%% context switch bugs (%ld out of %ld)", (double)sched->nr_context_switch_bugs/(double)sched->nr_timestamps*100.0, From 9d372ca59bcb9339b4a34a9bf978a1fc15b68b03 Mon Sep 17 00:00:00 2001 From: Dongsheng Yang Date: Fri, 16 May 2014 14:37:05 +0900 Subject: [PATCH 3/8] perf sched: Cleanup, remove unused variables in map_switch_event() In map_switch_event(), we don't care the previous process currently, this patch remove the infomation we get but not used. Signed-off-by: Dongsheng Yang Link: http://lkml.kernel.org/r/1400218625-14613-1-git-send-email-yangds.fnst@cn.fujitsu.com Signed-off-by: Jiri Olsa --- tools/perf/builtin-sched.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 0b4fe533e1a1..d7176830b9b2 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1266,9 +1266,8 @@ static int process_sched_wakeup_event(struct perf_tool *tool, static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine) { - const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), - next_pid = perf_evsel__intval(evsel, sample, "next_pid"); - struct thread *sched_out __maybe_unused, *sched_in; + const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid"); + struct thread *sched_in; int new_shortname; u64 timestamp0, timestamp = sample->time; s64 delta; @@ -1291,7 +1290,6 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, return -1; } - sched_out = machine__findnew_thread(machine, 0, prev_pid); sched_in = machine__findnew_thread(machine, 0, next_pid); sched->curr_thread[this_cpu] = sched_in; From c5765ece8a050836c6255e1276fc8e0e867078da Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 15 May 2014 02:13:38 +0900 Subject: [PATCH 4/8] perf session: Fix possible null pointer dereference in session.c cppcheck detected following warning: [tools/perf/util/session.c:1628] -> [tools/perf/util/session.c:1632]: (warning) Possible null pointer dereference: session - otherwise it is redundant to check it against null. In order to avoide null pointer, check the pointer before use. Signed-off-by: Masanari Iida Link: http://lkml.kernel.org/r/1400087618-13628-1-git-send-email-standby24x7@gmail.com Signed-off-by: Jiri Olsa --- tools/perf/util/session.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 55960f22233c..64a186edc7be 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1625,13 +1625,14 @@ int perf_session__cpu_bitmap(struct perf_session *session, void perf_session__fprintf_info(struct perf_session *session, FILE *fp, bool full) { - int fd = perf_data_file__fd(session->file); struct stat st; - int ret; + int fd, ret; if (session == NULL || fp == NULL) return; + fd = perf_data_file__fd(session->file); + ret = fstat(fd, &st); if (ret == -1) return; From 21a8b756b84ecaa0b7f29199669c151e2ce5e723 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Fri, 16 May 2014 10:41:09 +0200 Subject: [PATCH 5/8] perf tools: Consolidate types.h for ARM and ARM64 Prevents a build breakage since commit d944c4eebcf4c0d5e5d9728fec110cbf0047ad7f 'tools: Consolidate types.h' Signed-off-by: Jean Pihet Link: http://lkml.kernel.org/r/1400229672-16104-1-git-send-email-jean.pihet@linaro.org Signed-off-by: Jiri Olsa --- tools/perf/arch/arm/include/perf_regs.h | 2 +- tools/perf/arch/arm64/include/perf_regs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/arch/arm/include/perf_regs.h b/tools/perf/arch/arm/include/perf_regs.h index 2a1cfde66b69..bcca511f5884 100644 --- a/tools/perf/arch/arm/include/perf_regs.h +++ b/tools/perf/arch/arm/include/perf_regs.h @@ -2,7 +2,7 @@ #define ARCH_PERF_REGS_H #include -#include "../../util/types.h" +#include #include #define PERF_REGS_MASK ((1ULL << PERF_REG_ARM_MAX) - 1) diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h index 23595467402d..e9441b9e2a30 100644 --- a/tools/perf/arch/arm64/include/perf_regs.h +++ b/tools/perf/arch/arm64/include/perf_regs.h @@ -2,7 +2,7 @@ #define ARCH_PERF_REGS_H #include -#include "../../util/types.h" +#include #include #define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1) From 3418f9667e8cc4070a86215e6c12baa5bc2f2799 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Fri, 16 May 2014 10:41:10 +0200 Subject: [PATCH 6/8] perf tests: Introduce perf_regs_load function on ARM Introducing perf_regs_load function, which is going to be used for dwarf unwind test in following patches. It takes single argument as a pointer to the regs dump buffer and populates it with current registers values. Signed-off-by: Jean Pihet Reviewed-by: Will Deacon Cc: Arnaldo Carvalho de Melo Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1400229672-16104-2-git-send-email-jean.pihet@linaro.org Signed-off-by: Jiri Olsa --- tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm/include/perf_regs.h | 2 + tools/perf/arch/arm/tests/regs_load.S | 58 +++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 tools/perf/arch/arm/tests/regs_load.S diff --git a/tools/perf/arch/arm/Makefile b/tools/perf/arch/arm/Makefile index 67e9b3d38e89..9b8f87e8c7b9 100644 --- a/tools/perf/arch/arm/Makefile +++ b/tools/perf/arch/arm/Makefile @@ -4,4 +4,5 @@ LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o endif ifndef NO_LIBUNWIND LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o endif diff --git a/tools/perf/arch/arm/include/perf_regs.h b/tools/perf/arch/arm/include/perf_regs.h index bcca511f5884..33abcfa3057c 100644 --- a/tools/perf/arch/arm/include/perf_regs.h +++ b/tools/perf/arch/arm/include/perf_regs.h @@ -5,6 +5,8 @@ #include #include +void perf_regs_load(u64 *regs); + #define PERF_REGS_MASK ((1ULL << PERF_REG_ARM_MAX) - 1) #define PERF_REG_IP PERF_REG_ARM_PC #define PERF_REG_SP PERF_REG_ARM_SP diff --git a/tools/perf/arch/arm/tests/regs_load.S b/tools/perf/arch/arm/tests/regs_load.S new file mode 100644 index 000000000000..e09e983946fe --- /dev/null +++ b/tools/perf/arch/arm/tests/regs_load.S @@ -0,0 +1,58 @@ +#include + +#define R0 0x00 +#define R1 0x08 +#define R2 0x10 +#define R3 0x18 +#define R4 0x20 +#define R5 0x28 +#define R6 0x30 +#define R7 0x38 +#define R8 0x40 +#define R9 0x48 +#define SL 0x50 +#define FP 0x58 +#define IP 0x60 +#define SP 0x68 +#define LR 0x70 +#define PC 0x78 + +/* + * Implementation of void perf_regs_load(u64 *regs); + * + * This functions fills in the 'regs' buffer from the actual registers values, + * in the way the perf built-in unwinding test expects them: + * - the PC at the time at the call to this function. Since this function + * is called using a bl instruction, the PC value is taken from LR. + * The built-in unwinding test then unwinds the call stack from the dwarf + * information in unwind__get_entries. + * + * Notes: + * - the 8 bytes stride in the registers offsets comes from the fact + * that the registers are stored in an u64 array (u64 *regs), + * - the regs buffer needs to be zeroed before the call to this function, + * in this case using a calloc in dwarf-unwind.c. + */ + +.text +.type perf_regs_load,%function +ENTRY(perf_regs_load) + str r0, [r0, #R0] + str r1, [r0, #R1] + str r2, [r0, #R2] + str r3, [r0, #R3] + str r4, [r0, #R4] + str r5, [r0, #R5] + str r6, [r0, #R6] + str r7, [r0, #R7] + str r8, [r0, #R8] + str r9, [r0, #R9] + str sl, [r0, #SL] + str fp, [r0, #FP] + str ip, [r0, #IP] + str sp, [r0, #SP] + str lr, [r0, #LR] + str lr, [r0, #PC] // store pc as lr in order to skip the call + // to this function + mov pc, lr +ENDPROC(perf_regs_load) From 90fa9deb32b908fb258225ab562c4ef7ae8dd35a Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Fri, 16 May 2014 10:41:11 +0200 Subject: [PATCH 7/8] perf tests: Add dwarf unwind test on ARM Adding dwarf unwind test, that setups live machine data over the perf test thread and does the remote unwind. Need to use -fno-optimize-sibling-calls for test compilation, otherwise 'krava_*' function calls are optimized into jumps and omitted from the stack unwind. So far it was enabled only for x86. Signed-off-by: Jean Pihet Reviewed-by: Will Deacon Cc: Arnaldo Carvalho de Melo Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1400229672-16104-3-git-send-email-jean.pihet@linaro.org Signed-off-by: Jiri Olsa --- tools/perf/Makefile.perf | 2 +- tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm/include/perf_regs.h | 3 ++ tools/perf/arch/arm/tests/dwarf-unwind.c | 60 ++++++++++++++++++++++++ tools/perf/config/Makefile | 4 +- tools/perf/tests/builtin-test.c | 2 +- tools/perf/tests/tests.h | 2 +- 7 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 tools/perf/arch/arm/tests/dwarf-unwind.c diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 2baf61cec7ff..dea2d633c374 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -411,7 +411,7 @@ LIB_OBJS += $(OUTPUT)tests/code-reading.o LIB_OBJS += $(OUTPUT)tests/sample-parsing.o LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o ifndef NO_DWARF_UNWIND -ifeq ($(ARCH),x86) +ifeq ($(ARCH),$(filter $(ARCH),x86 arm)) LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o endif endif diff --git a/tools/perf/arch/arm/Makefile b/tools/perf/arch/arm/Makefile index 9b8f87e8c7b9..221f21d5ca28 100644 --- a/tools/perf/arch/arm/Makefile +++ b/tools/perf/arch/arm/Makefile @@ -5,4 +5,5 @@ endif ifndef NO_LIBUNWIND LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o endif diff --git a/tools/perf/arch/arm/include/perf_regs.h b/tools/perf/arch/arm/include/perf_regs.h index 33abcfa3057c..f619c9c5a4bf 100644 --- a/tools/perf/arch/arm/include/perf_regs.h +++ b/tools/perf/arch/arm/include/perf_regs.h @@ -8,6 +8,9 @@ void perf_regs_load(u64 *regs); #define PERF_REGS_MASK ((1ULL << PERF_REG_ARM_MAX) - 1) +#define PERF_REGS_MAX PERF_REG_ARM_MAX +#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32 + #define PERF_REG_IP PERF_REG_ARM_PC #define PERF_REG_SP PERF_REG_ARM_SP diff --git a/tools/perf/arch/arm/tests/dwarf-unwind.c b/tools/perf/arch/arm/tests/dwarf-unwind.c new file mode 100644 index 000000000000..9f870d27cb39 --- /dev/null +++ b/tools/perf/arch/arm/tests/dwarf-unwind.c @@ -0,0 +1,60 @@ +#include +#include "perf_regs.h" +#include "thread.h" +#include "map.h" +#include "event.h" +#include "tests/tests.h" + +#define STACK_SIZE 8192 + +static int sample_ustack(struct perf_sample *sample, + struct thread *thread, u64 *regs) +{ + struct stack_dump *stack = &sample->user_stack; + struct map *map; + unsigned long sp; + u64 stack_size, *buf; + + buf = malloc(STACK_SIZE); + if (!buf) { + pr_debug("failed to allocate sample uregs data\n"); + return -1; + } + + sp = (unsigned long) regs[PERF_REG_ARM_SP]; + + map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp); + if (!map) { + pr_debug("failed to get stack map\n"); + free(buf); + return -1; + } + + stack_size = map->end - sp; + stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size; + + memcpy(buf, (void *) sp, stack_size); + stack->data = (char *) buf; + stack->size = stack_size; + return 0; +} + +int test__arch_unwind_sample(struct perf_sample *sample, + struct thread *thread) +{ + struct regs_dump *regs = &sample->user_regs; + u64 *buf; + + buf = calloc(1, sizeof(u64) * PERF_REGS_MAX); + if (!buf) { + pr_debug("failed to allocate sample uregs data\n"); + return -1; + } + + perf_regs_load(buf); + regs->abi = PERF_SAMPLE_REGS_ABI; + regs->regs = buf; + regs->mask = PERF_REGS_MASK; + + return sample_ustack(sample, thread, buf); +} diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index f2edc593a7a7..729bbdf5cec7 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -40,11 +40,11 @@ ifeq ($(ARCH),arm64) LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 endif -# So far there's only x86 libdw unwind support merged in perf. +# So far there's only x86 and arm libdw unwind support merged in perf. # Disable it on all other architectures in case libdw unwind # support is detected in system. Add supported architectures # to the check. -ifneq ($(ARCH),x86) +ifneq ($(ARCH),$(filter $(ARCH),x86 arm)) NO_LIBDW_DWARF_UNWIND := 1 endif diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 0d5afaf72944..5e0764b09317 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -115,7 +115,7 @@ static struct test { .desc = "Test parsing with no sample_id_all bit set", .func = test__parse_no_sample_id_all, }, -#if defined(__x86_64__) || defined(__i386__) +#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) #ifdef HAVE_DWARF_UNWIND_SUPPORT { .desc = "Test dwarf unwind", diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index a9d7cb019f9e..8f91fb051ef1 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -45,7 +45,7 @@ int test__hists_filter(void); int test__mmap_thread_lookup(void); int test__thread_mg_share(void); -#if defined(__x86_64__) || defined(__i386__) +#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) #ifdef HAVE_DWARF_UNWIND_SUPPORT struct thread; struct perf_sample; From 97eac381b113932bd7bd4a5c3c68b18e9ff7a2a0 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Fri, 16 May 2014 10:41:12 +0200 Subject: [PATCH 8/8] perf tools: Add libdw DWARF post unwind support for ARM Adding libdw DWARF post unwind support, which is part of elfutils-devel/libdw-dev package from version 0.158. The new code is contained in unwin-libdw.c object, and implements unwind__get_entries unwind interface function. Signed-off-by: Jean Pihet Reviewed-by: Will Deacon Cc: Arnaldo Carvalho de Melo Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1400229672-16104-4-git-send-email-jean.pihet@linaro.org Signed-off-by: Jiri Olsa --- tools/perf/arch/arm/Makefile | 5 ++++ tools/perf/arch/arm/util/unwind-libdw.c | 36 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tools/perf/arch/arm/util/unwind-libdw.c diff --git a/tools/perf/arch/arm/Makefile b/tools/perf/arch/arm/Makefile index 221f21d5ca28..09d62153d384 100644 --- a/tools/perf/arch/arm/Makefile +++ b/tools/perf/arch/arm/Makefile @@ -4,6 +4,11 @@ LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o endif ifndef NO_LIBUNWIND LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o +endif +ifndef NO_LIBDW_DWARF_UNWIND +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o +endif +ifndef NO_DWARF_UNWIND LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o endif diff --git a/tools/perf/arch/arm/util/unwind-libdw.c b/tools/perf/arch/arm/util/unwind-libdw.c new file mode 100644 index 000000000000..b4176c60117a --- /dev/null +++ b/tools/perf/arch/arm/util/unwind-libdw.c @@ -0,0 +1,36 @@ +#include +#include "../../util/unwind-libdw.h" +#include "../../util/perf_regs.h" + +bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg) +{ + struct unwind_info *ui = arg; + struct regs_dump *user_regs = &ui->sample->user_regs; + Dwarf_Word dwarf_regs[PERF_REG_ARM_MAX]; + +#define REG(r) ({ \ + Dwarf_Word val = 0; \ + perf_reg_value(&val, user_regs, PERF_REG_ARM_##r); \ + val; \ +}) + + dwarf_regs[0] = REG(R0); + dwarf_regs[1] = REG(R1); + dwarf_regs[2] = REG(R2); + dwarf_regs[3] = REG(R3); + dwarf_regs[4] = REG(R4); + dwarf_regs[5] = REG(R5); + dwarf_regs[6] = REG(R6); + dwarf_regs[7] = REG(R7); + dwarf_regs[8] = REG(R8); + dwarf_regs[9] = REG(R9); + dwarf_regs[10] = REG(R10); + dwarf_regs[11] = REG(FP); + dwarf_regs[12] = REG(IP); + dwarf_regs[13] = REG(SP); + dwarf_regs[14] = REG(LR); + dwarf_regs[15] = REG(PC); + + return dwfl_thread_state_registers(thread, 0, PERF_REG_ARM_MAX, + dwarf_regs); +}