new packages: libandroid-spawn and uftrace

This commit is contained in:
Leonid Pliushch 2019-08-28 15:06:58 +03:00
parent 82df909b01
commit a28f7639fc
12 changed files with 525 additions and 0 deletions

View File

@ -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
}

View File

@ -0,0 +1,156 @@
/*
* dhcpcd - DHCP client daemon
* Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
* 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 <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -0,0 +1,53 @@
/*
* dhcpcd - DHCP client daemon
* Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
* 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 <signal.h>
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

26
packages/uftrace/build.sh Normal file
View File

@ -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
}

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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) {}

View File

@ -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 && dp<i && (isdigit(l[i]) || isdigit(r[i]))) {
+ /* Otherwise, if common prefix of digit sequence is
+ * all zeros, digits order less than non-digits. */
+ return (unsigned char)(l[i]-'0') - (unsigned char)(r[i]-'0');
+ }
+
+ return l[i] - r[i];
+}
+
+static int versionsort(const struct dirent **a, const struct dirent **b)
+{
+ return strverscmp((*a)->d_name, (*b)->d_name);
+}
+
static bool kernel_tracing_enabled;
/* tree of executed kernel functions */

View File

@ -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)
{

View File

@ -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)

View File

@ -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 <stdio.h>
#include <inttypes.h>
#include <assert.h>
+#include <errno.h>
#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 <time.h>
#include <assert.h>
#include <sys/stat.h>
+#include <errno.h>
#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 <inttypes.h>
#include <stdio_ext.h>
#include <assert.h>
+#include <errno.h>
#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;
}