void debugger_cleanup( void ) { if( !nub_inited ) return; if( sv.dbg_attached ) send_dgram( sv.sock, kMDG_disconnect ); if( sv.sock_listen > 0 ) { delete_async_handler( sv.async_listener_id ); close( sv.sock_listen ); } close_sock(); sv.sock = sv.sock_listen = -1; unlink( socket_name ); free( socket_name ); if( debugger_enabled() ) breakpoints_cleanup(); while( sv.cmd_root ) { cmd_entry_t *ce = sv.cmd_root; sv.cmd_root = ce->next; free(ce); } nub_inited = 0; }
static DECL_SYMBOL_ACTION(emulate_debugger_enable) { if (task == csa_READ) { if (iter) return 0; command_arg_set_num(SYM_ARG_1st, debugger_enabled()); } else { int val; command_arg_get_num(SYM_ARG_1st, &val); debugger_enable(val); } return 1; }
void debugger_init( void ) { struct sockaddr_un addr; /* only enable the debugger nub when it is explicitely requested by the user */ if( !debugger_enabled() ) return; printm("Debugger nub enabled\n"); sv.sock = -1; /* create a unix socket for the debugger */ socket_name = molsocket_name(); /* malloced */ unlink( socket_name ); if( (sv.sock_listen=socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) fatal_err("socket"); addr.sun_family = AF_UNIX; strcpy( addr.sun_path, socket_name ); if( bind(sv.sock_listen, (struct sockaddr*)&addr, sizeof(addr)) < 0 ) fatal_err("bind"); if( listen(sv.sock_listen, 2) < 0 ) fatal_err("listen"); sv.hup_count = 0; sv.async_listener_id = add_async_handler( sv.sock_listen, POLLIN, nub_rcv_connection, 1 /* SIGIO */ ); /* initialize debugger */ nub_inited = 1; if( debugger_enabled() ) { breakpoints_init(); add_mmu_cmds(); } set_print_hook( debugger_print ); }
void add_cmd( const char *cmdname, const char *help, int dummy, dbg_cmd_fp func ) { cmd_entry_t *ce; if( !debugger_enabled() ) return; assert( nub_inited ); ce = malloc( sizeof(cmd_entry_t) ); ce->cmdname = cmdname; ce->help = help; ce->func = func; ce->next = sv.cmd_root; sv.cmd_root = ce; }
static int rvec_unexpected_mmu_cond( int rvec, int param1, int param2 ) { switch( rvec ) { case RVEC_UNUSUAL_DSISR_BITS: /* dar, dsisr */ printm("RVEC_UNUSUAL_DSISR_BITS: dar %08X, dsisr %08X\n", param1, param2 ); break; case RVEC_MMU_IO_SEG_ACCESS: printm("RVEC_MMU_IO_SEG_ACCESS\n"); break; case RVEC_BAD_NIP: /* nip_phys */ printm("Instruction Pointer not in ROM/RAM (nip %08lX, nip_phys %08X)\n", mregs->nip, param1 ); if( !debugger_enabled() ) quit_emulation(); stop_emulation(); break; default: printm("rvec_unexpected_mmu_cond, unimplemented vector %d\n", rvec ); break; } return 0; }
/* when the engine is not running, events are polled */ void debugger_nub_poll( void ) { struct pollfd ufds[2]; int n=1; if( !debugger_enabled() ) return; ufds[0].fd = sv.sock_listen; ufds[0].events = POLLIN; if( sv.sock != -1 ) { n++; ufds[1].fd = sv.sock; ufds[1].events = POLLHUP | POLLIN; } if( poll(ufds, n, 0) > 0 ) { if( n>1 && ufds[1].revents ) nub_rcv( sv.sock, ufds[1].revents ); if( ufds[0].revents ) nub_rcv_connection( sv.sock_listen, ufds[0].revents ); } }
static int osip_prom_iface( int sel, int *args ) { int len, ph = args[1]; mol_device_node_t *dn; char *p, *buf; char tmpbuf[256]; unsigned char *pdata; if( args[0] == kPromClose ) { if( !debugger_enabled() ) promif_cleanup(); return 0; } if( !(dn=to_dn(ph)) && (args[0] != kPromPeer || ph) ) return -1; switch( args[0] ) { case kPromPeer: if( !ph ) return to_ph( prom_get_root() ); return dn ? to_ph( dn->sibling ) : -1; case kPromChild: return to_ph( dn->child ); case kPromParent: return to_ph( dn->parent ); case kPromPackageToPath: /* ph, buf, size */ if( !(p=transl_mphys(args[2])) ) return -1; strncpy( p, get_full_name(dn,tmpbuf,sizeof(tmpbuf)), args[3] ); return strlen( tmpbuf ); case kPromGetPropLen: /* ph, name */ if( !(p=transl_mphys(args[2])) ) return -1; return prom_get_property(dn, p, &len) ? len : -1; case kPromGetProp: /* ph, name, buf, size */ p = transl_mphys( args[2] ); buf = transl_mphys( args[3] ); if( !p || !buf ) return -1; if( !(pdata=prom_get_property(dn, p, &len)) || args[4] < 0 ) return -1; memcpy( buf, pdata, MIN(len,args[4]) ); return len; case kPromNextProp: /* ph, prev, buf */ p = transl_mphys( args[2] ); buf = transl_mphys( args[3] ); if( !p || !buf ) return -1; if( !(p=prom_next_property(dn, p)) ) return 0; strcpy( buf, p ); return 1; case kPromSetProp: /* ph, name, buf, len */ p = transl_mphys( args[2] ); buf = transl_mphys( args[3] ); if( !p || !buf || args[4] < 0 ) return -1; if( args[4] > 0x1000 ) { printm("kPromSetProp: limit exceeded\n"); return -1; } prom_add_property( dn, p, buf, args[4] ); return args[4]; case kPromChangePHandle: /* old_ph, new_ph */ if( !prom_phandle_to_dn(args[2]) ) dn->node = (void*)args[2]; else if( dn->node != (void*)args[2] ) { printm("duplicate phandle\n"); return -1; } return 0; default: printm("bad selector\n"); return -1; } return -1; }