Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1416560 > unrolled thread
| Started by | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| First post | 2016-06-07 22:10 +0200 |
| Last post | 2016-06-08 09:50 +0200 |
| Articles | 18 — 3 participants |
Back to article view | Back to linux.kernel
[GIT PULL 00/24] perf/core improvements and fixes Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:10 +0200
[PATCH 08/24] perf tools: Fix crash in build_id_cache__kallsyms_path() Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:10 +0200
[PATCH 02/24] tools lib bpf: Rename bpf_map__get_name() to bpf_map__name() Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:10 +0200
[PATCH 20/24] perf unwind: Check the target platform before assigning unwind methods Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:10 +0200
[PATCH 17/24] perf unwind: Rename unwind-libunwind.c to unwind-libunwind-local.c Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:10 +0200
[PATCH 19/24] perf tools: Export normalize_arch() function Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 22/24] perf unwind: Introduce flag to separate local/remote unwind compilation Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 10/24] perf config: Use new perf_config_set__init() to initialize config set Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 06/24] tools lib bpf: Make bpf_program__get_private() use IS_ERR() Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 09/24] perf config: Constructor should free its allocated memory when failing Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 15/24] perf unwind: Don't mix LIBUNWIND_LIBS into LIBUNWIND_LDFLAGS Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 11/24] perf unwind: Use LIBUNWIND_DIR for remote libunwind feature check Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 12/24] perf unwind: Decouple thread->address_space on libunwind Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 13/24] perf unwind: Introduce 'struct unwind_libunwind_ops' for local unwind Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
[PATCH 01/24] tools lib bpf: Use IS_ERR() reporting macros with bpf_map__get_private() Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-07 22:20 +0200
Re: [GIT PULL 00/24] perf/core improvements and fixes Taeung Song <treeze.taeung@gmail.com> - 2016-06-08 01:20 +0200
Re: [GIT PULL 00/24] perf/core improvements and fixes Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-06-08 15:20 +0200
Re: [GIT PULL 00/24] perf/core improvements and fixes Ingo Molnar <mingo@kernel.org> - 2016-06-08 09:50 +0200
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:10 +0200 |
| Subject | [GIT PULL 00/24] perf/core improvements and fixes |
| Message-ID | <rHvu1-7bR-3@gated-at.bofh.it> |
Hi Ingo,
Please consider pulling, this is on top of perf-core-for-mingo-20160606,
Thanks,
- Arnaldo
The following changes since commit 7db91f251056f90fec4121f028680ab3153a0f3c:
perf config: Handle the error when config set is NULL at collect_config() (2016-06-06 17:43:19 -0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20160607
for you to fetch changes up to 057fbfb25cde4a368418f3f720cdc31d48800c4d:
perf callchain: Support aarch64 cross-platform (2016-06-07 15:13:35 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Support cross unwinding, i.e. collecting '--call-graph dwarf' perf.data files
in one machine and then doing analysis in another machine of a different
hardware architecture. This enables, for instance, to do:
perf record -a --call-graph dwarf
on a x86-32 or aarch64 system and then do 'perf report' on it on a
x86_64 workstation. (He Kuang)
- Fix crash in build_id_cache__kallsyms_path(), recent regression (Wang Nan)
Infrastructure:
- Make tools/lib/bpf use the IS_ERR return facility consistently and also stop
using the _get_ term for non-reference count methods (Arnaldo Carvalho de Melo)
- 'perf config' refactorings (Taeung Song)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
----------------------------------------------------------------
Arnaldo Carvalho de Melo (7):
tools lib bpf: Use IS_ERR() reporting macros with bpf_map__get_private()
tools lib bpf: Rename bpf_map__get_name() to bpf_map__name()
tools lib bpf: Use IS_ERR() reporting macros with bpf_map__get_def()
tools lib bpf: Rename bpf_map__get_fd() to bpf_map__fd()
tools lib bpf: Remove _get_ from non-refcount method names
tools lib bpf: Make bpf_program__get_private() use IS_ERR()
tools lib bpf: Rename set_private() to set_priv()
He Kuang (14):
perf unwind: Use LIBUNWIND_DIR for remote libunwind feature check
perf unwind: Decouple thread->address_space on libunwind
perf unwind: Introduce 'struct unwind_libunwind_ops' for local unwind
perf unwind: Move unwind__prepare_access from thread_new into thread__insert_map
perf unwind: Don't mix LIBUNWIND_LIBS into LIBUNWIND_LDFLAGS
perf unwind: Separate local/remote libunwind config
perf unwind: Rename unwind-libunwind.c to unwind-libunwind-local.c
perf tools: Extract common API out of unwind-libunwind-local.c
perf tools: Export normalize_arch() function
perf unwind: Check the target platform before assigning unwind methods
perf unwind: Change fixed name of libunwind__arch_reg_id to macro
perf unwind: Introduce flag to separate local/remote unwind compilation
perf callchain: Support x86 target platform
perf callchain: Support aarch64 cross-platform
Taeung Song (2):
perf config: Constructor should free its allocated memory when failing
perf config: Use new perf_config_set__init() to initialize config set
Wang Nan (1):
perf tools: Fix crash in build_id_cache__kallsyms_path()
tools/lib/bpf/libbpf.c | 60 +--
tools/lib/bpf/libbpf.h | 25 +-
tools/perf/arch/arm/util/Build | 2 +-
tools/perf/arch/arm64/util/Build | 2 +-
tools/perf/arch/arm64/util/unwind-libunwind.c | 4 +-
tools/perf/arch/common.c | 2 +-
tools/perf/arch/common.h | 1 +
tools/perf/arch/x86/util/Build | 2 +-
tools/perf/arch/x86/util/unwind-libunwind.c | 6 +-
tools/perf/config/Makefile | 52 +-
tools/perf/util/Build | 3 +
tools/perf/util/bpf-loader.c | 132 +++--
tools/perf/util/build-id.c | 11 +-
tools/perf/util/config.c | 51 +-
tools/perf/util/libunwind/arm64.c | 35 ++
tools/perf/util/libunwind/x86_32.c | 37 ++
tools/perf/util/machine.c | 14 +-
tools/perf/util/thread.c | 13 +-
tools/perf/util/thread.h | 9 +-
tools/perf/util/unwind-libunwind-local.c | 697 ++++++++++++++++++++++++++
tools/perf/util/unwind-libunwind.c | 688 ++-----------------------
tools/perf/util/unwind.h | 22 +-
22 files changed, 1056 insertions(+), 812 deletions(-)
create mode 100644 tools/perf/util/libunwind/arm64.c
create mode 100644 tools/perf/util/libunwind/x86_32.c
create mode 100644 tools/perf/util/unwind-libunwind-local.c
[toc] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:10 +0200 |
| Subject | [PATCH 08/24] perf tools: Fix crash in build_id_cache__kallsyms_path() |
| Message-ID | <rHvu3-7bR-53@gated-at.bofh.it> |
| In reply to | #1416560 |
From: Wang Nan <wangnan0@huawei.com>
build_id_cache__kallsyms_path() accepts a string buffer but also allocs
a buffer using asnprintf. Unfortunately, the its only user passes it a
stack-allocated buffer. Freeing it causes crashes like this:
$ perf script
*** Error in `/home/wangnan/perf': free(): invalid pointer: 0x00007fffffff9630 ***
======= Backtrace: =========
lib64/libc.so.6(+0x6eeef)[0x7ffff5dbaeef]
lib64/libc.so.6(+0x78cae)[0x7ffff5dc4cae]
lib64/libc.so.6(+0x79987)[0x7ffff5dc5987]
/home/w00229757/perf(build_id_cache__kallsyms_path+0x6b)[0x49681b]
/home/w00229757/perf[0x4bdd40]
/home/w00229757/perf(dso__load+0xa3a)[0x4c048a]
/home/w00229757/perf(map__load+0x6f)[0x4d561f]
/home/w00229757/perf(thread__find_addr_map+0x235)[0x49e935]
/home/w00229757/perf(machine__resolve+0x7d)[0x49ec6d]
/home/w00229757/perf[0x4555a8]
/home/w00229757/perf[0x4d9507]
/home/w00229757/perf[0x4d9e80]
/home/w00229757/perf(ordered_events__flush+0x354)[0x4dd444]
/home/w00229757/perf(perf_session__process_events+0x3d0)[0x4dc140]
/home/w00229757/perf(cmd_script+0x12b0)[0x4592e0]
/home/w00229757/perf[0x4911f1]
/home/w00229757/perf(main+0x68f)[0x4352ef]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7ffff5d6dbd5]
/home/w00229757/perf[0x435415]
======= Memory map: ========
This patch simplifies build_id_cache__kallsyms_path(), not even
considering allocating a string buffer, so never frees anything. Its
caller should manage memory allocation.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Fixes: 01412261d994 ("perf buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid")
Link: http://lkml.kernel.org/r/1465271678-7392-1-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/build-id.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 67f986c8c378..20aef90bf194 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -147,20 +147,17 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
size_t size)
{
- bool is_alloc = !!bf;
bool retry_old = true;
- asnprintf(&bf, size, "%s/%s/%s/kallsyms",
- buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
+ snprintf(bf, size, "%s/%s/%s/kallsyms",
+ buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
retry:
if (!access(bf, F_OK))
return bf;
- if (is_alloc)
- free(bf);
if (retry_old) {
/* Try old style kallsyms cache */
- asnprintf(&bf, size, "%s/%s/%s",
- buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
+ snprintf(bf, size, "%s/%s/%s",
+ buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
retry_old = false;
goto retry;
}
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:10 +0200 |
| Subject | [PATCH 02/24] tools lib bpf: Rename bpf_map__get_name() to bpf_map__name() |
| Message-ID | <rHvu3-7bR-55@gated-at.bofh.it> |
| In reply to | #1416560 |
From: Arnaldo Carvalho de Melo <acme@redhat.com>
For consistency, leaving "get" for reference counting.
Acked-by: Wang Nan <wangnan0@huawei.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Milian Wolff <milian.wolff@kdab.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/n/tip-crnflv84ejyhpba933ec71gs@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/lib/bpf/libbpf.c | 6 ++----
tools/lib/bpf/libbpf.h | 2 +-
tools/perf/util/bpf-loader.c | 18 ++++++------------
3 files changed, 9 insertions(+), 17 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 9bba1a907abe..4dc617befd13 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1328,11 +1328,9 @@ int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef)
return 0;
}
-const char *bpf_map__get_name(struct bpf_map *map)
+const char *bpf_map__name(struct bpf_map *map)
{
- if (!map)
- return NULL;
- return map->name;
+ return map ? map->name : NULL;
}
int bpf_map__set_private(struct bpf_map *map, void *priv,
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 916abf971249..f8fbba4ccef3 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -182,7 +182,7 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
int bpf_map__get_fd(struct bpf_map *map);
int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef);
-const char *bpf_map__get_name(struct bpf_map *map);
+const char *bpf_map__name(struct bpf_map *map);
typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
int bpf_map__set_private(struct bpf_map *map, void *priv,
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index e9a034e86b91..c819eb8ba145 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -897,10 +897,9 @@ bpf_map_priv__clone(struct bpf_map_priv *priv)
static int
bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
{
+ const char *map_name = bpf_map__name(map);
struct bpf_map_priv *priv = bpf_map__priv(map);
- const char *map_name;
- map_name = bpf_map__get_name(map);
if (IS_ERR(priv)) {
pr_debug("Failed to get private from map %s\n", map_name);
return PTR_ERR(priv);
@@ -948,11 +947,9 @@ __bpf_map__config_value(struct bpf_map *map,
{
struct bpf_map_def def;
struct bpf_map_op *op;
- const char *map_name;
+ const char *map_name = bpf_map__name(map);
int err;
- map_name = bpf_map__get_name(map);
-
err = bpf_map__get_def(map, &def);
if (err) {
pr_debug("Unable to get map definition from '%s'\n",
@@ -1014,10 +1011,9 @@ __bpf_map__config_event(struct bpf_map *map,
struct perf_evsel *evsel;
struct bpf_map_def def;
struct bpf_map_op *op;
- const char *map_name;
+ const char *map_name = bpf_map__name(map);
int err;
- map_name = bpf_map__get_name(map);
evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str);
if (!evsel) {
pr_debug("Event (for '%s') '%s' doesn't exist\n",
@@ -1259,13 +1255,11 @@ bpf_map_config_foreach_key(struct bpf_map *map,
void *arg)
{
int err, map_fd;
- const char *name;
struct bpf_map_op *op;
struct bpf_map_def def;
+ const char *name = bpf_map__name(map);
struct bpf_map_priv *priv = bpf_map__priv(map);
- name = bpf_map__get_name(map);
-
if (IS_ERR(priv)) {
pr_debug("ERROR: failed to get private from map %s\n", name);
return -BPF_LOADER_ERRNO__INTERNAL;
@@ -1472,9 +1466,9 @@ int bpf__apply_obj_config(void)
#define bpf__for_each_stdout_map(pos, obj, objtmp) \
bpf__for_each_map(pos, obj, objtmp) \
- if (bpf_map__get_name(pos) && \
+ if (bpf_map__name(pos) && \
(strcmp("__bpf_stdout__", \
- bpf_map__get_name(pos)) == 0))
+ bpf_map__name(pos)) == 0))
int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
{
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:10 +0200 |
| Subject | [PATCH 20/24] perf unwind: Check the target platform before assigning unwind methods |
| Message-ID | <rHvu3-7bR-59@gated-at.bofh.it> |
| In reply to | #1416560 |
From: He Kuang <hekuang@huawei.com>
Currently, 'perf script' uses host unwind methods to parse perf.data
callchain info without taking the target architecture into account, i.e.
assuming the perf.data file was generated on the same machine where the
analysis is being performed. So we get wrong result without any warnings
when unwinding callchains of x86(32-bit) on x86(64-bit) machine.
This patch adds an extra step that checks the target platform before
assigning unwind methods. In later patches in this series, we can use
this info to assign the right unwind methods for supported platforms.
Committer note:
After fixing it to register the local unwinder for live mode tools
('perf trace', 'perf top'), i.e. tools that don't use a perf.data file,
it works as intended and passes the 'perf test unwind' test:
# perf trace -e nanosleep --call dwarf usleep 1
0.328 ( 0.058 ms): usleep/11115 nanosleep(rqtp: 0x7fff083fa480) = 0
__nanosleep_nocancel+0x7 (/usr/lib64/libc-2.22.so)
usleep+0x34 (/usr/lib64/libc-2.22.so)
main+0x1eb (/usr/bin/usleep)
__libc_start_main+0xf0 (/usr/lib64/libc-2.22.so)
_start+0x29 (/usr/bin/usleep)
# perf test 48
48: Test dwarf unwind : Ok
#
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1464924803-22214-11-git-send-email-hekuang@huawei.com
[ Fixed exit path for 'live' mode tools, where we need to default to local unwinding ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/thread.c | 2 +-
tools/perf/util/unwind-libunwind.c | 25 ++++++++++++++++++++++++-
tools/perf/util/unwind.h | 8 +++++---
3 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0bf552560a41..f30f9566fddc 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -202,7 +202,7 @@ int thread__insert_map(struct thread *thread, struct map *map)
{
int ret;
- ret = unwind__prepare_access(thread);
+ ret = unwind__prepare_access(thread, map);
if (ret)
return ret;
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index f86f903ae8a8..0086726e00e0 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -1,5 +1,8 @@
#include "unwind.h"
#include "thread.h"
+#include "session.h"
+#include "debug.h"
+#include "arch/common.h"
struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops;
@@ -9,8 +12,28 @@ static void unwind__register_ops(struct thread *thread,
thread->unwind_libunwind_ops = ops;
}
-int unwind__prepare_access(struct thread *thread)
+int unwind__prepare_access(struct thread *thread, struct map *map)
{
+ const char *arch;
+ enum dso_type dso_type;
+
+ if (thread->addr_space) {
+ pr_debug("unwind: thread map already set, dso=%s\n",
+ map->dso->name);
+ return 0;
+ }
+
+ /* env->arch is NULL for live-mode (i.e. perf top) */
+ if (!thread->mg->machine->env || !thread->mg->machine->env->arch)
+ goto out_register;
+
+ dso_type = dso__type(map->dso, thread->mg->machine);
+ if (dso_type == DSO__TYPE_UNKNOWN)
+ return 0;
+
+ arch = normalize_arch(thread->mg->machine->env->arch);
+ pr_debug("unwind: target platform=%s\n", arch);
+out_register:
unwind__register_ops(thread, local_unwind_libunwind_ops);
return thread->unwind_libunwind_ops->prepare_access(thread);
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index bbd73d9bea45..bf9f5937caee 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -30,11 +30,12 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
/* libunwind specific */
#ifdef HAVE_LIBUNWIND_SUPPORT
int libunwind__arch_reg_id(int regnum);
-int unwind__prepare_access(struct thread *thread);
+int unwind__prepare_access(struct thread *thread, struct map *map);
void unwind__flush_access(struct thread *thread);
void unwind__finish_access(struct thread *thread);
#else
-static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
+static inline int unwind__prepare_access(struct thread *thread __maybe_unused,
+ struct map *map __maybe_unused)
{
return 0;
}
@@ -53,7 +54,8 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
return 0;
}
-static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
+static inline int unwind__prepare_access(struct thread *thread __maybe_unused,
+ struct map *map __maybe_unused)
{
return 0;
}
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:10 +0200 |
| Subject | [PATCH 17/24] perf unwind: Rename unwind-libunwind.c to unwind-libunwind-local.c |
| Message-ID | <rHvu3-7bR-61@gated-at.bofh.it> |
| In reply to | #1416560 |
From: He Kuang <hekuang@huawei.com>
Since unwind-libunwind.c contains code for specific arithecture, we
change it's name to unwind-libunwind-local.c, and let it only be built
if local libunwind is supported.
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1464924803-22214-8-git-send-email-hekuang@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/Build | 2 +-
tools/perf/util/unwind-libunwind-local.c | 727 +++++++++++++++++++++++++++++++
tools/perf/util/unwind-libunwind.c | 727 -------------------------------
3 files changed, 728 insertions(+), 728 deletions(-)
create mode 100644 tools/perf/util/unwind-libunwind-local.c
delete mode 100644 tools/perf/util/unwind-libunwind.c
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 8c6c8a0ca642..5e23d85d2d69 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -99,7 +99,7 @@ libperf-$(CONFIG_DWARF) += probe-finder.o
libperf-$(CONFIG_DWARF) += dwarf-aux.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
-libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
+libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
new file mode 100644
index 000000000000..b0c5db1333f9
--- /dev/null
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -0,0 +1,727 @@
+/*
+ * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
+ *
+ * Lots of this code have been borrowed or heavily inspired from parts of
+ * the libunwind 0.99 code which are (amongst other contributors I may have
+ * forgotten):
+ *
+ * Copyright (C) 2002-2007 Hewlett-Packard Co
+ * Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * And the bugs have been added by:
+ *
+ * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>
+ * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>
+ *
+ */
+
+#include <elf.h>
+#include <gelf.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <linux/list.h>
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+#include "callchain.h"
+#include "thread.h"
+#include "session.h"
+#include "perf_regs.h"
+#include "unwind.h"
+#include "symbol.h"
+#include "util.h"
+#include "debug.h"
+#include "asm/bug.h"
+
+extern int
+UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
+ unw_word_t ip,
+ unw_dyn_info_t *di,
+ unw_proc_info_t *pi,
+ int need_unwind_info, void *arg);
+
+#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
+
+extern int
+UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
+ unw_word_t ip,
+ unw_word_t segbase,
+ const char *obj_name, unw_word_t start,
+ unw_word_t end);
+
+#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
+
+#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
+#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
+
+/* Pointer-encoding formats: */
+#define DW_EH_PE_omit 0xff
+#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
+#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
+#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
+#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
+#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
+
+/* Pointer-encoding application: */
+#define DW_EH_PE_absptr 0x00 /* absolute value */
+#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
+
+/*
+ * The following are not documented by LSB v1.3, yet they are used by
+ * GCC, presumably they aren't documented by LSB since they aren't
+ * used on Linux:
+ */
+#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
+#define DW_EH_PE_aligned 0x50 /* aligned pointer */
+
+/* Flags intentionaly not handled, since they're not needed:
+ * #define DW_EH_PE_indirect 0x80
+ * #define DW_EH_PE_uleb128 0x01
+ * #define DW_EH_PE_udata2 0x02
+ * #define DW_EH_PE_sleb128 0x09
+ * #define DW_EH_PE_sdata2 0x0a
+ * #define DW_EH_PE_textrel 0x20
+ * #define DW_EH_PE_datarel 0x30
+ */
+
+struct unwind_info {
+ struct perf_sample *sample;
+ struct machine *machine;
+ struct thread *thread;
+};
+
+#define dw_read(ptr, type, end) ({ \
+ type *__p = (type *) ptr; \
+ type __v; \
+ if ((__p + 1) > (type *) end) \
+ return -EINVAL; \
+ __v = *__p++; \
+ ptr = (typeof(ptr)) __p; \
+ __v; \
+ })
+
+static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
+ u8 encoding)
+{
+ u8 *cur = *p;
+ *val = 0;
+
+ switch (encoding) {
+ case DW_EH_PE_omit:
+ *val = 0;
+ goto out;
+ case DW_EH_PE_ptr:
+ *val = dw_read(cur, unsigned long, end);
+ goto out;
+ default:
+ break;
+ }
+
+ switch (encoding & DW_EH_PE_APPL_MASK) {
+ case DW_EH_PE_absptr:
+ break;
+ case DW_EH_PE_pcrel:
+ *val = (unsigned long) cur;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((encoding & 0x07) == 0x00)
+ encoding |= DW_EH_PE_udata4;
+
+ switch (encoding & DW_EH_PE_FORMAT_MASK) {
+ case DW_EH_PE_sdata4:
+ *val += dw_read(cur, s32, end);
+ break;
+ case DW_EH_PE_udata4:
+ *val += dw_read(cur, u32, end);
+ break;
+ case DW_EH_PE_sdata8:
+ *val += dw_read(cur, s64, end);
+ break;
+ case DW_EH_PE_udata8:
+ *val += dw_read(cur, u64, end);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ out:
+ *p = cur;
+ return 0;
+}
+
+#define dw_read_encoded_value(ptr, end, enc) ({ \
+ u64 __v; \
+ if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
+ return -EINVAL; \
+ } \
+ __v; \
+ })
+
+static u64 elf_section_offset(int fd, const char *name)
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
+ u64 offset = 0;
+
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+ if (elf == NULL)
+ return 0;
+
+ do {
+ if (gelf_getehdr(elf, &ehdr) == NULL)
+ break;
+
+ if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
+ break;
+
+ offset = shdr.sh_offset;
+ } while (0);
+
+ elf_end(elf);
+ return offset;
+}
+
+#ifndef NO_LIBUNWIND_DEBUG_FRAME
+static int elf_is_exec(int fd, const char *name)
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ int retval = 0;
+
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+ if (elf == NULL)
+ return 0;
+ if (gelf_getehdr(elf, &ehdr) == NULL)
+ goto out;
+
+ retval = (ehdr.e_type == ET_EXEC);
+
+out:
+ elf_end(elf);
+ pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);
+ return retval;
+}
+#endif
+
+struct table_entry {
+ u32 start_ip_offset;
+ u32 fde_offset;
+};
+
+struct eh_frame_hdr {
+ unsigned char version;
+ unsigned char eh_frame_ptr_enc;
+ unsigned char fde_count_enc;
+ unsigned char table_enc;
+
+ /*
+ * The rest of the header is variable-length and consists of the
+ * following members:
+ *
+ * encoded_t eh_frame_ptr;
+ * encoded_t fde_count;
+ */
+
+ /* A single encoded pointer should not be more than 8 bytes. */
+ u64 enc[2];
+
+ /*
+ * struct {
+ * encoded_t start_ip;
+ * encoded_t fde_addr;
+ * } binary_search_table[fde_count];
+ */
+ char data[0];
+} __packed;
+
+static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
+ u64 offset, u64 *table_data, u64 *segbase,
+ u64 *fde_count)
+{
+ struct eh_frame_hdr hdr;
+ u8 *enc = (u8 *) &hdr.enc;
+ u8 *end = (u8 *) &hdr.data;
+ ssize_t r;
+
+ r = dso__data_read_offset(dso, machine, offset,
+ (u8 *) &hdr, sizeof(hdr));
+ if (r != sizeof(hdr))
+ return -EINVAL;
+
+ /* We dont need eh_frame_ptr, just skip it. */
+ dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
+
+ *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
+ *segbase = offset;
+ *table_data = (enc - (u8 *) &hdr) + offset;
+ return 0;
+}
+
+static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
+ u64 *table_data, u64 *segbase,
+ u64 *fde_count)
+{
+ int ret = -EINVAL, fd;
+ u64 offset = dso->data.eh_frame_hdr_offset;
+
+ if (offset == 0) {
+ fd = dso__data_get_fd(dso, machine);
+ if (fd < 0)
+ return -EINVAL;
+
+ /* Check the .eh_frame section for unwinding info */
+ offset = elf_section_offset(fd, ".eh_frame_hdr");
+ dso->data.eh_frame_hdr_offset = offset;
+ dso__data_put_fd(dso);
+ }
+
+ if (offset)
+ ret = unwind_spec_ehframe(dso, machine, offset,
+ table_data, segbase,
+ fde_count);
+
+ return ret;
+}
+
+#ifndef NO_LIBUNWIND_DEBUG_FRAME
+static int read_unwind_spec_debug_frame(struct dso *dso,
+ struct machine *machine, u64 *offset)
+{
+ int fd;
+ u64 ofs = dso->data.debug_frame_offset;
+
+ if (ofs == 0) {
+ fd = dso__data_get_fd(dso, machine);
+ if (fd < 0)
+ return -EINVAL;
+
+ /* Check the .debug_frame section for unwinding info */
+ ofs = elf_section_offset(fd, ".debug_frame");
+ dso->data.debug_frame_offset = ofs;
+ dso__data_put_fd(dso);
+ }
+
+ *offset = ofs;
+ if (*offset)
+ return 0;
+
+ return -EINVAL;
+}
+#endif
+
+static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
+{
+ struct addr_location al;
+
+ thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
+ MAP__FUNCTION, ip, &al);
+ if (!al.map) {
+ /*
+ * We've seen cases (softice) where DWARF unwinder went
+ * through non executable mmaps, which we need to lookup
+ * in MAP__VARIABLE tree.
+ */
+ thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
+ MAP__VARIABLE, ip, &al);
+ }
+ return al.map;
+}
+
+static int
+find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
+{
+ struct unwind_info *ui = arg;
+ struct map *map;
+ unw_dyn_info_t di;
+ u64 table_data, segbase, fde_count;
+ int ret = -EINVAL;
+
+ map = find_map(ip, ui);
+ if (!map || !map->dso)
+ return -EINVAL;
+
+ pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
+
+ /* Check the .eh_frame section for unwinding info */
+ if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
+ &table_data, &segbase, &fde_count)) {
+ memset(&di, 0, sizeof(di));
+ di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
+ di.start_ip = map->start;
+ di.end_ip = map->end;
+ di.u.rti.segbase = map->start + segbase;
+ di.u.rti.table_data = map->start + table_data;
+ di.u.rti.table_len = fde_count * sizeof(struct table_entry)
+ / sizeof(unw_word_t);
+ ret = dwarf_search_unwind_table(as, ip, &di, pi,
+ need_unwind_info, arg);
+ }
+
+#ifndef NO_LIBUNWIND_DEBUG_FRAME
+ /* Check the .debug_frame section for unwinding info */
+ if (ret < 0 &&
+ !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
+ int fd = dso__data_get_fd(map->dso, ui->machine);
+ int is_exec = elf_is_exec(fd, map->dso->name);
+ unw_word_t base = is_exec ? 0 : map->start;
+ const char *symfile;
+
+ if (fd >= 0)
+ dso__data_put_fd(map->dso);
+
+ symfile = map->dso->symsrc_filename ?: map->dso->name;
+
+ memset(&di, 0, sizeof(di));
+ if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
+ map->start, map->end))
+ return dwarf_search_unwind_table(as, ip, &di, pi,
+ need_unwind_info, arg);
+ }
+#endif
+
+ return ret;
+}
+
+static int access_fpreg(unw_addr_space_t __maybe_unused as,
+ unw_regnum_t __maybe_unused num,
+ unw_fpreg_t __maybe_unused *val,
+ int __maybe_unused __write,
+ void __maybe_unused *arg)
+{
+ pr_err("unwind: access_fpreg unsupported\n");
+ return -UNW_EINVAL;
+}
+
+static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
+ unw_word_t __maybe_unused *dil_addr,
+ void __maybe_unused *arg)
+{
+ return -UNW_ENOINFO;
+}
+
+static int resume(unw_addr_space_t __maybe_unused as,
+ unw_cursor_t __maybe_unused *cu,
+ void __maybe_unused *arg)
+{
+ pr_err("unwind: resume unsupported\n");
+ return -UNW_EINVAL;
+}
+
+static int
+get_proc_name(unw_addr_space_t __maybe_unused as,
+ unw_word_t __maybe_unused addr,
+ char __maybe_unused *bufp, size_t __maybe_unused buf_len,
+ unw_word_t __maybe_unused *offp, void __maybe_unused *arg)
+{
+ pr_err("unwind: get_proc_name unsupported\n");
+ return -UNW_EINVAL;
+}
+
+static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
+ unw_word_t *data)
+{
+ struct map *map;
+ ssize_t size;
+
+ map = find_map(addr, ui);
+ if (!map) {
+ pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
+ return -1;
+ }
+
+ if (!map->dso)
+ return -1;
+
+ size = dso__data_read_addr(map->dso, map, ui->machine,
+ addr, (u8 *) data, sizeof(*data));
+
+ return !(size == sizeof(*data));
+}
+
+static int access_mem(unw_addr_space_t __maybe_unused as,
+ unw_word_t addr, unw_word_t *valp,
+ int __write, void *arg)
+{
+ struct unwind_info *ui = arg;
+ struct stack_dump *stack = &ui->sample->user_stack;
+ u64 start, end;
+ int offset;
+ int ret;
+
+ /* Don't support write, probably not needed. */
+ if (__write || !stack || !ui->sample->user_regs.regs) {
+ *valp = 0;
+ return 0;
+ }
+
+ ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
+ if (ret)
+ return ret;
+
+ end = start + stack->size;
+
+ /* Check overflow. */
+ if (addr + sizeof(unw_word_t) < addr)
+ return -EINVAL;
+
+ if (addr < start || addr + sizeof(unw_word_t) >= end) {
+ ret = access_dso_mem(ui, addr, valp);
+ if (ret) {
+ pr_debug("unwind: access_mem %p not inside range"
+ " 0x%" PRIx64 "-0x%" PRIx64 "\n",
+ (void *) (uintptr_t) addr, start, end);
+ *valp = 0;
+ return ret;
+ }
+ return 0;
+ }
+
+ offset = addr - start;
+ *valp = *(unw_word_t *)&stack->data[offset];
+ pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
+ (void *) (uintptr_t) addr, (unsigned long)*valp, offset);
+ return 0;
+}
+
+static int access_reg(unw_addr_space_t __maybe_unused as,
+ unw_regnum_t regnum, unw_word_t *valp,
+ int __write, void *arg)
+{
+ struct unwind_info *ui = arg;
+ int id, ret;
+ u64 val;
+
+ /* Don't support write, I suspect we don't need it. */
+ if (__write) {
+ pr_err("unwind: access_reg w %d\n", regnum);
+ return 0;
+ }
+
+ if (!ui->sample->user_regs.regs) {
+ *valp = 0;
+ return 0;
+ }
+
+ id = libunwind__arch_reg_id(regnum);
+ if (id < 0)
+ return -EINVAL;
+
+ ret = perf_reg_value(&val, &ui->sample->user_regs, id);
+ if (ret) {
+ pr_err("unwind: can't read reg %d\n", regnum);
+ return ret;
+ }
+
+ *valp = (unw_word_t) val;
+ pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
+ return 0;
+}
+
+static void put_unwind_info(unw_addr_space_t __maybe_unused as,
+ unw_proc_info_t *pi __maybe_unused,
+ void *arg __maybe_unused)
+{
+ pr_debug("unwind: put_unwind_info called\n");
+}
+
+static int entry(u64 ip, struct thread *thread,
+ unwind_entry_cb_t cb, void *arg)
+{
+ struct unwind_entry e;
+ struct addr_location al;
+
+ thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
+ MAP__FUNCTION, ip, &al);
+
+ e.ip = ip;
+ e.map = al.map;
+ e.sym = al.sym;
+
+ pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
+ al.sym ? al.sym->name : "''",
+ ip,
+ al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
+
+ return cb(&e, arg);
+}
+
+static void display_error(int err)
+{
+ switch (err) {
+ case UNW_EINVAL:
+ pr_err("unwind: Only supports local.\n");
+ break;
+ case UNW_EUNSPEC:
+ pr_err("unwind: Unspecified error.\n");
+ break;
+ case UNW_EBADREG:
+ pr_err("unwind: Register unavailable.\n");
+ break;
+ default:
+ break;
+ }
+}
+
+static unw_accessors_t accessors = {
+ .find_proc_info = find_proc_info,
+ .put_unwind_info = put_unwind_info,
+ .get_dyn_info_list_addr = get_dyn_info_list_addr,
+ .access_mem = access_mem,
+ .access_reg = access_reg,
+ .access_fpreg = access_fpreg,
+ .resume = resume,
+ .get_proc_name = get_proc_name,
+};
+
+static int _unwind__prepare_access(struct thread *thread)
+{
+ if (callchain_param.record_mode != CALLCHAIN_DWARF)
+ return 0;
+
+ thread->addr_space = unw_create_addr_space(&accessors, 0);
+ if (!thread->addr_space) {
+ pr_err("unwind: Can't create unwind address space.\n");
+ return -ENOMEM;
+ }
+
+ unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
+ return 0;
+}
+
+static void _unwind__flush_access(struct thread *thread)
+{
+ if (callchain_param.record_mode != CALLCHAIN_DWARF)
+ return;
+
+ unw_flush_cache(thread->addr_space, 0, 0);
+}
+
+static void _unwind__finish_access(struct thread *thread)
+{
+ if (callchain_param.record_mode != CALLCHAIN_DWARF)
+ return;
+
+ unw_destroy_addr_space(thread->addr_space);
+}
+
+static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
+ void *arg, int max_stack)
+{
+ u64 val;
+ unw_word_t ips[max_stack];
+ unw_addr_space_t addr_space;
+ unw_cursor_t c;
+ int ret, i = 0;
+
+ ret = perf_reg_value(&val, &ui->sample->user_regs, PERF_REG_IP);
+ if (ret)
+ return ret;
+
+ ips[i++] = (unw_word_t) val;
+
+ /*
+ * If we need more than one entry, do the DWARF
+ * unwind itself.
+ */
+ if (max_stack - 1 > 0) {
+ WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
+ addr_space = ui->thread->addr_space;
+
+ if (addr_space == NULL)
+ return -1;
+
+ ret = unw_init_remote(&c, addr_space, ui);
+ if (ret)
+ display_error(ret);
+
+ while (!ret && (unw_step(&c) > 0) && i < max_stack) {
+ unw_get_reg(&c, UNW_REG_IP, &ips[i]);
+ ++i;
+ }
+
+ max_stack = i;
+ }
+
+ /*
+ * Display what we got based on the order setup.
+ */
+ for (i = 0; i < max_stack && !ret; i++) {
+ int j = i;
+
+ if (callchain_param.order == ORDER_CALLER)
+ j = max_stack - i - 1;
+ ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0;
+ }
+
+ return ret;
+}
+
+static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
+ struct thread *thread,
+ struct perf_sample *data, int max_stack)
+{
+ struct unwind_info ui = {
+ .sample = data,
+ .thread = thread,
+ .machine = thread->mg->machine,
+ };
+
+ if (!data->user_regs.regs)
+ return -EINVAL;
+
+ if (max_stack <= 0)
+ return -EINVAL;
+
+ return get_entries(&ui, cb, arg, max_stack);
+}
+
+static struct unwind_libunwind_ops
+_unwind_libunwind_ops = {
+ .prepare_access = _unwind__prepare_access,
+ .flush_access = _unwind__flush_access,
+ .finish_access = _unwind__finish_access,
+ .get_entries = _unwind__get_entries,
+};
+
+struct unwind_libunwind_ops *
+local_unwind_libunwind_ops = &_unwind_libunwind_ops;
+
+static void unwind__register_ops(struct thread *thread,
+ struct unwind_libunwind_ops *ops)
+{
+ thread->unwind_libunwind_ops = ops;
+}
+
+int unwind__prepare_access(struct thread *thread)
+{
+ unwind__register_ops(thread, local_unwind_libunwind_ops);
+
+ return thread->unwind_libunwind_ops->prepare_access(thread);
+}
+
+void unwind__flush_access(struct thread *thread)
+{
+ if (thread->unwind_libunwind_ops)
+ thread->unwind_libunwind_ops->flush_access(thread);
+}
+
+void unwind__finish_access(struct thread *thread)
+{
+ if (thread->unwind_libunwind_ops)
+ thread->unwind_libunwind_ops->finish_access(thread);
+}
+
+int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
+ struct thread *thread,
+ struct perf_sample *data, int max_stack)
+{
+ if (thread->unwind_libunwind_ops)
+ return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
+ return 0;
+}
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
deleted file mode 100644
index b0c5db1333f9..000000000000
--- a/tools/perf/util/unwind-libunwind.c
+++ /dev/null
@@ -1,727 +0,0 @@
-/*
- * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
- *
- * Lots of this code have been borrowed or heavily inspired from parts of
- * the libunwind 0.99 code which are (amongst other contributors I may have
- * forgotten):
- *
- * Copyright (C) 2002-2007 Hewlett-Packard Co
- * Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * And the bugs have been added by:
- *
- * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>
- * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>
- *
- */
-
-#include <elf.h>
-#include <gelf.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <linux/list.h>
-#include <libunwind.h>
-#include <libunwind-ptrace.h>
-#include "callchain.h"
-#include "thread.h"
-#include "session.h"
-#include "perf_regs.h"
-#include "unwind.h"
-#include "symbol.h"
-#include "util.h"
-#include "debug.h"
-#include "asm/bug.h"
-
-extern int
-UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
- unw_word_t ip,
- unw_dyn_info_t *di,
- unw_proc_info_t *pi,
- int need_unwind_info, void *arg);
-
-#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
-
-extern int
-UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
- unw_word_t ip,
- unw_word_t segbase,
- const char *obj_name, unw_word_t start,
- unw_word_t end);
-
-#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
-
-#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
-#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
-
-/* Pointer-encoding formats: */
-#define DW_EH_PE_omit 0xff
-#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
-#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
-#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
-#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
-#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
-
-/* Pointer-encoding application: */
-#define DW_EH_PE_absptr 0x00 /* absolute value */
-#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
-
-/*
- * The following are not documented by LSB v1.3, yet they are used by
- * GCC, presumably they aren't documented by LSB since they aren't
- * used on Linux:
- */
-#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
-#define DW_EH_PE_aligned 0x50 /* aligned pointer */
-
-/* Flags intentionaly not handled, since they're not needed:
- * #define DW_EH_PE_indirect 0x80
- * #define DW_EH_PE_uleb128 0x01
- * #define DW_EH_PE_udata2 0x02
- * #define DW_EH_PE_sleb128 0x09
- * #define DW_EH_PE_sdata2 0x0a
- * #define DW_EH_PE_textrel 0x20
- * #define DW_EH_PE_datarel 0x30
- */
-
-struct unwind_info {
- struct perf_sample *sample;
- struct machine *machine;
- struct thread *thread;
-};
-
-#define dw_read(ptr, type, end) ({ \
- type *__p = (type *) ptr; \
- type __v; \
- if ((__p + 1) > (type *) end) \
- return -EINVAL; \
- __v = *__p++; \
- ptr = (typeof(ptr)) __p; \
- __v; \
- })
-
-static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
- u8 encoding)
-{
- u8 *cur = *p;
- *val = 0;
-
- switch (encoding) {
- case DW_EH_PE_omit:
- *val = 0;
- goto out;
- case DW_EH_PE_ptr:
- *val = dw_read(cur, unsigned long, end);
- goto out;
- default:
- break;
- }
-
- switch (encoding & DW_EH_PE_APPL_MASK) {
- case DW_EH_PE_absptr:
- break;
- case DW_EH_PE_pcrel:
- *val = (unsigned long) cur;
- break;
- default:
- return -EINVAL;
- }
-
- if ((encoding & 0x07) == 0x00)
- encoding |= DW_EH_PE_udata4;
-
- switch (encoding & DW_EH_PE_FORMAT_MASK) {
- case DW_EH_PE_sdata4:
- *val += dw_read(cur, s32, end);
- break;
- case DW_EH_PE_udata4:
- *val += dw_read(cur, u32, end);
- break;
- case DW_EH_PE_sdata8:
- *val += dw_read(cur, s64, end);
- break;
- case DW_EH_PE_udata8:
- *val += dw_read(cur, u64, end);
- break;
- default:
- return -EINVAL;
- }
-
- out:
- *p = cur;
- return 0;
-}
-
-#define dw_read_encoded_value(ptr, end, enc) ({ \
- u64 __v; \
- if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
- return -EINVAL; \
- } \
- __v; \
- })
-
-static u64 elf_section_offset(int fd, const char *name)
-{
- Elf *elf;
- GElf_Ehdr ehdr;
- GElf_Shdr shdr;
- u64 offset = 0;
-
- elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
- if (elf == NULL)
- return 0;
-
- do {
- if (gelf_getehdr(elf, &ehdr) == NULL)
- break;
-
- if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
- break;
-
- offset = shdr.sh_offset;
- } while (0);
-
- elf_end(elf);
- return offset;
-}
-
-#ifndef NO_LIBUNWIND_DEBUG_FRAME
-static int elf_is_exec(int fd, const char *name)
-{
- Elf *elf;
- GElf_Ehdr ehdr;
- int retval = 0;
-
- elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
- if (elf == NULL)
- return 0;
- if (gelf_getehdr(elf, &ehdr) == NULL)
- goto out;
-
- retval = (ehdr.e_type == ET_EXEC);
-
-out:
- elf_end(elf);
- pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);
- return retval;
-}
-#endif
-
-struct table_entry {
- u32 start_ip_offset;
- u32 fde_offset;
-};
-
-struct eh_frame_hdr {
- unsigned char version;
- unsigned char eh_frame_ptr_enc;
- unsigned char fde_count_enc;
- unsigned char table_enc;
-
- /*
- * The rest of the header is variable-length and consists of the
- * following members:
- *
- * encoded_t eh_frame_ptr;
- * encoded_t fde_count;
- */
-
- /* A single encoded pointer should not be more than 8 bytes. */
- u64 enc[2];
-
- /*
- * struct {
- * encoded_t start_ip;
- * encoded_t fde_addr;
- * } binary_search_table[fde_count];
- */
- char data[0];
-} __packed;
-
-static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
- u64 offset, u64 *table_data, u64 *segbase,
- u64 *fde_count)
-{
- struct eh_frame_hdr hdr;
- u8 *enc = (u8 *) &hdr.enc;
- u8 *end = (u8 *) &hdr.data;
- ssize_t r;
-
- r = dso__data_read_offset(dso, machine, offset,
- (u8 *) &hdr, sizeof(hdr));
- if (r != sizeof(hdr))
- return -EINVAL;
-
- /* We dont need eh_frame_ptr, just skip it. */
- dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
-
- *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
- *segbase = offset;
- *table_data = (enc - (u8 *) &hdr) + offset;
- return 0;
-}
-
-static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
- u64 *table_data, u64 *segbase,
- u64 *fde_count)
-{
- int ret = -EINVAL, fd;
- u64 offset = dso->data.eh_frame_hdr_offset;
-
- if (offset == 0) {
- fd = dso__data_get_fd(dso, machine);
- if (fd < 0)
- return -EINVAL;
-
- /* Check the .eh_frame section for unwinding info */
- offset = elf_section_offset(fd, ".eh_frame_hdr");
- dso->data.eh_frame_hdr_offset = offset;
- dso__data_put_fd(dso);
- }
-
- if (offset)
- ret = unwind_spec_ehframe(dso, machine, offset,
- table_data, segbase,
- fde_count);
-
- return ret;
-}
-
-#ifndef NO_LIBUNWIND_DEBUG_FRAME
-static int read_unwind_spec_debug_frame(struct dso *dso,
- struct machine *machine, u64 *offset)
-{
- int fd;
- u64 ofs = dso->data.debug_frame_offset;
-
- if (ofs == 0) {
- fd = dso__data_get_fd(dso, machine);
- if (fd < 0)
- return -EINVAL;
-
- /* Check the .debug_frame section for unwinding info */
- ofs = elf_section_offset(fd, ".debug_frame");
- dso->data.debug_frame_offset = ofs;
- dso__data_put_fd(dso);
- }
-
- *offset = ofs;
- if (*offset)
- return 0;
-
- return -EINVAL;
-}
-#endif
-
-static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
-{
- struct addr_location al;
-
- thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
- MAP__FUNCTION, ip, &al);
- if (!al.map) {
- /*
- * We've seen cases (softice) where DWARF unwinder went
- * through non executable mmaps, which we need to lookup
- * in MAP__VARIABLE tree.
- */
- thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
- MAP__VARIABLE, ip, &al);
- }
- return al.map;
-}
-
-static int
-find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
- int need_unwind_info, void *arg)
-{
- struct unwind_info *ui = arg;
- struct map *map;
- unw_dyn_info_t di;
- u64 table_data, segbase, fde_count;
- int ret = -EINVAL;
-
- map = find_map(ip, ui);
- if (!map || !map->dso)
- return -EINVAL;
-
- pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
-
- /* Check the .eh_frame section for unwinding info */
- if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
- &table_data, &segbase, &fde_count)) {
- memset(&di, 0, sizeof(di));
- di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
- di.start_ip = map->start;
- di.end_ip = map->end;
- di.u.rti.segbase = map->start + segbase;
- di.u.rti.table_data = map->start + table_data;
- di.u.rti.table_len = fde_count * sizeof(struct table_entry)
- / sizeof(unw_word_t);
- ret = dwarf_search_unwind_table(as, ip, &di, pi,
- need_unwind_info, arg);
- }
-
-#ifndef NO_LIBUNWIND_DEBUG_FRAME
- /* Check the .debug_frame section for unwinding info */
- if (ret < 0 &&
- !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
- int fd = dso__data_get_fd(map->dso, ui->machine);
- int is_exec = elf_is_exec(fd, map->dso->name);
- unw_word_t base = is_exec ? 0 : map->start;
- const char *symfile;
-
- if (fd >= 0)
- dso__data_put_fd(map->dso);
-
- symfile = map->dso->symsrc_filename ?: map->dso->name;
-
- memset(&di, 0, sizeof(di));
- if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
- map->start, map->end))
- return dwarf_search_unwind_table(as, ip, &di, pi,
- need_unwind_info, arg);
- }
-#endif
-
- return ret;
-}
-
-static int access_fpreg(unw_addr_space_t __maybe_unused as,
- unw_regnum_t __maybe_unused num,
- unw_fpreg_t __maybe_unused *val,
- int __maybe_unused __write,
- void __maybe_unused *arg)
-{
- pr_err("unwind: access_fpreg unsupported\n");
- return -UNW_EINVAL;
-}
-
-static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
- unw_word_t __maybe_unused *dil_addr,
- void __maybe_unused *arg)
-{
- return -UNW_ENOINFO;
-}
-
-static int resume(unw_addr_space_t __maybe_unused as,
- unw_cursor_t __maybe_unused *cu,
- void __maybe_unused *arg)
-{
- pr_err("unwind: resume unsupported\n");
- return -UNW_EINVAL;
-}
-
-static int
-get_proc_name(unw_addr_space_t __maybe_unused as,
- unw_word_t __maybe_unused addr,
- char __maybe_unused *bufp, size_t __maybe_unused buf_len,
- unw_word_t __maybe_unused *offp, void __maybe_unused *arg)
-{
- pr_err("unwind: get_proc_name unsupported\n");
- return -UNW_EINVAL;
-}
-
-static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
- unw_word_t *data)
-{
- struct map *map;
- ssize_t size;
-
- map = find_map(addr, ui);
- if (!map) {
- pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
- return -1;
- }
-
- if (!map->dso)
- return -1;
-
- size = dso__data_read_addr(map->dso, map, ui->machine,
- addr, (u8 *) data, sizeof(*data));
-
- return !(size == sizeof(*data));
-}
-
-static int access_mem(unw_addr_space_t __maybe_unused as,
- unw_word_t addr, unw_word_t *valp,
- int __write, void *arg)
-{
- struct unwind_info *ui = arg;
- struct stack_dump *stack = &ui->sample->user_stack;
- u64 start, end;
- int offset;
- int ret;
-
- /* Don't support write, probably not needed. */
- if (__write || !stack || !ui->sample->user_regs.regs) {
- *valp = 0;
- return 0;
- }
-
- ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
- if (ret)
- return ret;
-
- end = start + stack->size;
-
- /* Check overflow. */
- if (addr + sizeof(unw_word_t) < addr)
- return -EINVAL;
-
- if (addr < start || addr + sizeof(unw_word_t) >= end) {
- ret = access_dso_mem(ui, addr, valp);
- if (ret) {
- pr_debug("unwind: access_mem %p not inside range"
- " 0x%" PRIx64 "-0x%" PRIx64 "\n",
- (void *) (uintptr_t) addr, start, end);
- *valp = 0;
- return ret;
- }
- return 0;
- }
-
- offset = addr - start;
- *valp = *(unw_word_t *)&stack->data[offset];
- pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
- (void *) (uintptr_t) addr, (unsigned long)*valp, offset);
- return 0;
-}
-
-static int access_reg(unw_addr_space_t __maybe_unused as,
- unw_regnum_t regnum, unw_word_t *valp,
- int __write, void *arg)
-{
- struct unwind_info *ui = arg;
- int id, ret;
- u64 val;
-
- /* Don't support write, I suspect we don't need it. */
- if (__write) {
- pr_err("unwind: access_reg w %d\n", regnum);
- return 0;
- }
-
- if (!ui->sample->user_regs.regs) {
- *valp = 0;
- return 0;
- }
-
- id = libunwind__arch_reg_id(regnum);
- if (id < 0)
- return -EINVAL;
-
- ret = perf_reg_value(&val, &ui->sample->user_regs, id);
- if (ret) {
- pr_err("unwind: can't read reg %d\n", regnum);
- return ret;
- }
-
- *valp = (unw_word_t) val;
- pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
- return 0;
-}
-
-static void put_unwind_info(unw_addr_space_t __maybe_unused as,
- unw_proc_info_t *pi __maybe_unused,
- void *arg __maybe_unused)
-{
- pr_debug("unwind: put_unwind_info called\n");
-}
-
-static int entry(u64 ip, struct thread *thread,
- unwind_entry_cb_t cb, void *arg)
-{
- struct unwind_entry e;
- struct addr_location al;
-
- thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
- MAP__FUNCTION, ip, &al);
-
- e.ip = ip;
- e.map = al.map;
- e.sym = al.sym;
-
- pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
- al.sym ? al.sym->name : "''",
- ip,
- al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
-
- return cb(&e, arg);
-}
-
-static void display_error(int err)
-{
- switch (err) {
- case UNW_EINVAL:
- pr_err("unwind: Only supports local.\n");
- break;
- case UNW_EUNSPEC:
- pr_err("unwind: Unspecified error.\n");
- break;
- case UNW_EBADREG:
- pr_err("unwind: Register unavailable.\n");
- break;
- default:
- break;
- }
-}
-
-static unw_accessors_t accessors = {
- .find_proc_info = find_proc_info,
- .put_unwind_info = put_unwind_info,
- .get_dyn_info_list_addr = get_dyn_info_list_addr,
- .access_mem = access_mem,
- .access_reg = access_reg,
- .access_fpreg = access_fpreg,
- .resume = resume,
- .get_proc_name = get_proc_name,
-};
-
-static int _unwind__prepare_access(struct thread *thread)
-{
- if (callchain_param.record_mode != CALLCHAIN_DWARF)
- return 0;
-
- thread->addr_space = unw_create_addr_space(&accessors, 0);
- if (!thread->addr_space) {
- pr_err("unwind: Can't create unwind address space.\n");
- return -ENOMEM;
- }
-
- unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
- return 0;
-}
-
-static void _unwind__flush_access(struct thread *thread)
-{
- if (callchain_param.record_mode != CALLCHAIN_DWARF)
- return;
-
- unw_flush_cache(thread->addr_space, 0, 0);
-}
-
-static void _unwind__finish_access(struct thread *thread)
-{
- if (callchain_param.record_mode != CALLCHAIN_DWARF)
- return;
-
- unw_destroy_addr_space(thread->addr_space);
-}
-
-static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
- void *arg, int max_stack)
-{
- u64 val;
- unw_word_t ips[max_stack];
- unw_addr_space_t addr_space;
- unw_cursor_t c;
- int ret, i = 0;
-
- ret = perf_reg_value(&val, &ui->sample->user_regs, PERF_REG_IP);
- if (ret)
- return ret;
-
- ips[i++] = (unw_word_t) val;
-
- /*
- * If we need more than one entry, do the DWARF
- * unwind itself.
- */
- if (max_stack - 1 > 0) {
- WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
- addr_space = ui->thread->addr_space;
-
- if (addr_space == NULL)
- return -1;
-
- ret = unw_init_remote(&c, addr_space, ui);
- if (ret)
- display_error(ret);
-
- while (!ret && (unw_step(&c) > 0) && i < max_stack) {
- unw_get_reg(&c, UNW_REG_IP, &ips[i]);
- ++i;
- }
-
- max_stack = i;
- }
-
- /*
- * Display what we got based on the order setup.
- */
- for (i = 0; i < max_stack && !ret; i++) {
- int j = i;
-
- if (callchain_param.order == ORDER_CALLER)
- j = max_stack - i - 1;
- ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0;
- }
-
- return ret;
-}
-
-static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
- struct thread *thread,
- struct perf_sample *data, int max_stack)
-{
- struct unwind_info ui = {
- .sample = data,
- .thread = thread,
- .machine = thread->mg->machine,
- };
-
- if (!data->user_regs.regs)
- return -EINVAL;
-
- if (max_stack <= 0)
- return -EINVAL;
-
- return get_entries(&ui, cb, arg, max_stack);
-}
-
-static struct unwind_libunwind_ops
-_unwind_libunwind_ops = {
- .prepare_access = _unwind__prepare_access,
- .flush_access = _unwind__flush_access,
- .finish_access = _unwind__finish_access,
- .get_entries = _unwind__get_entries,
-};
-
-struct unwind_libunwind_ops *
-local_unwind_libunwind_ops = &_unwind_libunwind_ops;
-
-static void unwind__register_ops(struct thread *thread,
- struct unwind_libunwind_ops *ops)
-{
- thread->unwind_libunwind_ops = ops;
-}
-
-int unwind__prepare_access(struct thread *thread)
-{
- unwind__register_ops(thread, local_unwind_libunwind_ops);
-
- return thread->unwind_libunwind_ops->prepare_access(thread);
-}
-
-void unwind__flush_access(struct thread *thread)
-{
- if (thread->unwind_libunwind_ops)
- thread->unwind_libunwind_ops->flush_access(thread);
-}
-
-void unwind__finish_access(struct thread *thread)
-{
- if (thread->unwind_libunwind_ops)
- thread->unwind_libunwind_ops->finish_access(thread);
-}
-
-int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
- struct thread *thread,
- struct perf_sample *data, int max_stack)
-{
- if (thread->unwind_libunwind_ops)
- return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
- return 0;
-}
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 19/24] perf tools: Export normalize_arch() function |
| Message-ID | <rHvDH-7fg-1@gated-at.bofh.it> |
| In reply to | #1416560 |
From: He Kuang <hekuang@huawei.com>
Export normalize_arch() function, so other part of perf can get
normalized form of arch string.
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1464924803-22214-10-git-send-email-hekuang@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/arch/common.c | 2 +-
tools/perf/arch/common.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index e83c8ce24303..fa090a9eaa38 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -102,7 +102,7 @@ static int lookup_triplets(const char *const *triplets, const char *name)
* Return architecture name in a normalized form.
* The conversion logic comes from the Makefile.
*/
-static const char *normalize_arch(char *arch)
+const char *normalize_arch(char *arch)
{
if (!strcmp(arch, "x86_64"))
return "x86";
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
index 7529cfb143ce..6b01c736b7d9 100644
--- a/tools/perf/arch/common.h
+++ b/tools/perf/arch/common.h
@@ -6,5 +6,6 @@
extern const char *objdump_path;
int perf_env__lookup_objdump(struct perf_env *env);
+const char *normalize_arch(char *arch);
#endif /* ARCH_PERF_COMMON_H */
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 22/24] perf unwind: Introduce flag to separate local/remote unwind compilation |
| Message-ID | <rHvDI-7fg-5@gated-at.bofh.it> |
| In reply to | #1416560 |
From: He Kuang <hekuang@huawei.com>
This is a preparation for including unwind-libunwind-local.c in other
files for remote libunwind.
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1464924803-22214-13-git-send-email-hekuang@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/unwind-libunwind-local.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 631b40d94643..01c2e86977f4 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -22,8 +22,10 @@
#include <unistd.h>
#include <sys/mman.h>
#include <linux/list.h>
+#ifndef REMOTE_UNWIND_LIBUNWIND
#include <libunwind.h>
#include <libunwind-ptrace.h>
+#endif
#include "callchain.h"
#include "thread.h"
#include "session.h"
@@ -689,5 +691,7 @@ _unwind_libunwind_ops = {
.get_entries = _unwind__get_entries,
};
+#ifndef REMOTE_UNWIND_LIBUNWIND
struct unwind_libunwind_ops *
local_unwind_libunwind_ops = &_unwind_libunwind_ops;
+#endif
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 10/24] perf config: Use new perf_config_set__init() to initialize config set |
| Message-ID | <rHvDI-7fg-13@gated-at.bofh.it> |
| In reply to | #1416560 |
From: Taeung Song <treeze.taeung@gmail.com>
Instead of perf_config(), this function initializes config set by
reading various files: user config ~/.perfconfig and system config
$(sysconfdir)/perfconfig).
If there are the same config variable in both user and system config
files, user config has higher priority than system config.
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1465291577-20973-3-git-send-email-treeze.taeung@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/config.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index e086f593a2aa..8749eca3055f 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -646,13 +646,58 @@ out_free:
return -1;
}
+static int perf_config_set__init(struct perf_config_set *set)
+{
+ int ret = -1;
+ const char *home = NULL;
+
+ /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
+ if (config_exclusive_filename)
+ return perf_config_from_file(collect_config, config_exclusive_filename, set);
+ if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) {
+ if (perf_config_from_file(collect_config, perf_etc_perfconfig(), set) < 0)
+ goto out;
+ }
+
+ home = getenv("HOME");
+ if (perf_config_global() && home) {
+ char *user_config = strdup(mkpath("%s/.perfconfig", home));
+ struct stat st;
+
+ if (user_config == NULL) {
+ warning("Not enough memory to process %s/.perfconfig, "
+ "ignoring it.", home);
+ goto out;
+ }
+
+ if (stat(user_config, &st) < 0)
+ goto out_free;
+
+ if (st.st_uid && (st.st_uid != geteuid())) {
+ warning("File %s not owned by current user or root, "
+ "ignoring it.", user_config);
+ goto out_free;
+ }
+
+ if (!st.st_size)
+ goto out_free;
+
+ ret = perf_config_from_file(collect_config, user_config, set);
+
+out_free:
+ free(user_config);
+ }
+out:
+ return ret;
+}
+
struct perf_config_set *perf_config_set__new(void)
{
struct perf_config_set *set = zalloc(sizeof(*set));
if (set) {
INIT_LIST_HEAD(&set->sections);
- if (perf_config(collect_config, set) < 0) {
+ if (perf_config_set__init(set) < 0) {
perf_config_set__delete(set);
set = NULL;
}
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 06/24] tools lib bpf: Make bpf_program__get_private() use IS_ERR() |
| Message-ID | <rHvDI-7fg-21@gated-at.bofh.it> |
| In reply to | #1416560 |
From: Arnaldo Carvalho de Melo <acme@redhat.com>
For consistency with bpf_map__priv() and elsewhere.
Acked-by: Wang Nan <wangnan0@huawei.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Milian Wolff <milian.wolff@kdab.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/n/tip-x17nk5mrazkf45z0l0ahlmo8@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/lib/bpf/libbpf.c | 5 ++---
tools/lib/bpf/libbpf.h | 3 +--
tools/perf/util/bpf-loader.c | 27 ++++++++++++---------------
3 files changed, 15 insertions(+), 20 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 0412182fb365..7eb7fb26e999 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1230,10 +1230,9 @@ int bpf_program__set_private(struct bpf_program *prog,
return 0;
}
-int bpf_program__get_private(struct bpf_program *prog, void **ppriv)
+void *bpf_program__priv(struct bpf_program *prog)
{
- *ppriv = prog->priv;
- return 0;
+ return prog ? prog->priv : ERR_PTR(-EINVAL);
}
const char *bpf_program__title(struct bpf_program *prog, bool needs_copy)
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index ea65775e8302..372cecbde207 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -81,8 +81,7 @@ typedef void (*bpf_program_clear_priv_t)(struct bpf_program *,
int bpf_program__set_private(struct bpf_program *prog, void *priv,
bpf_program_clear_priv_t clear_priv);
-int bpf_program__get_private(struct bpf_program *prog,
- void **ppriv);
+void *bpf_program__priv(struct bpf_program *prog);
const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index c19010e6cefb..1907d5313960 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -380,15 +380,14 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
struct bpf_insn *orig_insns, int orig_insns_cnt,
struct bpf_prog_prep_result *res)
{
+ struct bpf_prog_priv *priv = bpf_program__priv(prog);
struct probe_trace_event *tev;
struct perf_probe_event *pev;
- struct bpf_prog_priv *priv;
struct bpf_insn *buf;
size_t prologue_cnt = 0;
int i, err;
- err = bpf_program__get_private(prog, (void **)&priv);
- if (err || !priv)
+ if (IS_ERR(priv) || !priv)
goto errout;
pev = &priv->pev;
@@ -535,13 +534,12 @@ static int map_prologue(struct perf_probe_event *pev, int *mapping,
static int hook_load_preprocessor(struct bpf_program *prog)
{
+ struct bpf_prog_priv *priv = bpf_program__priv(prog);
struct perf_probe_event *pev;
- struct bpf_prog_priv *priv;
bool need_prologue = false;
int err, i;
- err = bpf_program__get_private(prog, (void **)&priv);
- if (err || !priv) {
+ if (IS_ERR(priv) || !priv) {
pr_debug("Internal error when hook preprocessor\n");
return -BPF_LOADER_ERRNO__INTERNAL;
}
@@ -607,9 +605,11 @@ int bpf__probe(struct bpf_object *obj)
if (err)
goto out;
- err = bpf_program__get_private(prog, (void **)&priv);
- if (err || !priv)
+ priv = bpf_program__priv(prog);
+ if (IS_ERR(priv) || !priv) {
+ err = PTR_ERR(priv);
goto out;
+ }
pev = &priv->pev;
err = convert_perf_probe_events(pev, 1);
@@ -645,13 +645,12 @@ int bpf__unprobe(struct bpf_object *obj)
{
int err, ret = 0;
struct bpf_program *prog;
- struct bpf_prog_priv *priv;
bpf_object__for_each_program(prog, obj) {
+ struct bpf_prog_priv *priv = bpf_program__priv(prog);
int i;
- err = bpf_program__get_private(prog, (void **)&priv);
- if (err || !priv)
+ if (IS_ERR(priv) || !priv)
continue;
for (i = 0; i < priv->pev.ntevs; i++) {
@@ -702,14 +701,12 @@ int bpf__foreach_tev(struct bpf_object *obj,
int err;
bpf_object__for_each_program(prog, obj) {
+ struct bpf_prog_priv *priv = bpf_program__priv(prog);
struct probe_trace_event *tev;
struct perf_probe_event *pev;
- struct bpf_prog_priv *priv;
int i, fd;
- err = bpf_program__get_private(prog,
- (void **)&priv);
- if (err || !priv) {
+ if (IS_ERR(priv) || !priv) {
pr_debug("bpf: failed to get private field\n");
return -BPF_LOADER_ERRNO__INTERNAL;
}
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 09/24] perf config: Constructor should free its allocated memory when failing |
| Message-ID | <rHvDI-7fg-33@gated-at.bofh.it> |
| In reply to | #1416560 |
From: Taeung Song <treeze.taeung@gmail.com>
Because of die() at perf_parse_file() a config set was freed in
collect_config(), if failed. But it is natural to free a config set
after collect_config() is done when some problems happened.
So, in case of failure, lastly free a config set at perf_config_set__new()
instead of freeing the config set in collect_config().
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1465291577-20973-2-git-send-email-treeze.taeung@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/config.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index c73f1c4d1ca9..e086f593a2aa 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -643,7 +643,6 @@ static int collect_config(const char *var, const char *value,
out_free:
free(key);
- perf_config_set__delete(set);
return -1;
}
@@ -653,7 +652,10 @@ struct perf_config_set *perf_config_set__new(void)
if (set) {
INIT_LIST_HEAD(&set->sections);
- perf_config(collect_config, set);
+ if (perf_config(collect_config, set) < 0) {
+ perf_config_set__delete(set);
+ set = NULL;
+ }
}
return set;
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 15/24] perf unwind: Don't mix LIBUNWIND_LIBS into LIBUNWIND_LDFLAGS |
| Message-ID | <rHvDI-7fg-27@gated-at.bofh.it> |
| In reply to | #1416560 |
From: He Kuang <hekuang@huawei.com> LIBUNWIND_LIBS contains libunwind libraries used for local only, don't mix this into LIBUNWIND_LDFLAGS so we can later use LIBUNWIND_LDFLAGS both for local and remote libunwind. Signed-off-by: He Kuang <hekuang@huawei.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Kan Liang <kan.liang@intel.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Pekka Enberg <penberg@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/r/1464924803-22214-6-git-send-email-hekuang@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/config/Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 6f9f566a757c..118df2d04b08 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -80,13 +80,12 @@ ifdef LIBUNWIND_DIR LIBUNWIND_ARCHS = x86 x86_64 arm aarch64 debug-frame-arm debug-frame-aarch64 $(foreach libunwind_arch,$(LIBUNWIND_ARCHS),$(call libunwind_arch_set_flags,$(libunwind_arch))) endif -LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS) # Set per-feature check compilation flags FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) -FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) +FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) -FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) +FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) ifeq ($(NO_PERF_REGS),0) CFLAGS += -DHAVE_PERF_REGS_SUPPORT @@ -409,7 +408,7 @@ ifndef NO_LIBUNWIND CFLAGS += -DHAVE_LIBUNWIND_SUPPORT EXTLIBS += $(LIBUNWIND_LIBS) CFLAGS += $(LIBUNWIND_CFLAGS) - LDFLAGS += $(LIBUNWIND_LDFLAGS) + LDFLAGS += $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) endif ifndef NO_LIBAUDIT -- 2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 11/24] perf unwind: Use LIBUNWIND_DIR for remote libunwind feature check |
| Message-ID | <rHvDI-7fg-31@gated-at.bofh.it> |
| In reply to | #1416560 |
From: He Kuang <hekuang@huawei.com> Pass LIBUNWIND_DIR to feature check flags for remote libunwind tests. So perf can be able to detect remote libunwind libraries from arbitrary directory. Signed-off-by: He Kuang <hekuang@huawei.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Kan Liang <kan.liang@intel.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Pekka Enberg <penberg@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/r/1464924803-22214-2-git-send-email-hekuang@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/config/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 1e46277286c2..6f9f566a757c 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -67,9 +67,18 @@ endif # # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ # + +libunwind_arch_set_flags = $(eval $(libunwind_arch_set_flags_code)) +define libunwind_arch_set_flags_code + FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include + FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib +endef + ifdef LIBUNWIND_DIR LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib + LIBUNWIND_ARCHS = x86 x86_64 arm aarch64 debug-frame-arm debug-frame-aarch64 + $(foreach libunwind_arch,$(LIBUNWIND_ARCHS),$(call libunwind_arch_set_flags,$(libunwind_arch))) endif LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS) -- 2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 12/24] perf unwind: Decouple thread->address_space on libunwind |
| Message-ID | <rHvDJ-7fg-41@gated-at.bofh.it> |
| In reply to | #1416560 |
From: He Kuang <hekuang@huawei.com>
Currently, the type of thread->addr_space is unw_addr_space_t, which is
a pointer defined in libunwind headers. For local libunwind, we can
simple include "libunwind.h", but for remote libunwind, the header file
is depends on the target libunwind platform. This patch uses 'void *'
instead to decouple the dependence on libunwind.
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1464924803-22214-3-git-send-email-hekuang@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/thread.h | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 08fcb14cf637..4c9f0aa11f1f 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -9,9 +9,6 @@
#include "symbol.h"
#include <strlist.h>
#include <intlist.h>
-#ifdef HAVE_LIBUNWIND_SUPPORT
-#include <libunwind.h>
-#endif
struct thread_stack;
@@ -36,7 +33,7 @@ struct thread {
void *priv;
struct thread_stack *ts;
#ifdef HAVE_LIBUNWIND_SUPPORT
- unw_addr_space_t addr_space;
+ void *addr_space;
#endif
};
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 13/24] perf unwind: Introduce 'struct unwind_libunwind_ops' for local unwind |
| Message-ID | <rHvDJ-7fg-43@gated-at.bofh.it> |
| In reply to | #1416560 |
From: He Kuang <hekuang@huawei.com>
Currently, libunwind operations are fixed, and they are chosen according
to the host architecture. This will lead to a problem that if a thread
is run as x86_32 on a x86_64 machine, perf will use libunwind methods
for x86_64 to parse the callchain and get wrong results.
This patch changes the fixed methods of libunwind operations to be
thread/map related, and each thread can have individual libunwind
operations. Local libunwind methods are registered as default value.
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1464924803-22214-4-git-send-email-hekuang@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/thread.h | 4 ++-
tools/perf/util/unwind-libunwind.c | 53 +++++++++++++++++++++++++++++++++++---
tools/perf/util/unwind.h | 9 +++++++
3 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 4c9f0aa11f1f..07ffb18221ab 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -11,6 +11,7 @@
#include <intlist.h>
struct thread_stack;
+struct unwind_libunwind_ops;
struct thread {
union {
@@ -33,7 +34,8 @@ struct thread {
void *priv;
struct thread_stack *ts;
#ifdef HAVE_LIBUNWIND_SUPPORT
- void *addr_space;
+ void *addr_space;
+ struct unwind_libunwind_ops *unwind_libunwind_ops;
#endif
};
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 63687d3a344e..b0c5db1333f9 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -579,7 +579,7 @@ static unw_accessors_t accessors = {
.get_proc_name = get_proc_name,
};
-int unwind__prepare_access(struct thread *thread)
+static int _unwind__prepare_access(struct thread *thread)
{
if (callchain_param.record_mode != CALLCHAIN_DWARF)
return 0;
@@ -594,7 +594,7 @@ int unwind__prepare_access(struct thread *thread)
return 0;
}
-void unwind__flush_access(struct thread *thread)
+static void _unwind__flush_access(struct thread *thread)
{
if (callchain_param.record_mode != CALLCHAIN_DWARF)
return;
@@ -602,7 +602,7 @@ void unwind__flush_access(struct thread *thread)
unw_flush_cache(thread->addr_space, 0, 0);
}
-void unwind__finish_access(struct thread *thread)
+static void _unwind__finish_access(struct thread *thread)
{
if (callchain_param.record_mode != CALLCHAIN_DWARF)
return;
@@ -662,7 +662,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
return ret;
}
-int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
+static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
struct thread *thread,
struct perf_sample *data, int max_stack)
{
@@ -680,3 +680,48 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
return get_entries(&ui, cb, arg, max_stack);
}
+
+static struct unwind_libunwind_ops
+_unwind_libunwind_ops = {
+ .prepare_access = _unwind__prepare_access,
+ .flush_access = _unwind__flush_access,
+ .finish_access = _unwind__finish_access,
+ .get_entries = _unwind__get_entries,
+};
+
+struct unwind_libunwind_ops *
+local_unwind_libunwind_ops = &_unwind_libunwind_ops;
+
+static void unwind__register_ops(struct thread *thread,
+ struct unwind_libunwind_ops *ops)
+{
+ thread->unwind_libunwind_ops = ops;
+}
+
+int unwind__prepare_access(struct thread *thread)
+{
+ unwind__register_ops(thread, local_unwind_libunwind_ops);
+
+ return thread->unwind_libunwind_ops->prepare_access(thread);
+}
+
+void unwind__flush_access(struct thread *thread)
+{
+ if (thread->unwind_libunwind_ops)
+ thread->unwind_libunwind_ops->flush_access(thread);
+}
+
+void unwind__finish_access(struct thread *thread)
+{
+ if (thread->unwind_libunwind_ops)
+ thread->unwind_libunwind_ops->finish_access(thread);
+}
+
+int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
+ struct thread *thread,
+ struct perf_sample *data, int max_stack)
+{
+ if (thread->unwind_libunwind_ops)
+ return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
+ return 0;
+}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 12790cf94618..bbd73d9bea45 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -14,6 +14,15 @@ struct unwind_entry {
typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
+struct unwind_libunwind_ops {
+ int (*prepare_access)(struct thread *thread);
+ void (*flush_access)(struct thread *thread);
+ void (*finish_access)(struct thread *thread);
+ int (*get_entries)(unwind_entry_cb_t cb, void *arg,
+ struct thread *thread,
+ struct perf_sample *data, int max_stack);
+};
+
#ifdef HAVE_DWARF_UNWIND_SUPPORT
int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
struct thread *thread,
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-07 22:20 +0200 |
| Subject | [PATCH 01/24] tools lib bpf: Use IS_ERR() reporting macros with bpf_map__get_private() |
| Message-ID | <rHvDJ-7fg-53@gated-at.bofh.it> |
| In reply to | #1416560 |
From: Arnaldo Carvalho de Melo <acme@redhat.com>
To try to, over time, consistently use the IS_ERR() interface instead of
using two return values, i.e. the integer return value for an error and
the pointer address to return the bpf_map->priv pointer.
Also rename it to bpf__priv(), to leave the "get" term for reference
counting.
Noticed while working on using BPF for collecting non-integer syscall
argument payloads (struct sockaddr in calls such as connect(), for
instance), where we need to use BPF maps and thus generalise
bpf__setup_stdout() to connect bpf_output events with maps in a bpf
proggie.
Acked-by: Wang Nan <wangnan0@huawei.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Milian Wolff <milian.wolff@kdab.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/n/tip-saypxyd6ptrct379jqgxx4bl@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/lib/bpf/libbpf.c | 9 ++-------
tools/lib/bpf/libbpf.h | 2 +-
tools/perf/util/bpf-loader.c | 23 +++++++++--------------
3 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 7e543c3102d4..9bba1a907abe 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1351,14 +1351,9 @@ int bpf_map__set_private(struct bpf_map *map, void *priv,
return 0;
}
-int bpf_map__get_private(struct bpf_map *map, void **ppriv)
+void *bpf_map__priv(struct bpf_map *map)
{
- if (!map)
- return -EINVAL;
-
- if (ppriv)
- *ppriv = map->priv;
- return 0;
+ return map ? map->priv : ERR_PTR(-EINVAL);
}
struct bpf_map *
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index a51594c7b518..916abf971249 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -187,6 +187,6 @@ const char *bpf_map__get_name(struct bpf_map *map);
typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
int bpf_map__set_private(struct bpf_map *map, void *priv,
bpf_map_clear_priv_t clear_priv);
-int bpf_map__get_private(struct bpf_map *map, void **ppriv);
+void *bpf_map__priv(struct bpf_map *map);
#endif
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 493307d1414c..e9a034e86b91 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -897,15 +897,13 @@ bpf_map_priv__clone(struct bpf_map_priv *priv)
static int
bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
{
- struct bpf_map_priv *priv;
+ struct bpf_map_priv *priv = bpf_map__priv(map);
const char *map_name;
- int err;
map_name = bpf_map__get_name(map);
- err = bpf_map__get_private(map, (void **)&priv);
- if (err) {
+ if (IS_ERR(priv)) {
pr_debug("Failed to get private from map %s\n", map_name);
- return err;
+ return PTR_ERR(priv);
}
if (!priv) {
@@ -1264,12 +1262,11 @@ bpf_map_config_foreach_key(struct bpf_map *map,
const char *name;
struct bpf_map_op *op;
struct bpf_map_def def;
- struct bpf_map_priv *priv;
+ struct bpf_map_priv *priv = bpf_map__priv(map);
name = bpf_map__get_name(map);
- err = bpf_map__get_private(map, (void **)&priv);
- if (err) {
+ if (IS_ERR(priv)) {
pr_debug("ERROR: failed to get private from map %s\n", name);
return -BPF_LOADER_ERRNO__INTERNAL;
}
@@ -1489,10 +1486,9 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
bool need_init = false;
bpf__for_each_stdout_map(map, obj, tmp) {
- struct bpf_map_priv *priv;
+ struct bpf_map_priv *priv = bpf_map__priv(map);
- err = bpf_map__get_private(map, (void **)&priv);
- if (err)
+ if (IS_ERR(priv))
return -BPF_LOADER_ERRNO__INTERNAL;
/*
@@ -1520,10 +1516,9 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
}
bpf__for_each_stdout_map(map, obj, tmp) {
- struct bpf_map_priv *priv;
+ struct bpf_map_priv *priv = bpf_map__priv(map);
- err = bpf_map__get_private(map, (void **)&priv);
- if (err)
+ if (IS_ERR(priv))
return -BPF_LOADER_ERRNO__INTERNAL;
if (priv)
continue;
--
2.5.5
[toc] | [prev] | [next] | [standalone]
| From | Taeung Song <treeze.taeung@gmail.com> |
|---|---|
| Date | 2016-06-08 01:20 +0200 |
| Message-ID | <rHyrU-Ac-13@gated-at.bofh.it> |
| In reply to | #1416560 |
Hi, Arnaldo I found something weird about perf/core branch on your repository. (I don't know whether it is just my illusion or not) I can't pull new commits on top of perf-core-for-mingo-20160606 by normal way as below # git remote show acme * remote acme Fetch URL: git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git # git log --oneline edb13ed tools lib bpf: Rename set_private() to set_priv() be834ff tools lib bpf: Make bpf_program__get_private() use IS_ERR() ... # git pull acme perf/core From git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux * branch perf/core -> FETCH_HEAD Already up-to-date. And then nothing changed, I didn't also find new commits and new tag 'perf-core-for-mingo-20160607'. However, if using tag perf-core-for-mingo-20160607, I can get new commits from your repository as below. # git fetch acme --tags remote: Counting objects: 4888, done. remote: Compressing objects: 100% (4800/4800), done. remote: Total 4888 (delta 266), reused 1212 (delta 59) Receiving objects: 100% (4888/4888), 21.36 MiB | 3.72 MiB/s, done. Resolving deltas: 100% (266/266), done. From git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux * [new tag] perf-core-for-mingo-20160307 -> perf-core-for-mingo-20160307 * [new tag] perf-core-for-mingo-20160329 -> perf-core-for-mingo-20160329 * [new tag] perf-core-for-mingo-20160407 -> perf-core-for-mingo-20160407 * [new tag] perf-core-for-mingo-20160607 -> perf-core-for-mingo-20160607 * [new tag] perf-ebpf-for-mingo -> perf-ebpf-for-mingo * [new tag] perf-urgent-for-mingo-20160510 -> perf-urgent-for-mingo-20160510 * [new tag] v2.6.11 -> v2.6.11 * [new tag] v2.6.11-tree -> v2.6.11-tree But there is a strange thing about git branch. I can't find which branch is that have tag perf-core-for-mingo-20160607 like below. # git branch -a --contains perf-core-for-mingo-20160607 As the final outcome, I got new commits on top of perf-core-for-mingo-20160606 directly using a tag 'perf-core-for-mingo-20160607' as below. # git reset --hard perf-core-for-mingo-20160607 HEAD is now at 057fbfb perf callchain: Support aarch64 cross-platform But isn't it a problem ? Just use a tag? Thanks, Taeung On 06/08/2016 05:04 AM, Arnaldo Carvalho de Melo wrote: > Hi Ingo, > > Please consider pulling, this is on top of perf-core-for-mingo-20160606, > > Thanks, > > - Arnaldo > > The following changes since commit 7db91f251056f90fec4121f028680ab3153a0f3c: > > perf config: Handle the error when config set is NULL at collect_config() (2016-06-06 17:43:19 -0300) > > are available in the git repository at: > > git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20160607 > > for you to fetch changes up to 057fbfb25cde4a368418f3f720cdc31d48800c4d: > > perf callchain: Support aarch64 cross-platform (2016-06-07 15:13:35 -0300) > > ---------------------------------------------------------------- > perf/core improvements and fixes: > > User visible: > > - Support cross unwinding, i.e. collecting '--call-graph dwarf' perf.data files > in one machine and then doing analysis in another machine of a different > hardware architecture. This enables, for instance, to do: > > perf record -a --call-graph dwarf > > on a x86-32 or aarch64 system and then do 'perf report' on it on a > x86_64 workstation. (He Kuang) > > - Fix crash in build_id_cache__kallsyms_path(), recent regression (Wang Nan) > > Infrastructure: > > - Make tools/lib/bpf use the IS_ERR return facility consistently and also stop > using the _get_ term for non-reference count methods (Arnaldo Carvalho de Melo) > > - 'perf config' refactorings (Taeung Song) > > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> > > ---------------------------------------------------------------- > Arnaldo Carvalho de Melo (7): > tools lib bpf: Use IS_ERR() reporting macros with bpf_map__get_private() > tools lib bpf: Rename bpf_map__get_name() to bpf_map__name() > tools lib bpf: Use IS_ERR() reporting macros with bpf_map__get_def() > tools lib bpf: Rename bpf_map__get_fd() to bpf_map__fd() > tools lib bpf: Remove _get_ from non-refcount method names > tools lib bpf: Make bpf_program__get_private() use IS_ERR() > tools lib bpf: Rename set_private() to set_priv() > > He Kuang (14): > perf unwind: Use LIBUNWIND_DIR for remote libunwind feature check > perf unwind: Decouple thread->address_space on libunwind > perf unwind: Introduce 'struct unwind_libunwind_ops' for local unwind > perf unwind: Move unwind__prepare_access from thread_new into thread__insert_map > perf unwind: Don't mix LIBUNWIND_LIBS into LIBUNWIND_LDFLAGS > perf unwind: Separate local/remote libunwind config > perf unwind: Rename unwind-libunwind.c to unwind-libunwind-local.c > perf tools: Extract common API out of unwind-libunwind-local.c > perf tools: Export normalize_arch() function > perf unwind: Check the target platform before assigning unwind methods > perf unwind: Change fixed name of libunwind__arch_reg_id to macro > perf unwind: Introduce flag to separate local/remote unwind compilation > perf callchain: Support x86 target platform > perf callchain: Support aarch64 cross-platform > > Taeung Song (2): > perf config: Constructor should free its allocated memory when failing > perf config: Use new perf_config_set__init() to initialize config set > > Wang Nan (1): > perf tools: Fix crash in build_id_cache__kallsyms_path() > > tools/lib/bpf/libbpf.c | 60 +-- > tools/lib/bpf/libbpf.h | 25 +- > tools/perf/arch/arm/util/Build | 2 +- > tools/perf/arch/arm64/util/Build | 2 +- > tools/perf/arch/arm64/util/unwind-libunwind.c | 4 +- > tools/perf/arch/common.c | 2 +- > tools/perf/arch/common.h | 1 + > tools/perf/arch/x86/util/Build | 2 +- > tools/perf/arch/x86/util/unwind-libunwind.c | 6 +- > tools/perf/config/Makefile | 52 +- > tools/perf/util/Build | 3 + > tools/perf/util/bpf-loader.c | 132 +++-- > tools/perf/util/build-id.c | 11 +- > tools/perf/util/config.c | 51 +- > tools/perf/util/libunwind/arm64.c | 35 ++ > tools/perf/util/libunwind/x86_32.c | 37 ++ > tools/perf/util/machine.c | 14 +- > tools/perf/util/thread.c | 13 +- > tools/perf/util/thread.h | 9 +- > tools/perf/util/unwind-libunwind-local.c | 697 ++++++++++++++++++++++++++ > tools/perf/util/unwind-libunwind.c | 688 ++----------------------- > tools/perf/util/unwind.h | 22 +- > 22 files changed, 1056 insertions(+), 812 deletions(-) > create mode 100644 tools/perf/util/libunwind/arm64.c > create mode 100644 tools/perf/util/libunwind/x86_32.c > create mode 100644 tools/perf/util/unwind-libunwind-local.c >
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-06-08 15:20 +0200 |
| Message-ID | <rHLyO-E7-23@gated-at.bofh.it> |
| In reply to | #1416722 |
Em Wed, Jun 08, 2016 at 08:10:50AM +0900, Taeung Song escreveu: > I found something weird about perf/core branch on your repository. > (I don't know whether it is just my illusion or not) > > I can't pull new commits on top of perf-core-for-mingo-20160606 > by normal way as below I forgot to push perf/core, having pushed just perf-core-for-mingo-20160607, which is enough for Ingo to pull what I sent to him, but not for you to get if you use perf/core, as usual, instead of perf-core-for-mingo-20160607. I pushed perf/core now, please update your local repo and all should be ok now. - Arnaldo
[toc] | [prev] | [next] | [standalone]
| From | Ingo Molnar <mingo@kernel.org> |
|---|---|
| Date | 2016-06-08 09:50 +0200 |
| Message-ID | <rHGpr-5GS-7@gated-at.bofh.it> |
| In reply to | #1416560 |
* Arnaldo Carvalho de Melo <acme@kernel.org> wrote: > Hi Ingo, > > Please consider pulling, this is on top of perf-core-for-mingo-20160606, > > Thanks, > > - Arnaldo > > The following changes since commit 7db91f251056f90fec4121f028680ab3153a0f3c: > > perf config: Handle the error when config set is NULL at collect_config() (2016-06-06 17:43:19 -0300) > > are available in the git repository at: > > git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20160607 > > for you to fetch changes up to 057fbfb25cde4a368418f3f720cdc31d48800c4d: > > perf callchain: Support aarch64 cross-platform (2016-06-07 15:13:35 -0300) > > ---------------------------------------------------------------- > perf/core improvements and fixes: > > User visible: > > - Support cross unwinding, i.e. collecting '--call-graph dwarf' perf.data files > in one machine and then doing analysis in another machine of a different > hardware architecture. This enables, for instance, to do: > > perf record -a --call-graph dwarf > > on a x86-32 or aarch64 system and then do 'perf report' on it on a > x86_64 workstation. (He Kuang) > > - Fix crash in build_id_cache__kallsyms_path(), recent regression (Wang Nan) > > Infrastructure: > > - Make tools/lib/bpf use the IS_ERR return facility consistently and also stop > using the _get_ term for non-reference count methods (Arnaldo Carvalho de Melo) > > - 'perf config' refactorings (Taeung Song) > > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> > > ---------------------------------------------------------------- > Arnaldo Carvalho de Melo (7): > tools lib bpf: Use IS_ERR() reporting macros with bpf_map__get_private() > tools lib bpf: Rename bpf_map__get_name() to bpf_map__name() > tools lib bpf: Use IS_ERR() reporting macros with bpf_map__get_def() > tools lib bpf: Rename bpf_map__get_fd() to bpf_map__fd() > tools lib bpf: Remove _get_ from non-refcount method names > tools lib bpf: Make bpf_program__get_private() use IS_ERR() > tools lib bpf: Rename set_private() to set_priv() > > He Kuang (14): > perf unwind: Use LIBUNWIND_DIR for remote libunwind feature check > perf unwind: Decouple thread->address_space on libunwind > perf unwind: Introduce 'struct unwind_libunwind_ops' for local unwind > perf unwind: Move unwind__prepare_access from thread_new into thread__insert_map > perf unwind: Don't mix LIBUNWIND_LIBS into LIBUNWIND_LDFLAGS > perf unwind: Separate local/remote libunwind config > perf unwind: Rename unwind-libunwind.c to unwind-libunwind-local.c > perf tools: Extract common API out of unwind-libunwind-local.c > perf tools: Export normalize_arch() function > perf unwind: Check the target platform before assigning unwind methods > perf unwind: Change fixed name of libunwind__arch_reg_id to macro > perf unwind: Introduce flag to separate local/remote unwind compilation > perf callchain: Support x86 target platform > perf callchain: Support aarch64 cross-platform > > Taeung Song (2): > perf config: Constructor should free its allocated memory when failing > perf config: Use new perf_config_set__init() to initialize config set > > Wang Nan (1): > perf tools: Fix crash in build_id_cache__kallsyms_path() > > tools/lib/bpf/libbpf.c | 60 +-- > tools/lib/bpf/libbpf.h | 25 +- > tools/perf/arch/arm/util/Build | 2 +- > tools/perf/arch/arm64/util/Build | 2 +- > tools/perf/arch/arm64/util/unwind-libunwind.c | 4 +- > tools/perf/arch/common.c | 2 +- > tools/perf/arch/common.h | 1 + > tools/perf/arch/x86/util/Build | 2 +- > tools/perf/arch/x86/util/unwind-libunwind.c | 6 +- > tools/perf/config/Makefile | 52 +- > tools/perf/util/Build | 3 + > tools/perf/util/bpf-loader.c | 132 +++-- > tools/perf/util/build-id.c | 11 +- > tools/perf/util/config.c | 51 +- > tools/perf/util/libunwind/arm64.c | 35 ++ > tools/perf/util/libunwind/x86_32.c | 37 ++ > tools/perf/util/machine.c | 14 +- > tools/perf/util/thread.c | 13 +- > tools/perf/util/thread.h | 9 +- > tools/perf/util/unwind-libunwind-local.c | 697 ++++++++++++++++++++++++++ > tools/perf/util/unwind-libunwind.c | 688 ++----------------------- > tools/perf/util/unwind.h | 22 +- > 22 files changed, 1056 insertions(+), 812 deletions(-) > create mode 100644 tools/perf/util/libunwind/arm64.c > create mode 100644 tools/perf/util/libunwind/x86_32.c > create mode 100644 tools/perf/util/unwind-libunwind-local.c Pulled, thanks a lot Arnaldo! Ingo
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web