From ef933ff5089d38b7976a14da96bcb7113c036071 Mon Sep 17 00:00:00 2001 From: Yatis Date: Sat, 13 Mar 2021 17:48:37 +0100 Subject: [PATCH] Gintracer v0.8.1 - World independent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @update <> Now, the tracer have it own world (a copy of gint world), so this allows the tracer to be completely independent vis-à-vis the traced world. The world can be analyzed with a menu (not implemented but noted in the TODO) --- Makefile | 4 ++-- TODO | 12 ++++++---- demo/main.c | 27 +++++++++++++++++++-- gintrace.g3a | Bin 119924 -> 119940 bytes include/gintrace/tracer.h | 1 + libgintrace-cg.a | Bin 115316 -> 115338 bytes src/gint.c | 48 +++++++++++++++++++++++--------------- src/menu/callgraph.c | 29 +++++++++++++---------- src/tracer.c | 8 +++++++ src/ubc/handler.c | 13 ++++++++--- src/ubc/ubc.c | 13 +++++++++-- 11 files changed, 110 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index e67b518..5e261fc 100644 --- a/Makefile +++ b/Makefile @@ -238,14 +238,14 @@ ifeq ($1,fx) target-$(tname)-cflags += -D FX9860G -m3 target-$(tname)-ldflags += -T fx9860g.ld target-$(tname)-libs := -L. -L $(GCC_INCLUDE_FX) - target-$(tname)-libs += -lgintrace-fx -lgint-fx -lgcc + target-$(tname)-libs += -lgint-fx -lgintrace-fx -lgint-fx -lgcc target-$(tname)-exec := $3.g1a endif ifeq ($1,cg) target-$(tname)-cflags += -D FXCG50 -m4-nofpu target-$(tname)-ldflags += -T fxcg50.ld target-$(tname)-libs := -L. -L $(GCC_INCLUDE_CG) - target-$(tname)-libs += -lgintrace-cg -lgint-cg -lgcc + target-$(tname)-libs += -lgint-cg -lgintrace-cg -lgint-cg -lgcc target-$(tname)-exec := $3.g3a endif diff --git a/TODO b/TODO index 692d95a..e888b58 100644 --- a/TODO +++ b/TODO @@ -3,17 +3,19 @@ * fix fx9860 support @update -* makefile: generate the demo * makefile: handle header dependencies +* makefile: handle dynamic lib generation * makefile: generate the documentation * context: refacto printXY() ! * hexdump: search commands * callgraph: improve user interface. -* disasm: set manually multiple breakpoint -* savefile -* load saved file -* list color scheme on SMEM. * icon @feature * add documentation +* switch to justUI +* add drivers menu +* savefile +* load saved file +* list color scheme on SMEM. +* disasm: set manually multiple breakpoint diff --git a/demo/main.c b/demo/main.c index 12ec687..52e6383 100644 --- a/demo/main.c +++ b/demo/main.c @@ -5,6 +5,9 @@ #include #include +extern void *kernel_env_gint; +extern void *kernel_env_casio; +extern void *gint_switch_to_world(void *buffctx); /* main(): User entry */ int main(void) @@ -13,6 +16,26 @@ int main(void) void **systab; void *syscall; +#if 0 + int x = 0; + int key = 0; + while (1) { + dclear(C_WHITE); + dtext(0, 0, C_BLACK, "Unable to create tracer session"); + dtext(0, 10, C_BLACK, "Press [MENU]..."); + dprint(x, 20, C_BLACK, "buffctx: %p", drivers_get_current()); + dprint(x, 30, C_BLACK, "gintctx: %p", kernel_env_gint); + dprint(x, 40, C_BLACK, "casioctx: %p", kernel_env_casio); + dupdate(); + + key = getkey().key; + if (key == KEY_LEFT) + x = x + 10; + if (key == KEY_RIGHT) + x = x - 10; + } +#endif + /* get syscall address */ systab = *(void ***)0x8002007c; //syscall = systab[0x1e48]; // Fugue_debug_menu @@ -38,10 +61,10 @@ int main(void) //--- void (*bfile_openfile_os)(const uint16_t *filename, int mode, int p3); - gint_switch_to_casio(); + gint_switch_to_world(kernel_env_casio); bfile_openfile_os = syscall; bfile_openfile_os(u"\\\\fls0\\abcdefgijklmn", BFile_ReadOnly, 0); - gint_switch_to_gint(); + gint_switch_to_world(kernel_env_gint); diff --git a/gintrace.g3a b/gintrace.g3a index d59a78a432922638010b7b9a87a73192e7613347..4a392eb3dbee9878dc0de1c430e3f3edb9185da2 100644 GIT binary patch delta 21741 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 delta 21773 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 #include #include +#include /* external symbols */ extern void *kernel_env_casio; extern void *kernel_env_gint; +extern void *kernel_env_tracer; /* gint_switch(): Temporarily switch out of gint */ void gint_switch(void (*function)(void)) { + void *buffctx_current; + void *buffctx; + + /* check useless action */ + if (function == NULL) + return; + + /* check useless world switch */ + buffctx_current = drivers_get_current(); + if (kernel_env_casio == buffctx_current) { + function(); + return; + } + /* Switch from gint to the OS after a short wait */ ubc_uninstall(); - drivers_wait(); - drivers_switch(kernel_env_gint, kernel_env_casio); + buffctx = drivers_switch(kernel_env_casio); ubc_install(); - if(function != NULL) - function(); + /* involve the function */ + function(); /* then switch back to gint once the os finishes working */ ubc_uninstall(); - drivers_wait(); - drivers_switch(kernel_env_casio, kernel_env_gint); + drivers_switch(buffctx); ubc_install(); } /* Switch from gint to the OS after a short wait */ -void gint_switch_to_casio(void) +void *gint_switch_to_world(void *buffctx) { - ubc_uninstall(); - drivers_wait(); - drivers_switch(kernel_env_gint, kernel_env_casio); - ubc_install(); -} + void *buffctx_current; -/* Switch from gint to the OS after a short wait */ -void gint_switch_to_gint(void) -{ - ubc_uninstall(); - drivers_wait(); - drivers_switch(kernel_env_casio, kernel_env_gint); - ubc_install(); + buffctx_current = drivers_get_current(); + if (buffctx != buffctx_current) { + ubc_uninstall(); + drivers_switch(buffctx); + ubc_install(); + } + return (buffctx_current); } diff --git a/src/menu/callgraph.c b/src/menu/callgraph.c index 8044d8c..04f6703 100644 --- a/src/menu/callgraph.c +++ b/src/menu/callgraph.c @@ -14,6 +14,11 @@ #include "./src/menu/internal/dictionary.h" +/* internal info (TODO: move me) */ +extern void *kernel_env_gint; +extern void *kernel_env_casio; +extern void *gint_switch_to_world(void *buffctx); + //--- // callode management //--- @@ -321,11 +326,11 @@ static void callgraph_command(struct tsession *session, int argc, char **argv) /* check if the file exist */ input_write_noint("Check if the file exist"); - gint_switch_to_casio(); + gint_switch_to_world(kernel_env_casio); char line[256]; int fd = BFile_Open(pathname, BFile_ReadOnly); if (fd >= 0) { - gint_switch_to_gint(); + gint_switch_to_world(kernel_env_gint); while (1) { if (input_read(line, 3, "'%s' exist, erase ? [n/Y]:", argv[1]) <= 0) { @@ -338,39 +343,39 @@ static void callgraph_command(struct tsession *session, int argc, char **argv) } if (line[0] != 'Y') continue; - gint_switch_to_casio(); + gint_switch_to_world(kernel_env_casio); BFile_Remove(pathname); break; } } /* create the file then dump information */ - gint_switch_to_gint(); + gint_switch_to_world(kernel_env_gint); int size = callnode_export(-1, session->menu.callgraph.root, line); input_write_noint("Create the file (%d)", size); - gint_switch_to_casio(); + gint_switch_to_world(kernel_env_casio); fd = BFile_Create(pathname, BFile_File, &size); if (fd != 0) { - gint_switch_to_gint(); + gint_switch_to_world(kernel_env_gint); input_write("Bfile_Create: error %d", fd); return; } - gint_switch_to_gint(); + gint_switch_to_world(kernel_env_gint); input_write_noint("Create success"); - gint_switch_to_casio(); + gint_switch_to_world(kernel_env_casio); fd = BFile_Open(pathname, BFile_ReadWrite); if (fd < 0) { BFile_Remove(pathname); - gint_switch_to_gint(); + gint_switch_to_world(kernel_env_gint); input_write("BFile_Open: error %d", fd); return; } - gint_switch_to_gint(); + gint_switch_to_world(kernel_env_gint); input_write_noint("Open success, now write..."); - gint_switch_to_casio(); + gint_switch_to_world(kernel_env_casio); callnode_export(fd, session->menu.callgraph.root, line); BFile_Close(fd); - gint_switch_to_gint(); + gint_switch_to_world(kernel_env_gint); input_write("success"); } diff --git a/src/tracer.c b/src/tracer.c index 08ce18f..375b513 100644 --- a/src/tracer.c +++ b/src/tracer.c @@ -12,6 +12,7 @@ struct tsession *tracer_create_session(void *address, int menu) extern void gintrace_handler(struct ucontext *context); struct tsession *session; + /* check error */ if (address == NULL || (menu & (TRACER_DISASM | TRACER_CONTEXT | TRACER_HEXDUMP @@ -19,6 +20,7 @@ struct tsession *tracer_create_session(void *address, int menu) return(NULL); } + /* try to create the session */ session = calloc(sizeof(struct tsession), 1); if (session == NULL) return (NULL); @@ -35,6 +37,7 @@ struct tsession *tracer_create_session(void *address, int menu) if ((menu & TRACER_CALLGRAPH) != 0) menu_register(session->display.gmenu, &menu_callgraph, "CallG"); + /* force install the UBC driver */ ubc_install(); ubc_set_handler(&gintrace_handler); ubc_set_breakpoint(0, address, NULL); @@ -53,6 +56,11 @@ struct tsession *tracer_set_session(struct tsession *new) void *old; old = session; + //FIXME: save current trace info session = new; + //FIXME: restore current trace info + //ubc_install(); + //ubc_set_handler(&gintrace_handler); + //ubc_set_breakpoint(0, address, NULL); return (old); } diff --git a/src/ubc/handler.c b/src/ubc/handler.c index 688f6ba..2c09362 100644 --- a/src/ubc/handler.c +++ b/src/ubc/handler.c @@ -8,6 +8,11 @@ #include +// custom function +extern void *kernel_env_gint; +extern void *kernel_env_tracer; +extern void *gint_switch_to_world(void *buffctx); + /* gintrac_handler(): UBC handler * @note: * To force generate the callgraph, we use a dirty workaround to force break @@ -20,6 +25,7 @@ void gintrace_handler(struct ucontext *context) static uintptr_t breakpoint = 0x00000000; static uintptr_t spc = 0x00000000; struct tsession *session; + void *buffctx; /* force disable the UBC to avoid error */ ubc_block(); @@ -33,6 +39,7 @@ void gintrace_handler(struct ucontext *context) session->info.context = context; /* check callgraph job */ + //FIXME: move me if (breakpoint != 0x00000000 && spc != 0x00000000 && spc != breakpoint) { @@ -44,7 +51,7 @@ void gintrace_handler(struct ucontext *context) } /* user break point */ - gint_switch_to_gint(); + buffctx = gint_switch_to_world(kernel_env_tracer); menu_init(session->display.gmenu); while (menu_is_open(session->display.gmenu) == 0) { menu_draw(session->display.gmenu); @@ -52,6 +59,7 @@ void gintrace_handler(struct ucontext *context) } /* if no instruction skip, restore */ + //FIXME: move me if (session->menu.disasm.skip == 0) { spc = context->spc; ubc_set_breakpoint(0, (void*)context->spc, NULL); @@ -62,8 +70,7 @@ void gintrace_handler(struct ucontext *context) spc = breakpoint; } - /* unblock UBC interrupt */ ubc_unblock(); - gint_switch_to_casio(); + gint_switch_to_world(buffctx); } diff --git a/src/ubc/ubc.c b/src/ubc/ubc.c index 932f557..da1db96 100644 --- a/src/ubc/ubc.c +++ b/src/ubc/ubc.c @@ -1,11 +1,16 @@ #include "gintrace/ubc.h" -#include -/* internal saved driver state */ +#include +#include + +/* internal UBC driver information */ struct sh7305_ubc_context ubctx; void (*ubc_handler)(struct ucontext *ctx) = NULL; int ubc_driver_installed = 0; +extern void *kernel_env_gint; +void *kernel_env_tracer = NULL; + /* ubc_install(): Install the UBC driver */ void ubc_install(void) @@ -42,6 +47,10 @@ void ubc_install(void) SH7305_UBC.CBR1.CE = 0; SH7305_UBC.CBCR.UBDE = 1; + /* generate the "tracer" tmp context */ + if (kernel_env_tracer == NULL) + drivers_context_duplicate(&kernel_env_tracer, kernel_env_gint); + /* indicate that the UBC driver is installed */ ubc_driver_installed = 1; }