diff --git a/packages/libandroid-spawn/build.sh b/packages/libandroid-spawn/build.sh new file mode 100644 index 0000000000..f08b252cf7 --- /dev/null +++ b/packages/libandroid-spawn/build.sh @@ -0,0 +1,18 @@ +TERMUX_PKG_HOMEPAGE=http://man7.org/linux/man-pages/man3/posix_spawn.3.html +TERMUX_PKG_DESCRIPTION="Shared library for the posix_spawn system function" +TERMUX_PKG_LICENSE="BSD 3-Clause" +TERMUX_PKG_VERSION=0.1 +TERMUX_PKG_SKIP_SRC_EXTRACT=true +TERMUX_PKG_BUILD_IN_SRC=true + +termux_step_make() { + $CC $CFLAGS $CPPFLAGS -I$TERMUX_PKG_BUILDER_DIR -c $TERMUX_PKG_BUILDER_DIR/posix_spawn.c + $CC $LDFLAGS -shared posix_spawn.o -o libandroid-spawn.so + $AR rcu libandroid-spawn.a posix_spawn.o +} + +termux_step_make_install() { + install -Dm600 $TERMUX_PKG_BUILDER_DIR/posix_spawn.h $TERMUX_PREFIX/include/spawn.h + install -Dm600 libandroid-spawn.a $TERMUX_PREFIX/lib/libandroid-spawn.a + install -Dm600 libandroid-spawn.so $TERMUX_PREFIX/lib/libandroid-spawn.so +} diff --git a/packages/libandroid-spawn/posix_spawn.c b/packages/libandroid-spawn/posix_spawn.c new file mode 100644 index 0000000000..18ceb0661a --- /dev/null +++ b/packages/libandroid-spawn/posix_spawn.c @@ -0,0 +1,156 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2012 Roy Marples + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* This implementation of posix_spawn is only suitable for the needs of dhcpcd + * but it could easily be extended to other applications. */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "posix_spawn.h" + +#ifndef _NSIG +#ifdef _SIG_MAXSIG +#define _NSIG _SIG_MAXSIG + 1 +#else +/* Guess */ +#define _NSIG SIGPWR + 1 +#endif +#endif + +extern char **environ; + +static int +posix_spawnattr_handle(const posix_spawnattr_t *attrp) +{ + struct sigaction sa; + int i; + + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGMASK) + sigprocmask(SIG_SETMASK, &attrp->posix_attr_sigmask, NULL); + + if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGDEF) { + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + for (i = 1; i < _NSIG; i++) { + if (sigismember(&attrp->posix_attr_sigdefault, i)) { + if (sigaction(i, &sa, NULL) == -1) + return -1; + } + } + } + + return 0; +} + +inline static int +is_vfork_safe(short int flags) +{ + return !(flags & (POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK)); +} + +int +posix_spawn(pid_t *pid, const char *path, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, + char *const argv[], char *const envp[]) +{ + short int flags; + pid_t p; + volatile int error; + + error = 0; + flags = attrp ? attrp->posix_attr_flags : 0; + if (file_actions == NULL && is_vfork_safe(flags)) + p = vfork(); + else +#ifdef THERE_IS_NO_FORK + return ENOSYS; +#else + p = fork(); +#endif + switch (p) { + case -1: + return errno; + case 0: + if (attrp) { + error = posix_spawnattr_handle(attrp); + if (error) + _exit(127); + } + execve(path, argv, envp); + error = errno; + _exit(127); + default: + if (error != 0) + waitpid(p, NULL, WNOHANG); + else if (pid != NULL) + *pid = p; + return error; + } +} + +int +posix_spawnattr_init(posix_spawnattr_t *attr) +{ + + memset(attr, 0, sizeof(*attr)); + attr->posix_attr_flags = 0; + sigprocmask(0, NULL, &attr->posix_attr_sigmask); + sigemptyset(&attr->posix_attr_sigdefault); + return 0; +} + +int +posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) +{ + + attr->posix_attr_flags = flags; + return 0; +} + +int +posix_spawnattr_setsigmask(posix_spawnattr_t *attr, const sigset_t *sigmask) +{ + + attr->posix_attr_sigmask = *sigmask; + return 0; +} + +int +posix_spawnattr_setsigdefault(posix_spawnattr_t *attr, const sigset_t *sigmask) +{ + + attr->posix_attr_sigdefault = *sigmask; + return 0; +} diff --git a/packages/libandroid-spawn/posix_spawn.h b/packages/libandroid-spawn/posix_spawn.h new file mode 100644 index 0000000000..ccfb0f0c14 --- /dev/null +++ b/packages/libandroid-spawn/posix_spawn.h @@ -0,0 +1,53 @@ +/* + * dhcpcd - DHCP client daemon + * Copyright (c) 2006-2012 Roy Marples + * All rights reserved + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef POSIX_SPAWN_H +#define POSIX_SPAWN_H + +#include + +typedef struct { + short posix_attr_flags; +#define POSIX_SPAWN_SETSIGDEF 0x10 +#define POSIX_SPAWN_SETSIGMASK 0x20 + sigset_t posix_attr_sigmask; + sigset_t posix_attr_sigdefault; +} posix_spawnattr_t; + +typedef struct { +// int unused; +} posix_spawn_file_actions_t; + +int posix_spawn(pid_t *, const char *, + const posix_spawn_file_actions_t *, const posix_spawnattr_t *, + char *const [], char *const []); +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_setsigmask(posix_spawnattr_t *, const sigset_t *); +int posix_spawnattr_setsigdefault(posix_spawnattr_t *, const sigset_t *); + +#endif diff --git a/packages/uftrace/build.sh b/packages/uftrace/build.sh new file mode 100644 index 0000000000..369800b3e3 --- /dev/null +++ b/packages/uftrace/build.sh @@ -0,0 +1,26 @@ +TERMUX_PKG_HOMEPAGE=https://uftrace.github.io/slide +TERMUX_PKG_DESCRIPTION="Function (graph) tracer for user-space" +TERMUX_PKG_LICENSE="GPL-2.0" +TERMUX_PKG_VERSION=0.9.3 +TERMUX_PKG_SRCURL=https://github.com/namhyung/uftrace/archive/v${TERMUX_PKG_VERSION}.tar.gz +TERMUX_PKG_SHA256=d801d72e3cdd83c510aeecc5160482d879498cf08fffd21e64f84151001e18ea +TERMUX_PKG_DEPENDS="capstone, libandroid-glob, libandroid-spawn, libelf, ncurses, python2" +TERMUX_PKG_BUILD_DEPENDS="argp" + +termux_step_pre_configure() { + # uftrace uses custom configure script implementation, so we need to provide some flags + export CFLAGS="${CFLAGS} -I${TERMUX_PREFIX}/include -DEFD_SEMAPHORE=1 -DEF_ARM_ABI_FLOAT_HARD=0x400 -w" + export LDFLAGS="${LDFLAGS} -Wl,--wrap=_Unwind_Resume -landroid-glob -largp" + + if [ "$TERMUX_ARCH" = "i686" ]; then + export ARCH="i386" + else + export ARCH="$TERMUX_ARCH" + fi +} + +termux_step_post_make_install() { + $CC $CFLAGS $CPPFLAGS -c $TERMUX_PKG_BUILDER_DIR/fakeprofiler.c + $CC $LDFLAGS -shared fakeprofiler.o -o libfakeprofiler.so + install -Dm600 libfakeprofiler.so $TERMUX_PREFIX/lib/libfakeprofiler.so +} diff --git a/packages/uftrace/cmds-live.c.patch b/packages/uftrace/cmds-live.c.patch new file mode 100644 index 0000000000..09ed3947db --- /dev/null +++ b/packages/uftrace/cmds-live.c.patch @@ -0,0 +1,10 @@ ++++ ./cmds/live.c 2019-08-26 14:48:20.538152232 +0300 +@@ -97,7 +97,7 @@ + + int command_live(int argc, char *argv[], struct opts *opts) + { +- char template[32] = "/tmp/uftrace-live-XXXXXX"; ++ char template[128] = "@TERMUX_PREFIX@/tmp/uftrace-live-XXXXXX"; + int fd; + struct sigaction sa = { + .sa_flags = SA_RESETHAND, diff --git a/packages/uftrace/cmds-record.c.patch b/packages/uftrace/cmds-record.c.patch new file mode 100644 index 0000000000..6633a1802d --- /dev/null +++ b/packages/uftrace/cmds-record.c.patch @@ -0,0 +1,67 @@ ++++ ./cmds/record.c 2019-08-26 14:37:07.385308338 +0300 +@@ -60,6 +60,65 @@ + static bool has_sched_event; + static bool finish_received; + ++static int shm_unlink(const char *name) { ++ size_t namelen; ++ char *fname; ++ ++ /* Construct the filename. */ ++ while (name[0] == '/') ++name; ++ ++ if (name[0] == '\0') { ++ /* The name "/" is not supported. */ ++ errno = EINVAL; ++ return -1; ++ } ++ ++ namelen = strlen(name); ++ fname = (char *) alloca(sizeof("@TERMUX_PREFIX@/tmp/") - 1 + namelen + 1); ++ memcpy(fname, "@TERMUX_PREFIX@/tmp/", sizeof("@TERMUX_PREFIX@/tmp/") - 1); ++ memcpy(fname + sizeof("@TERMUX_PREFIX@/tmp/") - 1, name, namelen + 1); ++ ++ return unlink(fname); ++} ++ ++static int shm_open(const char *name, int oflag, mode_t mode) { ++ size_t namelen; ++ char *fname; ++ int fd; ++ ++ /* Construct the filename. */ ++ while (name[0] == '/') ++name; ++ ++ if (name[0] == '\0') { ++ /* The name "/" is not supported. */ ++ errno = EINVAL; ++ return -1; ++ } ++ ++ namelen = strlen(name); ++ fname = (char *) alloca(sizeof("@TERMUX_PREFIX@/tmp/") - 1 + namelen + 1); ++ memcpy(fname, "@TERMUX_PREFIX@/tmp/", sizeof("@TERMUX_PREFIX@/tmp/") - 1); ++ memcpy(fname + sizeof("@TERMUX_PREFIX@/tmp/") - 1, name, namelen + 1); ++ ++ fd = open(fname, oflag, mode); ++ if (fd != -1) { ++ /* We got a descriptor. Now set the FD_CLOEXEC bit. */ ++ int flags = fcntl(fd, F_GETFD, 0); ++ flags |= FD_CLOEXEC; ++ flags = fcntl(fd, F_SETFD, flags); ++ ++ if (flags == -1) { ++ /* Something went wrong. We cannot return the descriptor. */ ++ int save_errno = errno; ++ close(fd); ++ fd = -1; ++ errno = save_errno; ++ } ++ } ++ ++ return fd; ++} ++ + static bool can_use_fast_libmcount(struct opts *opts) + { + if (debug) diff --git a/packages/uftrace/disable-librt.patch b/packages/uftrace/disable-librt.patch new file mode 100644 index 0000000000..0b547b1e5d --- /dev/null +++ b/packages/uftrace/disable-librt.patch @@ -0,0 +1,10 @@ ++++ ./Makefile 2019-08-26 04:27:09.354957504 +0300 +@@ -53,7 +53,7 @@ + COMMON_CFLAGS := -D_GNU_SOURCE $(CFLAGS) $(CPPFLAGS) + COMMON_CFLAGS += -iquote $(srcdir) -iquote $(objdir) -iquote $(srcdir)/arch/$(ARCH) + #CFLAGS-DEBUG = -g -D_GNU_SOURCE $(CFLAGS_$@) +-COMMON_LDFLAGS := -lrt -ldl -pthread -Wl,-z,noexecstack $(LDFLAGS) ++COMMON_LDFLAGS := -ldl -pthread -Wl,-z,noexecstack $(LDFLAGS) + ifneq ($(elfdir),) + COMMON_CFLAGS += -I$(elfdir)/include + COMMON_LDFLAGS += -L$(elfdir)/lib diff --git a/packages/uftrace/fakeprofiler.c b/packages/uftrace/fakeprofiler.c new file mode 100644 index 0000000000..6d287d8016 --- /dev/null +++ b/packages/uftrace/fakeprofiler.c @@ -0,0 +1,2 @@ +void __attribute__((no_instrument_function)) __cyg_profile_func_enter (void *this_fn, void *call_site) {} +void __attribute__((no_instrument_function)) __cyg_profile_func_exit (void *this_fn, void *call_site) {} diff --git a/packages/uftrace/kernel.c.patch b/packages/uftrace/kernel.c.patch new file mode 100644 index 0000000000..097689d47d --- /dev/null +++ b/packages/uftrace/kernel.c.patch @@ -0,0 +1,44 @@ ++++ ./utils/kernel.c 2019-08-26 05:01:08.580055352 +0300 +@@ -29,6 +29,42 @@ + + #define TRACING_DIR "/sys/kernel/debug/tracing" + ++int strverscmp(const char *l0, const char *r0) ++{ ++ const unsigned char *l = (const void *)l0; ++ const unsigned char *r = (const void *)r0; ++ size_t i, dp, j; ++ int z = 1; ++ ++ /* Find maximal matching prefix and track its maximal digit ++ * suffix and whether those digits are all zeros. */ ++ for (dp=i=0; l[i]==r[i]; i++) { ++ int c = l[i]; ++ if (!c) return 0; ++ if (!isdigit(c)) dp=i+1, z=1; ++ else if (c!='0') z=0; ++ } ++ ++ if (l[dp]!='0' && r[dp]!='0') { ++ /* If we're not looking at a digit sequence that began ++ * with a zero, longest digit string is greater. */ ++ for (j=i; isdigit(l[j]); j++) ++ if (!isdigit(r[j])) return 1; ++ if (isdigit(r[j])) return -1; ++ } else if (z && dpd_name, (*b)->d_name); ++} ++ + static bool kernel_tracing_enabled; + + /* tree of executed kernel functions */ diff --git a/packages/uftrace/libmcount-record.c.patch b/packages/uftrace/libmcount-record.c.patch new file mode 100644 index 0000000000..bf73f4ee96 --- /dev/null +++ b/packages/uftrace/libmcount-record.c.patch @@ -0,0 +1,46 @@ ++++ ./libmcount/record.c 2019-08-26 14:43:15.836981805 +0300 +@@ -23,6 +23,44 @@ + + #define ARG_STR_MAX 98 + ++static int shm_open(const char *name, int oflag, mode_t mode) { ++ size_t namelen; ++ char *fname; ++ int fd; ++ ++ /* Construct the filename. */ ++ while (name[0] == '/') ++name; ++ ++ if (name[0] == '\0') { ++ /* The name "/" is not supported. */ ++ errno = EINVAL; ++ return -1; ++ } ++ ++ namelen = strlen(name); ++ fname = (char *) alloca(sizeof("/data/data/com.termux/files/usr/tmp/") - 1 + namelen + 1); ++ memcpy(fname, "/data/data/com.termux/files/usr/tmp/", sizeof("/data/data/com.termux/files/usr/tmp/") - 1); ++ memcpy(fname + sizeof("/data/data/com.termux/files/usr/tmp/") - 1, name, namelen + 1); ++ ++ fd = open(fname, oflag, mode); ++ if (fd != -1) { ++ /* We got a descriptor. Now set the FD_CLOEXEC bit. */ ++ int flags = fcntl(fd, F_GETFD, 0); ++ flags |= FD_CLOEXEC; ++ flags = fcntl(fd, F_SETFD, flags); ++ ++ if (flags == -1) { ++ /* Something went wrong. We cannot return the descriptor. */ ++ int save_errno = errno; ++ close(fd); ++ fd = -1; ++ errno = save_errno; ++ } ++ } ++ ++ return fd; ++} ++ + static struct mcount_shmem_buffer *allocate_shmem_buffer(char *sess_id, size_t size, + int tid, int idx) + { diff --git a/packages/uftrace/libmcount-wrap.c.patch b/packages/uftrace/libmcount-wrap.c.patch new file mode 100644 index 0000000000..4f6721210d --- /dev/null +++ b/packages/uftrace/libmcount-wrap.c.patch @@ -0,0 +1,20 @@ ++++ ./libmcount/wrap.c 2019-08-26 04:38:48.830364663 +0300 +@@ -324,7 +324,8 @@ + real_cxa_rethrow(); + } + +-__visible_default void _Unwind_Resume(void *exception) ++void __real__Unwind_Resume(void *exception); ++__visible_default void __wrap__Unwind_Resume(void *exception) + { + struct mcount_thread_data *mtdp; + +@@ -345,7 +346,7 @@ + mcount_rstack_restore(mtdp); + } + +- real_unwind_resume(exception); ++ __real__Unwind_Resume(exception); + } + + __visible_default void * __cxa_begin_catch(void *exception) diff --git a/packages/uftrace/pr_warn.patch b/packages/uftrace/pr_warn.patch new file mode 100644 index 0000000000..6686e71d32 --- /dev/null +++ b/packages/uftrace/pr_warn.patch @@ -0,0 +1,73 @@ ++++ ./cmds/info.c 2019-08-26 14:53:01.793449309 +0300 +@@ -1146,7 +1146,7 @@ + + ret = open_info_file(opts, &handle); + if (ret < 0) { +- pr_warn("cannot open record data: %s: %m\n", opts->dirname); ++ pr_warn("cannot open record data: %s: %s\n", opts->dirname, strerror(errno)); + return -1; + } + ++++ ./cmds/report.c 2019-08-26 14:57:29.911809302 +0300 +@@ -1,6 +1,7 @@ + #include + #include + #include ++#include + + #include "uftrace.h" + #include "utils/utils.h" +@@ -523,7 +524,7 @@ + report_calc_avg(&base_tree); + + if (open_data_file(&dummy_opts, &data.handle) < 0) { +- pr_warn("cannot open record data: %s: %m\n", opts->diff); ++ pr_warn("cannot open record data: %s: %s\n", opts->diff, strerror(errno)); + goto out; + } + +@@ -609,7 +610,7 @@ + + ret = open_data_file(opts, &handle); + if (ret < 0) { +- pr_warn("cannot open record data: %s: %m\n", opts->dirname); ++ pr_warn("cannot open record data: %s: %s\n", opts->dirname, strerror(errno)); + return -1; + } + ++++ ./cmds/dump.c 2019-08-26 14:59:44.802869609 +0300 +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + #include "uftrace.h" + #include "version.h" +@@ -1582,7 +1583,7 @@ + + ret = open_data_file(opts, &handle); + if (ret < 0) { +- pr_warn("cannot open record data: %s: %m\n", opts->dirname); ++ pr_warn("cannot open record data: %s: %s\n", opts->dirname, strerror(errno)); + return -1; + } + ++++ ./cmds/replay.c 2019-08-26 15:01:30.621223877 +0300 +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + #include "uftrace.h" + #include "utils/utils.h" +@@ -1111,7 +1112,7 @@ + + ret = open_data_file(opts, &handle); + if (ret < 0) { +- pr_warn("cannot open record data: %s: %m\n", opts->dirname); ++ pr_warn("cannot open record data: %s: %s\n", opts->dirname, strerror(errno)); + return -1; + } +