📄 nlmacc.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Low-level Netware implementation code for the debugger trap.
*
****************************************************************************/
#include "debugme.h"
#include <stddef.h>
#include <string.h> /* may only call functions defined in nlmstrt.c */
#include <fcntl.h>
#include <stdio.h>
#include <nwtypes.h>
#include "miniproc.h"
#include "loader.h"
//#include "nlmheadr.h"
#if !defined ( _USE_NEW_KERNEL )
#include "nwsemaph.h"
#endif
#include "debugapi.h"
#undef TRUE
#undef FALSE
#include "dbg386.h"
#include "trpimp.h"
#include "trperr.h"
#include "packet.h"
#include "exenov.h"
#include "madregs.h"
#include "nlmport.h"
#include "nw3to4.h"
#include "x86cpu.h"
#include "misc7386.h"
#define NO_DREG ((byte)-1)
#define NUM_DREG 4
#define FLG_T 0x0100UL
typedef LONG pPID;
#if defined ( _USE_NEW_KERNEL )
void * kSemaphoreAlloc( const char *, long );
unsigned long kSemaphoreExamineCount( void *sp );
int kSemaphoreFree( void *sp );
int kSemaphoreWait( void *sp );
int kSemaphoreTimedWait( void *sp, unsigned long ms);
int kSemaphoreSignal( void *sp );
int kSemaphoreTry( void *sp );
int kSemaphoreValidate( void *sp );
int kGetSemaphoreInfo( void *sp, char *name, size_t nameMax,
unsigned long *count, int *waitingThreads, void *owner );
// R.E.
int kSemaphoreSignalAll( void *sp );
#endif
struct {
dword address;
byte type;
byte size;
} DR[ NUM_DREG ];
typedef struct msb {
struct msb *next;
struct LoadDefinitionStructure *load;
pPID os_id;
dword dbg_id;
dword xnum;
dword errnum;
trap_cpu_regs cpu;
trap_fpu_regs fpu;
#if defined ( _USE_NEW_KERNEL )
void * ksem;
void * tksem;
#else
dword sem;
#endif
char *description;
unsigned asleep:1;/* sleeping on our semaphore */
unsigned frozen:1;/* allowed to execute? */
unsigned in_start_proc:1;/* our helper thread! */
unsigned clib_created:1;/* created by CLIB*/
unsigned to_be_killed:1;/* condemned */
int exception_number;
} msb;
typedef enum {
NLM_NONE,
NLM_PRELOADING,
NLM_LOADING,
NLM_IN_START_PROC,
NLM_FORCED_INIT_FAILURE,
NLM_LOADED,
} nlmstate;
typedef struct nlm_entry {
struct nlm_entry *next;
struct LoadDefinitionStructure ld;
bool is_load;
} nlm_entry;
static unsigned_8 RealNPXType;
nlmstate NLMState;
#define BUFF_SIZE 256
char CmdLine[BUFF_SIZE];
char NLMName[14];
char UtilBuff[BUFF_SIZE];
msb *MSB;
msb *MSBHead;
trap_cpu_regs HelperThreadRegs;
dword ThreadId;
#if defined ( _USE_NEW_KERNEL )
void * kDebugSem = NULL;
void * kHelperSem = NULL;
#else
dword DebugSem = 0;
dword HelperSem = 0;
#endif
struct LoadDefinitionStructure *DebuggerLoadedNLM = NULL;
nlm_entry *NLMList = NULL;
nlm_entry *LastNLMListEntry = NULL;
bool FakeBreak;
bool DebuggerRunning;
bool ExpectingEvent;
bool TrapInt1;
byte SavedFirstByte;
dword DebugProcess;
byte DebugPriority;
byte RunningPriority;
/* from MYPRELUD.C */
extern struct ResourceTagStructure *AllocTag;
extern struct ResourceTagStructure *SemaphoreTag;
extern struct ResourceTagStructure *ProcessTag;
extern void ServMessage(char*);
/* from NLMIO.C */
extern int IOCreat( char *name );
extern int IOOpen( char *openname, int openmode );
extern int IOClose( int closehandle );
extern int IOWrite( int writehandle, char *buff, int buff_len );
extern int IOWriteConsole( char *buff, int buff_len );
extern int IOSeek( int seekhandle, int seekmode, long seekpos );
extern int IORead( int readhandle, char *buff, int len );
extern void StringToNLMPath( char *name, char *res );
/* from NLMINTR.ASM */
extern void DoALongJumpTo( unsigned_32, unsigned_32, unsigned_32, unsigned_32, unsigned_32, unsigned_32, unsigned_32, unsigned_32, unsigned_32, unsigned_32 );
dword ReturnESP;
extern void Return( void );
extern int AdjustStack( dword old_esp, dword adjust );
extern word GetDS( void );
extern word GetCS( void );
/* from NLMCLIB.C */
extern struct LoadDefinitionStructure *GetNLMFromPID(pPID);
extern void BoobyTrapPID(pPID);
extern void UnBoobyTrapPID(pPID);
extern char *GetPIDName(pPID);
extern int ValidatePID(pPID);
extern void SetupPIDForACleanExit(pPID);
#if defined ( __NW40__ )
extern int ImportCLIBSymbols( void );
#endif
/* Must be CLIB! */
void _exit( int __status );
#if defined ( __NW50__ )
void NXVmExit( int status ) ;
int get_app_type ( void );
/* return flags for get_app_type()... */
#define LIBRARY_UNKNOWN 0x01 /* thread has default library context */
#define LIBRARY_LIBC 0x02 /* thread has specific NKS/LibC context */
#define LIBRARY_CLIB 0x04 /* thread has CLib context */
#define LIBRARY_JAVA 0x08 /* thread belongs to Java Virtual Machine */
#endif
/* from SERVNAME.C */
extern char ServPref[];
typedef struct watch {
addr48_ptr addr;
dword value;
dword linear;
short dregs;
short len;
} watch;
#define MAX_WP 32
watch WatchPoints[ MAX_WP ];
int WatchCount;
/*
// Code to release all waiters on a semaphore and delete it
*/
#if defined ( _USE_NEW_KERNEL )
int msb_KernelSemaphoreReleaseAll( msb * m )
{
void * ksem = m->ksem;
m->ksem = NULL;
m->tksem = ksem;
return( kSemaphoreSignalAll( ksem ) );
}
int KernelSemaphoreReleaseAll( void * sp )
{
kSemaphoreSignalAll( sp );
return ( kSemaphoreFree( sp ) );
}
#endif
void NewNLMListEntry( struct LoadDefinitionStructure *ld )
{
nlm_entry *new;
new = Alloc( sizeof( *new ), AllocTag );
new->next = NLMList;
new->ld = *ld;
new->is_load = TRUE;
NLMList = new;
// _DBG_EVENT(( "NewNLMListEntry: %8x %s\r\n", ld, &(ld->LDFileName[1]) ));
}
void DeadNLMListEntry( struct LoadDefinitionStructure *ld )
{
nlm_entry *curr;
for( curr = NLMList; curr != NULL; curr = curr->next ) {
if( !curr->is_load )
continue;
if( curr->ld.LDCodeImageOffset != ld->LDCodeImageOffset )
continue;
curr->is_load = FALSE;
// _DBG_EVENT(( "DeadNLMListEntry: %8x %s\r\n", ld, &(ld->LDFileName[1]) ));
break;
}
}
void FreeAnNLMListEntry( void )
{
nlm_entry *junk;
junk = NLMList;
NLMList = NLMList->next;
Free( junk );
}
msb *LocateThread( pPID pid )
{
msb *m;
m = MSBHead;
_DBG_THREAD(( "Looking for MSB for thread=%8x -- \r\n", pid ));
while( m != NULL ) {
if( m->os_id == pid ) {
_DBG_THREAD(( "Found MSB=%8x TID=%d\r\n", m, m->dbg_id ));
return( m );
}
m = m->next;
}
m = Alloc( sizeof( msb ), AllocTag );
if( NULL == m ){
_DBG_ERROR(( "LocateThread: Failed to allocate msb block\r\n" ));
return NULL;
}
m->description = NULL;
m->load = NULL;
m->os_id = pid;
m->dbg_id = ++ThreadId;
m->asleep = FALSE;
m->frozen = FALSE;
m->in_start_proc = FALSE;
m->clib_created = FALSE;
m->to_be_killed = FALSE;
#if defined ( _USE_NEW_KERNEL )
m->ksem = NULL;
m->tksem = NULL;
#else
m->sem = 0;
#endif
m->next = MSBHead;
//_DBG_THREAD(( "Allocating MSB=%8x TID=%d\r\n", m, m->dbg_id ));
MSBHead = m;
return( m );
}
void FreeThread( msb *m )
{
msb **owner;
msb *curr;
_DBG_THREAD(( "Trying to free thread MSB=%8x -- \r\n", m ));
owner = &MSBHead;
for( ;; ) {
curr = *owner;
if( curr == NULL )
return;
if( curr == m ) {
*owner = curr->next;
_DBG_THREAD(( "Freed it\r\n" ));
#if defined ( _USE_NEW_KERNEL )
if( m->ksem){
kSemaphoreFree( m->ksem );
m->ksem = NULL;
}
#else
if( m->sem )
CDeAllocateSemaphore( m->sem );
#endif
Free( m );
_DBG_THREAD(( "\r\n" ));
return;
}
owner = &(curr->next);
}
}
void FreeInvalidThreads( void )
{
msb **owner;
msb *curr;
owner = &MSBHead;
for( ;; ) {
curr = *owner;
if( curr == NULL )
return;
if( !ValidatePID( curr->os_id ) ) {
*owner = curr->next; /* remove MSB from chain */
#if defined ( _USE_NEW_KERNEL )
if( curr->ksem ){
kSemaphoreFree( curr->ksem );
curr->ksem = NULL;
}
#else
if( curr->sem )
CDeAllocateSemaphore( curr->sem );
#endif
//owner = &(curr->next);
owner = &MSBHead; /* start from the begiining again */
Free( curr ); /* free MSB */
} else {
owner = &(curr->next);
}
}
}
void Suicide( void )
{
CDestroyProcess( CGetMyProcessID() );
}
void TheBigSleep( void )
{
while( TRUE ) {
CSleepUntilInterrupt();
}
}
void WakeDebugger( void )
{
if( !DebuggerRunning ) {
ClearDebugRegs();
DebuggerRunning = TRUE;
#if defined ( _USE_NEW_KERNEL )
kSemaphoreSignal( kDebugSem );
#else
CVSemaphore( DebugSem );
#endif
}
}
void SleepDebugger( void )
{
DebuggerRunning = FALSE;
#if defined ( _USE_NEW_KERNEL )
kSemaphoreWait( kDebugSem );
#else
CPSemaphore( DebugSem );
#endif
DebuggerRunning = TRUE;
}
#if 0
bool IsInOSCode( LONG eip )
{
LoadedListHandle loadhandle;
struct LoadDefinitionStructure *loaded;
for( loadhandle = GetNextLoadedListEntry( 0 );
loadhandle != 0; loadhandle = GetNextLoadedListEntry( loadhandle ) ) {
loaded = ValidateModuleHandle( loadhandle );
if( eip >= loaded->LDCodeImageOffset
&& eip < loaded->LDCodeImageOffset + loaded->LDCodeImageLength ) {
return( FALSE );
}
}
if( DebuggerLoadedNLM ) { /* might not be on the LoadedList yet */
if( eip >= DebuggerLoadedNLM->LDCodeImageOffset
&& eip < DebuggerLoadedNLM->LDCodeImageOffset
+ DebuggerLoadedNLM->LDCodeImageLength ) {
return( FALSE );
}
}
return( TRUE );
}
bool CheckIfBreakOKInOS( LONG eip )
{
if( !IsInOSCode( eip ) )
return( TRUE );
ServMessage( TRP_NLM_cant_debug_os );
return( FALSE );
}
#endif
unsigned_8 NPX( void )
{
if( HAVE_EMU == 0 )
return( RealNPXType );
#if defined ( __NW50__ ) || defined ( __NW40__ )
return( X86_EMU );
#elif defined ( __NW30__ )
{
struct ExternalPublicDefinitionStructure *epd;
#define EMU_NAME "__init_387_emulator"
#define EMU_LEN ( sizeof( EMU_NAME ) - 1 )
for( epd = ExternalPublicList; epd != NULL; epd = epd->EPDLink ) {
if( epd->EPDName[0] == EMU_LEN ) {
if( memcmp( EMU_NAME, &epd->EPDName[1], EMU_LEN ) == 0 ) {
return( X86_EMU );
}
}
}
return( RealNPXType );
}
#endif
}
#define SaveRegs( reg_struct ) \
reg_struct.EAX = FieldEAX( frame ); \
reg_struct.EBX = FieldEBX( frame ); \
reg_struct.ECX = FieldECX( frame ); \
reg_struct.EDX = FieldEDX( frame ); \
reg_struct.ESI = FieldESI( frame ); \
reg_struct.EDI = FieldEDI( frame ); \
reg_struct.EBP = FieldEBP( frame ); \
reg_struct.ESP = FieldESP( frame ); \
reg_struct.EIP = FieldEIP( frame ); \
reg_struct.EFL = FieldEFLAGS( frame ); \
reg_struct.CS = FieldCS( frame ); \
reg_struct.DS = FieldDS( frame ); \
reg_struct.ES = FieldES( frame ); \
reg_struct.SS = FieldDS( frame ); \
reg_struct.FS = FieldFS( frame ); \
reg_struct.GS = FieldGS( frame );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -