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