x86call.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 611 行 · 第 1/2 页
C
611 行
return( 0 );
DisAsm( &dd );
if( dd.ins.type == DI_X86_push3 && IsCSReg( dd.ins.op[ OP_1 ] ) ) {
*ip_value = GetFarAddr( return_addr_location );
} else {
ip_value->mach.offset = GetAnOffset( return_addr_location );
}
return( 1 );
}
return_addr = GetFarAddr( return_addr_location );
MCAddrOvlReturn( &return_addr );
DbgAddr = return_addr;
if( GetDisasmPrev( &DbgAddr ) != MS_OK )
return( 0 );
DisAsm( &dd );
if( dd.ins.type == DI_X86_call3 ) {
*ip_value = GetFarAddr( return_addr_location );
return( 1 );
} else if( dd.ins.type == DI_X86_call ) {
DbgAddr = prev_ins;
if( GetDisasmPrev( &DbgAddr ) != MS_OK )
return( 0 );
DisAsm( &dd );
if( dd.ins.type == DI_X86_push3 && IsCSReg( dd.ins.op[ OP_1 ] ) ) {
*ip_value = GetFarAddr( return_addr_location );
return( 0 );
}
}
return( 1 );
}
static int HeuristicTraceBack(
address *p_prev_sp,
address *start,
address *execution,
address *frame,
address *stack )
{
mad_disasm_data dd;
int word_size;
long sp_adjust;
long bp_adjust;
long saved_bp_loc = 0;
long bp_to_ra_offset = 0;
int found_inc_bp;
int found_mov_bp_sp;
int found_push_bp;
char *jmplabel;
address return_addr_location;
address bp_value;
address sp_value;
address saved_return_location;
int found_call;
int i;
InitCache( *start, 100 );
sp_value = *stack;
bp_value = *frame;
DbgAddr = *execution;
DisAsm( &dd );
if( dd.ins.type == DI_X86_retf || dd.ins.type == DI_X86_retf2 ) {
*execution = GetFarAddr( &sp_value );
found_call = 1;
} else if( dd.ins.type == DI_X86_ret || dd.ins.type == DI_X86_ret2 ) {
execution->mach.offset = GetAnOffset( &sp_value );
found_call = 1;
} else {
// Check for ADD SP,n right after current ip and adjust SP if its there
// because it must be popping parms
if( dd.ins.type == DI_X86_add3 && ConstOp( dd.ins.op[OP_2] ) && IsSPReg( dd.ins.op[OP_1] ) ){
sp_value.mach.offset += dd.ins.op[ OP_2 ].value;
}
// Run through code from the known symbol until and collect prolog info
word_size = Is32BitSegment ? 4 : 2;
sp_adjust = 0;
bp_adjust = 0;
found_inc_bp = 0;
found_mov_bp_sp = 0;
found_push_bp = 0;
DbgAddr = *start;
while( DbgAddr.mach.offset != execution->mach.offset ) {
DisAsm( &dd );
switch( dd.ins.type ) {
case DI_INVALID:
return( 0 );
case DI_X86_call3:
jmplabel = ToSegStr( dd.ins.op[ OP_1 ].value, dd.ins.op[ OP_1 ].extra, 0 );
if( IdentifyFunc( jmplabel, &sp_adjust ) )
continue;
break;
case DI_X86_call:
jmplabel = JmpLabel( dd.ins.op[ OP_1 ].value, 0 );
if( IdentifyFunc( jmplabel, &sp_adjust ) )
continue;
break;
case DI_X86_enter:
sp_adjust -= word_size; // push bp
found_push_bp = 1;
bp_to_ra_offset = sp_adjust; // mov bp,sp
found_mov_bp_sp = 1;
saved_bp_loc = 0; // 0[bp]
sp_adjust -= dd.ins.op[ OP_1 ].value; // sub sp,n
break;
case DI_X86_inc2:
if( IsBPReg( dd.ins.op[ OP_1 ] ) ) {
found_inc_bp = 1;
continue;
}
break;
case DI_X86_mov:
if( IsBPReg( dd.ins.op[ OP_1 ] ) && IsSPReg( dd.ins.op[ OP_2 ] ) ) {
found_mov_bp_sp = 1;
bp_to_ra_offset = sp_adjust;
saved_bp_loc -= sp_adjust;
}
continue;
case DI_X86_nop:
continue;
case DI_X86_pop:
case DI_X86_pop2:
case DI_X86_pop3d:
case DI_X86_pop3e:
case DI_X86_pop3s:
case DI_X86_pop4f:
case DI_X86_pop4g:
sp_adjust += word_size;
continue;
case DI_X86_push:
case DI_X86_push2:
case DI_X86_push3:
case DI_X86_push4f:
case DI_X86_push4g:
case DI_X86_push5:
sp_adjust -= word_size;
if( IsBPReg( dd.ins.op[ OP_1 ] ) ) {
saved_bp_loc = sp_adjust;
found_push_bp = 1;
}
continue;
case DI_X86_sub:
dd.ins.op[ OP_2 ].value = -dd.ins.op[ OP_2 ].value;
case DI_X86_add:
if( !ConstOp( dd.ins.op[ OP_2 ] ) )
break;
if( IsSPReg( dd.ins.op[ OP_1 ] ) ) {
sp_adjust += dd.ins.op[ OP_2 ].value;
continue;
} else if( IsBPReg( dd.ins.op[ OP_1 ] ) ) {
bp_adjust += dd.ins.op[ OP_2 ].value;
continue;
}
break;
default:
break;
}
break;
}
// find the address of the return address (return_addr_location)
if( found_mov_bp_sp ) {
return_addr_location = bp_value;
return_addr_location.mach.offset -= bp_adjust;
GetBPFromStack( &return_addr_location, &bp_value );
return_addr_location.mach.offset -= bp_to_ra_offset;
} else {
if( found_push_bp ) {
return_addr_location = sp_value;
return_addr_location.mach.offset += saved_bp_loc - sp_adjust;
GetBPFromStack( &return_addr_location, &bp_value );
}
return_addr_location = sp_value;
return_addr_location.mach.offset -= sp_adjust;
}
found_call = 0;
if( found_mov_bp_sp ) {
found_call = FindCall( execution, &return_addr_location );
if( !found_call ) {
return_addr_location = sp_value;
return_addr_location.mach.offset -= sp_adjust;
}
}
if( !found_call ) {
saved_return_location = return_addr_location;
// limit the search to 512*word_size (W2K can cause us to search 4Gb!)
for( i = 0; return_addr_location.mach.offset >= p_prev_sp->mach.offset && i < 512; ++i ) {
found_call = FindCall( execution, &return_addr_location );
if( found_call )
break;
return_addr_location.mach.offset -= word_size;
}
if( !found_call ) {
return_addr_location = saved_return_location;
for( i = 0; i < 10; ++i ) {
return_addr_location.mach.offset += word_size;
found_call = FindCall( execution, &return_addr_location );
if( found_call ) {
break;
}
}
}
}
}
*stack = DbgAddr;
*frame = bp_value;
return( found_call );
}
static void SymbolicTraceBack(
address *start,
unsigned characteristics,
long bp_disp,
address *execution,
address *frame,
address *stack )
{
address where;
if( execution->mach.offset == start->mach.offset ) {
/* return address is top item on the stack */
where = *stack;
} else {
where = *frame;
GetBPFromStack( &where, frame );
where.mach.offset += bp_disp;
}
execution->mach.offset = GetAnOffset( &where );
if( characteristics ) {
execution->mach.segment = (unsigned short) GetDataWord();
}
*stack = DbgAddr;
}
static int BPTraceBack( address *execution, address *frame,
address *stack )
{
address where;
int is_far;
where = *frame;
is_far = GetBPFromStack( &where, frame );
if( frame->mach.offset == 0 ) return( 0 );
execution->mach.offset = (unsigned short) GetDataWord();
if( is_far ) {
execution->mach.segment = (unsigned short) GetDataWord();
}
*stack = DbgAddr;
return( 1 );
}
unsigned DIGENTRY MICallUpStackSize( void )
{
return( sizeof( mad_call_up_data ) );
}
mad_status DIGENTRY MICallUpStackInit( mad_call_up_data *cud, const mad_registers *mr )
{
cud = cud;
mr = mr;
return( MS_OK );
}
mad_status DIGENTRY MICallUpStackLevel( mad_call_up_data *cud,
const address *startp,
unsigned rtn_characteristics,
long return_disp,
const mad_registers *in,
address *execution,
address *frame,
address *stack,
mad_registers **out )
{
address prev_sp_value;
address start;
cud = cud;
in = in;
*out = NULL;
Is32BitSegment = BIG_SEG( *execution );
start = *startp;
if( MCSystemConfig()->os == OS_WINDOWS && !Is32BitSegment ) {
memset( &start, 0, sizeof( start ) );
}
prev_sp_value = *stack;
if( start.mach.segment == 0 && start.mach.offset == 0 ) {
if( Is32BitSegment ) return( MS_FAIL );
if( !BPTraceBack( execution, frame, stack ) ) return( MS_FAIL );
} else {
if( return_disp != -1 ) {
SymbolicTraceBack( &start, rtn_characteristics, return_disp,
execution, frame, stack );
} else {
if( !HeuristicTraceBack( &prev_sp_value, &start,
execution, frame, stack ) ) return( MS_FAIL );
}
}
if( stack->mach.offset <= prev_sp_value.mach.offset ) return( MS_FAIL );
return( MS_OK );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?