cvtype.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,020 行 · 第 1/5 页
C
2,020 行
/****************************************************************************
*
* 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: CodeView type support.
*
****************************************************************************/
#include <stddef.h>
#include <string.h>
#include "walloca.h"
#include "cvinfo.h"
#define UNKNOWN_TYPE_IDX ((unsigned short)-1)
#define PT_REALLY_CHAR 0x0070
static dip_status ImpTypeArrayInfo( imp_image_handle *ii,
imp_type_handle *array, location_context *lc,
array_info *ai, imp_type_handle *index );
extern dip_status ImpTypeInfo( imp_image_handle *ii,
imp_type_handle *it, location_context *lc, type_info *ti );
static dip_status TypeVMGetName( imp_image_handle *ii, virt_mem base,
char **namep, unsigned *lenp, lf_all **pp )
{
lf_all *p;
unsigned skip;
char *name;
numeric_leaf dummy;
if( base == 0 ) {
*namep = NULL;
*lenp = 0;
return( DS_OK );
}
/*
The "+ sizeof( unsigned_32 )" is to make sure that the GetNumLeaf's
have enough stuff mapped in to work.
*/
p = VMBlock( ii, base, sizeof( *p ) + sizeof( unsigned_32 ) );
if( p == NULL ) return( DS_ERR|DS_FAIL );
switch( p->common.code ) {
case LF_ARRAY:
skip = sizeof( lf_array );
break;
case LF_CLASS:
case LF_STRUCTURE:
name = GetNumLeaf( &p->class_ + 1, &dummy );
skip = name - (char *)p;
break;
case LF_UNION:
name = GetNumLeaf( &p->union_ + 1, &dummy );
skip = name - (char *)p;
break;
case LF_ENUM:
skip = sizeof( lf_enum );
break;
case LF_ENUMERATE:
name = GetNumLeaf( &p->enumerate + 1, &dummy );
skip = name - (char *)p;
break;
case LF_FRIENDFCN:
skip = sizeof( lf_friendfcn );
break;
case LF_MEMBER:
name = GetNumLeaf( &p->member + 1, &dummy );
skip = name - (char *)p;
break;
case LF_STMEMBER:
skip = sizeof( lf_stmember );
break;
case LF_METHOD:
skip = sizeof( lf_method );
break;
case LF_NESTEDTYPE:
skip = sizeof( lf_nestedtype );
break;
case LF_ONEMETHOD:
skip = sizeof( lf_onemethod );
switch( p->onemethod.f.attr.f.mprop ) {
case CV_VIRTUAL:
case CV_INTROVIRT:
case CV_PUREVIRT:
case CV_PUREINTROVIRT:
skip += sizeof( unsigned_32 );
break;
}
break;
default:
*namep = NULL;
*lenp = 0;
return( DS_OK );
}
/* A name can't be longer than 255 bytes */
p = VMBlock( ii, base, 256 + skip );
if( p == NULL ) return( DS_ERR|DS_FAIL );
name = (unsigned_8 *)p + skip;
*lenp = name[0];
*namep = &name[1];
if( pp != NULL ) *pp = p;
return( DS_OK );
}
static virt_mem TypeIndexVM( imp_image_handle *ii, unsigned idx )
{
cv_directory_entry *cde;
unsigned_32 *p;
if( idx < CV_FIRST_USER_TYPE ) return( 0 );
cde = FindDirEntry( ii, MH_GBL, sstGlobalTypes );
if( cde == NULL ) return( 0 );
p = VMBlock( ii,
cde->lfo
+ (unsigned long)(idx-CV_FIRST_USER_TYPE) * sizeof( *p )
+ offsetof( cv_sst_global_types_header, offType ),
sizeof( *p ) );
if( p == NULL ) return( 0 );
return( *p + ii->types_base );
}
dip_status TypeIndexFillIn( imp_image_handle *ii, unsigned idx,
imp_type_handle *it )
{
it->array_dim = 0;
it->idx = idx;
if( idx < CV_FIRST_USER_TYPE ) {
it->handle = 0;
return( DS_OK );
}
it->handle = TypeIndexVM( ii, idx );
if( it->handle == 0 ) return( DS_ERR|DS_FAIL );
it->handle += sizeof( unsigned_16 );
return( DS_OK );
}
static dip_status TypeReal( imp_image_handle *ii,
imp_type_handle *in, imp_type_handle *out,
lf_all **pp )
{
lf_all *p;
*out = *in;
p = NULL;
for( ;; ) {
if( out->handle == 0 ) goto done;
p = VMBlock( ii, out->handle, sizeof( *p ) );
if( p == NULL ) return( DS_ERR|DS_FAIL );
switch( p->common.code ) {
case LF_MODIFIER:
if( TypeIndexFillIn( ii, p->modifier.f.index, out ) != DS_OK ) {
return( DS_ERR|DS_FAIL );
}
break;
default:
goto done;
}
}
done:
if( pp != NULL ) *pp = p;
return( DS_OK );
}
dip_status TypeCallInfo( imp_image_handle *ii, unsigned idx,
cv_calls *call_type, unsigned *parms )
{
lf_all *p;
dip_status ds;
imp_type_handle it;
ds = TypeIndexFillIn( ii, idx, &it );
if( ds != DS_OK ) return( ds );
ds = TypeReal( ii, &it, &it, &p );
if( ds != DS_OK ) return( ds );
switch( p->common.code ) {
case LF_PROCEDURE:
*call_type = p->procedure.f.call;
*parms = p->procedure.f.parms;
break;
case LF_MFUNCTION:
*call_type = p->mfunction.f.call;
*parms = p->mfunction.f.parms;
break;
default:
return( DS_FAIL );
}
return( DS_OK );
}
dip_status TypeMemberFuncInfo( imp_image_handle *ii, imp_type_handle *func_it,
imp_type_handle *class_it, imp_type_handle *this_it,
unsigned long *adjustp )
{
lf_all *p;
dip_status ds;
unsigned class_idx;
p = VMBlock( ii, func_it->handle, sizeof( *p ) );
if( p == NULL ) return( DS_ERR|DS_FAIL );
if( p->common.code != LF_MFUNCTION ) return( DS_FAIL );
if( adjustp != NULL ) {
*adjustp = p->mfunction.f.thisadjust;
}
class_idx = p->mfunction.f.class_idx;
if( this_it != NULL ) {
ds = TypeIndexFillIn( ii, p->mfunction.f.thisptr, this_it );
if( ds != DS_OK ) return( ds );
}
if( class_it != NULL ) {
ds = TypeIndexFillIn( ii, class_idx, class_it );
p = VMBlock( ii, class_it->handle, sizeof( *p ) );
if( p->common.code == LF_MODIFIER ){ //NON standard need it to handle forward refs
ds = TypeIndexFillIn( ii, p->modifier.f.index, class_it );
}
if( ds != DS_OK ) return( ds );
}
return( DS_OK );
}
dip_status TypeSymGetName( imp_image_handle *ii, imp_sym_handle *is,
char **namep, unsigned *lenp )
{
return( TypeVMGetName( ii, is->handle, namep, lenp, NULL ) );
}
typedef struct pending_type_list pending_type_list;
struct pending_type_list {
pending_type_list *prev;
virt_mem curr;
virt_mem end;
virt_mem containing_type;
unsigned len;
unsigned code;
};
typedef walk_result (LEAF_WALKER)( imp_image_handle *, sym_walk_info, pending_type_list *, lf_all *, void * );
static walk_result TypeListWalk( imp_image_handle *ii, virt_mem head,
virt_mem containing_type, LEAF_WALKER *wk, void *d )
{
lf_all *p;
unsigned_16 *len_p;
unsigned len;
walk_result wr;
numeric_leaf val;
void *ptr;
pending_type_list *list;
pending_type_list *free_list;
pending_type_list *tmp;
unsigned base_idx;
free_list = NULL;
list = __alloca( sizeof( *list ) );
list->prev = NULL;
list->curr = head;
list->containing_type = containing_type;
new_list:
if( list->curr == 0 ) return( WR_FAIL );
len_p = VMBlock( ii, list->curr, sizeof( *len_p ) );
if( len_p == NULL ) return( WR_FAIL );
list->curr += sizeof( *len_p );
list->end = list->curr + *len_p;
list->curr += sizeof( p->common.code ); /* skip the list introducer */
for( ;; ) {
while( list->curr >= list->end ) {
tmp = list;
list = list->prev;
if( list == NULL ) return( WR_CONTINUE );
wr = wk( ii, SWI_INHERIT_END, list, NULL, d );
if( wr != WR_CONTINUE ) return( wr );
tmp->prev = free_list;
free_list = tmp;
list->curr += list->len;
}
p = VMBlock( ii, list->curr, sizeof( *p ) + sizeof( unsigned_32 ) );
if( p == NULL ) return( WR_FAIL );
if( *(unsigned_8 *)p > LF_PAD0 ) {
list->curr += *(unsigned_8 *)p & 0x0f;
} else {
list->code = p->common.code;
switch( p->common.code ){
case LF_INDEX:
list->curr = TypeIndexVM( ii, p->index.f.index );
goto new_list;
case LF_BCLASS:
len = (unsigned_8 *)GetNumLeaf( &p->bclass + 1, &val ) - (unsigned_8 *)p;
base_idx = p->bclass.f.type;
goto inherit_class;
case LF_VBCLASS:
case LF_IVBCLASS:
len = (unsigned_8 *)GetNumLeaf( &p->vbclass + 1, &val ) - (unsigned_8 *)p;
ptr = VMBlock( ii, list->curr + len, sizeof( unsigned_32 ) );
len += (unsigned_8 *)GetNumLeaf( ptr, &val ) - (unsigned_8 *)ptr;
if( list->prev != NULL ) {
/*
If we're processing an inherited class, we want to
ignore any virtual base classes. They'll get handled
by the most derived class.
*/
list->curr += len;
continue;
}
base_idx = p->vbclass.f.btype;
inherit_class:
list->len = len;
wr = wk( ii, SWI_INHERIT_START, list, NULL, d );
if( wr == WR_STOP ) {
list->curr += list->len;
continue;
}
if( free_list == NULL ) {
free_list = __alloca( sizeof( *list ) );
free_list->prev = NULL;
}
tmp = free_list;
free_list = free_list->prev;
tmp->prev = list;
list = tmp;
list->containing_type = TypeIndexVM( ii, base_idx );
if( list->containing_type == 0 ) return( WR_FAIL );
p = VMBlock( ii, list->containing_type+sizeof( unsigned_16 ),
sizeof( *p ) );
if( p == NULL ) return( WR_FAIL );
switch( p->common.code ) {
case LF_CLASS:
case LF_STRUCTURE:
list->curr = TypeIndexVM( ii, p->class_.f.field );
break;
default:
Confused();
}
goto new_list;
case LF_ENUMERATE:
len = (unsigned_8 *)GetNumLeaf( &p->enumerate + 1, &val ) - (unsigned_8 *)p;
ptr = VMBlock( ii, list->curr + len, 1 );
len += *(unsigned_8 *)ptr + 1;
break;
case LF_FRIENDFCN:
len = *(unsigned_8 *)(&p->friendfcn + 1) + sizeof( p->friendfcn ) + 1;
break;
case LF_MEMBER:
len = (unsigned_8 *)GetNumLeaf( &p->member + 1, &val ) - (unsigned_8 *)p;
ptr = VMBlock( ii, list->curr + len, 1 );
len += *(unsigned_8 *)ptr + 1;
break;
case LF_STMEMBER:
len = *(unsigned_8 *)(&p->stmember + 1) + sizeof( p->stmember ) + 1;
break;
case LF_METHOD:
len = *(unsigned_8 *)(&p->method + 1) + sizeof( p->method ) + 1;
break;
case LF_NESTEDTYPE:
len = *(unsigned_8 *)(&p->nestedtype + 1) + sizeof( p->nestedtype ) + 1;
break;
case LF_VFUNCTAB:
len = sizeof( p->vfunctab );
break;
case LF_FRIENDCLS:
len = sizeof( p->friendcls );
break;
case LF_ONEMETHOD:
len = *(unsigned_8 *)(&p->onemethod + 1) + sizeof( p->onemethod ) + 1;
switch( p->onemethod.f.attr.f.mprop ) {
case CV_VIRTUAL:
case CV_INTROVIRT:
case CV_PUREVIRT:
case CV_PUREINTROVIRT:
len += sizeof( unsigned_32 );
break;
}
break;
case LF_VFUNCOFF:
len = sizeof( p->vfuncoff );
break;
default:
Confused();
return( WR_FAIL );
}
p = VMBlock( ii, list->curr, len );
if( p == NULL ) return( WR_FAIL );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?