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 d59a78a..4a392eb 100644 Binary files a/gintrace.g3a and b/gintrace.g3a differ diff --git a/include/gintrace/tracer.h b/include/gintrace/tracer.h index 8594440..6581020 100644 --- a/include/gintrace/tracer.h +++ b/include/gintrace/tracer.h @@ -15,6 +15,7 @@ struct tsession { /* session information */ struct { void *starting; + void *removed; struct ucontext *context; } info; diff --git a/libgintrace-cg.a b/libgintrace-cg.a index f9905a7..5666350 100644 Binary files a/libgintrace-cg.a and b/libgintrace-cg.a differ diff --git a/src/gint.c b/src/gint.c index c910fcc..f2dc2d1 100644 --- a/src/gint.c +++ b/src/gint.c @@ -4,44 +4,54 @@ #include #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; }