From 7fd42181a7f66b4403076cd9de98e18140a7eaf8 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 27 Jul 2010 18:20:56 +0300 Subject: [PATCH] wip, some dynamic stuff works --- loader/Makefile | 34 ++++-- loader/dl.c | 67 +++++++++++ loader/emu.c | 119 +++++++++++++++---- loader/ginge_dyn.sh | 12 ++ loader/header.h | 12 +- loader/host_pnd.c | 3 +- loader/loader.c | 3 +- loader/override.c | 259 ++++++++++++++++++++++++++++++++++++++++++ loader/patches.c | 102 +---------------- loader/realfuncs.h | 33 ++++++ loader/tools/static.c | 33 ++++-- 11 files changed, 540 insertions(+), 137 deletions(-) create mode 100644 loader/dl.c create mode 100755 loader/ginge_dyn.sh create mode 100644 loader/override.c create mode 100644 loader/realfuncs.h diff --git a/loader/Makefile b/loader/Makefile index d50bcd5..423e541 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -2,12 +2,15 @@ ARCH ?= arm CROSS_COMPILE ?= arm-linux- CC = $(CROSS_COMPILE)gcc AS = $(CROSS_COMPILE)as -CFLAGS += -Wall -ggdb -LDFLAGS += -static -ggdb -lpthread -lrt +CFLAGS += -Wall -ggdb -DLOADER +LDFLAGS += -ggdb -lpthread -lrt ifndef DEBUG CFLAGS += -O2 -fno-strict-aliasing LDFLAGS += -s -O2 endif +ifdef DBG +CFLAGS += -DDBG=$(DBG) +endif ifeq "$(ARCH)" "ia32" ARCH = ia32 @@ -22,13 +25,28 @@ endif vpath %.c = ../common/ -TARGET = ginge_sloader -OBJ += loader.o loader_$(ARCH).o patches.o emu.o host_fb.o host_pnd.o +TARGET_S = ginge_sloader +TARGET_D = ginge_dyn + +OBJ += emu.o host_fb.o host_pnd.o cmn.o +OBJ_S += $(OBJ) loader.o loader_$(ARCH).o patches.o +OBJ_D += $(OBJ) dl.o + +all: $(TARGET_S) $(TARGET_D) -$(TARGET): LDFLAGS += -Wl,-T script_$(ARCH).lds +$(TARGET_S): LDFLAGS += -Wl,-T script_$(ARCH).lds +$(TARGET_D): LDFLAGS += -ldl -$(TARGET): $(OBJ) - $(CC) -o $@ $^ $(LDFLAGS) +$(TARGET_S): $(OBJ_S) + $(CC) -o $@ $^ -static $(LDFLAGS) + +$(TARGET_D): $(OBJ_D) + $(CC) -o $@ $^ -shared $(LDFLAGS) clean: - $(RM) $(TARGET) $(OBJ) + $(RM) $(TARGET_S) $(TARGET_D) $(OBJ_S) $(OBJ_D) + +# basic deps +dl.o patches.o: override.c +*.o: header.h + diff --git a/loader/dl.c b/loader/dl.c new file mode 100644 index 0000000..154e012 --- /dev/null +++ b/loader/dl.c @@ -0,0 +1,67 @@ +// vim:shiftwidth=2:expandtab +#define _GNU_SOURCE +#include +#include +#include +#include +#include "header.h" + +#define DL +#include "override.c" + +__attribute__((constructor)) +static void ginge_init(void) +{ + unsigned int lowest_segment = (unsigned int)-1; + unsigned int start, end; + int i, ret; + FILE *f; + + for (i = 0; i < ARRAY_SIZE(real_funcs_np); i++) { + *real_funcs_np[i].func_ptr = dlsym(RTLD_NEXT, real_funcs_np[i].name); + if (*real_funcs_np[i].func_ptr == NULL) { + fprintf(stderr, "dlsym %s: %s\n", real_funcs_np[i].name, dlerror()); + exit(1); + } + // dbg("%p %s\n", *real_funcs_np[i].func_ptr, real_funcs_np[i].name); + } + + f = fopen("/proc/self/maps", "r"); + if (f == NULL) { + perror("open /proc/self/maps"); + exit(1); + } + + ret = fscanf(f, "%x-%x %*s %*s %*s %*s %*s\n", &start, &end); + if (ret != 2) { + perror("parse maps"); + exit(1); + } + lowest_segment = start; + + // assume first entry lists program's text section. + // unprotect it in case we need some patching. + ret = mprotect((void *)start, end - start, PROT_READ|PROT_WRITE|PROT_EXEC); + if (ret != 0) + perror("warning: mprotect"); + + while (1) { + ret = fscanf(f, "%x-%*s %*s %*s %*s %*s %*s\n", &start); + if (ret <= 0) + break; + + if (start < lowest_segment) + lowest_segment = start; + } + +#if 0 + rewind(f); + char buff[256]; + while (fgets(buff, sizeof(buff), f)) + fputs(buff, stdout); +#endif + fclose(f); + + emu_init((void *)lowest_segment); +} + diff --git a/loader/emu.c b/loader/emu.c index 3db8053..0d908d7 100644 --- a/loader/emu.c +++ b/loader/emu.c @@ -15,12 +15,22 @@ #include #include #include +#include +#include +#include #include "header.h" +#include "../common/host_fb.h" +#include "../common/cmn.h" #include "sys_cacheflush.h" +#include "realfuncs.h" -//#define LOG_IO -//#define LOG_IO_UNK +#if (dbg & 2) +#define LOG_IO_UNK +#endif +#if (dbg & 4) +#define LOG_IO +#endif //#define LOG_SEGV #ifdef LOG_IO @@ -754,7 +764,7 @@ static void segv_sigaction(int num, siginfo_t *info, void *ctx) u32 *regs = (u32 *)&context->uc_mcontext.arm_r0; u32 *pc = (u32 *)regs[15]; struct op_context *op_ctx; - int lp_size; + int i, lp_size; if (((regs[15] ^ (u32)&segv_sigaction) & 0xff000000) == 0 || // PC is in our segment or (((regs[15] ^ (u32)g_linkpage) & ~(LINKPAGE_ALLOC - 1)) == 0) || // .. in linkpage @@ -762,6 +772,8 @@ static void segv_sigaction(int num, siginfo_t *info, void *ctx) { // real crash - time to die err("segv %d %p @ %08x\n", info->si_code, info->si_addr, regs[15]); + for (i = 0; i < 8; i++) + err(" r%d=%08x r%2d=%08x\n", i, regs[i], i+8, regs[i+8]); signal(num, SIG_DFL); raise(num); return; @@ -808,7 +820,7 @@ static void segv_sigaction(int num, siginfo_t *info, void *ctx) void emu_init(void *map_bottom) { - struct sigaction segv_action = { + sigaction_t segv_action = { .sa_sigaction = segv_sigaction, .sa_flags = SA_SIGINFO, }; @@ -822,7 +834,8 @@ void emu_init(void *map_bottom) *((char *)g_handler_stack_end - 4096) = 1; g_linkpage = (void *)(((u32)map_bottom - LINKPAGE_ALLOC) & ~0xfff); - pret = mmap(g_linkpage, LINKPAGE_ALLOC, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + pret = mmap(g_linkpage, LINKPAGE_ALLOC, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (pret != g_linkpage) { perror(PFX "mmap linkpage"); exit(1); @@ -833,7 +846,7 @@ void emu_init(void *map_bottom) // host stuff ret = host_video_init(&host_stride, 0); if (ret != 0) { - err("can't alloc screen\n"); + err("can't init video\n"); exit(1); } host_screen = host_video_flip(); @@ -847,6 +860,7 @@ void emu_init(void *map_bottom) // mmsp2 defaults mmsp2.mlc_stl_adr = 0x03101000; // fb2 is at 0x03381000 + mmsp2.mlc_stl_cntl = 0x4ab; // 16bpp, region 1 active sigemptyset(&segv_action.sa_mask); sigaction(SIGSEGV, &segv_action, NULL); @@ -937,14 +951,11 @@ void *emu_do_mmap(unsigned int length, int prot, int flags, int fd, unsigned int if (fd == FAKEDEV_FB1) return emu_mmap_dev(length, prot, flags, offset + 0x03381000); - err("bad/ni mmap(?, %d, %x, %x, %d, %08x)", length, prot, flags, fd, offset); + err("bad/ni mmap(?, %d, %x, %x, %d, %08x)\n", length, prot, flags, fd, offset); errno = EINVAL; return MAP_FAILED; } -#include -#include - static int emu_sound_ioctl(int fd, int request, void *argp) { int *arg = argp; @@ -981,17 +992,18 @@ static int emu_sound_ioctl(int fd, int request, void *argp) return ioctl(fd, request, argp); } -#include - int emu_do_ioctl(int fd, int request, void *argp) { if (fd == emu_interesting_fds[IFD_SOUND].fd) return emu_sound_ioctl(fd, request, argp); - if (argp == NULL) - goto fail; + switch (fd) { + /* *********************** */ + case FAKEDEV_FB0: + case FAKEDEV_FB1: + if (argp == NULL) + goto fail; - if (fd == FAKEDEV_FB0 || fd == FAKEDEV_FB1) { switch (request) { case FBIOGET_FSCREENINFO: { struct fb_fix_screeninfo *fix = argp; @@ -1000,15 +1012,17 @@ int emu_do_ioctl(int fd, int request, void *argp) strcpy(fix->id, "mmsp2_RGB0"); fix->type = FB_TYPE_PACKED_PIXELS; fix->accel = FB_ACCEL_NONE; + fix->visual = FB_VISUAL_TRUECOLOR; + fix->line_length = 320*2; fix->smem_start = (fd == FAKEDEV_FB0) ? 0x03101000 : 0x03381000; fix->smem_len = 320*240*2; return 0; } case FBIOGET_VSCREENINFO: { struct fb_var_screeninfo *var = argp; - static const struct fb_bitfield fbb_red = { offset: 0, length: 4, }; - static const struct fb_bitfield fbb_green = { offset: 0, length: 4, }; - static const struct fb_bitfield fbb_blue = { offset: 0, length: 4, }; + static const struct fb_bitfield fbb_red = { offset: 11, length: 5, }; + static const struct fb_bitfield fbb_green = { offset: 5, length: 6, }; + static const struct fb_bitfield fbb_blue = { offset: 0, length: 5, }; memset(var, 0, sizeof(*var)); var->activate = FB_ACTIVATE_NOW; @@ -1025,12 +1039,79 @@ int emu_do_ioctl(int fd, int request, void *argp) var->blue = fbb_blue; return 0; } + case FBIOPUT_VSCREENINFO: { + struct fb_var_screeninfo *var = argp; + dbg(" put vscreen: %dx%d@%d\n", var->xres, var->yres, var->bits_per_pixel); + if (var->xres != 320 || var->yres != 240 || var->bits_per_pixel != 16) + return -1; + return 0; + } } + + /* *********************** */ + case FAKEDEV_TTY0: + // fake tty0 to make GPH SDL happy + if (request == 0x4b46) // KDGKBENT + return -1; + return 0; } fail: - err("bad/ni ioctl(%d, %08x, %p)", fd, request, argp); + err("bad/ni ioctl(%d, %08x, %p)\n", fd, request, argp); errno = EINVAL; return -1; } +static const struct { + const char *from; + const char *to; +} path_map[] = { + { "/mnt/tmp/", "/tmp/" }, +}; + +// FIXME: threads.. +static const char *wrap_path(const char *path) +{ + static char tmp_path[512]; + int i, len; + + // do only path mapping for now + for (i = 0; i < ARRAY_SIZE(path_map); i++) { + len = strlen(path_map[i].from); + if (strncmp(path, path_map[i].from, len) == 0) { + snprintf(tmp_path, sizeof(tmp_path), "%s%s", path_map[i].to, path + len); + dbg("mapped path \"%s\" -> \"%s\"\n", path, tmp_path); + return tmp_path; + } + } + + return path; +} + +void *emu_do_fopen(const char *path, const char *mode) +{ + return fopen(wrap_path(path), mode); +} + +int emu_do_system(const char *command) +{ + static char tmp_path[512]; + char *p, *p2; + + if (command == NULL) + return -1; + + // pass through stuff in PATH + p = strchr(command, ' '); + p2 = strchr(command, '/'); + if (p2 == NULL || (p != NULL && p2 > p)) + return system(command); + + make_local_path(tmp_path, sizeof(tmp_path), "ginge_prep"); + p = tmp_path + strlen(tmp_path); + + snprintf(p, sizeof(tmp_path) - (p - tmp_path), " %s", wrap_path(command)); + dbg("system: \"%s\"\n", tmp_path); + return system(tmp_path); +} + diff --git a/loader/ginge_dyn.sh b/loader/ginge_dyn.sh new file mode 100755 index 0000000..32c12f8 --- /dev/null +++ b/loader/ginge_dyn.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +root=$1 +shift + +loader="${root}lib/ld-linux.so.2" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${root}lib" +export LD_PRELOAD="${root}ginge_dyn" + +export GINGE_ROOT="${root}" + +exec "${loader}" "$@" diff --git a/loader/header.h b/loader/header.h index f2f6a45..8da398e 100644 --- a/loader/header.h +++ b/loader/header.h @@ -1,9 +1,10 @@ -#include "../common/host_fb.h" +#ifndef INCLUDE_sQt5fY5eUJn5tKV0IBTDxK0zqQutTqTp +#define INCLUDE_sQt5fY5eUJn5tKV0IBTDxK0zqQutTqTp 1 #define PFX "ginge: " #define err(f, ...) fprintf(stderr, PFX f, ##__VA_ARGS__) #define log(f, ...) fprintf(stdout, PFX f, ##__VA_ARGS__) -#if 1 +#ifdef DBG #define dbg log #define dbg_c printf #else @@ -22,12 +23,14 @@ enum { IFD_SOUND = 0, }; +// note: __FD_SETSIZE is 1024, fd_set stuff will crash if made larger enum { - FAKEDEV_MEM = 10001, + FAKEDEV_MEM = 1001, FAKEDEV_GPIO, FAKEDEV_FB0, FAKEDEV_FB1, FAKEDEV_MMUHACK, + FAKEDEV_TTY0, FAKEDEV_FD_BOUNDARY, }; @@ -37,6 +40,8 @@ void emu_init(void *map_bottom); void *emu_do_mmap(unsigned int length, int prot, int flags, int fd, unsigned int offset); int emu_do_ioctl(int fd, int request, void *argp); int 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 host_read_btns(void); @@ -47,3 +52,4 @@ enum { GP2X_UP = 0, GP2X_LEFT = 2, GP2X_DOWN = 4, GP2X_RIGHT = 6, #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif /* INCLUDE_sQt5fY5eUJn5tKV0IBTDxK0zqQutTqTp */ diff --git a/loader/host_pnd.c b/loader/host_pnd.c index a3d4215..5c79b91 100644 --- a/loader/host_pnd.c +++ b/loader/host_pnd.c @@ -11,6 +11,7 @@ #include #include "header.h" +#include "realfuncs.h" static int ifds[2] = { -1, -1 }; static int init_done; @@ -23,7 +24,7 @@ static void init(void) for (ifd = -1, i = 0; ifds[0] == -1 || ifds[1] == -1; i++) { snprintf(buff, sizeof(buff), "/dev/input/event%i", i); - ifd = open(buff, O_RDONLY | O_NONBLOCK); + ifd = open(buff, O_RDONLY | O_NONBLOCK, 0); if (ifd == -1) break; diff --git a/loader/loader.c b/loader/loader.c index df50542..28bdf8e 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -6,6 +6,7 @@ #include #include "header.h" +#include "realfuncs.h" #define CHECK_(val, fail_operator, expect, err_msg) \ if (val fail_operator expect) { \ @@ -73,7 +74,7 @@ int main(int argc, char *argv[]) for (i = 0; i < ARRAY_SIZE(maps); i++) { ret = fscanf(fi, "%lx-%lx %*s %*s %*s %*s %*s\n", &maps[i].start, &maps[i].end); - if (ret == 0) + if (ret <= 0) break; CHECK_EQ(ret, 2, "maps parse error"); } diff --git a/loader/override.c b/loader/override.c new file mode 100644 index 0000000..5a10193 --- /dev/null +++ b/loader/override.c @@ -0,0 +1,259 @@ +// vim:shiftwidth=2:expandtab +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "realfuncs.h" +#include "header.h" + +#if (DBG & 1) +#define strace printf +#else +#define strace(...) +#endif + +#define UNUSED __attribute__((unused)) + +static const struct dev_fd_t takeover_devs[] = { + { "/dev/mem", FAKEDEV_MEM }, + { "/dev/GPIO", FAKEDEV_GPIO }, + { "/dev/fb0", FAKEDEV_FB0 }, + { "/dev/fb/0", FAKEDEV_FB0 }, + { "/dev/fb1", FAKEDEV_FB1 }, + { "/dev/fb/1", FAKEDEV_FB1 }, + { "/dev/mmuhack", FAKEDEV_MMUHACK }, + { "/dev/tty", -1 }, // XXX hmh.. + { "/dev/tty0", FAKEDEV_TTY0 }, +}; + +static int w_open(const char *pathname, int flags, mode_t mode) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(takeover_devs); i++) { + if (strcmp(pathname, takeover_devs[i].name) == 0) { + ret = takeover_devs[i].fd; + break; + } + } + + if (i == ARRAY_SIZE(takeover_devs)) + ret = open(pathname, flags, mode); + + if (ret >= 0) { + for (i = 0; emu_interesting_fds[i].name != NULL; i++) { + if (strcmp(pathname, emu_interesting_fds[i].name) == 0) { + emu_interesting_fds[i].fd = ret; + break; + } + } + } + + strace("open(%s) = %d\n", pathname, ret); + return ret; +} + +static void *w_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) +{ + void *ret; + if (FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) + ret = emu_do_mmap(length, prot, flags, fd, offset); + else + ret = mmap(addr, length, prot, flags, fd, offset); + + // threads are using heap before they mmap their stack + // printf needs valid stack for pthread/errno + if (((long)&ret & 0xf0000000) == 0xb0000000) + strace("mmap(%p, %x, %x, %x, %d, %lx) = %p\n", addr, length, prot, flags, fd, (long)offset, ret); + return ret; +} +#define w_mmap2 w_mmap + +static ssize_t w_read(int fd, void *buf, size_t count) +{ + ssize_t ret; + if (fd == FAKEDEV_GPIO) + ret = emu_read_gpiodev(buf, count); + else + ret = read(fd, buf, count); + + //strace("read(%d, %p, %d) = %d\n", fd, buf, count, ret); + return ret; +} + +static int w_ioctl(int fd, int request, void *argp) +{ + int ret; + + if ((FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) || + fd == emu_interesting_fds[IFD_SOUND].fd) + ret = emu_do_ioctl(fd, request, argp); + else + ret = ioctl(fd, request, argp); + + strace("ioctl(%d, %08x, %p) = %d\n", fd, request, argp, ret); + return ret; +} + +static int w_sigaction(int signum, const void *act, void *oldact) +{ + strace("sigaction(%d, %p, %p) = %d\n", signum, act, oldact, 0); + return 0; +} + +/* dynamic only */ +static UNUSED int w_tcgetattr(int fd, struct termios *termios_p) +{ + int ret; + if (fd != FAKEDEV_TTY0) + ret = tcgetattr(fd, termios_p); + else + ret = 0; + + strace("tcgetattr(%d, %p) = %d\n", fd, termios_p, ret); + return ret; +} + +static UNUSED int w_tcsetattr(int fd, int optional_actions, + const struct termios *termios_p) +{ + int ret; + if (fd != FAKEDEV_TTY0) + ret = tcsetattr(fd, optional_actions, termios_p); + else + ret = 0; + + strace("tcsetattr(%d, %x, %p) = %d\n", fd, optional_actions, termios_p, ret); + return ret; +} + +static UNUSED FILE *w_fopen(const char *path, const char *mode) +{ + FILE *ret = emu_do_fopen(path, mode); + strace("fopen(%s, %s) = %p\n", path, mode, ret); + return ret; +} + +static UNUSED int w_system(const char *command) +{ + int ret = emu_do_system(command); + strace("system(%s) = %d\n", command, ret); + return ret; +} + +#undef open +#undef fopen +#undef mmap +#undef read +#undef ioctl +#undef sigaction +#undef tcgetattr +#undef tcsetattr +#undef system + +#ifdef DL + +#define MAKE_WRAP_SYM(sym) \ + /* alias wrap symbols to real names */ \ + typeof(sym) sym __attribute__((alias("w_" #sym))); \ + /* wrapper to real functions, to be set up on load */ \ + static typeof(sym) *p_real_##sym + +MAKE_WRAP_SYM(open); +MAKE_WRAP_SYM(fopen); +MAKE_WRAP_SYM(mmap); +MAKE_WRAP_SYM(read); +MAKE_WRAP_SYM(ioctl); +MAKE_WRAP_SYM(sigaction); +MAKE_WRAP_SYM(tcgetattr); +MAKE_WRAP_SYM(tcsetattr); +MAKE_WRAP_SYM(system); +typeof(mmap) mmap2 __attribute__((alias("w_mmap"))); + +#define REAL_FUNC_NP(name) \ + { #name, (void **)&p_real_##name } + +static const struct { + const char *name; + void **func_ptr; +} real_funcs_np[] = { + REAL_FUNC_NP(open), + REAL_FUNC_NP(fopen), + REAL_FUNC_NP(mmap), + REAL_FUNC_NP(read), + REAL_FUNC_NP(ioctl), + REAL_FUNC_NP(sigaction), + REAL_FUNC_NP(tcgetattr), + REAL_FUNC_NP(tcsetattr), + REAL_FUNC_NP(system), +}; + +#define open p_real_open +#define fopen p_real_fopen +#define mmap p_real_mmap +#define read p_real_read +#define ioctl p_real_ioctl +#define sigaction p_real_sigaction +#define tcgetattr p_real_tcgetattr +#define tcsetattr p_real_tcsetattr +#define system p_real_system + +#undef MAKE_WRAP_SYM +#undef REAL_FUNC_NP + +#endif + +// just call real funcs for static, pointer for dynamic +int real_open(const char *pathname, int flags, mode_t mode) +{ + return open(pathname, flags, mode); +} + +FILE *real_fopen(const char *path, const char *mode) +{ + return fopen(path, mode); +} + +void *real_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) +{ + return mmap(addr, length, prot, flags, fd, offset); +} + +int real_read(int fd, void *buf, size_t count) +{ + return read(fd, buf, count); +} + +int real_ioctl(int d, int request, void *argp) +{ + return ioctl(d, request, argp); +} + +int real_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact) +{ + return sigaction(signum, act, oldact); +} + +int real_tcgetattr(int fd, struct termios *termios_p) +{ + return tcgetattr(fd, termios_p); +} + +int real_tcsetattr(int fd, int optional_actions, + const struct termios *termios_p) +{ + return tcsetattr(fd, optional_actions, termios_p); +} + +int real_system(const char *command) +{ + return system(command); +} diff --git a/loader/patches.c b/loader/patches.c index f7e0b11..7d8cf97 100644 --- a/loader/patches.c +++ b/loader/patches.c @@ -1,21 +1,10 @@ // vim:shiftwidth=2:expandtab #include -#include -#include -#include -#include -#include -#include -#include #include "header.h" #include "sys_cacheflush.h" -#if 0 -#define strace printf -#else -#define strace(...) -#endif +#include "override.c" // note: first mask must be always full for search algo static const unsigned int sig_mask_all[] = { @@ -33,11 +22,11 @@ static const unsigned int sig_mmap[] = { }; #define sig_mask_mmap sig_mask_all -static const unsigned int sig_mmap_[] = { +static const unsigned int sig_mmap2[] = { 0xe52d5004, 0xe59d5008, 0xe52d4004, 0xe59d4008, 0xe1b0ca05, 0x1a000006, 0xe1a05625, 0xef9000c0 }; -#define sig_mask_mmap_ sig_mask_all +#define sig_mask_mmap2 sig_mask_all static const unsigned int sig_read[] = { 0xe59fc080, 0xe59cc000, 0xe33c0000, 0x1a000003, 0xef900003 @@ -56,89 +45,6 @@ static const unsigned int sig_mask_sigaction[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000 }; -static const struct dev_fd_t takeover_devs[] = { - { "/dev/mem", FAKEDEV_MEM }, - { "/dev/GPIO", FAKEDEV_GPIO }, - { "/dev/fb0", FAKEDEV_FB0 }, - { "/dev/fb/0", FAKEDEV_FB0 }, - { "/dev/fb1", FAKEDEV_FB1 }, - { "/dev/fb/1", FAKEDEV_FB1 }, - { "/dev/mmuhack", FAKEDEV_MMUHACK }, -}; - -static int w_open(const char *pathname, int flags, mode_t mode) -{ - int i, ret; - - for (i = 0; i < ARRAY_SIZE(takeover_devs); i++) { - if (strcmp(pathname, takeover_devs[i].name) == 0) { - ret = takeover_devs[i].fd; - break; - } - } - - if (i == ARRAY_SIZE(takeover_devs)) - ret = open(pathname, flags, mode); - - if (ret >= 0) { - for (i = 0; emu_interesting_fds[i].name != NULL; i++) { - if (strcmp(pathname, emu_interesting_fds[i].name) == 0) { - emu_interesting_fds[i].fd = ret; - break; - } - } - } - - strace("open(%s) = %d\n", pathname, ret); - return ret; -} - -static void *w_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) -{ - void *ret; - if (FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) - ret = emu_do_mmap(length, prot, flags, fd, offset); - else - ret = mmap(addr, length, prot, flags, fd, offset); - - // threads are using heap before they mmap their stack - // printf needs valid stack for pthtead/errno - if (((long)&ret & 0xf0000000) == 0xb0000000) - strace("mmap(%p, %x, %x, %x, %d, %lx) = %p\n", addr, length, prot, flags, fd, (long)offset, ret); - return ret; -} -#define w_mmap_ w_mmap - -static ssize_t w_read(int fd, void *buf, size_t count) -{ - ssize_t ret; - if (fd != FAKEDEV_GPIO) - return read(fd, buf, count); - - ret = emu_read_gpiodev(buf, count); - //strace("read(%d, %p, %d) = %d\n", fd, buf, count, ret); - return ret; -} - -static int w_ioctl(int fd, int request, void *argp) -{ - int ret; - - if ((FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) || - fd == emu_interesting_fds[IFD_SOUND].fd) - ret = emu_do_ioctl(fd, request, argp); - else - ret = ioctl(fd, request, argp); - - strace("ioctl(%d, %08x, %p) = %d\n", fd, request, argp, ret); - return ret; -} - -static int w_sigaction(int signum, const void *act, void *oldact) -{ - strace("sigaction(%d, %p, %p) = %d\n", signum, act, oldact, 0); - return 0; -} #define PATCH(f) { sig_##f, sig_mask_##f, ARRAY_SIZE(sig_##f), w_##f } @@ -150,7 +56,7 @@ static const struct { } patches[] = { PATCH(open), PATCH(mmap), - PATCH(mmap_), // mmap using mmap2 syscall + PATCH(mmap2), // mmap2 syscall PATCH(read), PATCH(ioctl), PATCH(sigaction), diff --git a/loader/realfuncs.h b/loader/realfuncs.h new file mode 100644 index 0000000..4bca950 --- /dev/null +++ b/loader/realfuncs.h @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int real_open(const char *pathname, int flags, mode_t mode); +FILE *real_fopen(const char *path, const char *mode); +void *real_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); +int real_read(int fd, void *buf, size_t count); +int real_ioctl(int fd, int request, void *argp); +int real_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); +typedef struct sigaction sigaction_t; +int real_tcgetattr(int fd, struct termios *termios_p); +int real_tcsetattr(int fd, int optional_actions, const struct termios *termios_p); +int real_system(const char *command); + +#define open real_open +#define fopen real_fopen +#define mmap real_mmap +#define read real_read +#define ioctl real_ioctl +#define sigaction real_sigaction +#define tcgetattr real_tcgetattr +#define tcsetattr real_tcsetattr +#define system real_system + diff --git a/loader/tools/static.c b/loader/tools/static.c index 50013c7..257a147 100644 --- a/loader/tools/static.c +++ b/loader/tools/static.c @@ -1,16 +1,31 @@ #include #include +#include #include #include #include #include #include #include +#include + +static int open_(const char *name) +{ + int fd = open(name, O_RDWR); + if (fd < 0) { + fprintf(stderr, "%s: ", name); + perror("open"); + return 1; + } + + return fd; +} int main(int argc, char *argv[]) { volatile void *memregs; - int memdev; + void *fbmem; + int memdev, fbdev; int i; printf("hi, home=%s\n", getenv("HOME")); @@ -18,21 +33,25 @@ int main(int argc, char *argv[]) for (i = 0; i < argc; i++) printf("%d \"%s\"\n", i, argv[i]); - memdev = open("/dev/mem", O_RDWR); - if (memdev < 0) { - perror("open"); - return 1; - } + memdev = open_("/dev/mem"); + fbdev = open_("/dev/fb0"); memregs = mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000); + fbmem = mmap(NULL, 320*240*2, PROT_READ|PROT_WRITE, MAP_SHARED, fbdev, 0); + ioctl(-1, 0); signal(7, SIG_DFL); +// tcgetattr(-1, NULL); +// tcsetattr(-1, 0, NULL); +#if 1 for (i = 0; i < 2; i++) printf("%02x %04x %08x\n", ((char *)memregs)[0x2011], ((short *)memregs)[0x1198/2], ((int *)memregs)[0xbcdc/4]); +#endif + memset(fbmem, 0xff, 320*240*2); - //sleep(1000); + sleep(10); return 0; } -- 2.39.2