Gintracer v0.8.2 - Special constructors / destructors
@update <> move the drivers' context into the trace session <> add "special" constructor for a "pre-initialisation", usefull to move the callgraph generation into its specific menu part. @fix <> when the TRACER_CALLGRAPH is not set, the callgraph was always generated. (fixed)
This commit is contained in:
parent
ef933ff508
commit
c2b41bbbd0
|
@ -44,7 +44,7 @@ int main(void)
|
|||
|
||||
/* prepare tracer */
|
||||
session = tracer_create_session(syscall,
|
||||
TRACER_DISASM | TRACER_CONTEXT | TRACER_HEXDUMP);
|
||||
TRACER_DISASM | TRACER_CONTEXT | TRACER_HEXDUMP | TRACER_CALLGRAPH);
|
||||
if (session == NULL) {
|
||||
dclear(C_WHITE);
|
||||
dtext(0, 0, C_BLACK, "Unable to create tracer session");
|
||||
|
|
BIN
gintrace.g3a
BIN
gintrace.g3a
Binary file not shown.
|
@ -14,6 +14,11 @@ struct menu {
|
|||
int (*keyboard)(void *data, int key);
|
||||
void (*command)(void *data, int argc, char **argv);
|
||||
void (*dtor)(void *data);
|
||||
|
||||
struct {
|
||||
int (*ctor)(void *data);
|
||||
int (*dtor)(void *data);
|
||||
} special;
|
||||
};
|
||||
|
||||
/* menu group information */
|
||||
|
@ -55,6 +60,11 @@ extern int menu_unregister(struct menu_group *gmenus, const char *name);
|
|||
/* menu_is_open(): Return the menu status */
|
||||
extern int menu_is_open(struct menu_group *gmenu);
|
||||
|
||||
/* menu_special_ctor(): Involve special contructor */
|
||||
extern int menu_special_ctor(struct menu_group *gmenu);
|
||||
/* menu_special_dtor(): Involve special destructor */
|
||||
extern int menu_special_dtor(struct menu_group *gmenu);
|
||||
|
||||
/* menu_init(): Initialize all menu */
|
||||
extern int menu_init(struct menu_group *gmenus);
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@ struct callgraph {
|
|||
} cursor;
|
||||
struct callnode *root;
|
||||
struct callnode *parent;
|
||||
struct {
|
||||
uintptr_t breakpoint;
|
||||
uintptr_t spc;
|
||||
} special;
|
||||
};
|
||||
|
||||
/* extern menu information */
|
||||
|
|
|
@ -17,6 +17,7 @@ struct tsession {
|
|||
void *starting;
|
||||
void *removed;
|
||||
struct ucontext *context;
|
||||
void *buffctx;
|
||||
} info;
|
||||
|
||||
/* display information */
|
||||
|
|
BIN
libgintrace-cg.a
BIN
libgintrace-cg.a
Binary file not shown.
|
@ -71,6 +71,41 @@ int menu_unregister(struct menu_group *gmenu, const char *name)
|
|||
return (menu_retval_unregistered);
|
||||
}
|
||||
|
||||
/* menu_special_ctor(): Involve special contructor */
|
||||
int menu_special_ctor(struct menu_group *gmenu)
|
||||
{
|
||||
struct menu_list *node;
|
||||
int a;
|
||||
|
||||
if (gmenu == NULL)
|
||||
return (menu_retval_efault);
|
||||
a = 0;
|
||||
node = gmenu->list;
|
||||
while (node != NULL) {
|
||||
if (node->menu != NULL && node->menu->special.ctor != NULL)
|
||||
a += node->menu->special.ctor((void*)gmenu->arg);
|
||||
node = node->next;
|
||||
}
|
||||
return (a);
|
||||
}
|
||||
/* menu_special_ctor(): Involve special contructor */
|
||||
int menu_special_dtor(struct menu_group *gmenu)
|
||||
{
|
||||
struct menu_list *node;
|
||||
int a;
|
||||
|
||||
if (gmenu == NULL)
|
||||
return (menu_retval_efault);
|
||||
a = 0;
|
||||
node = gmenu->list;
|
||||
while (node != NULL) {
|
||||
if (node->menu != NULL && node->menu->special.dtor != NULL)
|
||||
a += node->menu->special.dtor((void*)gmenu->arg);
|
||||
node = node->next;
|
||||
}
|
||||
return (a);
|
||||
}
|
||||
|
||||
/* menu_init(): Initialize all menu */
|
||||
int menu_init(struct menu_group *gmenu)
|
||||
{
|
||||
|
|
|
@ -379,6 +379,42 @@ static void callgraph_command(struct tsession *session, int argc, char **argv)
|
|||
input_write("success");
|
||||
}
|
||||
|
||||
/* callgraph_special_ctor(): Special constructor used to generate the graph */
|
||||
static int callgraph_special_ctor(struct tsession *session)
|
||||
{
|
||||
struct callgraph *callgraph = &session->menu.callgraph;
|
||||
|
||||
if (callgraph->special.breakpoint != 0x00000000
|
||||
&& callgraph->special.spc != 0x00000000
|
||||
&& callgraph->special.spc != callgraph->special.breakpoint) {
|
||||
callgraph_init(session);
|
||||
callgraph->special.spc = session->info.context->spc;
|
||||
ubc_set_breakpoint(0, (void*)callgraph->special.spc, NULL);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* callgraph_special_dtor(): Special destructor used to bypass the breakpoint*/
|
||||
//TODO: update, bad interconnection with the disasm menu :(
|
||||
static int callgraph_special_dtor(struct tsession *session)
|
||||
{
|
||||
struct callgraph *callgraph = &session->menu.callgraph;
|
||||
uintptr_t breakpoint;
|
||||
|
||||
breakpoint = session->menu.disasm.next_break;
|
||||
if (session->menu.disasm.skip == 0) {
|
||||
callgraph->special.spc = session->info.context->spc;
|
||||
ubc_set_breakpoint(0, (void*)callgraph->special.spc, NULL);
|
||||
callgraph->special.breakpoint = breakpoint;
|
||||
} else {
|
||||
callgraph->special.breakpoint = breakpoint;
|
||||
ubc_set_breakpoint(0, (void*)breakpoint, NULL);
|
||||
callgraph->special.spc = breakpoint;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
//---
|
||||
// Define the menu
|
||||
//---
|
||||
|
@ -388,5 +424,10 @@ struct menu menu_callgraph = {
|
|||
.display = (void*)&callgraph_display,
|
||||
.keyboard = (void*)&callgraph_keyboard,
|
||||
.command = (void*)&callgraph_command,
|
||||
.dtor = NULL
|
||||
.dtor = NULL,
|
||||
|
||||
.special = {
|
||||
.ctor = (void*)&callgraph_special_ctor,
|
||||
.dtor = (void*)&callgraph_special_dtor,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,10 +6,7 @@
|
|||
#include "gintrace/ubc.h"
|
||||
#include "gintrace/tracer.h"
|
||||
|
||||
#include <gint/gint.h>
|
||||
|
||||
// custom function
|
||||
extern void *kernel_env_gint;
|
||||
/* world information */
|
||||
extern void *kernel_env_tracer;
|
||||
extern void *gint_switch_to_world(void *buffctx);
|
||||
|
||||
|
@ -18,14 +15,9 @@ extern void *gint_switch_to_world(void *buffctx);
|
|||
* To force generate the callgraph, we use a dirty workaround to force break
|
||||
* at each instruction. But, the disassembler menu can skip one instruction
|
||||
* using OPTN key, so you should not "unskip" the user action. */
|
||||
//FIXME: move breakpoint
|
||||
//FIXME: move spc
|
||||
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();
|
||||
|
@ -38,39 +30,31 @@ void gintrace_handler(struct ucontext *context)
|
|||
}
|
||||
session->info.context = context;
|
||||
|
||||
/* check callgraph job */
|
||||
//FIXME: move me
|
||||
if (breakpoint != 0x00000000
|
||||
&& spc != 0x00000000
|
||||
&& spc != breakpoint) {
|
||||
menu_callgraph.init(session);
|
||||
spc = context->spc;
|
||||
ubc_set_breakpoint(0, (void*)context->spc, NULL);
|
||||
/* check if the special job force skip the breakpoint
|
||||
* @note:
|
||||
* This feature is used by the callgraph menu to force the call graph
|
||||
* generation.*/
|
||||
if (menu_special_ctor(session->display.gmenu) != 0) {
|
||||
ubc_unblock();
|
||||
return;
|
||||
}
|
||||
|
||||
/* user break point */
|
||||
buffctx = gint_switch_to_world(kernel_env_tracer);
|
||||
session->info.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);
|
||||
menu_keyboard(session->display.gmenu);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
breakpoint = session->menu.disasm.next_break;
|
||||
} else {
|
||||
breakpoint = session->menu.disasm.next_break;
|
||||
ubc_set_breakpoint(0, (void*)breakpoint, NULL);
|
||||
spc = breakpoint;
|
||||
/* check if a special destructor overwrite the default breakpoint
|
||||
* generation. If not, set the next break point. */
|
||||
if (menu_special_dtor(session->display.gmenu) == 0) {
|
||||
ubc_set_breakpoint(0,
|
||||
(void*)session->menu.disasm.next_break, NULL);
|
||||
}
|
||||
|
||||
/* unblock UBC interrupt */
|
||||
ubc_unblock();
|
||||
gint_switch_to_world(buffctx);
|
||||
gint_switch_to_world(session->info.buffctx);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue