gintrace/src/ubc/handler.c

59 lines
1.6 KiB
C

#include "gintrace/gui/menu.h"
#include "gintrace/menu/disasm.h"
#include "gintrace/menu/context.h"
#include "gintrace/menu/hexdump.h"
#include "gintrace/menu/callgraph.h"
#include "gintrace/ubc.h"
#include "gintrace/tracer.h"
#include <gint/drivers.h>
/* gintrac_handler(): UBC handler
* @note:
* 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. */
void gintrace_handler(struct ucontext *context)
{
struct tsession *session;
/* force disable the UBC to avoid error */
ubc_block();
/* check session validity */
session = tracer_get_session();
if (session == NULL) {
ubc_unblock();
return;
}
session->info.context = context;
/* 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 */
gint_world_switch_in(gint_world_os, gint_world_addin);
menu_init(session->display.gmenu);
while (menu_is_open(session->display.gmenu) == 0) {
menu_draw(session->display.gmenu);
menu_keyboard(session->display.gmenu);
}
/* 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_world_switch_out(gint_world_addin, gint_world_os);
}