📄 qnxpmd.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 post-mortem 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 <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/dumper.h>
#include <sys/console.h>
#include <sys/dev.h>
#include <sys/name.h>
#include "trpimp.h"
#include "qnxcomm.h"
#include "misc7086.h"
#include "mad.h"
#include "madregs.h"
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef struct {
word real_seg;
word is_32;
dword seg_len;
dword file_off;
dword mem_off;
} seg_data;
#define DUMP_SIGNATURE 0x706d7564
#define DUMP_VERSION 100
#define NO_FILE (-1)
enum {
MH_NONE,
MH_DEBUGGEE,
MH_SLIB,
MH_PROC
};
struct {
unsigned loaded : 1;
unsigned ignore_timestamp : 1;
unsigned fpu32 : 1;
unsigned read_gdts : 1;
unsigned enable_read_gdts : 1;
unsigned force_read_gdts : 1;
unsigned dbg32 : 1;
unsigned mapping_shared : 1;
int fd;
struct _dumper_hdr hdr;
seg_data *segs;
} PmdInfo;
#if 0
static void Out( char *str )
{
write( 1, str, strlen( str ) );
}
static void OutNum( unsigned i )
{
char numbuff[10];
char *ptr;
ptr = numbuff+10;
*--ptr = '\0';
do {
*--ptr = ( i % 10 ) + '0';
i /= 10;
} while( i != 0 );
Out( ptr );
}
#endif
unsigned ReqGet_sys_config()
{
struct _osinfo info;
get_sys_config_ret *ret;
ret = GetOutPtr(0);
if( PmdInfo.loaded ) {
info = PmdInfo.hdr.osdata;
} else {
qnx_osinfo( 0, &info );
}
ret->sys.mad = MAD_X86;
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;
case 686:
ret->sys.cpu = X86_686;
break;
}
if( info.sflags & _PSF_PROTECTED ) {
ret->sys.huge_shift = 3;
} else {
ret->sys.huge_shift = 12;
}
return( sizeof( *ret ) );
}
#define PRIV_MASK 0x03
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;
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( getnid(), _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 0 //NYI: Don't know how to find 16-bit Slib
extern int (__far * (__far *__f)) ();
slib.offset = FP_OFF( __f );
slib.segment = FP_SEG( __f );
/*
There are 3 different SLib segments, one for each priv level.
Make the assumption that they're all contiguous and figure out
the right one based on the difference between the debugger's
priv level and the debuggee's. Ugh. Talk to QSSL about this.
*/
slib.segment += ((PmdInfo.segs[0].real_seg & PRIV_MASK)
- (FP_SEG( &__f ) & PRIV_MASK)) * 8;
#endif
}
return( slib );
}
unsigned ReqMap_addr()
{
map_addr_req *acc;
map_addr_ret *ret;
unsigned index;
addr48_ptr slib;
unsigned seg;
acc = GetInPtr(0);
ret = GetOutPtr(0);
ret->lo_bound = 0;
ret->hi_bound = ~(addr48_off)9;
seg = acc->in_addr.segment;
switch( seg ) {
case MAP_FLAT_CODE_SELECTOR:
seg = 0x04;
break;
case MAP_FLAT_DATA_SELECTOR:
seg = 0x0c;
break;
}
seg &= ~PRIV_MASK;
ret->out_addr.offset = acc->in_addr.offset;
switch( acc->handle ) {
case MH_DEBUGGEE:
if( acc->in_addr.segment == MAP_FLAT_DATA_SELECTOR ) {
index = 0;
} else {
index = seg >> 3;
}
if( PmdInfo.loaded && index < PmdInfo.hdr.numsegs ) {
seg = PmdInfo.segs[ seg >> 3 ].real_seg;
ret->out_addr.offset += PmdInfo.segs[ index ].mem_off;
}
break;
case MH_SLIB:
slib = GetSLibTable( PmdInfo.dbg32 );
seg += slib.segment - 4;
break;
case MH_PROC:
seg += 0xE0 - 4;
break;
}
ret->out_addr.segment = seg | (PmdInfo.segs[0].real_seg & PRIV_MASK);
return( sizeof( *ret ) );
}
unsigned ReqChecksum_mem()
{
checksum_mem_ret *ret;
ret = GetOutPtr(0);
ret->result = 0;
return( sizeof( *ret ) );
}
#pragma aux ver_read = ".286p" \
"verr ax" \
"jz L1" \
"xor ax,ax" \
"L1:" \
parm [ax] value [ax]
extern unsigned short ver_read( unsigned short );
static unsigned ReadGDT( read_mem_req *acc, unsigned len, void *ret )
{
struct _seginfo info;
unsigned segment;
if( !PmdInfo.read_gdts ) return( 0 );
segment = acc->mem_addr.segment;
if( segment & 0x04 ) return( 0 );
if( segment == 0 ) return( 0 );
if( !ver_read( segment ) ) return( 0 );
if(qnx_segment_info(PROC_PID,PROC_PID,segment,&info)==-1) return( 0 );
if( acc->mem_addr.offset >= info.nbytes ) {
len = 0;
} else if( acc->mem_addr.offset+len > info.nbytes ) {
len = info.nbytes - acc->mem_addr.offset;
}
if( len == 0 ) return( 0 );
_fmemcpy( ret, MK_FP( segment, acc->mem_addr.offset ), len );
return( len );
}
unsigned ReqRead_mem()
{
read_mem_req *acc;
void *ret;
unsigned i;
unsigned len;
acc = GetInPtr(0);
ret = GetOutPtr(0);
if( !PmdInfo.loaded ) {
return( 0 );
}
len = acc->len;
for( i = 0; i < PmdInfo.hdr.numsegs; ++i ) {
if( PmdInfo.segs[i].real_seg == acc->mem_addr.segment ) {
if( acc->mem_addr.offset >= PmdInfo.segs[i].seg_len ) {
len = 0;
} else if( acc->mem_addr.offset+len > PmdInfo.segs[i].seg_len ) {
len = PmdInfo.segs[i].seg_len - acc->mem_addr.offset;
}
if( len != 0 ) {
lseek( PmdInfo.fd, PmdInfo.segs[i].file_off + acc->mem_addr.offset,
SEEK_SET );
len = read( PmdInfo.fd, ret, len );
if( len == -1 ) len = 0;
}
return( len );
}
}
return( ReadGDT( acc, len, ret ) );
}
unsigned ReqWrite_mem()
{
write_mem_ret *ret;
ret = GetOutPtr(0);
ret->len = 0;
return( sizeof( *ret ) );
}
unsigned ReqRead_io()
{
return( 0 );
}
unsigned ReqWrite_io()
{
write_io_ret *ret;
ret = GetOutPtr(0);
ret->len = 0;
return( sizeof( *ret ) );
}
static void ReadCPU( struct x86_cpu *r )
{
memset( r, 0, sizeof( *r ) );
if( PmdInfo.loaded ) {
r->eax = PmdInfo.hdr.reg.ax;
r->ebx = PmdInfo.hdr.reg.bx;
r->ecx = PmdInfo.hdr.reg.cx;
r->edx = PmdInfo.hdr.reg.dx;
r->esi = PmdInfo.hdr.reg.si;
r->edi = PmdInfo.hdr.reg.di;
r->ebp = PmdInfo.hdr.reg.bp;
r->esp = PmdInfo.hdr.reg.sp;
r->eip = PmdInfo.hdr.reg.ip;
r->efl = PmdInfo.hdr.reg.fl;
r->cs = PmdInfo.hdr.reg.cs;
r->ds = PmdInfo.hdr.reg.ds;
r->ss = PmdInfo.hdr.reg.ss;
r->es = PmdInfo.hdr.reg.es;
r->fs = PmdInfo.hdr.reg.fs;
r->gs = PmdInfo.hdr.reg.gs;
}
}
static void ReadFPU( struct x86_fpu *r )
{
memset( r, 0, sizeof( *r ) );
if( PmdInfo.loaded ) {
memcpy( r, PmdInfo.hdr.x87, sizeof( PmdInfo.hdr.x87 ) );
if( !PmdInfo.fpu32 ) FPUExpand( r );
}
}
unsigned ReqRead_cpu()
{
ReadCPU( GetOutPtr( 0 ) );
return( sizeof( struct x86_cpu ) );
}
unsigned ReqRead_fpu()
{
ReadFPU( GetOutPtr( 0 ) );
return( sizeof( struct x86_fpu ) );
}
unsigned ReqRead_regs( void )
{
mad_registers *mr;
mr = GetOutPtr( 0 );
ReadCPU( &mr->x86.cpu );
ReadFPU( &mr->x86.fpu );
return( sizeof( mr->x86 ) );
}
unsigned ReqWrite_cpu()
{
return( 0 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -