📄 qnxacc.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: Trap file for QNX interactive debugging.
*
****************************************************************************/
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <process.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <i86.h>
#include <malloc.h>
#include <sys/name.h>
#include <sys/proxy.h>
#include <sys/kernel.h>
#include <sys/debug.h>
#include <sys/stat.h>
#include <sys/proc_msg.h>
#include <sys/osinfo.h>
#include <sys/psinfo.h>
#include <sys/seginfo.h>
#include <sys/sched.h>
#include <sys/vc.h>
#include <sys/magic.h>
#include <sys/wait.h>
#include <sys/console.h>
#include <sys/dev.h>
#include <string.h>
#include "trpimp.h"
#include "trperr.h"
#include "qnxcomm.h"
#include "misc7086.h"
#include "mad.h"
#include "madregs.h"
typedef unsigned short USHORT;
typedef unsigned long ULONG;
#define BUFF_SIZE 256
static pid_t MID;
static pid_t OrigPGrp;
static char UtilBuff[BUFF_SIZE];
static struct {
unsigned long in;
unsigned long out;
unsigned long err;
} StdPos;
static int ForceFpu32;
enum {
MH_NONE,
MH_DEBUGGEE,
MH_SLIB,
MH_PROC
};
typedef struct {
pid_t tid;
unsigned frozen : 1;
unsigned fork : 1;
unsigned dying : 1;
} thread_info;
typedef struct {
unsigned at_end : 1;
unsigned loaded_proc : 1;
unsigned stopped : 1;
unsigned priv_level : 2;
unsigned dbg32 : 1;
unsigned proc32 : 1;
unsigned fpu32 : 1;
unsigned flat : 1;
unsigned fork : 1;
pid_t pid;
nid_t nid;
pid_t proc;
pid_t mid;
pid_t son;
int sig;
unsigned version;
long cpu;
long fpu;
long sflags;
int save_in;
int save_out;
addr48_ptr magic;
addr48_off code_offset;
addr48_off data_offset;
unsigned_32 last_eax;
unsigned max_threads;
thread_info *thread;
} process_info;
#define THREAD_GROW 10
static process_info ProcInfo;
#define PRIV_MASK 3
#define MAX_WP 32
struct _watch_struct WatchPoints[ MAX_WP ];
short WatchCount = 0;
#if 0
void Out( char *str )
{
write( 1, (char *)str, strlen( str ) );
}
void OutNum( unsigned long i )
{
char numbuff[16];
char *ptr;
ptr = numbuff+10;
*--ptr = '\0';
do {
*--ptr = ( i % 10 ) + '0';
i /= 10;
} while( i != 0 );
Out( ptr );
}
#endif
#define MAX_MEM_TRANS 256
static unsigned MoveMem( int op, char *data, addr_seg segv, addr_off offv,
unsigned size )
{
unsigned length;
unsigned trans;
unsigned amount;
struct _seginfo info;
if( ProcInfo.pid == 0 ) return( 0 );
if( qnx_segment_info( ProcInfo.proc, ProcInfo.pid, segv, &info ) == -1 ) {
info.nbytes = 0;
}
if( offv >= info.nbytes ) {
size = 0;
} else if( offv + size > info.nbytes ) {
size = info.nbytes - offv;
}
length = size;
for( ;; ) {
if( length == 0 ) break;
trans = (length > MAX_MEM_TRANS) ? MAX_MEM_TRANS : length;
if( __qnx_debug_xfer( ProcInfo.proc, ProcInfo.pid, op, data, trans, offv, segv ) != 0 ) {
/* something went wrong. need to find out how much trans'ed */
//NYI
amount = 0;
} else {
amount = trans;
}
data += amount;
offv += amount;
length -= amount;
if( amount != trans ) break;
}
return( size - length );
}
static unsigned WriteBuffer( char *data, addr_seg segv, addr_off offv,
unsigned size )
{
return( MoveMem( _DEBUG_MEM_WR, data, segv, offv, size ) );
}
static unsigned ReadBuffer( char *data, addr_seg segv, addr_off offv,
unsigned size )
{
return( MoveMem( _DEBUG_MEM_RD, data, segv, offv, size ) );
}
static thread_info *find_thread(pid_t tid)
{
thread_info *thread;
unsigned new_count;
for( thread = ProcInfo.thread; thread < &ProcInfo.thread[ProcInfo.max_threads]; thread++ ) {
if( thread->tid == tid ) {
if( tid == 0 ) thread->dying = FALSE;
return( thread );
}
}
if( tid == 0 ) {
/* need to expand the array */
new_count = ProcInfo.max_threads + THREAD_GROW;
thread = realloc( ProcInfo.thread, new_count * sizeof( *thread ) );
if( thread != NULL ) {
ProcInfo.thread = thread;
thread = &thread[ProcInfo.max_threads];
ProcInfo.max_threads = new_count;
memset( thread, 0, THREAD_GROW * sizeof( *thread ) );
return( thread );
}
}
return( NULL );
}
#define THREAD_ALL (-1)
#define NO_TID (INT_MAX)
static pid_t next_thread(pid_t last, int state) {
thread_info *thread;
pid_t tid = NO_TID;
pid_t curr;
for( thread = ProcInfo.thread; thread < &ProcInfo.thread[ProcInfo.max_threads]; thread++ ) {
if( thread->dying ) continue;
curr = thread->tid;
switch( state ) {
case THREAD_ALL:
break;
case THREAD_THAWED:
if( thread->frozen && (ProcInfo.pid != curr) ) continue;
break;
case THREAD_FROZEN:
if( !thread->frozen ) continue;
break;
}
if( curr > last && curr < tid ) {
tid = curr;
}
}
if( tid == NO_TID ) return( 0 );
return( tid );
}
unsigned ReqGet_sys_config()
{
struct _osinfo info;
get_sys_config_ret *ret;
ret = GetOutPtr(0);
if( ProcInfo.pid == 0 ) {
qnx_osinfo( 0, &info );
} else {
info.version = ProcInfo.version;
info.cpu = ProcInfo.cpu;
info.fpu = ProcInfo.fpu;
info.sflags = ProcInfo.sflags;
}
ret->sys.os = OS_QNX;
ret->sys.osmajor = info.version / 100;
ret->sys.osminor = info.version % 100;
if( info.sflags & _PSF_EMULATOR_INSTALLED ) {
ret->sys.fpu = X86_EMU;
} else if( (info.sflags & _PSF_NDP_INSTALLED) == 0 ) {
ret->sys.fpu = X86_NO;
} else {
switch( info.fpu ) {
case 87:
ret->sys.fpu = X86_87;
break;
case 287:
ret->sys.fpu = X86_287;
break;
case 387:
default:
ret->sys.fpu = X86_387;
break;
}
}
switch( info.cpu ) {
case 8088:
ret->sys.cpu = X86_86;
break;
case 186:
ret->sys.cpu = X86_186;
break;
case 286:
ret->sys.cpu = X86_286;
break;
case 386:
default:
ret->sys.cpu = X86_386;
break;
case 486:
ret->sys.cpu = X86_486;
break;
case 586:
ret->sys.cpu = X86_586;
break;
}
if( info.sflags & _PSF_PROTECTED ) {
ret->sys.huge_shift = 3;
} else {
ret->sys.huge_shift = 12;
}
ret->sys.mad = MAD_X86;
return( sizeof( *ret ) );
}
struct _slib_register {
msg_t msgcode;
short rsvd1;
long rsvd[3];
};
struct _slib_register_reply {
msg_t msgcode;
addr48_ptr dispatch;
long rsvd[2];
};
#define _SLIB_NAME "qnx/syslib"
#define _SLIB_REGISTER 0x1000
addr48_ptr GetSLibTable( bool is_32 )
{
addr48_ptr slib;
addr32_ptr slib16;
union {
struct _slib_register smsg;
struct _slib_register_reply rmsg;
} msg;
pid_t pid;
int ret;
slib.segment = 0;
slib.offset = 0;
/* get shared library function table pointer */
if( is_32 ) {
pid = qnx_name_locate( ProcInfo.nid, _SLIB_NAME, sizeof( msg ), NULL );
if( pid == -1 ) {
return( slib );
}
msg.smsg.msgcode = _SLIB_REGISTER;
ret = Send( pid, &msg, &msg, sizeof( msg.smsg ), sizeof( msg.rmsg ) );
qnx_vc_detach( pid );
if( ret == -1 || msg.rmsg.msgcode != EOK ) {
return( slib );
}
slib = msg.rmsg.dispatch;
} else {
if( __qnx_debug_xfer( ProcInfo.proc, ProcInfo.pid, _DEBUG_MEM_RD, &slib16,
sizeof( slib16 ), ProcInfo.magic.offset+offsetof(struct _magic,sptrs[0]),
ProcInfo.magic.segment ) != 0 ) {
return( slib );
}
slib.segment = slib16.segment;
slib.offset = slib16.offset;
}
return( slib );
}
unsigned ReqMap_addr()
{
map_addr_req *acc;
map_addr_ret *ret;
addr48_ptr slib;
unsigned seg;
acc = GetInPtr(0);
ret = GetOutPtr(0);
ret->lo_bound = 0;
ret->hi_bound = ~(addr48_off)0;
ret->out_addr.offset = acc->in_addr.offset;
seg = acc->in_addr.segment;
switch( seg ) {
case MAP_FLAT_CODE_SELECTOR:
seg = 0x04;
break;
case MAP_FLAT_DATA_SELECTOR:
seg = 0x0c;
break;
}
if( ProcInfo.pid != 0 ) {
switch( acc->handle ) {
case MH_DEBUGGEE:
if( ProcInfo.flat ) {
switch( acc->in_addr.segment & ~PRIV_MASK ) {
case 0x04:
case MAP_FLAT_CODE_SELECTOR & ~PRIV_MASK:
/* case MAP_FLAT_DATA_SELECTOR & ~PRIV_MASK: Same as above */
ret->out_addr.offset += ProcInfo.code_offset;
break;
default:
ret->out_addr.offset += ProcInfo.data_offset;
break;
}
}
break;
case MH_SLIB:
slib = GetSLibTable( ProcInfo.dbg32 );
seg += slib.segment - 4;
break;
case MH_PROC:
seg += 0xE0 - 4;
break;
}
}
if( ProcInfo.sflags & _PSF_PROTECTED ) {
ret->out_addr.segment = (seg & ~PRIV_MASK) | ProcInfo.priv_level;
}
return( sizeof( *ret ) );
}
unsigned ReqChecksum_mem()
{
addr_off offv;
USHORT length;
USHORT size;
int i;
USHORT amount;
ULONG sum;
checksum_mem_req *acc;
checksum_mem_ret *ret;
acc = GetInPtr(0);
ret = GetOutPtr(0);
sum = 0;
if( ProcInfo.pid != 0 ) {
length = acc->len;
offv = acc->in_addr.offset;
for( ;; ) {
if( length == 0 ) break;
size = (length > sizeof( UtilBuff )) ? sizeof( UtilBuff ) : length;
amount = MoveMem( _DEBUG_MEM_RD, UtilBuff, acc->in_addr.segment,
offv, size );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -