59 lines
1.6 KiB
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);
|
|
}
|