/* * SetDebugInterrupts32 * * called to setup for 32-bit interrupts (by debugger or Dr. WATCOM) * * - check for WDEBUG.386 (can't work without it!) * - stomp the IDT for INT1 and INT3. What actually happens is that * WDEBUG.386 stomps the IDT to point at its own routine in the 32-bit * world. This routine sets some internal state so that it knows * that an int1/3 occurred, and then calls the 16-bit routine that * we provide using HookIDT. This routine must cause some fault, * (in our case, we cause an illegal instruction fault), which then * causes us to go through the normal fault handling. * NOTE: after a int1/3 occurs, the WDEBUG.386 restores the IDT back * to normal. Thus, when you wish to start handling int1/int3's again, * the IDT must be reset to our handler (DoneWithInterrupt does this) * * - register our interrupt callback routine with WDEBUG.386. This routine * is invoked whenever a 32-bit fault occurs. The routine runs on a * stack that we specify. WDEBUG.386 copies the register information * into the provided structure (&SaveEAX) before it invokes the callback * routine. NOTE: "invoking" the callback routine really means that * WDEBUG.386 changes the registers of the Windows VM such that the * next time it runs, it begins execution at the callback routine. * No actual calls occur. */ int FAR PASCAL SetDebugInterrupts32( void ) { SetCount++; if( SetCount > 1 ) { return( 1 ); } if( CheckWin386Debug() != WGOD_VERSION ) { return( 0 ); } DPL = (GetCS() & 0x03) << 5; OurOwnInt = false; /* * set up our IDT */ GetIDTSel(); IDTInit( IDTSel ); HookIDT( ReflectInt1Int3 ); InterruptStackSel = FP_SEG( IStack ); InterruptStackOff = (DWORD) (FP_OFF( IStack ) + MAX_ISTACK-16); /* * set up to be notified of faults by wgod */ RegisterInterruptCallback( (LPVOID) InterruptCallback, (LPVOID) &SaveEAX, (LPVOID) &IStack[MAX_ISTACK-16] ); return( 1 ); } /* SetDebugInterrupts32 */
void CodeLoad( struct LoadDefinitionStructure *loaded, samp_block_kinds kind ) { seg_offset ovl_tbl; char buff[256]; ovl_tbl.segment = 0; ovl_tbl.offset = 0; memcpy( buff, loaded->LDFileName + 1, loaded->LDFileName[0] ); buff[loaded->LDFileName[0]] = '\0'; WriteCodeLoad( ovl_tbl, buff, kind ); WriteAddrMap( 1, GetCS(), loaded->LDCodeImageOffset ); }
void StartTimer( void ) { TimerMod = TimerMult; old_timer_handler = HookTimer( MK_FP( GetCS(), (int)&timer_handler ) ); /* // Only access the clock if we have overridden the default */ if(DEF_MULT != TimerMult) { outp( TIMER0, DIVISOR & 0xff ); outp( TIMER0, DIVISOR >> 8 ); }
// this definition needs to occur after __OS2MainInit() so that // the #undef of _STACKLOW doesn't break things void __OS2Init( int is_dll, thread_data *tdata ) /**********************************************/ { sys_info _sysinfo; __Is_DLL = is_dll; __FirstThreadData = tdata; DosQuerySysInfo( QSV_VERSION_MAJOR, QSV_VERSION_MINOR, &_sysinfo, sizeof( sys_info ) ); _RWD_osmajor = _sysinfo.version_major; _RWD_osminor = _sysinfo.version_minor; __saved_CS = GetCS(); #ifndef __SW_BM #undef _STACKLOW _STACKLOW = (unsigned)&_end; // cortns in F77 #endif }
trap_retval ReqProg_load( void ) { prog_load_ret *ret; _DBG(("We're in AccLoadProg")); GetSysRegs( &SysRegs ); ret = GetOutPtr( 0 ); ret->err = 0; ret->flags = LD_FLAG_IS_BIG | LD_FLAG_IS_PROT | LD_FLAG_IS_STARTED | LD_FLAG_DISPLAY_DAMAGED; ret->task_id = 4; ret->mod_handle = 0; Regs.DS = Regs.ES = Regs.FS = Regs.GS = GetDS(); Regs.SS = GetSS(); Regs.ESP = (dword)ADSStack + ADSSTACK_SIZE - sizeof( dword ); Regs.CS = GetCS(); Regs.EIP = (dword)&ADSLoop; Regs.EFL = GetFL(); Regs.EAX = Regs.EBX = Regs.ECX = Regs.EDX = Regs.ESI = 0; Regs.EDI = Regs.EBP = 0; IntNum = -1; _DBG(("We're back from AccLoadProg")); return( sizeof( *ret ) ); }
static void TestASM() { CommentLine("TestASM"); println("testing asm"); printf("Accumulator EAX: %p\n", GetEAX()); printf("Base EBX: %p\n", GetEBX()); printf("Counter ECX: %p\n", GetECX()); printf("Data EDX: %p\n", GetEDX()); printf("src str ndx ESI: %p\n", GetESI()); printf("dst str ndx EDI: %p\n", GetEDI()); printf("stack top ESP: %p\n", GetESP()); printf("frame base EBP: %p\n", GetEBP()); // printf("insn ptr EIP: %p\n", GetEIP()); printf("code segment CS: %p\n", GetCS()); printf("stack SS: %p\n", GetSS()); printf("data segment DS: %p\n", GetDS()); printf("data segment ES: %p\n", GetES()); }
/* * AccLoadProg - create a new process for debugging */ trap_retval ReqProg_load( void ) { char *parm; char *src; char *dst; char *endsrc; char exe_name[PATH_MAX]; char ch; BOOL rc; int len; MYCONTEXT con; thread_info *ti; HANDLE handle; prog_load_req *acc; prog_load_ret *ret; header_info hi; WORD stack; WORD version; DWORD pid; DWORD pid_started; DWORD cr_flags; char *buff = NULL; size_t nBuffRequired = 0; char *dll_name; char *service_name; char *dll_destination; char *service_parm; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); parm = GetInPtr( sizeof( *acc ) ); /* * reset status variables */ LastExceptionCode = -1; DebugString = NULL; DebugeeEnded = FALSE; RemoveAllThreads(); FreeLibList(); DidWaitForDebugEvent = FALSE; DebugeePid = 0; DebugeeTid = 0; SupportingExactBreakpoints = 0; /* * check if pid is specified */ ParseServiceStuff( parm, &dll_name, &service_name, &dll_destination, &service_parm ); pid = 0; src = parm; /* // Just to be really safe! */ nBuffRequired = GetTotalSize() + PATH_MAX + 16; if( NULL == ( buff = malloc( nBuffRequired ) ) ) { ret->err = ERROR_NOT_ENOUGH_MEMORY; return( sizeof( *ret ) ); } if( *src == '#' ) { src++; pid = strtoul( src, &endsrc, 16 ); if( pid == 0 ) { pid = -1; } strcpy( buff, endsrc ); } else { while( isdigit( *src ) ) { src++; } if( *src == 0 && src != parm ) { pid = atoi( parm ); } } /* * get program to debug. If the user has specified a pid, then * skip directly to doing a DebugActiveProcess */ IsWOW = FALSE; #if !defined( MD_x64 ) IsDOS = FALSE; #endif if( pid == 0 ) { if( FindFilePath( parm, exe_name, ExtensionList ) != 0 ) { ret->err = ERROR_FILE_NOT_FOUND; goto error_exit; } /* * Get type of application */ handle = CreateFile( (LPTSTR)exe_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); if( handle == INVALID_HANDLE_VALUE ) { ret->err = GetLastError(); goto error_exit; } GetFullPathName( exe_name, MAX_PATH, CurrEXEName, NULL ); /* * get the parm list */ if( strchr( CurrEXEName, ' ' ) != NULL ) { strcpy( buff, "\"" ); strcat( buff, CurrEXEName ); strcat( buff, "\"" ); } else { strcpy( buff, CurrEXEName ); } dst = &buff[strlen( buff )]; src = parm; while( *src != 0 ) { ++src; } // parm layout // <--parameters-->0<--program_name-->0<--arguments-->0 // for( len = GetTotalSize() - sizeof( *acc ) - (src - parm) - 1; len > 0; --len ) { ch = *src; if( ch == 0 ) { ch = ' '; } *dst = ch; ++dst; ++src; } *dst = 0; cr_flags = DEBUG_ONLY_THIS_PROCESS; if( !GetEXEHeader( handle, &hi, &stack ) ) { ret->err = GetLastError(); CloseHandle( handle ); goto error_exit; } if( hi.sig == EXE_PE ) { if( IS_PE64( hi.u.peh ) ) { DebugeeSubsystem = PE64( hi.u.peh ).subsystem; } else { DebugeeSubsystem = PE32( hi.u.peh ).subsystem; #if defined( MD_x64 ) IsWOW = TRUE; #endif } if( DebugeeSubsystem == SS_WINDOWS_CHAR ) { cr_flags |= CREATE_NEW_CONSOLE; } #if !defined( MD_x64 ) } else if( hi.sig == EXE_NE ) { IsWOW = TRUE; /* * find out the pid of WOW, if it is already running. */ pVDMEnumProcessWOW( EnumWOWProcessFunc, (LPARAM)&pid ); if( pid != 0 ) { version = LOWORD( GetVersion() ); if( LOBYTE( version ) == 3 && HIBYTE( version ) < 50 ) { int kill = MessageBox( NULL, TRP_NT_wow_warning, TRP_The_WATCOM_Debugger, MB_APPLMODAL + MB_YESNO ); if( kill == IDYES ) { DWORD axs = PROCESS_TERMINATE+STANDARD_RIGHTS_REQUIRED; HANDLE hprocess = OpenProcess( axs, FALSE, pid ); if( hprocess != 0 && TerminateProcess( hprocess, 0 ) ) { CloseHandle( hprocess ); pid = 0; } } } else { cr_flags |= CREATE_SEPARATE_WOW_VDM; pid = 0; // always start a new VDM. } } if( pid != 0 ) { ret->err = GetLastError(); CloseHandle( handle ); goto error_exit; } } else { IsDOS = TRUE; #endif } CloseHandle( handle ); } /* * start the debugee */ pid_started = pid; if( *dll_name ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_DLLNAME ); strcat( buff, dll_name ); } if( *service_name ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_SERVICE ); strcat( buff, service_name ); } if( *dll_destination ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_COPYDIR ); strcat( buff, dll_destination ); } if( *service_parm ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_SERVICEPARM ); strcat( buff, service_parm ); } ret->err = StartControlThread( buff, &pid_started, cr_flags ); if( ret->err != 0 ) { goto error_exit; } /* * CREATE_PROCESS_DEBUG_EVENT will always be the first debug event. * If it is not, then something is horribly wrong. */ rc = MyWaitForDebugEvent(); if( !rc || ( DebugEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT ) || ( DebugEvent.dwProcessId != pid_started ) ) { ret->err = GetLastError(); goto error_exit; } ProcessInfo.pid = DebugEvent.dwProcessId; ProcessInfo.process_handle = DebugEvent.u.CreateProcessInfo.hProcess; ProcessInfo.base_addr = DebugEvent.u.CreateProcessInfo.lpBaseOfImage; AddProcess( &hi ); AddThread( DebugEvent.dwThreadId, DebugEvent.u.CreateProcessInfo.hThread, DebugEvent.u.CreateProcessInfo.lpStartAddress ); DebugeePid = DebugEvent.dwProcessId; DebugeeTid = DebugEvent.dwThreadId; LastDebugEventTid = DebugEvent.dwThreadId; #if defined( MD_x86 ) #ifdef WOW if( IsWOW ) { ret->flags = LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; /* * we use our own CS and DS as the Flat CS and DS, for lack * of anything better */ FlatDS = GetDS(); FlatCS = GetCS(); if( !executeUntilVDMStart() ) { ret->err = GetLastError(); goto error_exit; } if( pid ) { addAllWOWModules(); } else { addKERNEL(); } /* * we save the starting CS:IP of the WOW app, since we will use * it to force execution of code later */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); WOWAppInfo.segment = ( WORD ) con.SegCs; WOWAppInfo.offset = ( WORD ) con.Eip; con.SegSs = con.SegDs; // Wow lies about the stack segment. Reset it con.Esp = stack; MySetThreadContext( ti, &con ); } else if( IsDOS ) { // TODO! Clean up this code ret->flags = 0; //LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; /* * we use our own CS and DS as the Flat CS and DS, for lack * of anything better */ FlatDS = GetDS(); FlatCS = GetCS(); if( !executeUntilVDMStart() ) { ret->err = GetLastError(); goto error_exit; } #if 0 if( pid ) { addAllWOWModules(); } else { addKERNEL(); } #endif /* * we save the starting CS:IP of the WOW app, since we will use * it to force execution of code later */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); WOWAppInfo.segment = ( WORD )con.SegCs; WOWAppInfo.offset = ( WORD )con.Eip; con.SegSs = con.SegDs; // Wow lies about the stack segment. Reset it con.Esp = stack; MySetThreadContext( ti, &con ); } else { #else { #endif #else { #endif LPVOID base; if( pid == 0 ) { base = (LPVOID)DebugEvent.u.CreateProcessInfo.lpStartAddress; } else { base = 0; } ret->flags = LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; if( executeUntilStart( pid != 0 ) ) { LPVOID old; /* * make the application load our DLL, so that we can have it * run code out of it. One small note: this will not work right * if the app does not load our DLL at the same address the * debugger loaded it at!!! */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); old = (LPVOID)AdjustIP( &con, 0 ); if( base != 0 ) { SetIP( &con, base ); } MySetThreadContext( ti, &con ); SetIP( &con, old ); MySetThreadContext( ti, &con ); } ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); #if defined( MD_x86 ) FlatCS = con.SegCs; FlatDS = con.SegDs; #endif ret->flags |= LD_FLAG_IS_BIG; } ret->flags |= LD_FLAG_HAVE_RUNTIME_DLLS; if( pid != 0 ) { ret->flags |= LD_FLAG_IS_STARTED; } ret->mod_handle = 0; error_exit: if( buff ) { free( buff ); buff = NULL; } return( sizeof( *ret ) ); } trap_retval ReqProg_kill( void ) { prog_kill_ret *ret; ret = GetOutPtr( 0 ); ret->err = 0; DelProcess( TRUE ); StopControlThread(); return( sizeof( *ret ) ); }
const char *RemoteLink( const char *parms, bool server ) { #ifdef SERVER unsigned long link; #if defined(ACAD) { XVersion = 2; if( GetCS() & 3 ) { Meg1 = 0x37; } else { Meg1 = 0x60; } } #elif defined(PHARLAP) { CONFIG_INF config; static unsigned char buff[256]; _dx_config_inf(&config, buff ); XVersion = config.c_major; if( XVersion >= 3 ) { Meg1 = config.c_dos_sel; } else { Meg1 = 0x60; } } #elif defined(CAUSEWAY) Meg1 = GetZeroSel(); #endif parms = parms; link = GetDosLong( LINK_VECTOR * 4 ); if( link >= (1024UL * 1024UL) || GetDosLong( link ) != LINK_SIGNATURE ) { return( TRP_ERR_not_from_command ); } RMBuffPtr = RMLinToPM( GetDosLong( link + 4 ), 0 ); RMProcAddr = GetDosLong( link + 8 ); PutDosLong( LINK_VECTOR * 4, GetDosLong( link + 12 ) ); #else static char fullpath[256]; /* static because ss != ds */ static char buff[256]; static char *endname; char *name; char *buffp; char *endparm; void __far *link[4]; void __far * __far * link_ptr; unsigned len; #if defined(PHARLAP) const char *exe_name; #endif _DBG_EnterFunc( "RemoteLink()" ); BackFromFork = 0; link_ptr = (void __far *)(LINK_VECTOR * 4); link[ 3 ] = *link_ptr; link[ 2 ] = MK_FP( GetCS(), (unsigned )BackFromProtMode ); link[ 1 ] = (void __far *)MK_LINEAR( &Buff ); link[ 0 ] = (void __far *)LINK_SIGNATURE; *link_ptr = (void __far *)MK_LINEAR( &link ); // parms has following format // "trap parameters string"+"\0"+"command line string"+"\0" _DBG_Write( "Parms: " ); _DBG_NoTabWriteln( parms ); while( *parms == ' ' ) ++parms; if( *parms == '`' ) { ++parms; buffp = buff; while( *parms != '\0' ) { if( *parms == '`' ) { ++parms; break; } *buffp++ = *parms++; } *buffp = '\0'; } while( *parms == ' ' ) ++parms; if( setjmp( RealModeState ) == 0 ) { name = FindExtender( fullpath, &endname ); if( name == NULL ) { _DBG_ExitFunc( "RemoteLink(), unable to find extender" ); return( TRP_ERR_no_extender ); } _DBG_Write( "Extender name: " ); _DBG_NoTabWriteln( name ); while( *endname++ != '\0' ) {} // skip after extender name + '\0' #if defined(ACAD) buffp = buff; *buffp = '\0'; #else { static char *endhelp; const char *help_name; #if defined(PHARLAP) exe_name = parms; while( *exe_name++ != '\0' ) {} // skip to command line help_name = GetHelpName( exe_name ); #else help_name = HELPNAME; #endif buffp = SearchPath( DOSEnvFind( "PATH" ), help_name, buff, &endhelp ); if( *buffp == '\0' ) { _DBG_ExitFunc( "RemoteLink(), unable to find extender help file" ); return( TRP_ERR_no_extender ); } } #endif _DBG_Write( "Extender help name: " ); _DBG_NoTabWriteln( buffp ); endparm = CopyStr( parms, endname + 1 ); // reserve length byte endparm = CopyStr( buffp, CopyStr( " ", endparm ) ); #if defined(PHARLAP) endparm = CopyStr( " ", endparm ); endparm = CopyStr( exe_name, endparm ); // add extra executable name #endif len = endparm - ( endname + 1 ); if( len > 126 ) len = 126; *endname = len; // setup length byte endparm = endname + len + 1; endparm[0] = '\r'; endparm[1] = '\0'; _DBG_Write( "Extender Cmd line: " ); _DBG_NoTabWriteln( endname + 1 ); _DBG_Writeln( "calling _fork() to start extender/debugee" ); if( _fork( name, endname ) != 0 ) { _DBG_ExitFunc( "RemoteLink(), unable to start extender" ); return( TRP_ERR_cant_start_extender ); } } else if( BackFromFork || !BeenToProtMode ) { _DBG_ExitFunc( "RemoteLink(), extender could not start extender help file" ); return( TRP_ERR_cant_start_extender ); } #endif server = server; _DBG_ExitFunc( "RemoteLink()" ); return( NULL ); }