From: Irina Tirdea <[email protected]>
Hi,
I have gathered in this set all remaining patches with Android fixes.
Starting from Bernhard's patch [1], I added 2 patches (patch 1 and 2) that
include on_exit implementation and Android support in the Makefile.
I have also added some documentation on building for Android (patch 3).
I have included version 3 for the patchset "perf: android: configure hardcoded
paths" [2]. Changes for v3:
() add documentation and update Makefile for Android for patch 4 and 5
() move the detection of cross-build objdump path in one file (common.c) so that
is available for addr2line as well. (patch 6)
() implement detection of cross-build path for addr2line (patch 7)
I have also included version 3 for the patch "perf stat: implement --big-num
grouping" [3] (patch 8). Changes for v3:
() replace LOCALE_SUPPORT with NO_LOCALE for consistency with recent changes
done by Namhyung
Thanks,
Irina
[1] https://lkml.org/lkml/2012/8/23/316
[2] https://lkml.org/lkml/2012/9/23/100
[3] https://lkml.org/lkml/2012/9/23/128
Bernhard Rosenkraenzer (1):
perf tools: add on_exit implementation
Irina Tirdea (6):
perf tools: update Makefile for Android
Documentation: add documentation on compiling for Android
perf tools: configure tmp path at build time
perf tools: configure shell path at compile time
perf tools: configure addr2line for cross-compiling
perf stat: implement --big-num grouping
Namhyung Kim (1):
perf tools: Try to find cross-built objdump path
tools/perf/Documentation/android.txt | 94 ++++++++++++++++
tools/perf/Documentation/jit-interface.txt | 4 +-
tools/perf/Documentation/perf-annotate.txt | 2 +
tools/perf/Documentation/perf-report.txt | 2 +
tools/perf/Makefile | 64 +++++++++--
tools/perf/arch/common.c | 164 ++++++++++++++++++++++++++++
tools/perf/arch/common.h | 12 ++
tools/perf/builtin-annotate.c | 9 ++
tools/perf/builtin-help.c | 2 +-
tools/perf/builtin-record.c | 32 ++++++
tools/perf/builtin-report.c | 7 ++
tools/perf/builtin-script.c | 12 +-
tools/perf/builtin-stat.c | 112 +++++++++++++++++--
tools/perf/config/feature-tests.mak | 38 ++++++-
tools/perf/perf-archive.sh | 13 ++-
tools/perf/util/annotate.c | 13 ++-
tools/perf/util/annotate.h | 1 -
tools/perf/util/dso-test-data.c | 2 +-
tools/perf/util/map.c | 3 +-
tools/perf/util/pmu.c | 2 +-
tools/perf/util/sort.c | 16 ++-
tools/perf/util/symbol.c | 4 +-
tools/perf/util/trace-event-info.c | 2 +-
23 files changed, 574 insertions(+), 36 deletions(-)
create mode 100644 tools/perf/Documentation/android.txt
create mode 100644 tools/perf/arch/common.c
create mode 100644 tools/perf/arch/common.h
--
1.7.9.5
From: Bernhard Rosenkraenzer <[email protected]>
on_exit() is only available in new versions of glibc.
It is not implemented in Bionic and will lead to linking errors when
compiling for Android.
Implement a wrapper for on_exit using atexit.
The implementation for on_exit is the one sent by Bernhard Rosenkraenzer in
https://lkml.org/lkml/2012/8/23/316. The configuration part from the Makefile
is different than the one from the original patch.
Signed-off-by: Bernhard Rosenkraenzer <[email protected]>
Signed-off-by: Irina Tirdea <[email protected]>
---
tools/perf/Makefile | 6 ++++++
tools/perf/builtin-record.c | 32 ++++++++++++++++++++++++++++++++
tools/perf/config/feature-tests.mak | 11 ++++++++++-
3 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index f9126f8..0e468b5 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -751,6 +751,12 @@ ifndef NO_STRLCPY
endif
endif
+ifndef NO_ON_EXIT
+ ifeq ($(call try-cc,$(SOURCE_ON_EXIT),),y)
+ BASIC_CFLAGS += -DHAVE_ON_EXIT
+ endif
+endif
+
ifndef NO_BACKTRACE
ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
BASIC_CFLAGS += -DBACKTRACE_SUPPORT
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e9231659..73b5d7f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,6 +31,38 @@
#include <sched.h>
#include <sys/mman.h>
+#ifndef HAVE_ON_EXIT
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t) (int, void *);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs(void);
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg)
+{
+ if (__on_exit_count == ATEXIT_MAX)
+ return -ENOMEM;
+ else if (__on_exit_count == 0)
+ atexit(__handle_on_exit_funcs);
+ __on_exit_funcs[__on_exit_count] = function;
+ __on_exit_args[__on_exit_count++] = arg;
+ return 0;
+}
+
+static void __handle_on_exit_funcs(void)
+{
+ int i;
+ for (i = 0; i < __on_exit_count; i++)
+ __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
+}
+#endif
+
enum write_mode_t {
WRITE_FORCE,
WRITE_APPEND
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 4add41b..eaeb0fd 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -203,4 +203,13 @@ int main(void)
return audit_open();
}
endef
-endif
\ No newline at end of file
+endif
+
+define SOURCE_ON_EXIT
+#include <stdio.h>
+
+int main(void)
+{
+ return on_exit(NULL, NULL);
+}
+endef
--
1.7.9.5
From: Irina Tirdea <[email protected]>
For cross-compiling on Android, some specific changes are needed in
the Makefile.
Update the Makefile to support cross-compiling for Android.
The original ideea for this was send by Bernhard Rosenkraenzer in
https://lkml.org/lkml/2012/8/23/316, but this is a rewrite.
Changes:
() support bionic in addition to glibc
() remove rt and pthread libraries that do not exist in Android
() use $(CFLAGS) when detecting initial compiler flags. This is needed
when setting CFLAGS as an argument of make (e.g. for setting --sysroot).
() include perf's local directory when building for Android to be able to find
relative paths if using --sysroot (e.g.: ../../include/linux/perf_event.h)
Signed-off-by: Bernhard Rosenkraenzer <[email protected]>
Signed-off-by: Irina Tirdea <[email protected]>
---
tools/perf/Makefile | 25 +++++++++++++++++++------
tools/perf/config/feature-tests.mak | 9 +++++++++
2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 0e468b5..1a23118 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -155,15 +155,15 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
-include config/feature-tests.mak
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all),y)
CFLAGS := $(CFLAGS) -fstack-protector-all
endif
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector),y)
CFLAGS := $(CFLAGS) -Wstack-protector
endif
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var),y)
CFLAGS := $(CFLAGS) -Wvolatile-register-var
endif
@@ -172,6 +172,13 @@ endif
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS =
+ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS)),y)
+ BIONIC := 1
+ EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
+ EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
+ BASIC_CFLAGS += -I.
+endif
+
# Guard against environment variables
BUILTIN_OBJS =
LIB_H =
@@ -467,12 +474,18 @@ else
FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
- ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
- msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
- else
+ ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
+ LIBC_SUPPORT := 1
+ endif
+ ifeq ($(BIONIC),1)
+ LIBC_SUPPORT := 1
+ endif
+ ifeq ($(LIBC_SUPPORT),1)
NO_LIBELF := 1
NO_DWARF := 1
NO_DEMANGLE := 1
+ else
+ msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
endif
else
FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index eaeb0fd..3ef5ec9 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -43,6 +43,15 @@ int main(void)
}
endef
+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+ return __ANDROID_API__;
+}
+endef
+
define SOURCE_ELF_MMAP
#include <libelf.h>
int main(void)
--
1.7.9.5
From: Irina Tirdea <[email protected]>
Add documentation for cross-compiling on Android including:
() instructions on how to set the Android NDK environment
() how to cross-compile perf for Android
() how to install on an Android device/emulator, set the runtime
environment and run it
Signed-off-by: Irina Tirdea <[email protected]>
---
tools/perf/Documentation/android.txt | 75 ++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
create mode 100644 tools/perf/Documentation/android.txt
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
new file mode 100644
index 0000000..a39dbbb
--- /dev/null
+++ b/tools/perf/Documentation/android.txt
@@ -0,0 +1,75 @@
+How to compile perf for Android
+=========================================
+
+I. Set the Android NDK environment
+------------------------------------------------
+
+(a). Use the Android NDK
+------------------------------------------------
+1. You need to download and install the Android Native Development Kit (NDK).
+Set the NDK variable to point to the path where you installed the NDK:
+ export NDK=/path/to/android-ndk
+
+2. Set cross-compiling environment variables for NDK toolchain and sysroot.
+For arm:
+ export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
+ export NDK_SYSROOT=${NDK}/platforms/android-9/arch-arm
+For x86:
+ export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android-
+ export NDK_SYSROOT=${NDK}/platforms/android-9/arch-x86
+
+This method is not working for Android NDK versions up to Revision 8b.
+perf uses some bionic enhancements that are not included in these NDK versions.
+You can use method (b) described below instead.
+
+(b). Use the Android source tree
+-----------------------------------------------
+1. Download the master branch of the Android source tree.
+Set the environment for the target you want using:
+ source build/envsetup.sh
+ lunch
+
+2. Build your own NDK sysroot to contain latest bionic changes and set the
+NDK sysroot environment variable.
+ cd ${ANDROID_BUILD_TOP}/ndk
+For arm:
+ ./build/tools/build-ndk-sysroot.sh --abi=arm
+ export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-arm
+For x86:
+ ./build/tools/build-ndk-sysroot.sh --abi=x86
+ export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-x86
+
+3. Set the NDK toolchain environment variable.
+For arm:
+ export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/arm-linux-androideabi-
+For x86:
+ export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/i686-linux-android-
+
+II. Compile perf for Android
+------------------------------------------------
+You need to run make with the NDK toolchain and sysroot defined above:
+ make CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
+
+III. Install perf
+-----------------------------------------------
+You need to connect to your Android device/emulator using adb.
+Install perf using:
+ adb push perf /data/perf
+
+If you also want to use perf-archive you need busybox tools for Android.
+For installing perf-archive, you first need to replace #!/bin/bash with #!/system/bin/sh:
+ sed 's/#!\/bin\/bash/#!\/system\/bin\/sh/g' perf-archive >> /tmp/perf-archive
+ chmod +x /tmp/perf-archive
+ adb push /tmp/perf-archive /data/perf-archive
+
+IV. Environment settings for running perf
+------------------------------------------------
+Some perf features need environment variables to run properly.
+You need to set these before running perf on the target:
+ adb shell
+ # PERF_PAGER=cat
+
+IV. Run perf
+------------------------------------------------
+Run perf on your device/emulator to which you previously connected using adb:
+ # ./data/perf
--
1.7.9.5
From: Irina Tirdea <[email protected]>
Shell path /bin/sh is hardcoded in various places in perf. Android has a
different folder structure and does not have /bin/sh.
Set the shell path at compile time in the Makefile by setting PERF_SHELL_PATH.
By default it is set to /bin/sh.
Signed-off-by: Irina Tirdea <[email protected]>
---
tools/perf/Makefile | 8 +++++++-
tools/perf/builtin-help.c | 2 +-
tools/perf/builtin-script.c | 12 ++++++------
3 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9b1f84c..29caf9a 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -142,6 +142,7 @@ ETC_PERFCONFIG = etc/perfconfig
endif
lib = lib
PERF_TMP_DIR = /tmp
+PERF_SHELL_PATH = /bin/sh
export prefix bindir sharedir sysconfdir
@@ -179,6 +180,7 @@ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS)),y)
EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
BASIC_CFLAGS += -I.
PERF_TMP_DIR = /data/local/tmp
+ PERF_SHELL_PATH = /system/bin/sh
endif
# Guard against environment variables
@@ -836,7 +838,11 @@ $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFL
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
'-DPERF_MAN_PATH="$(mandir_SQ)"' \
- '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
+ '-DPERF_INFO_PATH="$(infodir_SQ)"' \
+ '-DPERF_SHELL_PATH="$(PERF_SHELL_PATH)"' $<
+
+$(OUTPUT)builtin-script.o: builtin-script.c $(OUTPUT)PERF-CFLAGS
+ $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DPERF_SHELL_PATH='"$(PERF_SHELL_PATH)"' $<
$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 411ee56..542b752 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -154,7 +154,7 @@ static void exec_man_cmd(const char *cmd, const char *page)
{
struct strbuf shell_cmd = STRBUF_INIT;
strbuf_addf(&shell_cmd, "%s %s", cmd, page);
- execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL);
+ execl(PERF_SHELL_PATH, "sh", "-c", shell_cmd.buf, NULL);
warning("failed to exec '%s': %s", cmd, strerror(errno));
}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index fb96250..01b289b 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1320,7 +1320,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
goto out;
}
- __argv[j++] = "/bin/sh";
+ __argv[j++] = PERF_SHELL_PATH;
__argv[j++] = rec_script_path;
if (system_wide)
__argv[j++] = "-a";
@@ -1331,7 +1331,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
__argv[j++] = argv[i];
__argv[j++] = NULL;
- execvp("/bin/sh", (char **)__argv);
+ execvp(PERF_SHELL_PATH, (char **)__argv);
free(__argv);
exit(-1);
}
@@ -1347,7 +1347,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
}
j = 0;
- __argv[j++] = "/bin/sh";
+ __argv[j++] = PERF_SHELL_PATH;
__argv[j++] = rep_script_path;
for (i = 1; i < rep_args + 1; i++)
__argv[j++] = argv[i];
@@ -1355,7 +1355,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
__argv[j++] = "-";
__argv[j++] = NULL;
- execvp("/bin/sh", (char **)__argv);
+ execvp(PERF_SHELL_PATH, (char **)__argv);
free(__argv);
exit(-1);
}
@@ -1384,7 +1384,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
goto out;
}
- __argv[j++] = "/bin/sh";
+ __argv[j++] = PERF_SHELL_PATH;
__argv[j++] = script_path;
if (system_wide)
__argv[j++] = "-a";
@@ -1392,7 +1392,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
__argv[j++] = argv[i];
__argv[j++] = NULL;
- execvp("/bin/sh", (char **)__argv);
+ execvp(PERF_SHELL_PATH, (char **)__argv);
free(__argv);
exit(-1);
}
--
1.7.9.5
From: Namhyung Kim <[email protected]>
As we have architecture information of saved perf.data file, we can
try to find cross-built objdump path.
The triplets include support for Android (arm, x86 and mips architectures).
Signed-off-by: Namhyung Kim <[email protected]>
Signed-off-by: Irina Tirdea <[email protected]>
---
tools/perf/Makefile | 2 +
tools/perf/arch/common.c | 159 +++++++++++++++++++++++++++++++++++++++++
tools/perf/arch/common.h | 10 +++
tools/perf/builtin-annotate.c | 4 ++
tools/perf/builtin-report.c | 1 +
tools/perf/util/annotate.h | 1 -
6 files changed, 176 insertions(+), 1 deletion(-)
create mode 100644 tools/perf/arch/common.c
create mode 100644 tools/perf/arch/common.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 29caf9a..5149b8a 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -426,6 +426,8 @@ LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/hist.o
LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
+LIB_OBJS += $(OUTPUT)arch/common.o
+
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
# Benchmark modules
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
new file mode 100644
index 0000000..1db891f
--- /dev/null
+++ b/tools/perf/arch/common.c
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <sys/utsname.h>
+#include "common.h"
+
+const char *const arm_triplets[] = {
+ "arm-eabi-",
+ "arm-linux-androideabi-",
+ "arm-unknown-linux-",
+ "arm-unknown-linux-gnu-",
+ "arm-unknown-linux-gnueabi-",
+ NULL
+};
+
+const char *const powerpc_triplets[] = {
+ "powerpc-unknown-linux-gnu-",
+ "powerpc64-unknown-linux-gnu-",
+ NULL
+};
+
+const char *const s390_triplets[] = {
+ "s390-ibm-linux-",
+ NULL
+};
+
+const char *const sh_triplets[] = {
+ "sh-unknown-linux-gnu-",
+ "sh64-unknown-linux-gnu-",
+ NULL
+};
+
+const char *const sparc_triplets[] = {
+ "sparc-unknown-linux-gnu-",
+ "sparc64-unknown-linux-gnu-",
+ NULL
+};
+
+const char *const x86_triplets[] = {
+ "x86_64-pc-linux-gnu-",
+ "x86_64-unknown-linux-gnu-",
+ "i686-pc-linux-gnu-",
+ "i586-pc-linux-gnu-",
+ "i486-pc-linux-gnu-",
+ "i386-pc-linux-gnu-",
+ "i686-linux-android-",
+ "i686-android-linux-",
+ NULL
+};
+
+const char *const mips_triplets[] = {
+ "mips-unknown-linux-gnu-",
+ "mipsel-linux-android-",
+ NULL
+};
+
+static bool lookup_path(char *name)
+{
+ bool found = false;
+ char *path, *tmp;
+ char buf[PATH_MAX];
+ char *env = getenv("PATH");
+
+ if (!env)
+ return false;
+
+ env = strdup(env);
+ if (!env)
+ return false;
+
+ path = strtok_r(env, ":", &tmp);
+ while (path) {
+ scnprintf(buf, sizeof(buf), "%s/%s", path, name);
+ if (access(buf, F_OK) == 0) {
+ found = true;
+ break;
+ }
+ path = strtok_r(NULL, ":", &tmp);
+ }
+ free(env);
+ return found;
+}
+
+static int lookup_triplets(const char *const *triplets, const char *name)
+{
+ int i;
+ char buf[PATH_MAX];
+
+ for (i = 0; triplets[i] != NULL; i++) {
+ scnprintf(buf, sizeof(buf), "%s%s", triplets[i], name);
+ if (lookup_path(buf))
+ return i;
+ }
+ return -1;
+}
+
+static char *try_binutils_path(struct perf_session *session, const char *name)
+{
+ int idx;
+ char *arch, *env;
+ struct utsname uts;
+ const char *const *path_list;
+ char buf[PATH_MAX];
+
+ if (uname(&uts) < 0)
+ return NULL;
+
+ /*
+ * We don't need to try to find objdump path for native system.
+ * Just use default "objdump".
+ */
+ if (!strcmp(uts.machine, session->header.env.arch))
+ return NULL;
+
+ env = getenv("CROSS_COMPILE");
+ if (env) {
+ scnprintf(buf, sizeof(buf), "%s%s", env, name);
+ if (buf[0] == '/') {
+ if (access(buf, F_OK) == 0)
+ return strdup(buf);
+
+ return NULL;
+ }
+
+ if (lookup_path(buf))
+ return strdup(buf);
+ }
+
+ arch = session->header.env.arch;
+
+ if (!strcmp(arch, "arm"))
+ path_list = arm_triplets;
+ else if (!strcmp(arch, "powerpc"))
+ path_list = powerpc_triplets;
+ else if (!strcmp(arch, "sh"))
+ path_list = sh_triplets;
+ else if (!strcmp(arch, "s390"))
+ path_list = s390_triplets;
+ else if (!strcmp(arch, "sparc"))
+ path_list = sparc_triplets;
+ else if (!strcmp(arch, "x86") || !strcmp(arch, "i386") ||
+ !strcmp(arch, "i486") || !strcmp(arch, "i586") ||
+ !strcmp(arch, "i686"))
+ path_list = x86_triplets;
+ else if (!strcmp(arch, "mips"))
+ path_list = mips_triplets;
+ else
+ BUG_ON(1);
+
+ idx = lookup_triplets(path_list, name);
+ if (idx < 0)
+ return NULL;
+
+ scnprintf(buf, sizeof(buf), "%s%s", path_list[idx], name);
+ return strdup(buf);
+}
+
+void try_objdump_path(struct perf_session *session)
+{
+ objdump_path = try_binutils_path(session, "objdump");
+}
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
new file mode 100644
index 0000000..d88ecc3
--- /dev/null
+++ b/tools/perf/arch/common.h
@@ -0,0 +1,10 @@
+#ifndef ARCH_PERF_COMMON_H
+#define ARCH_PERF_COMMON_H
+
+#include "session.h"
+
+extern const char *objdump_path;
+
+void try_objdump_path(struct perf_session *session);
+
+#endif /* ARCH_PERF_COMMON_H */
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 9ea3854..8d90ab5 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -28,6 +28,7 @@
#include "util/hist.h"
#include "util/session.h"
#include "util/tool.h"
+#include "arch/common.h"
#include <linux/bitmap.h>
@@ -186,6 +187,9 @@ static int __cmd_annotate(struct perf_annotate *ann)
goto out_delete;
}
+ if (!objdump_path)
+ try_objdump_path(session);
+
ret = perf_session__process_events(session, &ann->tool);
if (ret)
goto out_delete;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index a61725d..e1549bc 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,6 +33,7 @@
#include "util/thread.h"
#include "util/sort.h"
#include "util/hist.h"
+#include "arch/common.h"
#include <linux/bitmap.h>
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 39242dc..a4dd25a 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -154,6 +154,5 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
#endif
extern const char *disassembler_style;
-extern const char *objdump_path;
#endif /* __PERF_ANNOTATE_H */
--
1.7.9.5
From: Irina Tirdea <[email protected]>
In glibc, printf supports ' to group numbers with thousands' grouping
characters. Bionic does not support ' for printf.
Implement thousands's grouping for numbers according to locale.
The implementation uses the algorithm from glibc
(http://www.gnu.org/software/libc/).
Bionic does not implement locales, so we need to add a configuration
option LOCALE_SUPPORT. If it is not defined, default values for thousands
separator and grouping are used.
Signed-off-by: Irina Tirdea <[email protected]>
---
tools/perf/Makefile | 6 ++
tools/perf/builtin-stat.c | 112 ++++++++++++++++++++++++++++++++---
tools/perf/config/feature-tests.mak | 18 ++++++
3 files changed, 129 insertions(+), 7 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 5149b8a..bc75b2a 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -783,6 +783,12 @@ ifndef NO_BACKTRACE
endif
endif
+ifndef NO_LOCALE
+ ifeq ($(call try-cc,$(SOURCE_LOCALE),),y)
+ BASIC_CFLAGS += -DLOCALE_SUPPORT
+ endif
+endif
+
ifdef ASCIIDOC8
export ASCIIDOC8
endif
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 93b9011..855e918 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -60,6 +60,8 @@
#include <sys/prctl.h>
#include <locale.h>
+/* max double number have E+308 + \0 + sign */
+#define MAX_NR_STR 310
#define DEFAULT_SEPARATOR " "
#define CNTR_NOT_SUPPORTED "<not supported>"
#define CNTR_NOT_COUNTED "<not counted>"
@@ -631,18 +633,112 @@ static void print_ll_cache_misses(int cpu,
fprintf(output, " of all LL-cache hits ");
}
+/* Group the digits according to the grouping rules of the current locale.
+ The interpretation of GROUPING is as in `struct lconv' from <locale.h>. */
+static int group_number_locale(char *number, char **gnumber)
+{
+ const char *thousands_sep = NULL, *grouping = NULL;
+ int glen, tlen, dest_alloc_size, src_size, ret = 0, cnt;
+ char *dest_alloc_ptr, *dest_end, *src_start, *src_end;
+
+#ifndef LOCALE_SUPPORT
+ thousands_sep = ",";
+ grouping = "\x3";
+#else
+ struct lconv *lc = localeconv();
+ if (lc != NULL) {
+ thousands_sep = lc->thousands_sep;
+ grouping = lc->grouping;
+ }
+#endif
+
+ *gnumber = NULL;
+ /* No grouping */
+ if (thousands_sep == NULL || grouping == NULL ||
+ *thousands_sep == '\0' || *grouping == CHAR_MAX || *grouping <= 0) {
+ *gnumber = strdup(number);
+ if (*gnumber == NULL)
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ glen = *grouping++;
+ tlen = strlen(thousands_sep);
+
+ src_size = strlen(number);
+ /* Worst case scenario we have 1-character grouping */
+ dest_alloc_size = (src_size + src_size * tlen) * sizeof(char);
+ dest_alloc_ptr = zalloc(dest_alloc_size);
+ if (dest_alloc_ptr == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ /* -1 for '\0' */
+ dest_end = dest_alloc_ptr + dest_alloc_size - 1;
+
+ src_start = number;
+ src_end = number + src_size;
+
+ while (src_end > src_start) {
+ *--dest_end = *--src_end;
+ if (--glen == 0 && src_end > src_start) {
+ /* A new group */
+ cnt = tlen;
+ do
+ *--dest_end = thousands_sep[--cnt];
+ while (cnt > 0);
+
+ if (*grouping == CHAR_MAX || *grouping < 0) {
+ /* No further grouping to be done.
+ Copy the rest of the number. */
+ do
+ *--dest_end = *--src_end;
+ while (src_end > src_start);
+ break;
+ } else if (*grouping != '\0') {
+ glen = *grouping++;
+ } else {
+ /* The previous grouping repeats ad infinitum */
+ glen = grouping[-1];
+ }
+ }
+ }
+
+ /* Make a copy with the exact needed size of the grouped number */
+ *gnumber = strdup(dest_end);
+ if (*gnumber == NULL) {
+ ret = -ENOMEM;
+ goto out_free_dest;
+ }
+
+ /* fall through */
+out_free_dest:
+ free(dest_alloc_ptr);
+out:
+ return ret;
+}
+
static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
{
double total, ratio = 0.0;
char cpustr[16] = { '\0', };
const char *fmt;
+ char avgstr[MAX_NR_STR], *pavgstr;
+ int ret;
- if (csv_output)
- fmt = "%s%.0f%s%s";
- else if (big_num)
- fmt = "%s%'18.0f%s%-25s";
- else
- fmt = "%s%18.0f%s%-25s";
+ sprintf(avgstr, "%.0f", avg);
+ pavgstr = avgstr;
+
+ if (csv_output) {
+ fmt = "%s%s%s%s";
+ } else {
+ fmt = "%s%18s%s%-25s";
+ if (big_num) {
+ ret = group_number_locale(avgstr, &pavgstr);
+ if (ret < 0)
+ pavgstr = avgstr;
+ }
+ }
if (no_aggr)
sprintf(cpustr, "CPU%*d%s",
@@ -651,7 +747,9 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
else
cpu = 0;
- fprintf(output, fmt, cpustr, avg, csv_sep, perf_evsel__name(evsel));
+ fprintf(output, fmt, cpustr, pavgstr, csv_sep, perf_evsel__name(evsel));
+ if (pavgstr != avgstr)
+ free(pavgstr);
if (evsel->cgrp)
fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 3ef5ec9..ec3a6f1 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -222,3 +222,21 @@ int main(void)
return on_exit(NULL, NULL);
}
endef
+
+ifndef NO_LOCALE
+define SOURCE_LOCALE
+#include <locale.h>
+
+int main(void)
+{
+ char *thousands_sep, *grouping;
+
+ struct lconv *lc = localeconv();
+ if (lc != NULL) {
+ thousands_sep = lc->thousands_sep;
+ grouping = lc->grouping;
+ }
+ return 0;
+}
+endef
+endif
--
1.7.9.5
From: Irina Tirdea <[email protected]>
When analyzing data recorded on a target with a different architecture than
the host, we must use addr2line from the toolchain for that architecture.
Add a command line option to set addr2line at runtime.
As we have architecture information of saved perf.data file, we can
also try to find cross-built addr2line path. The predefined triplets include
support for Android (arm, x86 and mips architectures).
Signed-off-by: Irina Tirdea <[email protected]>
---
tools/perf/Documentation/android.txt | 18 ++++++++++++++++++
tools/perf/Documentation/perf-annotate.txt | 2 ++
tools/perf/Documentation/perf-report.txt | 2 ++
tools/perf/arch/common.c | 5 +++++
tools/perf/arch/common.h | 2 ++
tools/perf/builtin-annotate.c | 5 +++++
tools/perf/builtin-report.c | 6 ++++++
tools/perf/util/annotate.c | 13 ++++++++++++-
tools/perf/util/sort.c | 16 +++++++++++++---
9 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
index 24fd01c..c2a8017 100644
--- a/tools/perf/Documentation/android.txt
+++ b/tools/perf/Documentation/android.txt
@@ -74,3 +74,21 @@ IV. Run perf
------------------------------------------------
Run perf on your device/emulator to which you previously connected using adb:
# ./data/perf
+
+V. Analyze data recorded in Android on the host
+------------------------------------------------
+perf report and perf annotate use objdump and addr2line tools from Linux.
+For analyzing data recorded for a different architecture you need to use the
+versions provided in the toolchain for that architecture. The detection of the
+proper toolchain is done at runtime; all you need to do is set some environment
+variables before running perf annotate/report:
+1. set CROSS_COMPILE
+ export CROSS_COMPILE=${NDK_TOOLCHAIN}
+or
+2. add the path to the toolchain to PATH
+ export PATH=$PATH:${ANDROID_TOOLCHAIN}
+or
+3. set the Android environment if you have the source tree
+(this will set $PATH for you as mentioned above)
+ source build/envsetup.sh
+ lunch
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index c8ffd9f..177906a 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -87,6 +87,8 @@ OPTIONS
--objdump=<path>::
Path to objdump binary.
+--addr2line=<path>::
+ Path to addr2line binary.
SEE ALSO
--------
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index f4d91be..b6bb26e 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -170,6 +170,8 @@ OPTIONS
--objdump=<path>::
Path to objdump binary.
+--addr2line=<path>::
+ Path to addr2line binary.
SEE ALSO
--------
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 1db891f..e84b139 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -157,3 +157,8 @@ void try_objdump_path(struct perf_session *session)
{
objdump_path = try_binutils_path(session, "objdump");
}
+
+void try_addr2line_path(struct perf_session *session)
+{
+ addr2line_path = try_binutils_path(session, "addr2line");
+}
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
index d88ecc3..ca95f0a 100644
--- a/tools/perf/arch/common.h
+++ b/tools/perf/arch/common.h
@@ -4,7 +4,9 @@
#include "session.h"
extern const char *objdump_path;
+extern const char *addr2line_path;
void try_objdump_path(struct perf_session *session);
+void try_addr2line_path(struct perf_session *session);
#endif /* ARCH_PERF_COMMON_H */
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 8d90ab5..6f3b21a 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -189,6 +189,8 @@ static int __cmd_annotate(struct perf_annotate *ann)
if (!objdump_path)
try_objdump_path(session);
+ if (!addr2line_path)
+ try_addr2line_path(session);
ret = perf_session__process_events(session, &ann->tool);
if (ret)
@@ -288,6 +290,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
"Specify disassembler style (e.g. -M intel for intel syntax)"),
OPT_STRING(0, "objdump", &objdump_path, "path",
"objdump binary to use for disassembly and annotations"),
+ OPT_STRING(0, "addr2line", &addr2line_path, "path",
+ "addr2line binary to use for obtaining "
+ "file names and line numbers"),
OPT_END()
};
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e1549bc..b1a1949 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -642,6 +642,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
"use branch records for histogram filling", parse_branch_mode),
OPT_STRING(0, "objdump", &objdump_path, "path",
"objdump binary to use for disassembly and annotations"),
+ OPT_STRING(0, "addr2line", &addr2line_path, "path",
+ "addr2line binary to use for obtaining "
+ "file names and line numbers"),
OPT_END()
};
@@ -673,6 +676,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
has_br_stack = perf_header__has_feat(&session->header,
HEADER_BRANCH_STACK);
+ if (!addr2line_path)
+ try_addr2line_path(session);
+
if (sort__branch_mode == -1 && has_br_stack)
sort__branch_mode = 1;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index f0a9103..bf5573f 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -18,6 +18,7 @@
const char *disassembler_style;
const char *objdump_path;
+const char *addr2line_path;
static struct ins *ins__find(const char *name);
static int disasm_line__parse(char *line, char **namep, char **rawp);
@@ -894,10 +895,18 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
struct source_line *src_line;
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evidx);
+ char symfs_filename[PATH_MAX];
if (!h->sum)
return 0;
+ snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
+ symbol_conf.symfs, filename);
+ if (access(symfs_filename, R_OK)) {
+ snprintf(symfs_filename, sizeof(symfs_filename), "%s",
+ filename);
+ }
+
src_line = notes->src->lines = calloc(len, sizeof(struct source_line));
if (!notes->src->lines)
return -1;
@@ -915,7 +924,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
continue;
offset = start + i;
- sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
+ sprintf(cmd, "%s -e %s %016" PRIx64,
+ addr2line_path ? addr2line_path : "addr2line",
+ symfs_filename, offset);
fp = popen(cmd, "r");
if (!fp)
continue;
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b5b1b92..037ab89 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,5 +1,6 @@
#include "sort.h"
#include "hist.h"
+#include "../arch/common.h"
regex_t parent_regex;
const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -256,12 +257,21 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
FILE *fp;
char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
size_t line_len;
+ char symfs_dso_name[PATH_MAX];
- if (path != NULL)
+ if (path != NULL || !self->ms.map)
goto out_path;
- snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
- self->ms.map->dso->long_name, self->ip);
+ snprintf(symfs_dso_name, sizeof(symfs_dso_name), "%s%s",
+ symbol_conf.symfs, self->ms.map->dso->long_name);
+ if (access(symfs_dso_name, R_OK)) {
+ snprintf(symfs_dso_name, sizeof(symfs_dso_name), "%s",
+ self->ms.map->dso->long_name);
+ }
+
+ snprintf(cmd, sizeof(cmd), "%s -e %s %016" PRIx64,
+ addr2line_path ? addr2line_path : "addr2line",
+ symfs_dso_name, self->ip);
fp = popen(cmd, "r");
if (!fp)
goto out_ip;
--
1.7.9.5
From: Irina Tirdea <[email protected]>
Temporary perf files are hardcoded to point to /tmp. Android does not have
a /tmp directory so it needs to set this path at compile time.
Add a compile-time definition (PERF_TMP_DIR) in the Makefile that sets the path
to temp directory. By default it points to /tmp.
Signed-off-by: Irina Tirdea <[email protected]>
---
tools/perf/Documentation/android.txt | 1 +
tools/perf/Documentation/jit-interface.txt | 4 +++-
tools/perf/Makefile | 17 ++++++++++++++++-
tools/perf/perf-archive.sh | 13 +++++++++++--
tools/perf/util/dso-test-data.c | 2 +-
tools/perf/util/map.c | 3 ++-
tools/perf/util/pmu.c | 2 +-
tools/perf/util/symbol.c | 4 +++-
tools/perf/util/trace-event-info.c | 2 +-
9 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
index a39dbbb..24fd01c 100644
--- a/tools/perf/Documentation/android.txt
+++ b/tools/perf/Documentation/android.txt
@@ -68,6 +68,7 @@ Some perf features need environment variables to run properly.
You need to set these before running perf on the target:
adb shell
# PERF_PAGER=cat
+ # PERF_TMP_DIR=/data/local/tmp
IV. Run perf
------------------------------------------------
diff --git a/tools/perf/Documentation/jit-interface.txt b/tools/perf/Documentation/jit-interface.txt
index a8656f5..10cb6ec 100644
--- a/tools/perf/Documentation/jit-interface.txt
+++ b/tools/perf/Documentation/jit-interface.txt
@@ -1,7 +1,9 @@
perf supports a simple JIT interface to resolve symbols for dynamic code generated
by a JIT.
-The JIT has to write a /tmp/perf-%d.map (%d = pid of process) file
+The JIT has to write a $PERF_TMP_DIR/perf-%d.map (%d = pid of process) file.
+You can set $PERF_TMP_DIR at compile time in the Makefile.
+By default it is /tmp.
This is a text file.
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 1a23118..9b1f84c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -141,6 +141,7 @@ sysconfdir = $(prefix)/etc
ETC_PERFCONFIG = etc/perfconfig
endif
lib = lib
+PERF_TMP_DIR = /tmp
export prefix bindir sharedir sysconfdir
@@ -177,6 +178,7 @@ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS)),y)
EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
BASIC_CFLAGS += -I.
+ PERF_TMP_DIR = /data/local/tmp
endif
# Guard against environment variables
@@ -255,7 +257,8 @@ $(OUTPUT)util/pmu-bison.c: util/pmu.y
$(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c
$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
-$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
+$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu.c $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c $(OUTPUT)PERF-CFLAGS
+ $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DPERF_TMP_DIR='"$(PERF_TMP_DIR)"' $<
LIB_FILE=$(OUTPUT)libperf.a
@@ -887,6 +890,18 @@ $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
+$(OUTPUT)util/dso-test-data.o: util/dso-test-data.c $(OUTPUT)PERF-CFLAGS
+ $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DPERF_TMP_DIR='"$(PERF_TMP_DIR)"' $<
+
+$(OUTPUT)util/map.o: util/map.c $(OUTPUT)PERF-CFLAGS
+ $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DPERF_TMP_DIR='"$(PERF_TMP_DIR)"' $<
+
+$(OUTPUT)util/symbol.o: util/symbol.c $(OUTPUT)PERF-CFLAGS
+ $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DPERF_TMP_DIR='"$(PERF_TMP_DIR)"' $<
+
+$(OUTPUT)util/trace-event-info.o: util/trace-event-info.c $(OUTPUT)PERF-CFLAGS
+ $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DPERF_TMP_DIR='"$(PERF_TMP_DIR)"' $<
+
$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh
index e919306..058c3b7 100644
--- a/tools/perf/perf-archive.sh
+++ b/tools/perf/perf-archive.sh
@@ -18,7 +18,16 @@ else
PERF_BUILDID_DIR=$PERF_BUILDID_DIR/
fi
-BUILDIDS=$(mktemp /tmp/perf-archive-buildids.XXXXXX)
+#
+# PERF_TMP_DIR environment variable set by perf
+# path to temp directory, default to /tmp
+#
+if [ -z $PERF_TMP_DIR ]; then
+ PERF_TMP_DIR=/tmp
+fi
+
+
+BUILDIDS=$(mktemp $PERF_TMP_DIR/perf-archive-buildids.XXXXXX)
NOBUILDID=0000000000000000000000000000000000000000
perf buildid-list -i $PERF_DATA --with-hits | grep -v "^$NOBUILDID " > $BUILDIDS
@@ -28,7 +37,7 @@ if [ ! -s $BUILDIDS ] ; then
exit 1
fi
-MANIFEST=$(mktemp /tmp/perf-archive-manifest.XXXXXX)
+MANIFEST=$(mktemp $PERF_TMP_DIR/perf-archive-manifest.XXXXXX)
PERF_BUILDID_LINKDIR=$(readlink -f $PERF_BUILDID_DIR)/
cut -d ' ' -f 1 $BUILDIDS | \
diff --git a/tools/perf/util/dso-test-data.c b/tools/perf/util/dso-test-data.c
index c6caede..ca81e65 100644
--- a/tools/perf/util/dso-test-data.c
+++ b/tools/perf/util/dso-test-data.c
@@ -18,7 +18,7 @@ do { \
static char *test_file(int size)
{
- static char buf_templ[] = "/tmp/test-XXXXXX";
+ static char buf_templ[] = PERF_TMP_DIR "/test-XXXXXX";
char *templ = buf_templ;
int fd, i;
unsigned char *buf;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 6109fa4..4e69b57 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -59,7 +59,8 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
no_dso = is_no_dso_memory(filename);
if (anon) {
- snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
+ snprintf(newfilename, sizeof(newfilename),
+ PERF_TMP_DIR "/perf-%d.map", pid);
filename = newfilename;
}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 8a2229d..5ebde18 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -637,7 +637,7 @@ static char *test_format_dir_get(void)
static char dir[PATH_MAX];
unsigned int i;
- snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX");
+ snprintf(dir, PATH_MAX, PERF_TMP_DIR "/perf-pmu-test-format-XXXXXX");
if (!mkdtemp(dir))
return NULL;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e2e8c69..d8aca82 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1051,7 +1051,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
dso->adjust_symbols = 0;
- if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
+ if (strncmp
+ (dso->name, PERF_TMP_DIR "/perf-",
+ strlen(PERF_TMP_DIR "/perf-")) == 0) {
struct stat st;
if (lstat(dso->name, &st) < 0)
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index a8d81c3..e50ea61 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -481,7 +481,7 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
int temp_fd;
snprintf(tdata->temp_file, sizeof(tdata->temp_file),
- "/tmp/perf-XXXXXX");
+ PERF_TMP_DIR "/perf-XXXXXX");
if (!mkstemp(tdata->temp_file))
die("Can't make temp file");
--
1.7.9.5
Em Mon, Oct 08, 2012 at 09:43:27AM +0300, Irina Tirdea escreveu:
> From: Irina Tirdea <[email protected]>
>
> For cross-compiling on Android, some specific changes are needed in
> the Makefile.
>
> Update the Makefile to support cross-compiling for Android.
> The original ideea for this was send by Bernhard Rosenkraenzer in
> https://lkml.org/lkml/2012/8/23/316, but this is a rewrite.
If this is a rewrite, I'm dropping Bernhard's SOB, leaving just him in
the CC list.
- Arnaldo
>
> Changes:
> () support bionic in addition to glibc
> () remove rt and pthread libraries that do not exist in Android
> () use $(CFLAGS) when detecting initial compiler flags. This is needed
> when setting CFLAGS as an argument of make (e.g. for setting --sysroot).
> () include perf's local directory when building for Android to be able to find
> relative paths if using --sysroot (e.g.: ../../include/linux/perf_event.h)
>
> Signed-off-by: Bernhard Rosenkraenzer <[email protected]>
> Signed-off-by: Irina Tirdea <[email protected]>
> ---
> tools/perf/Makefile | 25 +++++++++++++++++++------
> tools/perf/config/feature-tests.mak | 9 +++++++++
> 2 files changed, 28 insertions(+), 6 deletions(-)
>
> diff --git a/tools/perf/Makefile b/tools/perf/Makefile
> index 0e468b5..1a23118 100644
> --- a/tools/perf/Makefile
> +++ b/tools/perf/Makefile
> @@ -155,15 +155,15 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
>
> -include config/feature-tests.mak
>
> -ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
> +ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all),y)
> CFLAGS := $(CFLAGS) -fstack-protector-all
> endif
>
> -ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
> +ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector),y)
> CFLAGS := $(CFLAGS) -Wstack-protector
> endif
>
> -ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
> +ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var),y)
> CFLAGS := $(CFLAGS) -Wvolatile-register-var
> endif
>
> @@ -172,6 +172,13 @@ endif
> BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
> BASIC_LDFLAGS =
>
> +ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS)),y)
> + BIONIC := 1
> + EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
> + EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
> + BASIC_CFLAGS += -I.
> +endif
> +
> # Guard against environment variables
> BUILTIN_OBJS =
> LIB_H =
> @@ -467,12 +474,18 @@ else
> FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
> ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
> FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
> - ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
> - msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
> - else
> + ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
> + LIBC_SUPPORT := 1
> + endif
> + ifeq ($(BIONIC),1)
> + LIBC_SUPPORT := 1
> + endif
> + ifeq ($(LIBC_SUPPORT),1)
> NO_LIBELF := 1
> NO_DWARF := 1
> NO_DEMANGLE := 1
> + else
> + msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
> endif
> else
> FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
> diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
> index eaeb0fd..3ef5ec9 100644
> --- a/tools/perf/config/feature-tests.mak
> +++ b/tools/perf/config/feature-tests.mak
> @@ -43,6 +43,15 @@ int main(void)
> }
> endef
>
> +define SOURCE_BIONIC
> +#include <android/api-level.h>
> +
> +int main(void)
> +{
> + return __ANDROID_API__;
> +}
> +endef
> +
> define SOURCE_ELF_MMAP
> #include <libelf.h>
> int main(void)
> --
> 1.7.9.5
Em Mon, Oct 08, 2012 at 09:43:29AM +0300, Irina Tirdea escreveu:
> From: Irina Tirdea <[email protected]>
>
> Temporary perf files are hardcoded to point to /tmp. Android does not have
> a /tmp directory so it needs to set this path at compile time.
>
> Add a compile-time definition (PERF_TMP_DIR) in the Makefile that sets the path
> to temp directory. By default it points to /tmp.
[acme@sandy linux]$ am /wb/1.patch
Applying: perf tools: configure tmp path at build time
[perf/core eafbb72] perf tools: configure tmp path at build time
Author: Irina Tirdea <[email protected]>
9 files changed, 39 insertions(+), 9 deletions(-)
[acme@sandy linux]$ make -j8 -C tools/perf/ LIBUNWIND_DIR=/opt/libunwind O=/home/acme/git/build/perf install
make: Entering directory `/home/git/linux/tools/perf'
PERF_VERSION = 3.6.rc5.371.geafbb7
make: Leaving directory `/home/git/linux/tools/perf'
make: Entering directory `/home/git/linux/tools/perf'
make: *** No rule to make target `/home/acme/git/build/perf/util/pmu.c', needed by `/home/acme/git/build/perf/util/pmu.o'. Stop.
make: *** Waiting for unfinished jobs....
make: Leaving directory `/home/git/linux/tools/perf'
Remove this patch:
[acme@sandy linux]$ git reset --hard HEAD^
HEAD is now at 7747e2f Documentation: add documentation on compiling for Android
And it works again, dropping,
- Arnaldo
[acme@sandy linux]$ make -j8 -C tools/perf/ LIBUNWIND_DIR=/opt/libunwind O=/home/acme/git/build/perf install
make: Entering directory `/home/git/linux/tools/perf'
PERF_VERSION = 3.6.rc5.370.g7747e2
make: Leaving directory `/home/git/linux/tools/perf'
make: Entering directory `/home/git/linux/tools/perf'
GEN perf-archive
make[1]: Entering directory `/home/git/linux/tools/lib/traceevent'
make[2]: warning: jobserver unavailable: using -j1. Add `+' to parent make rule.
make[1]: Leaving directory `/home/git/linux/tools/lib/traceevent'
CC /home/acme/git/build/perf/perf.o
CC /home/acme/git/build/perf/util/pmu.o
CC /home/acme/git/build/perf/util/symbol.o
CC /home/acme/git/build/perf/util/dso-test-data.o
CC /home/acme/git/build/perf/util/trace-event-info.o
CC /home/acme/git/build/perf/util/map.o
AR /home/acme/git/build/perf/libperf.a
LINK /home/acme/git/build/perf/perf
install -d -m 755 '/home/acme/bin'
install /home/acme/git/build/perf/perf '/home/acme/bin'
install -d -m 755 '/home/acme/libexec/perf-core/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
install -d -m 755 '/home/acme/libexec/perf-core/scripts/perl/bin'
install /home/acme/git/build/perf/perf-archive -t '/home/acme/libexec/perf-core'
install scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '/home/acme/libexec/perf-core/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
install scripts/perl/*.pl -t '/home/acme/libexec/perf-core/scripts/perl'
install scripts/perl/bin/* -t '/home/acme/libexec/perf-core/scripts/perl/bin'
install -d -m 755 '/home/acme/libexec/perf-core/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
install -d -m 755 '/home/acme/libexec/perf-core/scripts/python/bin'
install scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '/home/acme/libexec/perf-core/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
install scripts/python/*.py -t '/home/acme/libexec/perf-core/scripts/python'
install scripts/python/bin/* -t '/home/acme/libexec/perf-core/scripts/python/bin'
install -d -m 755 '/home/acme/etc/bash_completion.d'
install bash_completion '/home/acme/etc/bash_completion.d/perf'
make: Leaving directory `/home/git/linux/tools/perf'
[acme@sandy linux]$
Em Mon, Oct 08, 2012 at 09:43:31AM +0300, Irina Tirdea escreveu:
> From: Namhyung Kim <[email protected]>
>
> As we have architecture information of saved perf.data file, we can
> try to find cross-built objdump path.
>
> The triplets include support for Android (arm, x86 and mips architectures).
perf_session is too high an abstraction for this, all the uses in this
function are of the kind:
session->header.env.MEMBER
So why not rename it to:
perf_session_env__lookup_binutils_path(struct perf_session_env *env, const char *name)
and then use just:
env->arch, etc?
More comments below
> +static char *try_binutils_path(struct perf_session *session, const char *name)
> +{
> + int idx;
> + char *arch, *env;
> + struct utsname uts;
> + const char *const *path_list;
> + char buf[PATH_MAX];
> +
> + if (uname(&uts) < 0)
> + return NULL;
> +
> + /*
> + * We don't need to try to find objdump path for native system.
> + * Just use default "objdump".
> + */
> + if (!strcmp(uts.machine, session->header.env.arch))
> + return NULL;
> +
> + env = getenv("CROSS_COMPILE");
> + if (env) {
> + scnprintf(buf, sizeof(buf), "%s%s", env, name);
> + if (buf[0] == '/') {
> + if (access(buf, F_OK) == 0)
> + return strdup(buf);
> +
> + return NULL;
> + }
> +
> + if (lookup_path(buf))
> + return strdup(buf);
> + }
> +
> + arch = session->header.env.arch;
> +
> + if (!strcmp(arch, "arm"))
> + path_list = arm_triplets;
> + else if (!strcmp(arch, "powerpc"))
> + path_list = powerpc_triplets;
> + else if (!strcmp(arch, "sh"))
> + path_list = sh_triplets;
> + else if (!strcmp(arch, "s390"))
> + path_list = s390_triplets;
> + else if (!strcmp(arch, "sparc"))
> + path_list = sparc_triplets;
> + else if (!strcmp(arch, "x86") || !strcmp(arch, "i386") ||
> + !strcmp(arch, "i486") || !strcmp(arch, "i586") ||
> + !strcmp(arch, "i686"))
> + path_list = x86_triplets;
> + else if (!strcmp(arch, "mips"))
> + path_list = mips_triplets;
> + else
> + BUG_ON(1);
> +
> + idx = lookup_triplets(path_list, name);
> + if (idx < 0)
> + return NULL;
> +
> + scnprintf(buf, sizeof(buf), "%s%s", path_list[idx], name);
> + return strdup(buf);
Please use instead:
char *s;
return asprintf(&s, "%s%s", path_list[idx], name) < 0 ? NULL : s;
Will produce the same result and is more compact.
> +}
> +
> +void try_objdump_path(struct perf_session *session)
> +{
> + objdump_path = try_binutils_path(session, "objdump");
> +}
> diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
> new file mode 100644
> index 0000000..d88ecc3
> --- /dev/null
> +++ b/tools/perf/arch/common.h
> @@ -0,0 +1,10 @@
> +#ifndef ARCH_PERF_COMMON_H
> +#define ARCH_PERF_COMMON_H
> +
> +#include "session.h"
> +
> +extern const char *objdump_path;
> +
> +void try_objdump_path(struct perf_session *session);
> +
> +#endif /* ARCH_PERF_COMMON_H */
> diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
> index 9ea3854..8d90ab5 100644
> --- a/tools/perf/builtin-annotate.c
> +++ b/tools/perf/builtin-annotate.c
> @@ -28,6 +28,7 @@
> #include "util/hist.h"
> #include "util/session.h"
> #include "util/tool.h"
> +#include "arch/common.h"
>
> #include <linux/bitmap.h>
>
> @@ -186,6 +187,9 @@ static int __cmd_annotate(struct perf_annotate *ann)
> goto out_delete;
> }
>
> + if (!objdump_path)
> + try_objdump_path(session);
Please do the test on perf_session_env__lookup_objdump() and handle
errors, i.e. what happens if that strdup/asprintf fails?
Ok, that is unlikely, but not impossible, but what happens if we don't
find the right objdump? Shouldn't we use ui__error("please install
required objdump" (or a better, more detailed message)?
> +
> ret = perf_session__process_events(session, &ann->tool);
> if (ret)
> goto out_delete;
> diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
> index a61725d..e1549bc 100644
> --- a/tools/perf/builtin-report.c
> +++ b/tools/perf/builtin-report.c
> @@ -33,6 +33,7 @@
> #include "util/thread.h"
> #include "util/sort.h"
> #include "util/hist.h"
> +#include "arch/common.h"
>
> #include <linux/bitmap.h>
>
> diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
> index 39242dc..a4dd25a 100644
> --- a/tools/perf/util/annotate.h
> +++ b/tools/perf/util/annotate.h
> @@ -154,6 +154,5 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
> #endif
>
> extern const char *disassembler_style;
> -extern const char *objdump_path;
>
> #endif /* __PERF_ANNOTATE_H */
> --
> 1.7.9.5
Em Mon, Oct 08, 2012 at 09:43:32AM +0300, Irina Tirdea escreveu:
> From: Irina Tirdea <[email protected]>
>
> When analyzing data recorded on a target with a different architecture than
> the host, we must use addr2line from the toolchain for that architecture.
> Add a command line option to set addr2line at runtime.
>
> As we have architecture information of saved perf.data file, we can
> also try to find cross-built addr2line path. The predefined triplets include
> support for Android (arm, x86 and mips architectures).
Comments made for the objdump patch applies here.
Also there are two patches here, no? One adding --addr2line and the
other trying to find it automatically according the perf_session_env
info in the perf.data header.
- Arnaldo
Em Mon, Oct 08, 2012 at 09:43:33AM +0300, Irina Tirdea escreveu:
>
> +/* Group the digits according to the grouping rules of the current locale.
> + The interpretation of GROUPING is as in `struct lconv' from <locale.h>. */
> +static int group_number_locale(char *number, char **gnumber)
> +{
> + const char *thousands_sep = NULL, *grouping = NULL;
> + int glen, tlen, dest_alloc_size, src_size, ret = 0, cnt;
Please set ret to -ENOMEM; and...
> + char *dest_alloc_ptr, *dest_end, *src_start, *src_end;
> +
When we have else clauses, I think its better to use
#ifdef LOCALE_SUPPORT
struct lconv *lc = localeconv();
if (lc != NULL) {
thousands_sep = lc->thousands_sep;
grouping = lc->grouping;
}
#else
thousands_sep = ",";
grouping = "\x3";
#endif
> +#ifndef LOCALE_SUPPORT
> + thousands_sep = ",";
> + grouping = "\x3";
> +#else
> + struct lconv *lc = localeconv();
> + if (lc != NULL) {
> + thousands_sep = lc->thousands_sep;
> + grouping = lc->grouping;
> + }
> +#endif
> +
> + *gnumber = NULL;
> + /* No grouping */
> + if (thousands_sep == NULL || grouping == NULL ||
> + *thousands_sep == '\0' || *grouping == CHAR_MAX || *grouping <= 0) {
> + *gnumber = strdup(number);
> + if (*gnumber == NULL)
> + ret = -ENOMEM;
> + goto out;
Humm, so we bail out unconditionally? :-)
this should be:
if (*gnumber == NULL)
goto out;
> + }
> +
> + glen = *grouping++;
> + tlen = strlen(thousands_sep);
> +
> + src_size = strlen(number);
> + /* Worst case scenario we have 1-character grouping */
> + dest_alloc_size = (src_size + src_size * tlen) * sizeof(char);
> + dest_alloc_ptr = zalloc(dest_alloc_size);
> + if (dest_alloc_ptr == NULL) {
> + ret = -ENOMEM;
remove the above
> + goto out;
> + }
> + /* -1 for '\0' */
> + dest_end = dest_alloc_ptr + dest_alloc_size - 1;
> +
> + src_start = number;
> + src_end = number + src_size;
> +
> + while (src_end > src_start) {
> + *--dest_end = *--src_end;
> + if (--glen == 0 && src_end > src_start) {
> + /* A new group */
> + cnt = tlen;
> + do
> + *--dest_end = thousands_sep[--cnt];
> + while (cnt > 0);
> +
> + if (*grouping == CHAR_MAX || *grouping < 0) {
> + /* No further grouping to be done.
> + Copy the rest of the number. */
> + do
> + *--dest_end = *--src_end;
> + while (src_end > src_start);
> + break;
> + } else if (*grouping != '\0') {
> + glen = *grouping++;
> + } else {
> + /* The previous grouping repeats ad infinitum */
> + glen = grouping[-1];
> + }
> + }
> + }
> +
> + /* Make a copy with the exact needed size of the grouped number */
> + *gnumber = strdup(dest_end);
> + if (*gnumber == NULL) {
> + ret = -ENOMEM;
ditto
> + goto out_free_dest;
> + }
> +
> + /* fall through */
Why the "fall through" comment? This is a common construct and this
comment mostly applies where one would expect a break in a switch
statement :-)
Ah, here you do:
ret = 0;
Since all went well.
> +out_free_dest:
> + free(dest_alloc_ptr);
> +out:
> + return ret;
> +}
Commit-ID: 78da39faf7c903bb6e3c20a726fde1bf98d10af8
Gitweb: http://git.kernel.org/tip/78da39faf7c903bb6e3c20a726fde1bf98d10af8
Author: Bernhard Rosenkraenzer <[email protected]>
AuthorDate: Mon, 8 Oct 2012 09:43:26 +0300
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 8 Oct 2012 17:38:25 -0300
perf tools: Add on_exit implementation
on_exit() is only available in new versions of glibc.
It is not implemented in Bionic and will lead to linking errors when
compiling for Android.
Implement a wrapper for on_exit using atexit.
The implementation for on_exit is the one sent by Bernhard Rosenkraenzer in
https://lkml.org/lkml/2012/8/23/316. The configuration part from the Makefile
is different than the one from the original patch.
Signed-off-by: Bernhard Rosenkraenzer <[email protected]>
Signed-off-by: Irina Tirdea <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Irina Tirdea <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 6 ++++++
tools/perf/builtin-record.c | 32 ++++++++++++++++++++++++++++++++
tools/perf/config/feature-tests.mak | 11 ++++++++++-
3 files changed, 48 insertions(+), 1 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index d80a333..a7d8745 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -753,6 +753,12 @@ ifndef NO_STRLCPY
endif
endif
+ifndef NO_ON_EXIT
+ ifeq ($(call try-cc,$(SOURCE_ON_EXIT),),y)
+ BASIC_CFLAGS += -DHAVE_ON_EXIT
+ endif
+endif
+
ifndef NO_BACKTRACE
ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
BASIC_CFLAGS += -DBACKTRACE_SUPPORT
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e9231659..73b5d7f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,6 +31,38 @@
#include <sched.h>
#include <sys/mman.h>
+#ifndef HAVE_ON_EXIT
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t) (int, void *);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs(void);
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg)
+{
+ if (__on_exit_count == ATEXIT_MAX)
+ return -ENOMEM;
+ else if (__on_exit_count == 0)
+ atexit(__handle_on_exit_funcs);
+ __on_exit_funcs[__on_exit_count] = function;
+ __on_exit_args[__on_exit_count++] = arg;
+ return 0;
+}
+
+static void __handle_on_exit_funcs(void)
+{
+ int i;
+ for (i = 0; i < __on_exit_count; i++)
+ __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
+}
+#endif
+
enum write_mode_t {
WRITE_FORCE,
WRITE_APPEND
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 4add41b..eaeb0fd 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -203,4 +203,13 @@ int main(void)
return audit_open();
}
endef
-endif
\ No newline at end of file
+endif
+
+define SOURCE_ON_EXIT
+#include <stdio.h>
+
+int main(void)
+{
+ return on_exit(NULL, NULL);
+}
+endef
Commit-ID: d816ec2d1bea55cfeac373f0ab0ab8a3105e49b4
Gitweb: http://git.kernel.org/tip/d816ec2d1bea55cfeac373f0ab0ab8a3105e49b4
Author: Irina Tirdea <[email protected]>
AuthorDate: Mon, 8 Oct 2012 09:43:27 +0300
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 8 Oct 2012 17:42:16 -0300
perf tools: Update Makefile for Android
For cross-compiling on Android, some specific changes are needed in
the Makefile.
Update the Makefile to support cross-compiling for Android.
The original ideea for this was send by Bernhard Rosenkraenzer in
https://lkml.org/lkml/2012/8/23/316, but this is a rewrite.
Changes:
() support bionic in addition to glibc
() remove rt and pthread libraries that do not exist in Android
() use $(CFLAGS) when detecting initial compiler flags. This is needed
when setting CFLAGS as an argument of make (e.g. for setting --sysroot).
() include perf's local directory when building for Android to be able to find
relative paths if using --sysroot (e.g.: ../../include/linux/perf_event.h)
Signed-off-by: Irina Tirdea <[email protected]>
Cc: Bernhard Rosenkraenzer <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 25 +++++++++++++++++++------
tools/perf/config/feature-tests.mak | 9 +++++++++
2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index a7d8745..318bec8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -155,15 +155,15 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
-include config/feature-tests.mak
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all),y)
CFLAGS := $(CFLAGS) -fstack-protector-all
endif
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector),y)
CFLAGS := $(CFLAGS) -Wstack-protector
endif
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var),y)
CFLAGS := $(CFLAGS) -Wvolatile-register-var
endif
@@ -172,6 +172,13 @@ endif
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS =
+ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS)),y)
+ BIONIC := 1
+ EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
+ EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
+ BASIC_CFLAGS += -I.
+endif
+
# Guard against environment variables
BUILTIN_OBJS =
LIB_H =
@@ -469,12 +476,18 @@ else
FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
- ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
- msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
- else
+ ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
+ LIBC_SUPPORT := 1
+ endif
+ ifeq ($(BIONIC),1)
+ LIBC_SUPPORT := 1
+ endif
+ ifeq ($(LIBC_SUPPORT),1)
NO_LIBELF := 1
NO_DWARF := 1
NO_DEMANGLE := 1
+ else
+ msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
endif
else
FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index eaeb0fd..3ef5ec9 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -43,6 +43,15 @@ int main(void)
}
endef
+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+ return __ANDROID_API__;
+}
+endef
+
define SOURCE_ELF_MMAP
#include <libelf.h>
int main(void)
Commit-ID: 7747e2f4fb5fb840994613dd1474c17cddb7836b
Gitweb: http://git.kernel.org/tip/7747e2f4fb5fb840994613dd1474c17cddb7836b
Author: Irina Tirdea <[email protected]>
AuthorDate: Mon, 8 Oct 2012 09:43:28 +0300
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 8 Oct 2012 17:44:39 -0300
Documentation: add documentation on compiling for Android
Add documentation for cross-compiling on Android including:
() instructions on how to set the Android NDK environment
() how to cross-compile perf for Android
() how to install on an Android device/emulator, set the runtime
environment and run it
Signed-off-by: Irina Tirdea <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/android.txt | 75 ++++++++++++++++++++++++++++++++++
1 files changed, 75 insertions(+), 0 deletions(-)
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
new file mode 100644
index 0000000..a39dbbb
--- /dev/null
+++ b/tools/perf/Documentation/android.txt
@@ -0,0 +1,75 @@
+How to compile perf for Android
+=========================================
+
+I. Set the Android NDK environment
+------------------------------------------------
+
+(a). Use the Android NDK
+------------------------------------------------
+1. You need to download and install the Android Native Development Kit (NDK).
+Set the NDK variable to point to the path where you installed the NDK:
+ export NDK=/path/to/android-ndk
+
+2. Set cross-compiling environment variables for NDK toolchain and sysroot.
+For arm:
+ export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
+ export NDK_SYSROOT=${NDK}/platforms/android-9/arch-arm
+For x86:
+ export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android-
+ export NDK_SYSROOT=${NDK}/platforms/android-9/arch-x86
+
+This method is not working for Android NDK versions up to Revision 8b.
+perf uses some bionic enhancements that are not included in these NDK versions.
+You can use method (b) described below instead.
+
+(b). Use the Android source tree
+-----------------------------------------------
+1. Download the master branch of the Android source tree.
+Set the environment for the target you want using:
+ source build/envsetup.sh
+ lunch
+
+2. Build your own NDK sysroot to contain latest bionic changes and set the
+NDK sysroot environment variable.
+ cd ${ANDROID_BUILD_TOP}/ndk
+For arm:
+ ./build/tools/build-ndk-sysroot.sh --abi=arm
+ export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-arm
+For x86:
+ ./build/tools/build-ndk-sysroot.sh --abi=x86
+ export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-x86
+
+3. Set the NDK toolchain environment variable.
+For arm:
+ export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/arm-linux-androideabi-
+For x86:
+ export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/i686-linux-android-
+
+II. Compile perf for Android
+------------------------------------------------
+You need to run make with the NDK toolchain and sysroot defined above:
+ make CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
+
+III. Install perf
+-----------------------------------------------
+You need to connect to your Android device/emulator using adb.
+Install perf using:
+ adb push perf /data/perf
+
+If you also want to use perf-archive you need busybox tools for Android.
+For installing perf-archive, you first need to replace #!/bin/bash with #!/system/bin/sh:
+ sed 's/#!\/bin\/bash/#!\/system\/bin\/sh/g' perf-archive >> /tmp/perf-archive
+ chmod +x /tmp/perf-archive
+ adb push /tmp/perf-archive /data/perf-archive
+
+IV. Environment settings for running perf
+------------------------------------------------
+Some perf features need environment variables to run properly.
+You need to set these before running perf on the target:
+ adb shell
+ # PERF_PAGER=cat
+
+IV. Run perf
+------------------------------------------------
+Run perf on your device/emulator to which you previously connected using adb:
+ # ./data/perf
>>
>> + if (!objdump_path)
>> + try_objdump_path(session);
>
> Please do the test on perf_session_env__lookup_objdump() and handle
> errors, i.e. what happens if that strdup/asprintf fails?
>
> Ok, that is unlikely, but not impossible, but what happens if we don't
> find the right objdump? Shouldn't we use ui__error("please install
> required objdump" (or a better, more detailed message)?
>
My initial intention was to use the default "objdump" in case of any
error. On second though, this should not be allowed since the data was
recorded on a different architecture. I'll print error messages
instead.
Thanks,
Irina
>> +
>> + *gnumber = NULL;
>> + /* No grouping */
>> + if (thousands_sep == NULL || grouping == NULL ||
>> + *thousands_sep == '\0' || *grouping == CHAR_MAX || *grouping <= 0) {
>> + *gnumber = strdup(number);
>> + if (*gnumber == NULL)
>> + ret = -ENOMEM;
>> + goto out;
>
> Humm, so we bail out unconditionally? :-)
>
> this should be:
>
> if (*gnumber == NULL)
> goto out;
>> + }
The initial code was correct, although not clear. We bail out if there
is no grouping (the outer if), set gnumber to a copy of number and
return success. If we cannot allocate a copy of gnumber then we return
the error code.
However, this is no longer needed since it is already done when we
call the grouping function. So I'll just return error in case there is
no grouping and the calling code will take care to use the original
number (with no grouping).
I'll also fix your other comments and submit a new version.
Thanks,
Irina