dipman.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,460 行 · 第 1/3 页
C
1,460 行
/****************************************************************************
*
* 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: Debug Information Processor (DIP) manager.
*
****************************************************************************/
#include <string.h>
#include <limits.h>
#include "walloca.h"
#include "dip.h"
#include "dipimp.h"
#include "dipcli.h"
#define IMAGE_MAP_INIT 16
#define IMAGE_MAP_GROW 16
#define MAX_LOAD_DIPS 32
#define MAX_REG_DIPS 1
#define MAX_DIPS (MAX_LOAD_DIPS+MAX_REG_DIPS)
typedef unsigned_16 image_idx;
struct process_info {
unsigned last_addr_mod_found;
unsigned map_entries;
image_handle **ih_map;
image_handle *ih_list;
image_handle **ih_add;
};
struct image_handle {
dip_imp_routines *dip;
image_handle *next;
void *extra;
unsigned index;
};
enum artificial_pointers {
AP_NEAR2 = 1,
AP_FAR2,
AP_NEAR4,
AP_FAR4,
AP_MASK = 0x7,
AP_SHIFT = 3,
AP_FULL = 0xe000
};
struct type_handle {
image_idx ii;
unsigned short ap;
unsigned : 0; /* for alignment */
};
struct cue_handle {
image_idx ii;
unsigned : 0; /* for alignment */
};
struct sym_handle {
image_idx ii;
unsigned : 0; /* for alignment */
};
#define CLI_HDL( hp, type ) (((type##_handle *)(hp))-1)
#define IMP_HDL( hp, type ) ((imp_##type##_handle *)((hp) + 1))
#define MK_MH( ii, sm ) ((unsigned_32)((ii)+1) << 16 | (sm))
#define MH_IMAGE( mh ) ((unsigned)((mh)>>16)-1)
#define MH_SMOD( mh ) ((unsigned)((mh)&0xffff))
#define II2IH( ii ) ((ActProc==NULL)||(ActProc->map_entries<=ii)?NULL:ActProc->ih_map[ii])
#define MH2IH( mh ) (((mh&0xffff0000)==0)?NULL:II2IH(MH_IMAGE(mh)))
#define NO_IMAGE_IDX ((unsigned)-1)
static unsigned LoadingImageIdx = NO_IMAGE_IDX;
static process_info *ActProc;
static struct {
dip_imp_routines *rtns;
unsigned long sys_hdl;
} LoadedDIPs[MAX_DIPS];
static unsigned MaxHdlSize[HK_LAST];
static const unsigned_8 MgrHdlOverhead[] = {
sizeof( image_handle ),
sizeof( type_handle ),
sizeof( cue_handle ),
sizeof( sym_handle )
};
char DIPDefaults[] = {
"dwarf\0"
"watcom\0"
"codeview\0"
"mapsym\0"
"export\0"
"\0"
};
static const address NilAddr;
/*
* System specific support routines
*/
dip_status DIPSysLoad( char *, dip_client_routines *,
dip_imp_routines **, unsigned long * );
void DIPSysUnload( unsigned long );
/*
* Client interface
*/
/*
* DCSymCreate is here so that DIPRegister'd functions can call it.
*/
imp_sym_handle *DCSymCreate( imp_image_handle *ii, void *d )
{
sym_handle *sh;
sh = DIPCliSymCreate( d );
sh->ii = CLI_HDL( ii, image )->index;
return( IMP_HDL( sh, sym ) );
}
imp_sym_handle * DIGCLIENT XDIPCliSymCreate( imp_image_handle *ii, void *d )
{
return( DCSymCreate( ii, d ) );
}
dip_client_routines DIPClientInterface = {
DIP_MAJOR,
DIP_MINOR_OLD,
sizeof( dip_client_routines ),
DIGCliAlloc,
DIGCliRealloc,
DIGCliFree,
DIPCliMapAddr,
XDIPCliSymCreate,
DIPCliItemLocation,
DIPCliAssignLocation,
DIPCliSameAddrSpace,
DIPCliAddrSection,
DIGCliOpen,
DIGCliSeek,
DIGCliRead,
DIGCliWrite,
DIGCliClose,
DIGCliRemove,
DIPCliStatus,
DIPCliCurrMAD,
DIGCliMachineData
};
/*
* Control Routines
*/
dip_status DIPInit( void )
{
return( DS_OK );
}
static void SetHdlSizes( dip_imp_routines *rtns )
{
handle_kind hk;
unsigned size;
for( hk = 0; hk < (sizeof(MaxHdlSize) / sizeof(MaxHdlSize[0])); ++hk ) {
size = rtns->handle_size( hk );
if( size > MaxHdlSize[hk] ) MaxHdlSize[hk] = size;
}
}
dip_status DIPLoad( char *path )
{
unsigned i;
dip_status status;
for( i = 0; LoadedDIPs[i].rtns != NULL; ++i ) {
if( i >= MAX_LOAD_DIPS ) {
return( DS_ERR|DS_TOO_MANY_DIPS );
}
}
status = DIPSysLoad( path, &DIPClientInterface,
&LoadedDIPs[i].rtns, &LoadedDIPs[i].sys_hdl );
if( status != DS_OK ) return( status );
if( DIPClientInterface.major != LoadedDIPs[i].rtns->major
|| DIPClientInterface.minor > LoadedDIPs[i].rtns->minor ) {
DIPSysUnload( LoadedDIPs[i].sys_hdl );
LoadedDIPs[i].rtns = NULL;
return( DS_ERR|DS_INVALID_DIP_VERSION );
}
SetHdlSizes( LoadedDIPs[i].rtns );
return( DS_OK );
}
dip_status DIPRegister( dip_imp_routines *dir )
{
unsigned i;
for( i = MAX_LOAD_DIPS; LoadedDIPs[i].rtns != NULL; ++i ) {
if( i >= MAX_DIPS ) {
return( DS_ERR|DS_TOO_MANY_DIPS );
}
}
LoadedDIPs[i].rtns = dir;
LoadedDIPs[i].sys_hdl = 0;
SetHdlSizes( LoadedDIPs[i].rtns );
return( DS_OK );
}
void DIPFiniLatest( void )
{
unsigned i;
i = MAX_DIPS;
for( ;; ) {
--i;
if( LoadedDIPs[i].rtns != NULL ) {
LoadedDIPs[i].rtns->shutdown();
if( LoadedDIPs[i].sys_hdl != 0 ) {
DIPSysUnload( LoadedDIPs[i].sys_hdl );
}
LoadedDIPs[i].rtns = NULL;
LoadedDIPs[i].sys_hdl = 0;
return;
}
if( i == 0 ) return;
}
}
void DIPFini( void )
{
unsigned i;
for( i = 0; i < MAX_DIPS; ++i ) {
if( LoadedDIPs[i].rtns != NULL ) {
LoadedDIPs[i].rtns->shutdown();
if( LoadedDIPs[i].sys_hdl != 0 ) {
DIPSysUnload( LoadedDIPs[i].sys_hdl );
}
}
LoadedDIPs[i].rtns = NULL;
LoadedDIPs[i].sys_hdl = 0;
}
}
unsigned DIPHandleSize( handle_kind h )
{
return( MaxHdlSize[h] + MgrHdlOverhead[h] );
}
dip_status DIPMoreMem( unsigned amount )
{
unsigned i;
for( i = 0; i < MAX_DIPS; ++i ) {
if( LoadedDIPs[i].rtns != NULL ) {
if( LoadedDIPs[i].rtns->more_mem( amount ) == DS_OK ) return( DS_OK );
}
}
return( DS_FAIL );
}
void DIPCancel( void )
{
unsigned i;
image_handle *ih;
for( i = 0; i < MAX_DIPS; ++i ) {
if( LoadedDIPs[i].rtns != NULL ) {
LoadedDIPs[i].rtns->cancel();
}
}
if( LoadingImageIdx != NO_IMAGE_IDX ) {
ih = II2IH( LoadingImageIdx );
if( ih != NULL ) {
ih->dip->unload_info( IMP_HDL( ih, image ) );
}
LoadingImageIdx = NO_IMAGE_IDX;
}
}
unsigned FindImageMapSlot( process_info *p )
{
image_handle **new;
unsigned new_num;
unsigned i;
unsigned j;
for( i = 0; i < p->map_entries; ++i ) {
if( p->ih_map[i] == NULL ) return( i );
}
new_num = p->map_entries + IMAGE_MAP_GROW;
new = DIGCliRealloc( p->ih_map, new_num * sizeof( p->ih_map[0] ) );
if( new == NULL ) {
DIPCliStatus( DS_ERR | DS_NO_MEM );
return( NO_IMAGE_IDX );
}
i = p->map_entries;
p->map_entries = new_num;
p->ih_map = new;
for( j = i; j < new_num; ++j ) new[j] = NULL;
return( i );
}
static void DIPCleanupInfo( process_info *p, image_handle *ih )
{
image_handle **owner;
image_handle *curr;
DIPCliImageUnload( MK_MH( ih->index, 0 ) );
ih->dip->unload_info( IMP_HDL( ih, image ) );
p->ih_map[ih->index] = NULL;
owner = &p->ih_list;
for( ;; ) {
curr = *owner;
if( curr == ih ) break;
owner = &curr->next;
}
*owner = ih->next;
if( p->ih_add == &ih->next ) {
p->ih_add = owner;
}
if( ih->index == p->last_addr_mod_found ) {
p->last_addr_mod_found = NO_IMAGE_IDX;
}
DIGCliFree( ih );
}
static void CleanupProcess( process_info *p, int unload )
{
image_handle *ih;
image_handle *next;
if( unload ) {
while( p->ih_list ) {
DIPCleanupInfo( p, p->ih_list );
}
} else {
for( ih = p->ih_list; ih != NULL; ih = next ) {
next = ih->next;
DIGCliFree( ih );
}
}
DIGCliFree( p->ih_map );
DIGCliFree( p );
}
process_info *DIPCreateProcess( void )
{
process_info *p;
image_handle *ih;
unsigned i;
unsigned j;
p = DIGCliAlloc( sizeof( process_info ) );
if( p == NULL ) {
DIPCliStatus( DS_ERR|DS_NO_MEM );
return( NULL );
}
p->last_addr_mod_found = NO_IMAGE_IDX;
p->ih_map = DIGCliAlloc( IMAGE_MAP_INIT * sizeof( p->ih_map[0] ) );
if( p->ih_map == NULL ) {
DIGCliFree( p );
DIPCliStatus( DS_ERR|DS_NO_MEM );
return( NULL );
}
p->map_entries = IMAGE_MAP_INIT;
for( i = 0; i < IMAGE_MAP_INIT; ++i ) p->ih_map[i] = NULL;
p->ih_list = NULL;
p->ih_add = &p->ih_list;
for( j = MAX_DIPS-1; j >= MAX_LOAD_DIPS; --j ) {
if( LoadedDIPs[j].rtns != NULL ) {
i = FindImageMapSlot( p );
if( i == NO_IMAGE_IDX ) {
CleanupProcess( p, 0 );
DIPCliStatus( DS_ERR|DS_NO_MEM );
return( NULL );
}
ih = DIGCliAlloc( sizeof( image_handle ) );
if( ih == NULL ) {
CleanupProcess( p, 0 );
DIPCliStatus( DS_ERR|DS_NO_MEM );
return( NULL );
}
p->ih_map[i] = ih;
ih->next = *p->ih_add;
*p->ih_add = ih;
p->ih_add = &ih->next;
ih->dip = LoadedDIPs[j].rtns;
ih->extra = NULL;
ih->index = i;
}
}
p->ih_add = &p->ih_list;
if( ActProc == NULL ) ActProc = p;
return( p );
}
process_info *DIPSetProcess( process_info *new )
{
process_info *old;
old = ActProc;
ActProc = new;
return( old );
}
void DIPDestroyProcess( process_info *p )
{
CleanupProcess( p, 1 );
if( p == ActProc ) ActProc = NULL;
}
unsigned DIPPriority( unsigned old )
{
unsigned prio;
unsigned curr;
unsigned j;
prio = UINT_MAX;
for( j = 0; j < MAX_DIPS; ++j ) {
if( LoadedDIPs[j].rtns == NULL ) continue;
curr = LoadedDIPs[j].rtns->dip_priority;
if( curr <= old ) continue;
if( curr >= prio ) continue;
prio = curr;
}
return( prio == UINT_MAX ? 0 : prio );
}
mod_handle DIPLoadInfo( dig_fhandle file, unsigned extra, unsigned prio )
{
unsigned i;
unsigned j;
image_handle *ih;
dip_status ret;
if( ActProc == NULL ) {
DIPCliStatus( DS_ERR|DS_NO_PROCESS );
return( NO_MOD );
}
i = FindImageMapSlot( ActProc );
if( i == NO_IMAGE_IDX ) return( NO_MOD );
ih = DIGCliAlloc( DIPHandleSize( HK_IMAGE ) + extra );
if( ih == NULL ) {
DIPCliStatus( DS_ERR|DS_NO_MEM );
return( NO_MOD );
}
for( j = 0; j < MAX_DIPS; ++j ) {
if( LoadedDIPs[j].rtns == NULL ) continue;
if( LoadedDIPs[j].rtns->dip_priority != prio ) continue;
ret = LoadedDIPs[j].rtns->load_info(file,IMP_HDL(ih,image));
if( ret == DS_OK ) {
ActProc->ih_map[i] = ih;
ih->next = *ActProc->ih_add;
*ActProc->ih_add = ih;
ActProc->ih_add = &ih->next;
ih->dip = LoadedDIPs[j].rtns;
ih->extra = (unsigned_8 *)ih + DIPHandleSize( HK_IMAGE );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?