drloc.c

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

C
703
字号
/****************************************************************************
*
*                            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:  DWARF reader location expression processing.
*
****************************************************************************/


#include "drpriv.h"
#include "drutils.h"
#include <stdlib.h>
#include <string.h>

static dw_locop_op const LocOpr[] = {
#define DW_LOC_OP( __n, __v )    __v,
#include "dwlocinf.h"
#undef DW_LOC_OP
};

static unsigned_32 ReadVWord( dr_handle where, int size )
//Read an int
{
    unsigned_32 ret;

    switch( size ) {
    case 1:
        ret = DWRVMReadByte( where );
        break;
    case 2:
        ret = DWRVMReadWord( where );
        break;
    case 4:
        ret = DWRVMReadDWord( where );
        break;
    }
    return( ret );
}
static uint_8 *DecodeULEB128( const uint_8 *input, uint_32 *value )
/*****************************************************************/
{
    uint_32     result;
    uint        shift;
    uint_8      in;

    result = 0;
    shift = 0;
    for( ;; ) {
        in = *input++;
        result |= ( in & 0x7f ) << shift;
        if( ( in & 0x80 ) == 0 ) break;
        shift += 7;
    }
    *value = result;
    return( (uint_8 *)input );
}

static uint_8 *DecodeLEB128( const uint_8 *input, uint_32 *value )
/****************************************************************/
{
    int_32      result;
    uint        shift;
    uint_8      in;

    result = 0;
    shift = 0;
    for( ;; ) {
        in = *input++;
        result |= ( in & 0x7f ) << shift;
        shift += 7;
        if( ( in & 0x80 ) == 0 ) break;
    }
    if( ( shift < 32 ) && ( in & 0x40 ) ) {
        result |= - ( 1 << shift );
    }
    *value = (uint_32)result;
    return( (uint_8 *)input );
}
//TODO: check stack bounds
static void DoLocExpr( char             *p,
                       int              length,
                       int              addr_size,
                       dr_loc_callbck   *callbck,
                       void             *d,
                       dr_handle        var )
{
    char            *end;
    dw_op           op;
    dw_locop_op     opr;
    uint_32         op1;
    uint_32         op2;
    uint_32         stk1;
    uint_32         stk2;
    uint_32         tmp;
    uint_32         stack[100];
    uint_32         *top;
    uint_32         *stk_top;
    dr_loc_kind     kind;

#define Pop( a )     (++a)
#define Push( a )    (--a)
#define IsEmpty( a, b )  ( (a) == (b) )
    end = &p[length];
    stk_top = &stack[100];
    top = stk_top;
    if( callbck->init!= NULL  ) {
        kind = callbck->init( d, &tmp );
        switch( kind ){
        case DR_LOC_NONE:
             kind = DR_LOC_ADDR;
             break;
        case DR_LOC_REG:
        case DR_LOC_ADDR:
            Push( top );
            top[0] = tmp;
        }
    } else {
        kind = DR_LOC_ADDR;
    }
    while( p  < end ) {
        op = *p;
        ++p;
        opr = LocOpr[ op ];
        /* decode operands */
        switch( opr ) {
        case DW_LOP_NOOP:
            break;
        case DW_LOP_ADDR:
            if( addr_size == 4 ) {
                op1 = *(uint_32 _WCUNALIGNED *)p;
                if( DWRCurrNode->byte_swap ) {
                    SWAP_32( op1 );
                }
            } else if( addr_size == 2 ) {
                op1 = *(uint_16 _WCUNALIGNED *)p;
                if( DWRCurrNode->byte_swap ) {
                    SWAP_16( op1 );
                }
            } else if( addr_size == 1 ) {
                op1 = *(uint_8 _WCUNALIGNED *)p;
            } else {
                op1 = 0;
            }
            p += addr_size;
            break;
        case DW_LOP_OPU1:
            op1 = *(uint_8 *)p;
            p += sizeof( uint_8 );
            break;
        case DW_LOP_OPS1:
            op1 = (int_32)*(int_8 *)p;
            p += sizeof(int_8 );
            break;
        case DW_LOP_OPU2:
            op1 = *(uint_16 _WCUNALIGNED *)p;
            p += sizeof(uint_16 );
            break;
        case DW_LOP_OPS2:
            op1 = (int_32)*(int_16 _WCUNALIGNED *)p;
            p += sizeof(int_16);
            break;
        case DW_LOP_OPS4:
            op1 = *(int_32 _WCUNALIGNED *)p;
            p += sizeof(int_32);
            break;
        case DW_LOP_OPU4:
            op1 = *(uint_32 _WCUNALIGNED *)p;
            p += sizeof(uint_32);
            break;
        case DW_LOP_U128:
            p = DecodeULEB128( p, &tmp );
            op1 = tmp;
            break;
        case DW_LOP_S128:
            p = DecodeLEB128( p, &tmp );
            op1 = tmp;
            break;
        case DW_LOP_U128_S128:
            p = DecodeULEB128( p, &tmp );
            op1 = tmp;
            p = DecodeLEB128( p, &tmp );
            op2 = tmp;
            break;
        case DW_LOP_LIT1:
            op1 = op-DW_OP_lit0;
            op = DW_OP_lit0;
            break;
        case DW_LOP_REG1:
            op1 = op-DW_OP_reg0;
            op = DW_OP_reg0;
            break;
        case DW_LOP_BRG1:
            op1 = op-DW_OP_breg0;
            op = DW_OP_breg0;
            p = DecodeLEB128( p, &tmp );
            op2 = tmp;
            break;
        case DW_LOP_STK2:
            stk2 = top[0];
            Pop( top );         /* drop thru */
        case DW_LOP_STK1:
            stk1 = top[0];
            break;
        default:
            DWREXCEPT( DREXCEP_BAD_DBG_INFO );
        }
        switch( op ) {
        case DW_OP_reg0:
        case DW_OP_regx:
            /* reg is location */
            Push( top );
            top[0] = op1;
            kind = DR_LOC_REG;
            break;
        case DW_OP_addr: {
            bool isfar;

            /* get contents of reg op1 */
            Push( top );
            top[0] = op1;
            if( (p != end) && ((*p == DW_OP_xderef) || (*p == DW_OP_xderef_size)) ) {
                isfar = TRUE;
            } else {
                isfar = FALSE;
            }
            if( !callbck->acon( d, top, isfar ) ) {
                return;
            }
        }   break;
        case DW_OP_lit0:
        case DW_OP_const1u:
        case DW_OP_const1s:
        case DW_OP_const2u:
        case DW_OP_const2s:
        case DW_OP_const4s:
        case DW_OP_const4u:
        case DW_OP_const8u:
        case DW_OP_const8s:
        case DW_OP_constu:
        case DW_OP_consts:
            Push( top );
            top[0] = op1;
            break;
        case DW_OP_fbreg:
        /* We should look at DW_AT_frame_base here, however at this
         * point the debugger seems to be able to figure out the base
         * correctly without it - at least assuming that it's (E)BP on x86.
         */
            Push( top );
            if( !callbck->frame( d, top ) ) {
                return;
            }
            top[0] += op1;
            break;
        case DW_OP_breg0:
        case DW_OP_bregx:
            /* get contents of reg op1 */
            Push( top );
            if( !callbck->reg( d, top, op1 ) ) {
                return;
            }
            top[0] += op2;
            break;
        case DW_OP_dup:
            stk1 = top[0];
            Push( top );
            top[0] = stk1;
            break;
        case DW_OP_drop:
            Pop( top );
            break;
        case DW_OP_over:
            stk1 = top[1];
            Push( top );
            top[0] = stk1;
            break;
        case DW_OP_pick:
            stk1 = top[op1];
            Push( top );
            top[0] = stk1;
            break;
        case DW_OP_swap:
            stk1 = top[0];
            top[0] = top[1];
            top[1] = stk1;
            break;
        case DW_OP_rot:
            stk1 = top[0];
            top[0] = top[1];
            top[1] = top[2];
            top[2] = stk1;
            break;
        case DW_OP_deref:
            op1 = addr_size; /* fall thru */
        case DW_OP_deref_size:
            /* dref addr */
            if( kind == DR_LOC_REG ) {  // indirect of reg name
                if( !callbck->reg( d, top, top[0] ) ) {
                    return;
                }
                kind = DR_LOC_ADDR;
            } else {
                if( !callbck->dref( d, top, top[0], op1 ) ) {
                    return;
                }
            }
            break;
        case DW_OP_xderef:
            op1 = addr_size; /* fall thru */
        case DW_OP_xderef_size:
           /*  xdref addr */
           stk1 = top[0];
           Pop( top );
            if( !callbck->drefx( d, top, stk1, top[0], op1 ) ) {
                return;
            }
           break;
        case DW_OP_abs:
            if( (int_32)stk1 < 0 ) {
                stk1 = -(int_32)stk1;
                top[0] =  stk1;
            }
            break;
        case DW_OP_and:
            top[0] = stk2 & stk1;
            break;
        case DW_OP_div:
            top[0] = stk2 / stk1;
            break;
        case DW_OP_minus:

⌨️ 快捷键说明

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