On fork call reconnect to swap daemon as separate process.
On call exec disconnect from swap daemon.
If exec returns error connect to swap daemon again.
Change-Id: I0f99b96507e2f1d52460fba5e4ed0eb997e39981
Signed-off-by: Vitaliy Cherepanov <v.cherepanov@samsung.com>
-lpthread \
-lrt
+ASMFLAG = -O0 -g
+
## FIXME: Ideally, UTILITY_SRCS is sources for probe infrastructure and
## PROBE_SRCS is sources for actual replacement functions. Unfortunatelly,
## it is not so easy and UTILITY_SRCS do not link alone.
./helper/btsym.c \
./helper/dacollection.c \
./helper/dacapture.c \
+ ./helper/daforkexec.c \
./custom_chart/da_chart.c \
PROBE_SRCS = \
./probe_graphics/da_gles20_tizen.cpp \
./probe_graphics/da_gles20_native.cpp
+ASM_SRC = ./helper/da_call_original.S
+
## Totally brain-dead.
## FIXME: Rewrite this normally with eval.
-CAPI_OBJS = $(patsubst %.c,%.o, $(CAPI_SRCS))
-TIZEN_OBJS = $(patsubst %.cpp,%.o, $(patsubst %.c,%.o, $(TIZEN_SRCS)))
+ASM_OBJ = $(patsubst %.S,%.o, $(ASM_SRC))
+CAPI_OBJS = $(patsubst %.c,%.o, $(CAPI_SRCS)) $(ASM_OBJ)
+TIZEN_OBJS = $(patsubst %.cpp,%.o, $(patsubst %.c,%.o, $(TIZEN_SRCS))) $(ASM_OBJ)
DUMMY_OBJS = $(patsubst %.c,%.o, $(DUMMY_SRCS))
tizen: headers $(TIZEN_TARGET)
dummy: headers $(DUMMY_TARGET)
+$(ASM_OBJ): $(ASM_SRC)
+ $(CC) $(ASMFLAG) -c $^ -o $@
+
GENERATED_HEADERS = include/api_id_mapping.h include/api_id_list.h include/id_list
headers: $(GENERATED_HEADERS)
--- /dev/null
+/*
+ * DA probe
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+/*
+ * function
+ * <some ret type> _da_call_original(void *funcp, char *args[], int args_count);
+ *
+ * arguments:
+ * funcp - function pointer address to call
+ * args - params array for function
+ * args_count - params count
+ * return values:
+ * depends on original function (funcp)
+ *
+ * use this function to call original function with variable arguments count
+ * in ld-preloaded probes
+ *
+ * example:
+ * #include <dlfcn.h>
+ * #include <dlsym.h>
+ *
+ * typedef int (*execl_type)(const char *path, const char *arg, ...);
+ * static execl_type execl_real;
+ * //....
+ * //_da_call_original function prototype
+ * int call_original(void *funcp, char *args[], int args_count);
+ * //...
+ * execl_real = (execl_type)dlsym(RTLD_NEXT , "execl");
+ * //...
+ * //probe execl
+ * int execl(const char *path, const char *arg, ...)
+ * {
+ * int res = 0;
+ * va_list ap;
+ * int args_count = 0, i;
+ *
+ * //additional argumets list terminates with NULL pointer on execl call
+ * //calculate arguments count with terminate NULL
+ * va_start(ap, arg);
+ * do
+ * args_count++;
+ * while (va_arg(ap, char *) != 0);
+ * va_end(ap);
+ *
+ * //add 2 for <path> and <arg> params
+ * args_count += 2;
+ *
+ * //create and fill args arras
+ * char *all_args[args_count];
+ *
+ * va_start(ap, arg);
+ *
+ * all_args[0] = (char *)path;
+ * all_args[1] = (char *)arg;
+ * for (i = 2; i < args_count; i++)
+ * all_args[i] = va_arg(ap, char *);
+ * //do something
+ * //.....
+ * //call original function
+ * res = _da_call_original(&execl_real, all_args, args_count);
+ * //do something
+ * //......
+ * return res;
+ *
+ * }
+ *
+ * this function is written in asm because there is no other way to prepare
+ * variable count of arguments for original function call
+ */
+
+#define stack_size 0x40
+
+#if defined(__x86_64__)
+ /* x86 64-bit ----------------------------------------------- */
+
+.text
+.global _da_call_original
+.type _da_call_original, @function
+_da_call_original:
+ mov $-1, %rax
+ ret
+#elif defined(__i386)
+
+.text
+.global _da_call_original
+.type _da_call_original, @function
+_da_call_original:
+ #save stack position
+ push %ebp
+ mov %esp, %ebp
+
+ #create local stack
+ sub $stack_size, %esp
+
+ #store registers
+ push %ebx
+ push %ecx
+ push %edx
+
+ #load args array pointer
+ movl 0xc(%ebp),%ecx
+ #load args_count
+ movl 0x10(%ebp), %ebx
+
+ #calculate stack size for original function call
+ #stack size = (args_count) * 4
+ shl $2, %ebx
+ #create stack for original function call
+ sub %ebx, %esp
+
+ #push all arguments to stack
+ #for (i = 0; i < args_count; i++) {
+ movl $0, %eax
+ jmp for_i_cmp
+ for_i:
+ #args[i] -> stack
+ mov (%ecx), %edx
+ mov %edx, (%esp)
+ #stack++
+ add $4, %esp
+ add $4, %ecx
+ add $4, %eax
+ for_i_cmp:
+ cmpl %ebx, %eax
+ jl for_i
+ #}
+
+ #shift stack back
+ sub %ebx, %esp
+
+ #call original function (funcp)
+ movl 8(%ebp), %eax
+ call *(%eax)
+ #now function result in %eax
+
+ #restore stack after call function
+ add %ebx, %esp
+
+ #restore registers
+ pop %edx
+ pop %ecx
+ pop %ebx
+
+ #restore local stack
+ add $stack_size, %esp
+ #return
+ pop %ebp
+ ret
+
+#elif defined(__arm__)
+.text
+.global _da_call_original
+.type _da_call_original, %function
+
+_da_call_original:
+ push {fp, lr, r5, r6, r7, r8}
+ #create local stack
+ add fp, sp, #4
+ sub sp, sp, #stack_size
+ #store params to stack
+ str r0, [fp, #-12]
+ str r1, [fp, #-16]
+ str r2, [fp, #-20]
+
+ #load args array pointer
+ ldr r5, [fp, #-16]
+ #load args_count
+ ldr r6, [fp, #-20]
+
+ #calculate stack size for original function call
+ #stack size = (args_count) * 4
+ lsl r6, r6, #2
+ #create stack for original function call
+ sub sp, sp, r6
+ #first 4 params pass throw r0-r3
+ #so move stack to 4 words
+ sub sp, sp, #16
+
+ #for (i = 4; i < arg; i++) {
+ mov r7, #16
+ b for_i_cmp
+ for_i:
+ #args[i] -> stack[i]
+ ldr r8, [r5, r7]
+ str r8, [sp, r7]
+ add r7, r7, #4
+ for_i_cmp:
+ cmp r7, r6
+ blt for_i
+ #}
+
+ #move stack pointer back to 4 words
+ add sp, sp, #16
+ #load first 4 args
+ ldr r0, [r5, #0 ]
+ ldr r1, [r5, #4 ]
+ ldr r2, [r5, #8 ]
+ ldr r3, [r5, #12]
+
+ #call original function (funcp)
+ ldr r5, [fp, #-12]
+ ldr r5, [r5]
+ blx r5
+ #now function result in r0
+
+ #restore stack after original fincion call
+ add sp, sp, r6
+
+ #local stack restore
+ add sp, sp, #stack_size
+ #return
+ pop {fp, pc, r5, r6, r7, r8}
+#endif
--- /dev/null
+/*
+ * DA probe
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+#include <sys/types.h>
+#include <signal.h>
+
+#include "daprobe.h"
+#include "dahelper.h"
+#include "binproto.h"
+#include "daforkexec.h"
+
+DECLARE(int, execl , const char *path, const char *arg, ...);
+DECLARE(int, execlp, const char *file, const char *arg, ...);
+DECLARE(int, execle, const char *path, const char *arg, ...);//, char * const envp[]);
+DECLARE(int, execv, const char *path, char *const argv[]);
+DECLARE(int, execve, const char *filename, char *const argv[],char *const envp[]);
+DECLARE(int, execvp, const char *file, char *const argv[]);
+DECLARE(int, execvpe, const char *file, char *const argv[],char *const envp[]);
+DECLARE(pid_t, fork, void);
+
+void init_exec_fork()
+{
+ INIT_FUNC_EXEC(fork);
+ INIT_FUNC_EXEC(execl);
+ INIT_FUNC_EXEC(execlp);
+ INIT_FUNC_EXEC(execle);
+ INIT_FUNC_EXEC(execv);
+ INIT_FUNC_EXEC(execve);
+ INIT_FUNC_EXEC(execvp);
+ INIT_FUNC_EXEC(execvpe);
+}
+
+#define prepare_params( FUNCTION , p1, p2) \
+ va_list ap; \
+ int args_count = 0; \
+ int i; \
+ \
+ INIT_FUNC_EXEC( FUNCTION ); \
+ \
+ va_start(ap, p2); \
+ do \
+ args_count++; \
+ while (va_arg(ap, char *)); \
+ va_end(ap); \
+ args_count += 2 + 1; \
+ \
+ char *arg_arr[args_count]; \
+ \
+ va_start(ap, p2); \
+ \
+ arg_arr[0] = (char *)p1; \
+ arg_arr[1] = (char *)p2; \
+ for (i = 2; i < args_count; i++) \
+ arg_arr[i] = va_arg(ap, char *); \
+ \
+ va_end(ap)
+
+int _da_call_original(void *funcp, char *args[], int args_count);
+
+#define print_params(buf, p1, p2) \
+ char *p = buf; \
+ char *pp; \
+ va_list par; \
+ p += sprintf(p, "--> %s ", __FUNCTION__); \
+ p += sprintf(p, "[%d]: <", getpid()); \
+ p += sprintf(p, " \"%s\",", p1); \
+ p += sprintf(p, " \"%s\",", p2); \
+ va_start(par, p2); \
+ while ( (pp = va_arg(par, char *)) != NULL) \
+ p += sprintf(p, " \"%s\",", pp); \
+ va_end(par); \
+ p += sprintf(p, ">");
+
+int execl(const char *path, const char *arg, ...)
+{
+ int res;
+ char buf[DA_LOG_MAX];
+
+ sprintf(buf, "execl [%d] ", getpid());
+ PRINTMSG(buf);
+
+ _uninit_();
+ prepare_params(execl, path, arg);
+ res = _da_call_original(&execl_p, arg_arr, args_count);
+ _init_();
+
+ sprintf(buf, "%s return %d [%d]", __FUNCTION__, res, getpid());
+ PRINTMSG(buf);
+ return res;
+}
+
+int execlp(const char *file, const char *arg, ...)
+{
+ int res;
+ char buf[DA_LOG_MAX];
+
+ sprintf(buf, "execlp [%d] ", getpid());
+ PRINTMSG(buf);
+
+ _uninit_();
+ prepare_params(execlp, file, arg);
+ res = _da_call_original(&execlp_p, arg_arr, args_count);
+ _init_();
+
+ sprintf(buf, "%s return %d [%d]", __FUNCTION__, res, getpid());
+ PRINTMSG(buf);
+ return res;
+}
+
+int execle(const char *path, const char *arg, ...
+ /* original func have one more argument but
+ * i can't leave it in code by compilation reasons
+ * so it is commented:
+ *
+ *,__attribute__((unused)) char * const envp[] */
+ )
+{
+ int res;
+ char buf[DA_LOG_MAX];
+
+ sprintf(buf, "execle [%d] ", getpid());
+ PRINTMSG(buf);
+
+ _uninit_();
+ prepare_params(execle, path, arg);
+ res = _da_call_original(&execle_p, arg_arr, args_count);
+ _init_();
+
+ sprintf(buf, "%s return %d [%d]", __FUNCTION__, res, getpid());
+ PRINTMSG(buf);
+ return res;
+}
+
+int execv(const char *path, char *const argv[])
+{
+ int res;
+ char buf[DA_LOG_MAX];
+
+ sprintf(buf, "execv [%d] ", getpid());
+ PRINTMSG(buf);
+
+ _uninit_();
+ res = execv_p(path, argv);
+ _init_();
+
+ sprintf(buf, "%s return %d [%d]", __FUNCTION__, res, getpid());
+ PRINTMSG(buf);
+ return res;
+}
+
+int execvp(const char *file, char *const argv[])
+{
+ int res;
+ char buf[DA_LOG_MAX];
+
+ sprintf(buf, "execvp [%d] ", getpid());
+ PRINTMSG(buf);
+
+ _uninit_();
+ res = execvp_p(file, argv);
+ _init_();
+
+ sprintf(buf, "%s return %d [%d]", __FUNCTION__, res, getpid());
+ PRINTMSG(buf);
+ return res;
+}
+
+int execve(const char *filename, char *const argv[],char *const envp[])
+{
+ int res;
+ char buf[DA_LOG_MAX];
+
+ sprintf(buf, "execve [%d] ", getpid());
+ PRINTMSG(buf);
+
+ _uninit_();
+ res = execve_p(filename, argv, envp);
+ _init_();
+
+ sprintf(buf, "%s return %d [%d]", __FUNCTION__, res, getpid());
+ PRINTMSG(buf);
+ return res;
+}
+
+int execvpe(const char *file, char *const argv[],char *const envp[])
+{
+ int res;
+ char buf[DA_LOG_MAX];
+
+ sprintf(buf, "execvpe [%d] ", getpid());
+ PRINTMSG(buf);
+
+ _uninit_();
+ res = execvpe_p(file, argv, envp);
+ _init_();
+
+ sprintf(buf, "%s return %d [%d]", __FUNCTION__, res, getpid());
+ PRINTMSG(buf);
+ return res;
+}
+
+pid_t fork(void)
+{
+ char msg[DA_LOG_MAX];
+ pid_t res = fork_p();
+
+ sprintf(msg, "<fork = %d>", res);
+ if (res == 0) {
+ if (gTraceInfo.socket.daemonSock >= 0) {
+ close(gTraceInfo.socket.daemonSock);
+ _init_();
+ }
+ }
+ PRINTMSG(msg);
+
+ return res;
+}
--- /dev/null
+/*
+ * DA probe
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+#ifndef __DAFORKEXEC_H_
+#define __DAFORKEXEC_H_
+
+#define INIT_FUNC_EXEC(FUNCNAME) \
+ if(!FUNCNAME##_p) { \
+ void *tmpPtr = dlsym(RTLD_NEXT , #FUNCNAME); \
+ if (tmpPtr == NULL || dlerror() != NULL) { \
+ perror("dlsym failed : " #FUNCNAME); \
+ exit(0); \
+ } \
+ memcpy(&FUNCNAME##_p, &tmpPtr, sizeof(tmpPtr)); \
+ }
+
+#define DECLARE(RET, FUNCTION, ...) \
+ typedef RET (* FUNCTION ## _p_t)(__VA_ARGS__); \
+ static FUNCTION ## _p_t FUNCTION ## _p = 0
+
+void init_exec_fork();
+
+#endif /* __DAFORKEXEC_H_ */
#include "daprobe.h"
#include "binproto.h"
+#include "daforkexec.h"
#define APP_INSTALL_PATH "/opt/apps"
#define TISEN_APP_POSTFIX ".exe"
(struct sockaddr *)&clientAddr, clientLen) >= 0)
{
char buf[64];
+ /* send pid */
+ sprintf(buf, "%d|%llu", getpid(),
+ gTraceInfo.app.startTime);
+ printLogStr(buf, MSG_PID);
+
/* recv initial configuration value */
recvlen = recv(gTraceInfo.socket.daemonSock, &log,
sizeof(log.type) + sizeof(log.length),
/* closed by other peer */
}
- sprintf(buf, "%d|%llu", getpid(),
- gTraceInfo.app.startTime);
- printLogStr(buf, MSG_PID);
PRINTMSG("createSocket connect() success\n");
} else {
close(gTraceInfo.socket.daemonSock);
return err;
}
-void __attribute__((constructor)) _init_probe()
+void _init_(void)
{
+ char msg[DA_LOG_MAX];
probeBlockStart();
+ init_exec_fork();
initialize_hash_table();
initialize_screencapture();
}
- PRINTMSG("dynamic analyzer probe helper so loading...\n");
+ sprintf(msg, "dynamic analyzer probe helper so loading... pid[%d]\n",
+ getpid());
+ PRINTMSG(msg);
gTraceInfo.init_complete = 1;
probeBlockEnd();
+
}
-void __attribute__((destructor)) _fini_probe()
+void __attribute__((constructor)) _init_probe()
+{
+ _init_();
+ char msg[DA_LOG_MAX];
+ sprintf(msg, "<-lib construnctor");
+ PRINTMSG(msg);
+}
+
+void _uninit_(void)
{
int i;
+ char msg[DA_LOG_MAX];
probeBlockStart();
gTraceInfo.init_complete = -1;
- PRINTMSG("dynamic analyzer probe helper so unloading...\n");
+ sprintf(msg, "dynamic analyzer probe helper so unloading... pid[%d]\n",
+ getpid());
+ PRINTMSG(msg);
remove_all_glist();
probeBlockEnd();
}
+void __attribute__((destructor)) _fini_probe()
+{
+ char msg[DA_LOG_MAX];
+ sprintf(msg, "->lib destructor. pid[%d]\n", getpid());
+ PRINTMSG(msg);
+ _uninit_();
+}
+
/**************************************************************************
* Helper APIs
/* return 0; */
/* } */
+extern void _init_(void);
+extern void _uninit_(void);
+
#endif /* __BIN_PROTO_H__ */