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 + -
显示快捷键?