lkml.org 
[lkml]   [2012]   [Jun]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
Subject[PATCH] perf: Make perf buildable for Android
From
Hi,
this patch allows compiling perf for Android (with Bionic instead of glibc).
Nothing overly complicated in there, just a couple of workarounds
for missing functionality and header oddities in Bionic.

Signed-off-by: Bernhard Rosenkraenzer <Bernhard.Rosenkranzer@linaro.org>

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 92271d3..d15cdae 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -117,7 +117,7 @@ ifndef PERF_DEBUG
endif

CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99
$(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2
$(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
-EXTLIBS = -lpthread -lrt -lelf -lm
+EXTLIBS = -lpthread -lelf -lm
ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-D_GNU_SOURCE
ALL_LDFLAGS = $(LDFLAGS)
STRIP ?= strip
@@ -474,12 +474,23 @@ 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);
+ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(FLAGS_GLIBC)),y)
+ # Found Bionic instead of glibc...
+ # That works too, but needs a bit of special treatment
+ BASIC_CFLAGS += -DANDROID -include compat-android.h
+ ANDROID := 1
+ else
+ msg := $(error No gnu/libc-version.h found, please install
glibc-dev[el]/glibc-static);
+ endif
else
msg := $(error No libelf.h/libelf found, please install
libelf-dev/elfutils-libelf-devel);
endif
endif

+ifneq ($(ANDROID),1)
+EXTLIBS += -lrt
+endif
+
ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
BASIC_CFLAGS += -DLIBELF_NO_MMAP
endif
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 223ffdc..1f20f4d 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -469,10 +469,17 @@ static int test__basic_mmap(void)
.watermark = 0,
};
cpu_set_t cpu_set;
+#ifndef ANDROID
const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
"getpgid", };
pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
(void*)getpgid };
+#else
+ // No getsid() on Android
+ const char *syscall_names[] = { "getppid", "getpgrp",
+ "getpgid", };
+ pid_t (*syscalls[])(void) = { getppid, getpgrp, (void*)getpgid };
+#endif
#define nsyscalls ARRAY_SIZE(syscall_names)
int ids[nsyscalls];
unsigned int nr_events[nsyscalls],
diff --git a/tools/perf/compat-android.h b/tools/perf/compat-android.h
new file mode 100644
index 0000000..7681f35
--- /dev/null
+++ b/tools/perf/compat-android.h
@@ -0,0 +1,90 @@
+/* Android compatibility header
+ * Provides missing bits in Bionic on Android, ignored
+ * on regular Linux.
+ *
+ * Written by Bernhard.Rosenkranzer@linaro.org
+ *
+ * Released into the public domain. Do with this file
+ * whatever you want.
+ */
+#ifdef ANDROID
+/* Bionic has its own idea about ALIGN, and kills other definitions.
+ * Done outside the multiple-inclusion wrapper to make sure we
+ * can override Bionic's ALIGN by simply including compat-android.h
+ * again after including Bionic headers.
+ */
+#undef ALIGN
+#undef __ALIGN_MASK
+#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
+#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
+
+#ifndef _COMPAT_ANDROID_H_
+#define _COMPAT_ANDROID_H_ 1
+#include <stdio.h>
+#include <signal.h>
+#include <asm/page.h> // for PAGE_SIZE
+#include <asm/termios.h> // for winsize
+
+#ifndef __WORDSIZE
+#include <stdint.h>
+#define __WORDSIZE _BITSIZE
+#endif
+
+#ifndef roundup
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+#endif
+
+#ifndef __force
+#define __force
+#endif
+
+// Assorted functions that are missing from Bionic
+static void psignal(int sig, const char *s) {
+ if(sig>=0 && sig<NSIG) {
+ if(s)
+ fprintf(stderr, "%s: %s\n", s, sys_siglist[sig]);
+ else
+ fprintf(stderr, "%s\n", sys_siglist[sig]);
+ } else {
+ if(s)
+ fprintf(stderr, "%s: invalid signal\n", s);
+ else
+ fputs("invalid signal\n", stderr);
+ }
+}
+
+static ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
+ size_t ret = 0;
+
+ if (!lineptr || !n || !stream)
+ return -1;
+
+ if(!*lineptr) {
+ *n = 128;
+ *lineptr = (char*)malloc(*n);
+ if(!*lineptr)
+ return -1;
+ }
+
+ while(!feof(stream) && !ferror(stream)) {
+ int c;
+ if(ret == *n) {
+ *n += 128;
+ *lineptr = (char*)realloc(*lineptr, *n);
+ if(!*lineptr) {
+ *n = 0;
+ return -1;
+ }
+ }
+ c = fgetc(stream);
+ if(c == EOF)
+ break;
+ *lineptr[ret++] = c;
+ if(c == '\n')
+ break;
+ }
+ *lineptr[ret] = 0;
+ return ret;
+}
+#endif
+#endif
diff --git a/tools/perf/config/feature-tests.mak
b/tools/perf/config/feature-tests.mak
index d9084e0..498cd4d 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -43,6 +43,19 @@ int main(void)
}
endef

+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+#ifndef __ANDROID_API__
+ error out
+#else
+ return 0;
+#endif
+}
+endef
+
define SOURCE_ELF_MMAP
#include <libelf.h>
int main(void)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index efa5dc8..ead88ea 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -6,6 +6,7 @@
#include "symbol.h"
#include <linux/list.h>
#include <linux/rbtree.h>
+#include <pthread.h>

struct objdump_line {
struct list_head node;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 2a6f33c..867415a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -6,6 +6,7 @@
#include "strlist.h"
#include "thread.h"
#include "thread_map.h"
+#include "../compat-android.h"

static const char *perf_event__names[] = {
[0] = "TOTAL",
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1b19728..2b0554b 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -6,6 +6,7 @@

#include "../perf.h"
#include "map.h"
+#include "../compat-android.h"

/*
* PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0f99f39..77c5ced 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -70,15 +70,19 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/select.h>
+#ifndef ANDROID
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
+#endif
#include <netdb.h>
#include <pwd.h>
#include <inttypes.h>
#include "../../../include/linux/magic.h"
#include "types.h"
+#ifndef ANDROID
#include <sys/ttydefaults.h>
+#endif

extern const char *graph_line;
extern const char *graph_dotted_line;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 42e8aca..9eb8a4b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -32,6 +32,12 @@
#include <sched.h>
#include <sys/mman.h>

+#ifdef ANDROID
+// While stdlib.h has a prototype for it,
+// Bionic doesn't actually implement on_exit()
+static struct perf_record *__global_rec;
+#endif
+
enum write_mode_t {
WRITE_FORCE,
WRITE_APPEND
@@ -156,6 +162,11 @@ static void perf_record__sig_exit(int exit_status
__used, void *arg)
signal(signr, SIG_DFL);
kill(getpid(), signr);
}
+#ifdef ANDROID
+static void perf_record__sig_exit_android(void) {
+ perf_record__sig_exit(0, __global_rec);
+}
+#endif

static bool perf_evlist__equal(struct perf_evlist *evlist,
struct perf_evlist *other)
@@ -339,6 +350,11 @@ static void perf_record__exit(int status __used, void *arg)
symbol__exit();
}
}
+#ifdef ANDROID
+static void perf_record__exit_android(void) {
+ perf_record__exit(0, __global_rec);
+}
+#endif

static void perf_event__synthesize_guest_os(struct machine *machine,
void *data)
{
@@ -412,7 +428,12 @@ static int __cmd_record(struct perf_record *rec,
int argc, const char **argv)

rec->page_size = sysconf(_SC_PAGE_SIZE);

+#ifndef ANDROID
on_exit(perf_record__sig_exit, rec);
+#else
+ __global_rec = rec;
+ atexit(perf_record__sig_exit_android);
+#endif
signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGUSR1, sig_handler);
@@ -496,7 +517,11 @@ static int __cmd_record(struct perf_record *rec,
int argc, const char **argv)
/*
* perf_session__delete(session) will be called at perf_record__exit()
*/
+#ifndef ANDROID
on_exit(perf_record__exit, rec);
+#else
+ atexit(perf_record__exit_android);
+#endif

if (opts->pipe_output) {
err = perf_header__write_pipe(output);

\
 
 \ /
  Last update: 2012-06-25 18:21    [W:0.597 / U:0.076 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site