示例#1
0
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.s._32[I64LO32];
        }
        // 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.s._32[I64LO32], 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.s._32[I64LO32], 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.s._32[I64LO32]; // 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.s._32[I64LO32] = -dd.ins.op[ OP_2 ].value.s._32[I64LO32];
                /* fall through */
            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.s._32[I64LO32];
                    continue;
                } else if( IsBPReg( dd.ins.op[ OP_1 ] ) ) {
                    bp_adjust += dd.ins.op[ OP_2 ].value.s._32[I64LO32];
                    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 );
}
示例#2
0
void  FormatIns( char *buf, instruction *curr_ins, form_option format )
/*********************************************************************/

{
    const char          *name;
    int                 len;
    operand             *op;
    int                 i;
    int                 seg_override;
    bool                prefix;
    char                tmp_buff[ 80 ];
    char                *ptr;

    if( curr_ins->opcode == I_INVALID ) {
        strcpy( buf, "?????" );
        return;
    }
    CurrIns = *curr_ins;
    prefix = false;
    for( i = 0; i <= 3; ++i ) {
        if( CurrIns.pref & PrefixTab[ i ] ) {
            strcpy( tmp_buff, InsName[ PrefixName[ i ] ] );
            PadBlanks( tmp_buff );
            if( format & FORM_NAME_UPPER ) {
                ZapUpper( tmp_buff );
            }
            strcat( buf, tmp_buff );
            prefix = true;
        }
    }
    seg_override = NULL_REG;
    if( CurrIns.pref & PREF_xS ) {
        seg_override = CurrIns.seg_used;
        FixStringIns( &CurrIns );
    }
    if( CurrIns.opcode < FIRST_WTK_INS ) {
        name = InsName[ CurrIns.opcode ];
    } else {
        name = GetWtkInsName( CurrIns.opcode - FIRST_WTK_INS );
    }
    strcpy( tmp_buff, name );
#ifdef O2A
    if( DO_UNIX ) {
        ToUnixInsName( tmp_buff, &CurrIns );
    }
#endif
    if( format & FORM_NAME_UPPER ) {
        ZapUpper( tmp_buff );
    }
    strcat( buf, tmp_buff );
    PadBlanks( buf );
    if( prefix ) {          /* if a prefix like 'lock', need space after name */
        strcat( buf, " " );
    }

    tmp_buff[ 0 ] = '\0';
#ifdef O2A
    if( !DO_UNIX ) {
#endif
        if( CurrIns.opcode == I_CALL_FAR || CurrIns.opcode == I_JMP_FAR ) {
            if( CurrIns.modifier == MOD_NONE ) {
                if( format & FORM_ASSEMBLER ) {
                    strcpy( tmp_buff, "far ptr " );
                } else {
                    strcpy( tmp_buff, "far " );
                }
            }
        } else if( CurrIns.opcode == I_CALL ||
                ( IsJumpIns( CurrIns.opcode ) && CurrIns.ins_size != 2 ) ) {
            if( CurrIns.modifier == MOD_NONE ) {
                if( format & FORM_ASSEMBLER ) {
                    strcpy( tmp_buff, "near ptr " );
                }
            }
        }
        if( format & FORM_NAME_UPPER ) {
            ZapUpper( tmp_buff );
        }
        strcat( buf, tmp_buff );

#ifdef O2A
    } else if( CurrIns.num_oper >= 2 ) { // swap operands
        operand tmp;
        int     last;

        last = CurrIns.num_oper - 1;
        tmp = CurrIns.op[ OP_1 ];
        CurrIns.op[ OP_1 ] = CurrIns.op[ last ];
        CurrIns.op[ last ] = tmp;
        if( CurrIns.mem_ref_op == 0 ) {
            CurrIns.mem_ref_op = last;
        } else if( CurrIns.mem_ref_op == last ) {
            CurrIns.mem_ref_op = 0;
        }
    }
#endif
    for( i = 0; i < CurrIns.num_oper; ++i ) {
        if( i > 0 ) {
            len = strlen( buf );
            buf[ len ] = ',';
            buf[ len + 1 ] = '\0';
        }
        op = &CurrIns.op[ i ];
        if( CurrIns.mem_ref_op == i ) {
            if(
#ifdef O2A
                !DO_UNIX  &&
#endif
                CurrIns.modifier != MOD_NONE ) {
                strcpy( tmp_buff, ModifierTab[ CurrIns.modifier ] );
                if( format & FORM_NAME_UPPER ) {
                    ZapUpper( tmp_buff );
                }
                strcat( buf, tmp_buff );
            }
            if( seg_override != NULL_REG ) {
                DumpOverride( tmp_buff, seg_override );
                if( format & FORM_REG_UPPER ) ZapUpper( tmp_buff );
                strcat( buf, tmp_buff );
            }
        }
        switch( op->mode ) {
        case ADDR_REG:
            ptr = tmp_buff;
#ifdef O2A
            if( DO_UNIX ) {
                *ptr++ = '%';
            }
#endif
            strcpy( ptr, X86RegisterName[ op->base ] );
            if( format & FORM_REG_UPPER ) ZapUpper( ptr );
            strcat( buf, tmp_buff );
            break;
        case ADDR_CONST:
#ifdef O2A
            if( DO_UNIX ) {
                strcat( buf, "$" );
            }
#endif
            if( op->size == 0 ) {
                len = strlen( buf );
                ltoa( op->disp, &buf[ len ], 10 );
            } else {
                strcat( buf, ToStr( op->disp, 2 * op->size, op->offset ) );
            }
            break;
        case ADDR_LABEL:
#ifdef O2A
            if( !DO_UNIX  &&
                ( format & FORM_ASSEMBLER && IsJumpIns( CurrIns.opcode ) ) ) {
                if( CurrIns.ins_size == 2 ) {
                    if( format & FORM_NAME_UPPER ) {
                        strcat( buf, "SHORT " );
                    } else {
                        strcat( buf, "short " );
                    }
                }
            }
#endif
            strcat( buf, JmpLabel( op->disp, op->offset ) );
            break;
        case ADDR_ABS:
            strcat( buf, ToBrStr( op->disp, op->offset ) );
            break;
        case ADDR_BASE:
        case ADDR_INDEX:
        case ADDR_BASE_INDEX:
            if(
#ifdef O2A
                DO_UNIX  ||
#endif
                ( format & FORM_INDEX_IN ) == 0 ) {
                if( op->size != 0 ) {
                    strcat( buf, ToIndex( op->disp, op->offset ) );
                }
            }
            len = strlen( buf );
            buf[ len ] = START_INDEX;
            FormIndex( op, tmp_buff );
            if( format & FORM_REG_UPPER ) {
                ZapUpper( tmp_buff );
            }
            strcpy( &buf[ len + 1 ], tmp_buff );
            if(
#ifdef O2A
                !DO_UNIX  &&
#endif
                ( format & FORM_INDEX_IN ) ) {
                if( op->size != 0 ) {
                    name = ToIndex( op->disp, op->offset );
                    if( *name != '+' && *name != '-' ) {
                        strcat( buf, "+" );
                    }
                    strcat( buf, name );
                }
            }
            len = strlen( buf );
            buf[ len ] = END_INDEX;
            buf[ len + 1 ] = '\0';
            break;
        case ADDR_SEG_OFFSET:
            /* modifier or seg override */
            strcat( buf, ToSegStr( op->disp, (op+1)->disp, op->offset ) );
            break;
        case ADDR_ES_DI:
        case ADDR_ES_EDI:
            /* we have an overridden string instruction */
            ptr = DumpOverride( tmp_buff, ES_REG );
            *ptr++ = START_INDEX;
            strcpy( ptr,
                X86RegisterName[ op->mode == ADDR_ES_DI ? DI_REG : EDI_REG ] );
            ptr += strlen( ptr );
            *ptr++ = END_INDEX;
            *ptr = '\0';
            if( format & FORM_REG_UPPER ) ZapUpper( tmp_buff );
            strcat( buf, tmp_buff );
            break;
        case ADDR_WTK:
            {
                char * tmpstr;
                wop_type tmptype = (wop_type)op->size;
                if( tmptype == WST  ||  tmptype == ANY_SINGLE ) {
                    tmpstr = "ws";
                } else {
                    tmpstr = "wd";
                }
                strcat( buf, tmpstr );
                itoa( (int)op->disp, &buf[ strlen( buf ) ], 10 );
            }
            break;
        case ADDR_WTK_OPCODE:
            strcat( buf, InsName[ op->disp ] );
            break;
        }
    }
    if( CurrIns.pref & EMU_INTERRUPT ) {
        strcat( buf, "; int " );
        strcat( buf, ToStr( CurrIns.op[ OP_3 ].disp, 2, -1 ) );
    }
}