📄 nlmacc.c
字号:
#ifdef DEBUG_ME
void DumpRegs( msb *m, char *str )
{
if( DebugClasses & (D_THREAD|D_ERROR) ) {
ConsolePrintf( "EAX:%8.8x EBX:%8.8x ECX:%8.8x EDX:%8.8x ESI:%8.8x ESI:%8.8x\r\n",
m->cpu.EAX, m->cpu.EBX, m->cpu.ECX, m->cpu.EDX,
m->cpu.ESI, m->cpu.EDI );
ConsolePrintf( "ESP:%8.8x EBP:%8.8x EIP:%8.8x EFL:%8.8x %s=%8.8x\r\n",
m->cpu.ESP, m->cpu.EBP, m->cpu.EIP, m->cpu.EFL, str, m );
}
}
#else
#define DumpRegs( m, s )
#endif
static void BigKludge( msb *m );
#pragma aux BigKludge parm [ esi ];
static LONG DebugEntry( StackFrame *frame )
{
msb *m;
struct LoadDefinitionStructure *load;
int exception_number;
char *description;
long error_code;
exception_number = FieldExceptionNumber( frame );
description = FieldExceptionDescription( frame );
error_code = FieldErrorCode( frame );
_DBG_EVENT(( "*DebugEntry: Event %d (%s): RunningProcess=%8.8x\r\n",
exception_number, description, RunningProcess ));
if( !ExpectingEvent ) {
_DBG_EVENT(( " Not expecting event\r\n" ));
return( RETURN_TO_NEXT_DEBUGGER );
}
if( DebuggerRunning &&
( ( exception_number == KEYBOARD_BREAK_EVENT )
|| ( exception_number == ENTER_DEBUGGER_EVENT )
|| ( exception_number == KEYBOARD_BREAK_EVENT )
|| ( exception_number == INVALID_INTERRUPT_ABEND )
|| ( exception_number == ASSEMBLY_ABEND ) ) ) {
return( RETURN_TO_NEXT_DEBUGGER );
}
if( exception_number == 1 && !TrapInt1 && !FakeBreak ) {
return( RETURN_TO_NEXT_DEBUGGER ); /* Break set by system debugger */
}
if( exception_number == 2 ) { /* NMI */
if( DebuggerRunning ) {
return( RETURN_TO_NEXT_DEBUGGER );
} else {
FieldEFLAGS( frame ) |= FLG_T;
FakeBreak = TRUE;
return( RETURN_TO_PROGRAM );
}
}
FreeInvalidThreads();
load = (struct LoadDefinitionStructure *)error_code;
switch( exception_number ) {
case START_NLM_EVENT:
/* The NLM is being loaded. We are on the loader thread here */
_DBG_EVENT(( " START_NLM_EVENT: LDS=%x (%s) D_LDS=%x NLMState=%x\r\n",
load, &(load->LDFileName[1]),
DebuggerLoadedNLM, NLMState ));
if( NLMState == NLM_LOADED ) {
m = LocateThread( RunningProcess );
m->load = load;
NewNLMListEntry( load );
_DBG_EVENT(( "MSB=%x NLMState = NLM_LOADED\r\n", m ));
break;
} else if( NLMState == NLM_PRELOADING
&& !DebuggerLoadedNLM
&& memcmp( load->LDFileName, NLMName, NLMName[0] + 1 )
== 0 ) {
m = LocateThread( RunningProcess );
m->description = NULL;
m->load = load;
m->in_start_proc = TRUE;
SavedFirstByte = *(byte *)(m->load->LDInitializationProcedure);
*(byte *)(m->load->LDInitializationProcedure) = 0xCC;
NLMState = NLM_LOADING;
_DBG_EVENT(( "MSB=%x NLMState = NLM_LOADING\r\n", m ));
} else {
_DBG_EVENT(( "NLMState = unknown state\r\n" ));
}
return( RETURN_TO_PROGRAM );
case TERMINATE_NLM_EVENT:
_DBG_EVENT(( " TERMINATE_NLM_EVENT: LDS=%x (%s) D_LDS=%x\r\n",
load, &(load->LDFileName[1]), DebuggerLoadedNLM ));
if( load == DebuggerLoadedNLM ) {
DebuggerLoadedNLM = NULL;
ExpectingEvent = FALSE;
MSB = NULL;
WakeDebugger();
} else {
DeadNLMListEntry( load );
if( DebuggerLoadedNLM != NULL )
break;
}
return( RETURN_TO_PROGRAM );
case START_THREAD_EVENT:
load = GetNLMFromPID( RunningProcess );
_DBG_EVENT(( " START_THREAD_EVENT: LDS=%x (%s) D_LDS=%x\r\n",
load, &(load->LDFileName[1]), DebuggerLoadedNLM ));
m = LocateThread( RunningProcess );
m->load = load;
if( load == DebuggerLoadedNLM ) {
m->clib_created = TRUE;
}
_DBG_EVENT(( "MSB=%x\r\n", m ));
return( RETURN_TO_PROGRAM );
case TERMINATE_THREAD_EVENT:
/* The thread is terminating. Free it's control block and let it die */
load = GetNLMFromPID( RunningProcess ); // returns NULL
_DBG_EVENT(( " TERMINATE_THREAD_EVENT: LDS=%x (%s) D_LDS=%x,\r\n",
load, &(load->LDFileName[1]), DebuggerLoadedNLM ));
m = LocateThread( RunningProcess );
_DBG_EVENT(( "MSB=%x, NLM=%x\r\n", m, m->load ));
FreeThread( m );
return( RETURN_TO_PROGRAM );
case THREAD_BOOBY_TRAP_EVENT:
_DBG_EVENT(( " THREAD_BOOBY_TRAPEVENT:\r\n" ));
#ifdef __NW40__
if( GetFileServerMinorVersionNumber() < 10 ) {
// FieldESP( frame ) += 4; // SignalDebuggerEvent points to return address
}
#endif
case ENTER_DEBUGGER_EVENT:
case KEYBOARD_BREAK_EVENT:
case INVALID_INTERRUPT_ABEND:
case ASSEMBLY_ABEND:
case BREAKPOINT_FUNCTION_EVENT:
m = LocateThread( RunningProcess );
break;
case NLM_FAILED_INIT_EVENT:
_DBG_EVENT(( " NLM_FAILED_INIT_EVENT:\r\n" ));
if( NLMState != NLM_FORCED_INIT_FAILURE ) {
m = LocateThread( RunningProcess );
DebuggerLoadedNLM = NULL;
ExpectingEvent = FALSE;
MSB = NULL;
WakeDebugger();
}
return( RETURN_TO_PROGRAM );
break;
case 3:
m = LocateThread( RunningProcess );
if( NLMState == NLM_LOADING && m->in_start_proc ) {
_DBG_EVENT(( " 3: Helper thread hits initial break\r\n" ));
/* the helper thread hits a break point we set at start procedure */
SaveRegs( HelperThreadRegs );
DebuggerLoadedNLM = m->load;
--(FieldEIP( frame ));
*(byte *)(FieldEIP( frame )) = SavedFirstByte;
NLMState = NLM_IN_START_PROC;
_DBG_EVENT(( " 3: NLMState = NLM_IN_START_PROC\r\n" ));
} else {
--(FieldEIP( frame ));
#if 0
if( !CheckIfBreakOKInOS( FieldEIP( frame ) ) ) {
return( RETURN_TO_NEXT_DEBUGGER );
}
#endif
}
break;
default:
if( exception_number > 31 ) {
return( RETURN_TO_NEXT_DEBUGGER );
}
m = LocateThread( RunningProcess );
#if 0
if( !CheckIfBreakOKInOS( FieldEIP( frame ) ) ) {
return( RETURN_TO_NEXT_DEBUGGER );
}
#endif
break;
}
m->xnum = exception_number;
m->errnum = error_code;
m->description = FieldExceptionDescription( frame );
SaveRegs( m->cpu );
DumpRegs( m, "DebugEntry" );
if( NPX() != X86_NO ) {
Read387( &m->fpu );
}
/*
*
* This requires comment. Netware doesn't allow us to relinquish control
* at interrupt time. This means we have to fake the application into
* returning to the following routine and "becoming" the debugger.
*
*/
_DBG_EVENT(( "DebugEntry: Leaving MSB=%8x xnum=%d PID=%8x\r\n", m, m->xnum, m->os_id ));
FieldESI( frame ) = (LONG)m;
FieldEIP( frame ) = (LONG)&BigKludge;
return( RETURN_TO_PROGRAM );
}
void JumpTo( msb *m )
{
long ax,bx,cx,dx,si,di,bp,sp,fl,ip;
ax = m->cpu.EAX;
bx = m->cpu.EBX;
cx = m->cpu.ECX;
dx = m->cpu.EDX;
si = m->cpu.ESI;
di = m->cpu.EDI;
bp = m->cpu.EBP;
sp = m->cpu.ESP;
fl = m->cpu.EFL;
ip = m->cpu.EIP;
DumpRegs( m, "JumpTo" );
if( m->to_be_killed )
FreeThread( m );
DoALongJumpTo( ax,bx,cx,dx,si,di,bp,sp,fl,ip );
}
void BigKludge( msb *m )
{
_DBG_EVENT(( "*BigKludge: MSB=%8x xnum=%d PID=%8x\r\n", m, m->xnum, m->os_id ));
m->asleep = TRUE;
#if defined ( _USE_NEW_KERNEL )
if( NULL == m->ksem ){
m->ksem = kSemaphoreAlloc( NULL, 0 );
if( NULL == m->ksem ){
_DBG_ERROR(( "*BigKludge: Failed to allocate semaphore\r\n" ));
}
}
#else
if( m->sem == 0 ) {
m->sem = CAllocSemaphore( 0, SemaphoreTag );
}
#endif
if( m->xnum != THREAD_BOOBY_TRAP_EVENT ) {
_DBG_EVENT(( " Waking up the debugger for debug event\r\n" ));
BoobyTrapPID( m->os_id ); /* catch all other threads in NLM */
if( !DebuggerRunning ) {
MSB = m;
}
WakeDebugger();
}
#if defined ( _USE_NEW_KERNEL )
_DBG_THREAD(( "Putting to sleep MSB=%8x on sem=%8x\r\n", m, m->ksem ));
kSemaphoreWait( m->ksem );
#else
_DBG_THREAD(( "Putting to sleep MSB=%8x on sem=%8x\r\n", m, m->sem ));
CPSemaphore( m->sem );
#endif
m->asleep = FALSE;
_DBG_EVENT(( " Waking up as MSB=%8x\r\n", m ));
if( NPX() != X86_NO ) {
Write387( &m->fpu );
}
if( ( m->cpu.EFL & FLG_T ) && m->cpu.EIP == (dword)DebugEntry ) {
/* If we are about to trace through this routine, don't! Ouch! */
m->cpu.EFL &= ~FLG_T;
}
ActivateDebugRegs();
UnBoobyTrapPID( m->os_id );
//_DBG_THREAD(( "Rolling. EIP=%8x, ESP=%8x, Process=%8x\r\n", m->cpu.EIP, m->cpu.ESP, RunningProcess ));
if( m->to_be_killed ) {
if( m->in_start_proc ) {
int newESP;
//_DBG_THREAD(( " Attempting to kill myself!!!\r\n" ));
newESP = m->cpu.ESP;
FreeThread( m );
if( newESP <= HelperThreadRegs.ESP ) {
/* the stack frame has not already gone */
m->cpu = HelperThreadRegs;
ReturnESP = m->cpu.ESP;
m->cpu.EIP = (dword)Return;
m->cpu.EAX = -1;
NLMState = NLM_FORCED_INIT_FAILURE;
_DBG_EVENT(( " NLMState = NLM_FORCED_INIT_FAILURE\r\n" ));
}
} else if( m->clib_created ) {
#if defined ( __NW50__ )
int type = get_app_type();
if( type & LIBRARY_CLIB ) {
_DBG_THREAD(( " Warping off to _exit!!!\r\n" ));
m->cpu.EIP = (dword)_exit;
} else if( type & LIBRARY_LIBC) {
_DBG_THREAD(( " Warping off to NXVMExit!!!\r\n" ));
m->cpu.EIP = (dword)NXVmExit;
} else {
_DBG_THREAD(( " Warping off to suicide!!!\r\n" ));
m->cpu.EIP = (dword)Suicide;
}
#else
_DBG_THREAD(( " Warping off to _exit!!!\r\n" ));
m->cpu.EIP = (dword)_exit;
#endif
} else {
_DBG_THREAD(( " Suicide!!!\r\n" ));
m->cpu.EIP = (dword)Suicide;
}
}
JumpTo( m );
}
#if defined ( __NW50__ ) /* This is duplicate to 4.0 but I want to change soon */
static struct debuggerStructure DbgStruct = {
NULL,
NULL,
(LONG(*)(StackFrame *))DebugEntry,
AT_FIRST,
TSS_FRAME_BIT
};
#elif defined ( __NW40__ )
static struct debuggerStructure DbgStruct = {
NULL,
NULL,
(LONG(*)(StackFrame *))DebugEntry,
AT_FIRST,
TSS_FRAME_BIT
};
#elif defined ( __NW30__ )
static T_DebuggerStruct DbgStruct = {
NULL,
NULL,
DebugEntry
};
#endif
unsigned ReqGet_sys_config( void )
{
get_sys_config_ret *ret;
ret = GetOutPtr(0);
ret->sys.cpu = X86CPUType();
ret->sys.fpu = NPX();
ret->sys.osmajor = FileServerMajorVersionNumber;
ret->sys.osminor = FileServerMinorVersionNumber;
ret->sys.os = OS_NW386;
ret->sys.huge_shift = 12;
ret->sys.mad = MAD_X86;
return( sizeof( *ret ) );
}
unsigned ReqMap_addr( void )
{
nlm_entry *curr;
map_addr_req *acc;
map_addr_ret *ret;
struct LoadDefinitionStructure *ld;
//NYI: needs work for DWARF flat mode
acc = GetInPtr(0);
ret = GetOutPtr(0);
ret->out_addr.segment = acc->in_addr.segment;
ret->out_addr.offset = acc->in_addr.offset;
ret->lo_bound = 0;
ret->hi_bound = 0;
_DBG_MISC(( "AccMapAddr\r\n" ));
curr = (nlm_entry *)acc->handle;
if( curr == NULL ) { // main NLM
_DBG_MISC(( "Main NLM\r\n" ));
if( MSB == NULL )
return( sizeof( *ret ) );
if( MSB->load == NULL )
return( sizeof( *ret ) );
ld = MSB->load;
} else {
ld = &curr->ld;
}
ret->hi_bound = ~(addr48_off)0;
_DBG_MISC(( "Mapping %4x:%8x\r\n", acc->in_addr.segment, acc->in_addr.offset ));
switch( acc->in_addr.segment ) {
case MAP_FLAT_CODE_SELECTOR:
case MAP_FLAT_DATA_SELECTOR:
if( ret->out_addr.offset & NOV_EXP_ISCODE ) {
ret->lo_bound = NOV_EXP_ISCODE;
ret->out_addr.offset &= ~NOV_EXP_ISCODE;
ret->out_addr.offset += ld->LDCodeImageOffset;
} else {
ret->hi_bound = NOV_EXP_ISCODE - 1;
ret->out_addr.offset += ld->LDDataImageOffset;
}
if( acc->in_addr.segment == MAP_FLAT_CODE_SELECTOR ) {
ret->out_addr.segment = GetCS();
} else {
ret->out_addr.segment = GetDS();
}
break;
case 1:
ret->out_addr.offset += ld->LDCodeImageOffset;
ret->out_addr.segment = GetCS();
break;
case 2:
ret->out_addr.offset += ld->LDDataImageOffset;
ret->out_addr.segment = GetDS();
break;
}
_DBG_MISC(( "------ %4x:%8x\r\n", ret->out_addr.segment, ret->out_addr.offset ));
return( sizeof( *ret ) );
}
//obsolete
unsigned ReqAddr_info( void )
{
addr_info_ret *ret;
ret = GetOutPtr( 0 );
ret->is_32 = TRUE;
return( sizeof( *ret ) );
}
unsigned ReqMachine_data( void )
{
machine_data_ret *ret;
unsigned_8 *data;
ret = GetOutPtr( 0 );
data = GetOutPtr( sizeof( *ret ) );
ret->cache_start = 0;
ret->cache_end = ~(addr_off)0;
*data = X86AC_BIG;
return( sizeof( *ret ) + sizeof( *data ) );
}
static int ReadMemory( addr48_ptr *addr, unsigned long req, void *buf )
{
if( MSB == NULL )
return( -1 );
if( CValidatePointer( (char *)addr->offset ) == NULL )
return( -1 );
if( CValidatePointer( (char *)addr->offset+req-1 ) == NULL )
return( -1 );
memcpy( buf, (void *)addr->offset, req );
return( 0 );
}
static int WriteMemory( addr48_ptr *addr, unsigned long req, void *buf )
{
if( MSB == NULL )
return( -1 );
if( CValidatePointer( (char *)addr->offset ) == NULL )
return( -1 );
if( CValidatePointer( (char *)addr->offset+req-1 ) == NULL )
return( -1 );
memcpy( (void *)addr->offset, buf, req );
return( 0 );
}
static unsigned short ReadWrite( int (*rtn)(), addr48_ptr *addr,
char *buff, unsigned short requested )
{
int err;
unsigned short len;
err = rtn( addr, (unsigned long)requested, buff );
if( err == 0 ) {
addr->offset += requested;
return( requested );
}
len = requested;
while( len != 0 ) {
if( rtn( addr, 1UL, buff++ ) != 0 )
break;
--len;
addr->offset++;
}
return( requested - len );
}
unsigned ReqChecksum_mem( void )
{
unsigned short len;
addr48_ptr addr;
int i;
checksum_mem_req *acc;
checksum_mem_ret *ret;
long want;
long got;
acc = GetInPtr(0);
ret = GetOutPtr(0);
len = acc->len;
addr.offset = acc->in_addr.offset;
addr.segment = acc->in_addr.segment;
ret->result = 0;
while( len > 0 ) {
want = len;
if( want > BUFF_SIZE )
want = BUFF_SIZE;
got = ReadWrite( ReadMemory, &addr, UtilBuff, want );
for( i = 0; i < got; ++i ) {
ret->result += UtilBuff[ i ];
}
if( got != want )
break;
len -= want;
}
return( sizeof( *ret ) );
}
unsigned ReqRead_mem( void )
{
addr48_ptr addr;
read_mem_req *acc;
unsigned len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -