drloc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 703 行 · 第 1/2 页

C
703
字号
            top[0] = stk2 - stk1;
            break;
        case DW_OP_mod:
            top[0] = stk2 % stk1;
            break;
        case DW_OP_mul:
            top[0] = stk2 * stk1;
            break;
        case DW_OP_neg:
            top[0] = -stk1;
            break;
        case DW_OP_not:
            top[0] = ~stk1;
            break;
        case DW_OP_or:
            top[0] = stk2 | stk1;
            break;
        case DW_OP_plus:
            top[0] = stk2 + stk1;
            break;
        case DW_OP_plus_uconst:
            top[0] += op1;
            break;
        case DW_OP_shl:
            top[0] = stk2 << stk1;
            break;
        case DW_OP_shr:
            top[0] = stk2 >> stk1;
            break;
        case DW_OP_shra:
            top[0] = (int_32) stk2 >> stk1;
            break;
        case DW_OP_xor:
            top[0] = stk2 ^ stk1;
            break;
        case DW_OP_eq:
            top[0] = (int_32)stk2 == (int_32)stk1;
            break;
        case DW_OP_ge:
            top[0] = (int_32)stk2 >= (int_32)stk1;
            break;
        case DW_OP_gt:
            top[0] = (int_32)stk2 > (int_32)stk1;
            break;
        case DW_OP_le:
            top[0] = (int_32)stk2 <= (int_32)stk1;
            break;
        case DW_OP_lt:
            top[0] = (int_32)stk2 < (int_32)stk1;
            break;
        case DW_OP_ne:
            top[0] = (int_32)stk2 != (int_32)stk1;
            break;
        case DW_OP_bra:
            stk1 = top[0];
            Pop( top );
            if( stk1 == 0 ) break;  /* conditional fall thru */
        case DW_OP_skip:
            p += op1;
            break;
        case DW_OP_nop:
            break;
        case DW_OP_piece:
            /* call got piece */
            if( !callbck->ref( d, top[0], op1, kind ) ) {
                return;
            }
            Pop( top );
            kind = DR_LOC_ADDR;
            break;
        default:
            DWREXCEPT( DREXCEP_BAD_DBG_INFO );
        }
    }
    while( !IsEmpty( top, stk_top) ) {
        if( !callbck->ref( d, top[0], addr_size, kind ) ) {
            return;
        }
        Pop( top );
        kind = DR_LOC_ADDR;
    }
    return;
}

static dr_handle SearchLocList( uint_32 start, uint_32 context,
                                uint addr_size )
/*************************************************************/
// Search loc list for context return start of loc_expr block or NULL
{
    uint_32     low;
    uint_32     high;
    int         len;
    dr_handle   p;

    p =  DWRCurrNode->sections[DR_DEBUG_LOC].base;
    if( p == NULL ){
        DWREXCEPT( DREXCEP_BAD_DBG_INFO );
        return( NULL );
    }
    p += start;
    for( ;; ) {
        low = ReadVWord( p, addr_size );
        p+= addr_size;
        high = ReadVWord( p, addr_size );
        p+= addr_size;
        if( low == high && low == 0 ) {
            p = NULL;
            break;
        }
        if( low <= context && context < high ) break;
        len = DWRVMReadWord( p );
        p+= sizeof(uint_16);
        p += len;
    }
    return( p );
}

static int DWRLocExpr( dr_handle        var,
                       dr_handle        abbrev,
                       dr_handle        info,
                       dr_loc_callbck   *callbck,
                       void             *d )
/***********************************************/
{
    unsigned    form;
    uint_32     size;
    char        loc_buff[256];
    char        *expr;
    int         ret;
    dr_handle   loclist;
    uint_32     context;
    int         addr_size;

    addr_size = DWRGetAddrSize( DWRFindCompileUnit( info ) );
    form = DWRVMReadULEB128( &abbrev );
    ret = TRUE;
    for( ;; ) {
        switch( form ) {
        case DW_FORM_block1:
            size  = DWRVMReadByte( info );
            info += sizeof(unsigned_8);
            goto end_loop;
        case DW_FORM_block2:
             size = DWRVMReadWord( info );
             info += sizeof(unsigned_16);
            goto end_loop;
        case DW_FORM_block4:
            size = DWRVMReadDWord( info );
            info += sizeof(unsigned_32);
            goto end_loop;
        case DW_FORM_block:
            size = DWRVMReadULEB128( &info );
            goto end_loop;
        case DW_FORM_indirect:
            form = DWRVMReadULEB128( &info );
            break;
        case DW_FORM_ref_addr:
        case DW_FORM_data4:
            if( !callbck->live( d, &context ) ) {
                ret = FALSE;
                goto exit;
            }
            loclist =  DWRVMReadDWord( info );
            info = SearchLocList( loclist, context, addr_size );
            if( info == NULL ) {
                ret = FALSE;
                goto exit;
            }
            form = DW_FORM_block2;
            break;
        case DW_FORM_data2: //TODO kludge
            ret = DWRVMReadWord( info );
            ret = callbck->ref( d, ret, addr_size, DR_LOC_ADDR );
            goto exit;
        default:
            ret = FALSE;
            goto exit;
        }
    } end_loop:;
    if( size > sizeof( loc_buff ) ) {
         expr = DWRALLOC( size );
    } else if( size > 0 ) {
        expr = loc_buff;
    } else {
        ret = FALSE;
        goto exit;
    }
    ret = TRUE;
    DWRVMRead( info, expr, size );
    DoLocExpr( expr, size, addr_size, callbck, d, var );
    if( size > sizeof( loc_buff ) ) {
        DWRFREE( expr );
    }
exit:
    return( ret );
}

extern int DRLocBasedAT( dr_handle      var,
                         dr_loc_callbck *callbck,
                         void           *d )
/***********************************************/
{
    dw_tagnum   tag;
    dw_atnum    at;
    dr_handle   abbrev;
    dr_handle   sym = var;
    int         ret;

    abbrev = DWRVMReadULEB128( &var );
    abbrev = DWRLookupAbbrev( var, abbrev );
    tag = DWRVMReadULEB128( &abbrev );
    ++abbrev; /* skip child flag */
    switch( tag ) {
        break;
    case DW_TAG_member:
    case DW_TAG_inheritance:
        at = DW_AT_data_member_location;
        break;
    case DW_TAG_subprogram:
        at = DW_AT_vtable_elem_location;
        break;
    default:
        return( FALSE );
    }
    if( DWRScanForAttrib( &abbrev, &var, at ) != 0 ) {
        ret = DWRLocExpr( sym, abbrev, var, callbck, d );
    } else {
        if( tag == DW_TAG_member ) {
            // For members of a union, it is valid not to have any
            // DW_AT_data_member_location attribute (we might want to check
            // that we are in fact dealing with a union here). Just create
            // a dummy location "+0".
            uint_8      dummy_loc[] = { DW_OP_lit0, DW_OP_plus };
            int         addr_size;

            addr_size = DWRGetAddrSize( DWRFindCompileUnit( var ) );
            DoLocExpr( dummy_loc, sizeof(dummy_loc), addr_size, callbck, d, var );
            ret = TRUE;
        } else {
            ret = FALSE;
        }
    }
    return( ret );
}

extern int DRLocationAT( dr_handle      var,
                         dr_loc_callbck *callbck,
                         void           *d )
/***********************************************/
{
    dw_tagnum   tag;
    dw_atnum    at;
    dr_handle   abbrev;
    dr_handle   sym = var;
    int         ret;

    abbrev = DWRVMReadULEB128( &var );
    abbrev = DWRLookupAbbrev( var, abbrev );
    tag = DWRVMReadULEB128( &abbrev );
    ++abbrev; /* skip child flag */
    switch( tag ) {
    case DW_TAG_common_block:
    case DW_TAG_formal_parameter:
    case DW_TAG_variable:
    case DW_TAG_subprogram:
        at = DW_AT_location;
        break;
    case DW_TAG_string_type:
        at = DW_AT_string_length;
        break;
    default:
        return( FALSE );
    }
    if( DWRScanForAttrib( &abbrev, &var, at ) != 0 ) {
         ret = DWRLocExpr( sym, abbrev, var, callbck, d );
    } else {
        ret = FALSE;
    }
    return( ret );
}

extern int DRParmEntryAT( dr_handle         var,
                          dr_loc_callbck    *callbck,
                          void              *d )
/***************************************************/
{
    dw_tagnum   tag;
    dr_handle   abbrev;
    dr_handle   sym = var;
    int         ret;

    abbrev = DWRVMReadULEB128( &var );
    abbrev = DWRLookupAbbrev( var, abbrev );
    tag = DWRVMReadULEB128( &abbrev );
    ++abbrev; /* skip child flag */
    if( DWRScanForAttrib( &abbrev, &var, DW_AT_WATCOM_parm_entry ) != 0 ) {
         ret = DWRLocExpr( sym, abbrev, var, callbck, d );
    } else {
        ret = FALSE;
    }
    return( ret );
}
extern dr_handle DRStringLengthAT( dr_handle str )
/************************************************/
{
    dr_handle   abbrev;

    abbrev = DWRGetAbbrev( &str );
    if( DWRScanForAttrib( &abbrev, &str, DW_AT_string_length ) != 0 ) {
         return( str );
    } else {
         return( NULL );
    }
}

extern int DRRetAddrLocation( dr_handle      var,
                              dr_loc_callbck *callbck,
                              void           *d )
/****************************************************/
{
    dr_handle   abbrev;
    dr_handle   sym = var;
    int         ret;

    abbrev = DWRGetAbbrev( &var );
    if( DWRScanForAttrib( &abbrev, &var, DW_AT_return_addr ) != 0 ) {
         ret = DWRLocExpr( sym, abbrev, var, callbck, d );
    } else {
        ret = FALSE;
    }
    return( ret );
}

extern int DRSegLocation( dr_handle      var,
                          dr_loc_callbck *callbck,
                          void           *d )
/************************************************/
{
    dr_handle   abbrev;
    dr_handle   sym = var;
    int         ret;

    abbrev = DWRGetAbbrev( &var );
    if( DWRScanForAttrib( &abbrev, &var, DW_AT_segment ) != 0 ) {
         ret = DWRLocExpr( sym, abbrev, var, callbck, d );
    } else {
        ret = FALSE;
    }
    return( ret );
}

⌨️ 快捷键说明

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