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:
Yatis 2021-03-13 22:27:32 +01:00
parent ef933ff508
commit c2b41bbbd0
9 changed files with 106 additions and 31 deletions

View File

@ -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");

Binary file not shown.

View File

@ -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);

View File

@ -30,6 +30,10 @@ struct callgraph {
} cursor;
struct callnode *root;
struct callnode *parent;
struct {
uintptr_t breakpoint;
uintptr_t spc;
} special;
};
/* extern menu information */

View File

@ -17,6 +17,7 @@ struct tsession {
void *starting;
void *removed;
struct ucontext *context;
void *buffctx;
} info;
/* display information */

Binary file not shown.

View File

@ -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)
{

View File

@ -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,
}
};

View File

@ -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);
}