dbgchain.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 276 行

C
276
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <string.h>
#include <limits.h>
#include "dbgdefn.h"
#include "dbginfo.h"
#include "dbglit.h"
#include "dbgtback.h"
#include "dbginfo.h"
#include "dbgmem.h"
#include "dbgchain.h"
#include "dui.h"
#include "mad.h"

extern char             *TxtBuff;
extern update_list      WndFlags;

extern address          FindLclBlock( address addr );
extern int              AddrComp(address ,address );
extern void             GoToAddr( address addr );
extern bool             DlgBreak(address);
extern char             *StrCopy(char*,char*);
extern char             *CopySourceLine( cue_handle * );
extern unsigned         LineNumLkup(address);
extern void             UnAsm( address addr, unsigned, char *buff );
extern char             *DupStr(char*);
extern void             SetStackPos( location_context *lc, int pos );
extern int              GetStackPos();
extern char             *CnvNearestAddr( address, char *, unsigned );
extern char             *Format(char *,char *,... );

#define MODEST_CALL_LEVEL       20
#define MODEST_INCREMENT        10

address FindNextIns( address a )
{
    mad_disasm_data     *dd;

    _AllocA( dd, MADDisasmDataSize() );
    MADDisasm( dd, &a, 0 );
    return( a );
}


static void FreeChainInfo( traceback *curr, int start, int end )
{
    int         i;

    for( i = start; i < end; ++i ) {
        DbgFree( curr->chain[ i ].source_line );
        DbgFree( curr->chain[ i ].symbol );
        curr->chain[ i ].source_line = NULL;
        curr->chain[ i ].symbol = NULL;
    }
}


static bool ReAllocChain( traceback *curr, int new_size )
{
    call_chain  *new_chain;
    call_chain  *chain;

    chain = curr->chain;
    if( new_size >= (UINT_MAX / sizeof(call_chain)) ) return( FALSE );
    new_chain = DbgAlloc( new_size * sizeof(call_chain) );
    if( new_chain == NULL ) return( FALSE );
    memset( new_chain, 0, new_size*sizeof( call_chain ) );
    memcpy( new_chain, chain, curr->current_depth * sizeof(call_chain) );
    DbgFree( chain );
    curr->chain = new_chain;
    curr->allocated_size = new_size;
    return( TRUE );
}

static bool EarlyOut( cached_traceback *tb, address execution, address frame )
{
    call_chain  *chain;
    int         new_size;
    int         i;
    traceback   *curr;
    traceback   *prev;

    curr = tb->curr;
    prev = tb->prev;
    for( i = 0; i < prev->total_depth; ++i ) {
        chain = &prev->chain[ i ];
        if( AddrComp( chain->lc.execution, execution ) != 0 ) continue;
        if( AddrComp( chain->lc.frame, frame ) != 0 ) continue;
        new_size = curr->current_depth + prev->total_depth - i;
        if( new_size > curr->allocated_size ) {
            if( !ReAllocChain( curr, new_size ) ) return( FALSE );
        }
        curr->clean_size = prev->total_depth - i;
        memcpy( &curr->chain[ curr->current_depth ], chain,
                curr->clean_size * sizeof( call_chain ) );
        curr->current_depth = new_size;
        while( i < prev->total_depth ) {
            chain->source_line = NULL; // since we copied the ptr
            chain->symbol = NULL; // since we copied the ptr
            ++chain;
            ++i;
        }
        return( TRUE );
    }
    return( FALSE );
}


static CALL_CHAIN_RTN RecordTraceBackInfo;
static bool RecordTraceBackInfo( call_chain_entry *entry, void *_tb )
{
    address     prev_ins;
    address     execution;
    call_chain  *chain;
    traceback   *curr;
    mad_disasm_data     *dd;
    DIPHDL( cue, ch );
    cached_traceback *tb = _tb;

    execution = entry->lc.execution;
    curr = tb->curr;
    if( curr->current_depth >= curr->allocated_size ) {
        if( !ReAllocChain( curr, curr->allocated_size + MODEST_INCREMENT ) ) {
            return( FALSE );
        }
    }
    if( curr->current_depth != 0 ) {
        _AllocA( dd, MADDisasmDataSize() );
        prev_ins = execution;
        if( MADDisasm( dd, &prev_ins, -1 ) == MS_OK ) {
            execution.mach.offset -= MADDisasmInsSize( dd );
        }
    }
    if( EarlyOut( tb, execution, entry->lc.frame ) ) return( FALSE );
    chain = &curr->chain[ curr->current_depth ];
    chain->lc = entry->lc;
    chain->lc.execution = execution;
    chain->open = FALSE;
    chain->source_line = NULL;
    chain->symbol = NULL;
    if( DeAliasAddrCue( NO_MOD, execution, ch ) != SR_NONE ) {
        chain->source_line = CopySourceLine( ch );
    }
    CnvNearestAddr( chain->lc.execution, TxtBuff, TXT_LEN );
    DbgFree( chain->symbol );
    chain->symbol = DupStr( TxtBuff );
    chain->sym_len = 0;
    curr->current_depth++;
    return( TRUE );
}

static traceback *DoInitTraceBack( traceback *curr )
{
    curr->chain = DbgMustAlloc( MODEST_CALL_LEVEL * sizeof( call_chain ) );
    memset( curr->chain, 0, MODEST_CALL_LEVEL * sizeof( call_chain ) );
    curr->allocated_size = MODEST_CALL_LEVEL;
    curr->total_depth = 0;
    return( curr );
}

void InitTraceBack( cached_traceback *tb )
{
    tb->curr = DoInitTraceBack( &tb->a );
    tb->prev = DoInitTraceBack( &tb->b );
}

void FiniTraceBack( cached_traceback *tb )
{
    FreeChainInfo( tb->curr, 0, tb->curr->total_depth );
    FreeChainInfo( tb->prev, 0, tb->prev->total_depth );
    DbgFree( tb->curr->chain );
    DbgFree( tb->prev->chain );
}

void UpdateTraceBack( cached_traceback *tb )
{
    traceback           *curr;
    traceback           *prev;

    curr = tb->prev;
    prev = tb->curr;
    tb->curr = curr;
    tb->prev = prev;
    curr->current_depth = 0;
    if( WndFlags & UP_SYM_CHANGE ) {
        FreeChainInfo( prev, 0, prev->total_depth );
        prev->total_depth = 0;
    }
    curr->clean_size = 0;
    WalkCallChain( RecordTraceBackInfo, tb );
    FreeChainInfo( curr, curr->current_depth, curr->total_depth );
    FreeChainInfo( prev, 0, prev->total_depth );
    curr->total_depth = curr->current_depth;
}

call_chain *GetCallChain( cached_traceback *tb, int row )
{
    traceback   *curr;

    curr = tb->curr;
    if( row >= 0 && row < curr->total_depth ) {
        return( &curr->chain[ curr->total_depth - 1 - row ] );
    } else {
        return( NULL );
    }
}

void ShowCalls()
{
    cached_traceback    tb;
    int                 i;
    char                buff[TXT_LEN];
    char                *source;
    call_chain          *chain;

    InitTraceBack( &tb );
    UpdateTraceBack( &tb );
    i = 0;
    for( ;; ) {
        chain = GetCallChain( &tb, i++ );
        if( chain == NULL ) break;
        if( chain->source_line != NULL ) {
            source = chain->source_line;
        } else {
            UnAsm( chain->lc.execution, TXT_LEN, buff );
            source = buff;
        }
        Format( TxtBuff, "%s: %s", chain->symbol, source );
        DUIDlgTxt( TxtBuff );
    }
    FiniTraceBack( &tb );
}

void UnWindToFrame( call_chain *chain, int row, int rows )
/********************************************************/
{
    address     ip;

    ip = chain->lc.execution;
    if( row != 0 ) {
        chain->lc.execution = FindNextIns( ip );
    }
    SetStackPos( &chain->lc, -( rows - 1 - row ) );
    chain->lc.execution = ip;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?