2014-09-09 20:49 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)

* include/hbvm.h
  * src/vm/hvm.c
    + added new HVM function: hb_vmTryEval()
      This function tries to execute given block or function
      inside BEGIN SEQUENCE / RECOVER oErr / END SEQUENCE statement.
      It return HB_TRUE if it was executed without any problem and
      HB_FALSE otherwise. Result or RTE object is stored in 1-st
      parameter and should be freed by the caller using hb_itemRelese()

  * src/debug/dbgentry.c
    ! use hb_vmTryEval() instead of hb_itemDo() to evaluate trace point
      expressions. Now debugger does not crash when user sets tracepoint
      expression which cannot be evaluated in executed context.
    ! allow to use expressions with more then 99 variables
    ! added missing protections against GPF when wrong parameters are
      passed to __dbg*() functions
    * keep original trace and watch point expression for farther
      processing
    * replaced IS_IDENT_*() macros with HB_IS*IDCHAR()
    + added new debuger function:
         __dbgGetWatchPoints() -> <aWatchTracePoints>
      <aWatchTracePoints> contains subarrays describing trace and watch
      points:
         { <cExpression>, <lTracePoint>, <lValid>, <xResult> }
      It was the last function necessary to extract all information
      about debugged context from core internals. Now it's possible
      to create fully functional standalone debugger without storing
      and updating locally any information about debugger state.
      All such information can be accessed at any time using __dbg*()
      functions.
      It should greatly simplify creating 3-rd party debuggers like
      HWDebug or HBQTDebug.

  * src/debug/debugger.prg
    ! fixed callstack window updating during tracing and stepping.
      Tanks to Rolf for reporting the problem.
This commit is contained in:
Przemysław Czerpak
2014-09-09 20:49:09 +02:00
parent e31d7b4ca7
commit dfb6288137
5 changed files with 333 additions and 101 deletions

View File

@@ -286,6 +286,35 @@ static PHB_ITEM hb_dbgActivateBreakArray( HB_DEBUGINFO * info )
}
static PHB_ITEM hb_dbgActivateWatchArray( HB_DEBUGINFO * info )
{
int i, j;
PHB_ITEM pArray = hb_itemArrayNew( info->nWatchPoints );
for( i = 0; i < info->nWatchPoints; i++ )
{
PHB_ITEM pWatch = hb_arrayGetItemPtr( pArray, i + 1 ), xValue;
for( j = 0; j < info->nTracePoints; j++ )
{
if( info->aTrace[ j ].nIndex == i )
break;
}
xValue = hb_dbgEval( info, &info->aWatch[ i ] );
hb_arrayNew( pWatch, 4 );
hb_arraySetC( pWatch, 1, info->aWatch[ i ].szExpr );
hb_arraySetL( pWatch, 2, j < info->nTracePoints );
hb_arraySetL( pWatch, 3, xValue != NULL );
if( xValue )
{
hb_arraySetForward( pWatch, 4, xValue );
hb_itemRelease( xValue );
}
}
return pArray;
}
static PHB_ITEM hb_dbgActivateModuleArray( void )
{
PHB_ITEM pArray;
@@ -568,20 +597,23 @@ static const char * hb_dbgStripModuleName( const char * szName )
void hb_dbgAddBreak( void * handle, const char * szModule, int nLine, const char * szFunction )
{
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
HB_BREAKPOINT * pBreak;
if( szModule || szFunction )
{
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
HB_BREAKPOINT * pBreak;
pBreak = ARRAY_ADD( HB_BREAKPOINT, info->aBreak, info->nBreakPoints );
if( szModule )
pBreak->szModule = hb_strdup( hb_dbgStripModuleName( szModule ) );
else
pBreak->szModule = NULL;
pBreak->nLine = nLine;
pBreak = ARRAY_ADD( HB_BREAKPOINT, info->aBreak, info->nBreakPoints );
if( szModule )
pBreak->szModule = hb_strdup( hb_dbgStripModuleName( szModule ) );
else
pBreak->szModule = NULL;
pBreak->nLine = nLine;
if( szFunction )
pBreak->szFunction = hb_strdup( szFunction );
else
pBreak->szFunction = NULL;
if( szFunction )
pBreak->szFunction = hb_strdup( szFunction );
else
pBreak->szFunction = NULL;
}
}
@@ -815,20 +847,23 @@ static void hb_dbgAddVar( int * nVars, HB_VARINFO ** aVars, const char * szName,
void hb_dbgAddWatch( void * handle, const char * szExpr, HB_BOOL bTrace )
{
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
HB_WATCHPOINT * pWatch;
pWatch = ARRAY_ADD( HB_WATCHPOINT, info->aWatch, info->nWatchPoints );
pWatch->szExpr = hb_strdup( szExpr );
pWatch->pBlock = NULL;
pWatch->nVars = 0;
if( bTrace )
if( szExpr )
{
HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
HB_WATCHPOINT * pWatch;
pTrace->nIndex = info->nWatchPoints - 1;
pTrace->xValue = hb_dbgEval( info, pWatch );
pWatch = ARRAY_ADD( HB_WATCHPOINT, info->aWatch, info->nWatchPoints );
pWatch->szExpr = hb_strdup( szExpr );
pWatch->pBlock = NULL;
pWatch->nVars = 0;
if( bTrace )
{
HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
pTrace->nIndex = info->nWatchPoints - 1;
pTrace->xValue = hb_dbgEval( info, pWatch );
}
}
}
@@ -981,7 +1016,11 @@ static PHB_ITEM hb_dbgEval( HB_DEBUGINFO * info, HB_WATCHPOINT * watch )
int i;
info->bInside = HB_TRUE;
xResult = hb_itemDo( watch->pBlock, 1, aNewVars );
if( ! hb_vmTryEval( &xResult, watch->pBlock, 1, aNewVars ) )
{
hb_itemRelease( xResult );
xResult = NULL;
}
info->bInside = bInside;
for( i = 0; i < watch->nVars; i++ )
@@ -1022,13 +1061,14 @@ static PHB_ITEM hb_dbgEvalMacro( const char * szExpr, PHB_ITEM pItem )
}
#define IS_IDENT_START( c ) HB_ISFIRSTIDCHAR( ( HB_UCHAR ) ( c ) )
#define IS_IDENT_CHAR( c ) HB_ISNEXTIDCHAR( ( HB_UCHAR ) ( c ) )
static int hb_dbgEvalSubstituteVar( HB_WATCHPOINT * watch, char * szWord, int nStart, int nLen )
static int hb_dbgEvalSubstituteVar( HB_WATCHPOINT * watch,
char * szWord, int nStart, int nLen,
char ** pszOrig )
{
char buf[ 16 ];
char * szExpr;
HB_SIZE n;
int j;
char * t;
for( j = 0; j < watch->nVars; j++ )
{
@@ -1041,16 +1081,20 @@ static int hb_dbgEvalSubstituteVar( HB_WATCHPOINT * watch, char * szWord, int nS
else
hb_xfree( szWord );
t = ( char * ) hb_xgrab( strlen( watch->szExpr ) - nLen + 9 + 1 );
memmove( t, watch->szExpr, nStart );
memmove( t + nStart, "__dbg[", 6 );
t[ nStart + 6 ] = '0' + ( char ) ( ( j + 1 ) / 10 );
t[ nStart + 7 ] = '0' + ( char ) ( ( j + 1 ) % 10 );
t[ nStart + 8 ] = ']';
hb_strncpy( t + nStart + 9, watch->szExpr + nStart + nLen, strlen( watch->szExpr ) - nLen - nStart );
hb_xfree( watch->szExpr );
watch->szExpr = t;
return nStart + 9;
n = strlen( watch->szExpr );
j = hb_snprintf( buf, sizeof( buf ), "__dbg[%d]", j + 1 );
szExpr = ( char * ) hb_xgrab( n - nLen + j + 1 );
memcpy( szExpr, watch->szExpr, nStart );
memcpy( szExpr + nStart, buf, j );
memcpy( szExpr + nStart + j, watch->szExpr + nStart + nLen, n - nLen - nStart );
szExpr[ n + j - nLen ] = '\0';
if( * pszOrig == NULL )
* pszOrig = watch->szExpr;
else
hb_xfree( watch->szExpr );
watch->szExpr = szExpr;
return nStart + j;
}
@@ -1059,7 +1103,7 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
int i = 0;
PHB_ITEM pBlock;
HB_BOOL bAfterId = HB_FALSE;
char * s;
char * szBlock, * szOrig = NULL;
HB_ISIZ buffsize;
watch->nVars = 0;
@@ -1067,13 +1111,13 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
{
char c = watch->szExpr[ i ];
if( IS_IDENT_START( c ) )
if( HB_ISFIRSTIDCHAR( c ) )
{
int nStart = i, nLen;
int j = i;
char * szWord;
while( c && IS_IDENT_CHAR( c ) )
while( c && HB_ISNEXTIDCHAR( c ) )
c = watch->szExpr[ ++j ];
nLen = j - i;
@@ -1091,14 +1135,14 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
{
i += 2;
while( ( c = watch->szExpr[ i ] ) != '\0' && IS_IDENT_CHAR( c ) )
while( ( c = watch->szExpr[ i ] ) != '\0' && HB_ISNEXTIDCHAR( c ) )
i++;
continue;
}
}
szWord = hb_strupr( hb_strndup( watch->szExpr + nStart, nLen ) );
i = hb_dbgEvalSubstituteVar( watch, szWord, nStart, nLen );
i = hb_dbgEvalSubstituteVar( watch, szWord, nStart, nLen, &szOrig );
bAfterId = HB_TRUE;
continue;
}
@@ -1128,11 +1172,11 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
}
if( c == ':' ||
( c == '-' && watch->szExpr[ i + 1 ] == '>' &&
IS_IDENT_START( watch->szExpr[ i + 2 ] ) ) )
HB_ISFIRSTIDCHAR( watch->szExpr[ i + 2 ] ) ) )
{
if( c == ':' && watch->szExpr[ i + 1 ] == ':' )
{
i = hb_dbgEvalSubstituteVar( watch, hb_strdup( "SELF" ), i, 1 );
i = hb_dbgEvalSubstituteVar( watch, hb_strdup( "SELF" ), i, 1, &szOrig );
bAfterId = HB_TRUE;
continue;
}
@@ -1142,7 +1186,7 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
i++;
while( watch->szExpr[ i ] && IS_IDENT_CHAR( watch->szExpr[ i ] ) )
while( watch->szExpr[ i ] && HB_ISNEXTIDCHAR( watch->szExpr[ i ] ) )
i++;
bAfterId = HB_TRUE;
@@ -1189,18 +1233,24 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
buffsize = 8 + strlen( watch->szExpr ) + 1;
s = ( char * ) hb_xgrab( buffsize + 1 );
hb_strncpy( s, "{|__dbg|", buffsize );
hb_strncat( s, watch->szExpr, buffsize );
hb_strncat( s, "}", buffsize );
szBlock = ( char * ) hb_xgrab( buffsize + 1 );
hb_strncpy( szBlock, "{|__dbg|", buffsize );
hb_strncat( szBlock, watch->szExpr, buffsize );
hb_strncat( szBlock, "}", buffsize );
pBlock = hb_itemNew( NULL );
if( ! hb_dbgEvalMacro( s, pBlock ) )
if( ! hb_dbgEvalMacro( szBlock, pBlock ) )
{
hb_itemRelease( pBlock );
pBlock = NULL;
}
hb_xfree( s );
hb_xfree( szBlock );
if( szOrig != NULL )
{
hb_xfree( watch->szExpr );
watch->szExpr = szOrig;
}
return pBlock;
}
@@ -1417,34 +1467,38 @@ static int hb_dbgIsBreakPoint( HB_DEBUGINFO * info, const char * szModule, int n
HB_BOOL hb_dbgIsValidStopLine( void * handle, const char * szModule, int nLine )
{
HB_BOOL fResult = HB_FALSE;
HB_ISIZ nModules;
HB_ISIZ i;
if( szModule )
{
HB_ISIZ nModules;
HB_ISIZ i;
#if 0
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
#endif
HB_SYMBOL_UNUSED( handle );
HB_SYMBOL_UNUSED( handle );
szModule = hb_dbgStripModuleName( szModule );
szModule = hb_dbgStripModuleName( szModule );
HB_DBGCOMMON_LOCK();
nModules = hb_itemSize( s_common.pStopLines );
for( i = 1; i <= nModules; i++ )
{
PHB_ITEM pEntry = hb_arrayGetItemPtr( s_common.pStopLines, i );
if( FILENAME_EQUAL( hb_arrayGetCPtr( pEntry, 1 ), szModule ) )
HB_DBGCOMMON_LOCK();
nModules = hb_itemSize( s_common.pStopLines );
for( i = 1; i <= nModules; i++ )
{
int nMin = hb_arrayGetNL( pEntry, 2 );
int nOfs = nLine - nMin;
PHB_ITEM pEntry = hb_arrayGetItemPtr( s_common.pStopLines, i );
if( nOfs >= 0 && ( HB_SIZE ) ( nOfs >> 3 ) < hb_arrayGetCLen( pEntry, 3 ) )
fResult = ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs >> 3 ] & ( 1 << ( nOfs & 0x07 ) ) ) != 0;
if( FILENAME_EQUAL( hb_arrayGetCPtr( pEntry, 1 ), szModule ) )
{
int nMin = hb_arrayGetNL( pEntry, 2 );
int nOfs = nLine - nMin;
break;
if( nOfs >= 0 && ( HB_SIZE ) ( nOfs >> 3 ) < hb_arrayGetCLen( pEntry, 3 ) )
fResult = ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs >> 3 ] & ( 1 << ( nOfs & 0x07 ) ) ) != 0;
break;
}
}
HB_DBGCOMMON_UNLOCK();
}
HB_DBGCOMMON_UNLOCK();
return fResult;
}
@@ -1559,11 +1613,14 @@ void hb_dbgSetToCursor( void * handle, const char * szModule, int nLine )
{
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
szModule = hb_dbgStripModuleName( szModule );
if( szModule )
{
szModule = hb_dbgStripModuleName( szModule );
info->bToCursor = HB_TRUE;
info->szToCursorModule = hb_strdup( szModule );
info->nToCursorLine = nLine;
info->bToCursor = HB_TRUE;
info->szToCursorModule = hb_strdup( szModule );
info->nToCursorLine = nLine;
}
}
@@ -1579,31 +1636,35 @@ void hb_dbgSetTrace( void * handle )
void hb_dbgSetWatch( void * handle, int nWatch, const char * szExpr, HB_BOOL bTrace )
{
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
HB_WATCHPOINT * pWatch = &info->aWatch[ nWatch ];
int i;
hb_dbgClearWatch( pWatch );
pWatch->szExpr = hb_strdup( szExpr );
pWatch->pBlock = NULL;
for( i = 0; i < info->nTracePoints; i++ )
if( nWatch >= 0 && nWatch < info->nWatchPoints && szExpr )
{
HB_TRACEPOINT * pTrace = &info->aTrace[ i ];
HB_WATCHPOINT * pWatch = &info->aWatch[ nWatch ];
int i;
if( pTrace->nIndex == nWatch )
hb_dbgClearWatch( pWatch );
pWatch->szExpr = hb_strdup( szExpr );
pWatch->pBlock = NULL;
for( i = 0; i < info->nTracePoints; i++ )
{
if( pTrace->xValue )
hb_itemRelease( pTrace->xValue );
HB_TRACEPOINT * pTrace = &info->aTrace[ i ];
ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i );
break;
if( pTrace->nIndex == nWatch )
{
if( pTrace->xValue )
hb_itemRelease( pTrace->xValue );
ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i );
break;
}
}
}
if( bTrace )
{
HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
if( bTrace )
{
HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
pTrace->nIndex = nWatch;
pTrace->xValue = hb_dbgEval( info, pWatch );
pTrace->nIndex = nWatch;
pTrace->xValue = hb_dbgEval( info, pWatch );
}
}
}
@@ -1738,9 +1799,9 @@ HB_FUNC( __DBGGETEXPRVALUE )
PHB_ITEM pItem;
if( HB_ISCHAR( 2 ) )
pItem = hb_dbgGetExpressionValue( hb_parptr( 1 ), hb_parc( 2 ) );
pItem = hb_dbgGetExpressionValue( ptr, hb_parc( 2 ) );
else
pItem = hb_dbgGetWatchValue( hb_parptr( 1 ), hb_parni( 2 ) - 1 );
pItem = hb_dbgGetWatchValue( ptr, hb_parni( 2 ) - 1 );
if( pItem )
{
@@ -1787,10 +1848,11 @@ HB_FUNC( __DBGDELBREAK )
HB_FUNC( __DBGISBREAK )
{
void * ptr = hb_parptr( 1 );
const char * szModule = hb_parc( 2 );
if( ptr )
if( ptr && szModule )
hb_retni( hb_dbgIsBreakPoint( ( HB_DEBUGINFO * ) ptr,
hb_dbgStripModuleName( hb_parc( 2 ) ),
hb_dbgStripModuleName( szModule ),
hb_parni( 3 ) ) );
}
@@ -1834,6 +1896,14 @@ HB_FUNC( __DBGCNTWATCH )
hb_retni( hb_dbgCountWatch( ptr ) );
}
HB_FUNC( __DBGGETWATCHPOINTS )
{
void * ptr = hb_parptr( 1 );
if( ptr )
hb_itemReturnRelease( hb_dbgActivateWatchArray( ( HB_DEBUGINFO * ) ptr ) );
}
HB_FUNC( __DBGGETMODULENAME )
{
void * ptr = hb_parptr( 1 );

View File

@@ -444,6 +444,9 @@ METHOD PROCEDURE Activate() CLASS HBDebugger
ENDIF
lFirst := .T.
ENDIF
IF ::lShowCallStack
::oWndStack:Show()
ENDIF
::LoadVars()
::ShowVars()