execvp;
execve;
chdir;
+ readlink;
local:
*;
GP2X_A = 12, GP2X_B = 13, GP2X_X = 14, GP2X_Y = 15,
GP2X_VOL_UP = 16, GP2X_VOL_DOWN = 17, GP2X_PUSH = 18 };
+extern char *bin_path;
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif /* INCLUDE_sQt5fY5eUJn5tKV0IBTDxK0zqQutTqTp */
#include <stdlib.h>
#include <string.h>
#include <elf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <sys/mman.h>
#include "header.h"
#include "realfuncs.h"
+char *bin_path;
+
#define CHECK_(val, fail_operator, expect, err_msg) \
if (val fail_operator expect) { \
fprintf(stderr, err_msg ", exiting (%d)\n", (int)(long)val); \
int map_cnt;
int i, ret, envc, sfp;
long *stack_frame;
+ struct stat st;
+ char buf[64];
if (argc < 2) {
fprintf(stderr, "usage: %s <program> [args]\n", argv[0]);
lowest_segment = map_ptr;
}
+ // build self bin path
+ snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fileno(fi));
+ if (lstat(buf, &st) != 0)
+ FAIL_PERROR("lstat bin_path");
+ bin_path = malloc(st.st_size + 1);
+ CHECK_NE(bin_path, NULL, "bin_path");
+ ret = readlink(buf, bin_path, st.st_size);
+ if (ret < 0)
+ FAIL_PERROR("readlink");
+ bin_path[ret] = 0;
+
+ fclose(fi);
+
emu_init(lowest_segment);
// generate stack frame: argc, argv[], NULL, env[], NULL
return 1;
}
+ // update the environment
+ setenv("_", bin_path, 1);
+
sfp = 0;
stack_frame[sfp++] = argc - 1;
for (i = 1; i < argc; i++)
ret = 0;
else
ret = g_chdir_raw(path);
- strace("chdir(%s) = %d\n", path, ret);
+
+ strace("chdir(%s) = %ld\n", path, ret);
+ return g_syscall_error(ret);
+}
+
+static ssize_t w_readlink(const char *path, char *buf, size_t bufsiz)
+{
+ long ret;
+
+ if (path != NULL && strncmp(path, "/proc/", 6) == 0
+ && strcmp(strrchr(path, '/'), "/exe") == 0)
+ {
+ ret = snprintf(buf, bufsiz, "%s", bin_path);
+ if (ret > bufsiz)
+ ret = bufsiz;
+ }
+ else
+ ret = g_readlink_raw(path, buf, bufsiz);
+
+ strace("readlink(%s, %s, %zd) = %ld\n", path, buf, bufsiz, ret);
return g_syscall_error(ret);
}
#undef execvp
#undef execve
#undef chdir
+#undef readlink
#ifdef DL
MAKE_WRAP_SYM_N(execvp);
MAKE_WRAP_SYM(execve);
MAKE_WRAP_SYM_N(chdir);
+MAKE_WRAP_SYM_N(readlink);
typeof(mmap) mmap2 __attribute__((alias("w_mmap")));
#define REAL_FUNC_NP(name) \
return g_syscall_error(ret);
}
+ssize_t real_readlink(const char *path, char *buf, size_t bufsiz)
+{
+ long ret = g_readlink_raw(path, buf, bufsiz);
+ return g_syscall_error(ret);
+}
+
void real_sleep(unsigned int seconds)
{
struct timespec ts = { seconds, 0 };
0xffffffff, 0xffffffff, 0xffffffff, 0xff000000
};
+static const unsigned int sig_readlink[] = {
+ 0xef900055, // svc 0x900055
+ 0xe3700a01, // cmn r0, #0x1000
+ 0x312fff1e, // bxcc lr
+};
+#define sig_mask_readlink sig_mask_all
+
/* special */
static const unsigned int sig_cache1[] = {
0xee073f5e, // mcr 15, 0, r3, cr7, cr14, 2
PATCH (sigaction),
// PATCH_(execve, execve2, 0), // hangs
PATCH (chdir),
+ PATCH (readlink),
PATCH_(cache1, NULL, 2),
PATCH_(cache2, NULL, 2),
};
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_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
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_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);