From 7868435641e4209e956a591ff0844afc14f83f16 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 10 Jan 2016 03:13:07 +0200 Subject: [PATCH] try to handle exec-gp2xmenu exit --- loader/emu.c | 12 +++++++----- loader/header.h | 5 +++-- loader/host.c | 7 ++----- loader/host_pnd.c | 2 +- loader/host_wiz.c | 2 +- loader/loader.c | 3 +++ loader/override.c | 22 ++++++++++++++-------- loader/patches.c | 7 ++++--- loader/syscalls.S | 1 + loader/syscalls.h | 2 ++ 10 files changed, 38 insertions(+), 25 deletions(-) diff --git a/loader/emu.c b/loader/emu.c index 313bd06..38fea46 100644 --- a/loader/emu.c +++ b/loader/emu.c @@ -1371,17 +1371,19 @@ int emu_do_system(const char *command) return ret; } -int emu_do_execve(const char *filename, char *const argv[], char *const envp[]) +long emu_do_execve(const char *filename, char * const argv[], + char * const envp[]) { const char **new_argv; char *prep_path; - int i, ret, argc; + int i, argc; + long ret; if (filename == NULL) return -1; - if (strstr(filename, "/gp2xmenu") != NULL) - exit(0); + if (strstr(filename, "gp2xmenu") != NULL) + host_forced_exit(0); for (i = 0; argv[i] != NULL; i++) ; @@ -1406,7 +1408,7 @@ int emu_do_execve(const char *filename, char *const argv[], char *const envp[]) dbg("execve \"%s\" %s \"%s\"\n", new_argv[0], new_argv[1], new_argv[2]); ret = execve(new_argv[0], (char **)new_argv, envp); - perror("execve"); + err("execve(%s): %ld\n", new_argv[0], ret); return ret; } diff --git a/loader/header.h b/loader/header.h index ec4a495..0641878 100644 --- a/loader/header.h +++ b/loader/header.h @@ -49,11 +49,11 @@ long emu_do_ioctl(int fd, int request, void *argp); long emu_read_gpiodev(void *buf, int count); void *emu_do_fopen(const char *path, const char *mode); int emu_do_system(const char *command); -int emu_do_execve(const char *filename, char *const argv[], char *const envp[]); +long emu_do_execve(const char *filename, char *const argv[], char *const envp[]); int host_init(void); int host_read_btns(void); -void host_forced_exit(void); +void host_forced_exit(int status); enum { GP2X_UP = 0, GP2X_LEFT = 2, GP2X_DOWN = 4, GP2X_RIGHT = 6, GP2X_START = 8, GP2X_SELECT = 9, GP2X_L = 10, GP2X_R = 11, @@ -61,6 +61,7 @@ enum { GP2X_UP = 0, GP2X_LEFT = 2, GP2X_DOWN = 4, GP2X_RIGHT = 6, GP2X_VOL_UP = 16, GP2X_VOL_DOWN = 17, GP2X_PUSH = 18 }; extern char *bin_path; +extern char **g_argv; #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) diff --git a/loader/host.c b/loader/host.c index 7df4f10..a6c2856 100644 --- a/loader/host.c +++ b/loader/host.c @@ -26,9 +26,6 @@ #include "host_wiz.c" #endif -// for plat.c -char **g_argv; - int host_init(void) { in_init(); @@ -48,7 +45,7 @@ int host_read_btns(void) return actions[IN_BINDTYPE_PLAYER12]; } -void host_forced_exit(void) +void host_forced_exit(int status) { // exit() might not be enough because loader and app data is out of sync, // and other threads (which are really processes on this old glibc used) @@ -62,7 +59,7 @@ void host_forced_exit(void) usleep(300000); snprintf(cmd, sizeof(cmd), "killall -9 %s", g_argv[0]); system(cmd); - exit(1); + exit(status); } // vim:shiftwidth=2:expandtab diff --git a/loader/host_pnd.c b/loader/host_pnd.c index 86e9910..83a0888 100644 --- a/loader/host_pnd.c +++ b/loader/host_pnd.c @@ -32,7 +32,7 @@ static const struct in_pdata pandora_evdev_pdata = { static void host_actions(int actions[IN_BINDTYPE_COUNT]) { if (actions[IN_BINDTYPE_EMU] & 1) - host_forced_exit(); + host_forced_exit(1); } static void host_init_input(void) diff --git a/loader/host_wiz.c b/loader/host_wiz.c index 7763f35..3e08fe6 100644 --- a/loader/host_wiz.c +++ b/loader/host_wiz.c @@ -133,7 +133,7 @@ static void host_actions(int actions[IN_BINDTYPE_COUNT]) act |= 1 << GP2X_VOL_DOWN; } if (act & (1 << GP2X_Y)) - host_forced_exit(); + host_forced_exit(1); actions[IN_BINDTYPE_PLAYER12] = act; } } diff --git a/loader/loader.c b/loader/loader.c index 2d7d3d2..27ea856 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -17,6 +17,7 @@ #include "realfuncs.h" char *bin_path; +char **g_argv; #define CHECK_(val, fail_operator, expect, err_msg) \ if (val fail_operator expect) { \ @@ -81,6 +82,8 @@ int main(int argc, char *argv[]) return 1; } + g_argv = argv; + fi = fopen("/proc/self/maps", "r"); CHECK_NE(fi, NULL, "fopen maps"); diff --git a/loader/override.c b/loader/override.c index 5a722d9..1e0d415 100644 --- a/loader/override.c +++ b/loader/override.c @@ -251,15 +251,20 @@ static UNUSED int w_execvp(const char *file, char *const argv[]) return emu_do_execve(file, argv, environ); } -// static note: this can't safely return because of the way it's patched in -// static note2: can't be used, execve hangs? -static UNUSED int w_execve(const char *filename, char *const argv[], - char *const envp[]) +long w_execve_raw(const char *filename, char * const argv[], + char * const envp[]) { strace("execve(%s, %p, %p) = ?\n", filename, argv, envp); return emu_do_execve(filename, argv, envp); } +static UNUSED int w_execve(const char *filename, char * const argv[], + char * const envp[]) +{ + long ret = w_execve_raw(filename, argv, envp); + return g_syscall_error(ret); +} + static int w_chdir(const char *path) { long ret; @@ -338,7 +343,7 @@ MAKE_WRAP_SYM_N(execlp); MAKE_WRAP_SYM_N(execle); MAKE_WRAP_SYM_N(execv); MAKE_WRAP_SYM_N(execvp); -MAKE_WRAP_SYM(execve); +MAKE_WRAP_SYM_N(execve); MAKE_WRAP_SYM_N(chdir); MAKE_WRAP_SYM_N(readlink); typeof(mmap) mmap2 __attribute__((alias("w_mmap"))); @@ -361,7 +366,7 @@ static const struct { REAL_FUNC_NP(tcsetattr), REAL_FUNC_NP(system), // exec* - skipped - REAL_FUNC_NP(execve), + //REAL_FUNC_NP(execve), //REAL_FUNC_NP(chdir), }; @@ -375,7 +380,7 @@ static const struct { #define tcgetattr p_real_tcgetattr #define tcsetattr p_real_tcsetattr #define system p_real_system -#define execve p_real_execve +//#define execve p_real_execve //#define chdir p_real_chdir #undef MAKE_WRAP_SYM @@ -458,7 +463,8 @@ int real_system(const char *command) int real_execve(const char *filename, char *const argv[], char *const envp[]) { - return execve(filename, argv, envp); + long ret = g_execve_raw(filename, argv, envp); + return g_syscall_error(ret); } int real_chdir(const char *path) diff --git a/loader/patches.c b/loader/patches.c index b7ea613..d272b56 100644 --- a/loader/patches.c +++ b/loader/patches.c @@ -113,12 +113,12 @@ static const unsigned int sig_execve[] = { }; #define sig_mask_execve sig_mask_all -static const unsigned int sig_execve2[] = { +static const unsigned int sig_hw_execve[] = { 0xef90000b, // svc 0x90000b 0xe3700a01, // cmn r0, #4096 0xe1a04000, // mov r4, r0 }; -#define sig_mask_execve2 sig_mask_all +#define sig_mask_hw_execve sig_mask_all static const unsigned int sig_chdir[] = { 0xef90000c, // svc 0x90000c @@ -172,6 +172,7 @@ asm( \ SVC_CMN_R0_MOV_R4_WRAPPER(hw_read, w_read_raw) SVC_CMN_R0_MOV_R4_WRAPPER(hw_ioctl, w_ioctl_raw) +SVC_CMN_R0_MOV_R4_WRAPPER(hw_execve, w_execve_raw) #define PATCH_(p, f, t) { sig_##p, sig_mask_##p, ARRAY_SIZE(sig_##p), t, f, #p } #define PATCH(f) PATCH_(f, w_##f, 0) @@ -195,7 +196,7 @@ static const struct { PATCH (ioctl), PATCH_(hw_ioctl, hw_ioctl, 1), PATCH (sigaction), -// PATCH_(execve, execve2, 0), // hangs + PATCH_(hw_execve, hw_execve, 1), PATCH (chdir), PATCH (readlink), PATCH_(cache1, NULL, 2), diff --git a/loader/syscalls.S b/loader/syscalls.S index 7c57ef2..ab5800b 100644 --- a/loader/syscalls.S +++ b/loader/syscalls.S @@ -89,6 +89,7 @@ raw_syscall_easy g_chdir_raw, __NR_chdir raw_syscall_easy g_futex_raw, __NR_futex raw_syscall_easy g_nanosleep_raw, __NR_nanosleep raw_syscall_easy g_readlink_raw, __NR_readlink +raw_syscall_easy g_execve_raw, __NR_execve raw_syscall_easy g_clock_gettime_raw, __NR_clock_gettime raw_syscall_easy g_rt_sigprocmask_raw, __NR_rt_sigprocmask raw_syscall_easy g_exit_group_raw, __NR_exit_group diff --git a/loader/syscalls.h b/loader/syscalls.h index d5a8048..3dfc44a 100644 --- a/loader/syscalls.h +++ b/loader/syscalls.h @@ -25,6 +25,8 @@ long g_futex_raw(int *uaddr, int op, int val, const struct timespec *timeout); long g_nanosleep_raw(const struct timespec *req, struct timespec *rem); long g_readlink_raw(const char *pathname, char *buf, size_t bufsiz); +long g_execve_raw(const char *filename, char * const argv[], + char * const envp[]); long g_clock_gettime_raw(int clk_id, const struct timespec *tp); long g_rt_sigprocmask_raw(int how, const void *set, void *oldset, size_t sigsetsize); -- 2.39.2