dbginfo.c

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

C
899
字号
/****************************************************************************
*
*                            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:  Produce Watcom style debugging information in load file.
*
****************************************************************************/


#include <string.h>
#include <stdlib.h>
#include "walloca.h"
#include "linkstd.h"
#include "pcobj.h"
#include "alloc.h"
#include "dbginfo.h"
#include "newmem.h"
#include "msg.h"
#include "wlnkmsg.h"
#include "virtmem.h"
#include "objnode.h"
#include "loadfile.h"
#include "objcalc.h"
#include "objomf.h"
#include "overlays.h"
#include "specials.h"
#include "ring.h"
#include "dbgwat.h"
#include "dbgcomm.h"

#define EXE_MAJOR_VERSION   3
#define EXE_MINOR_VERSION   0

#define ADDR_INFO_LIMIT ( 63 * 1024U / sizeof( addrinfo ) )
#define DEMAND_INFO_SPLIT ( 16 * 1024 )

#define NON_SECT_INFO 0x8000

typedef struct {
    unsigned_32 offset;
    unsigned_16 num;
    unsigned_16 size;
} demanddata;

typedef struct odbimodinfo {
    unsigned_32 linelinksize;
    demanddata  types;
    demanddata  locals;
    demanddata  lines;
    unsigned_32 modnum;
    unsigned    dbisourceoffset;
} odbimodinfo;

typedef struct seginfo     {
    struct seginfo      *next;
    unsigned_32         dbioff;
    segheader           head;
    unsigned_32         endoflast;
    seg_leader *        prevlead;
    seg_leader *        final;
    byte                nonsect : 1;
    byte                full : 1;
    byte                finished : 1;
} seginfo;

typedef struct snamelist {        // source name list
    struct snamelist *  next;
    byte                len;        // length of the name
    char                name[1];       // stored WITH a nullchar
} snamelist;

static unsigned_32  DBISize;
static dbgheader    Master;            // rest depend on .obj files.

static snamelist *  DBISourceLang;     // list of source languages

static void             ReadSegInfo( section *, void ** );
static snamelist *      LangAlloc( byte len, void *buff );
static void             ODBIGenAddrInfo( seg_leader * );
static void             AllocDBIClasses( class_entry *class );
static void             NewArea( section *sect );
static void             DoName( char *cname, char *intelname, int len );

#ifdef _INT_DEBUG
struct {
    offset   sizeadded;
    offset   sizegenned;
} TraceInfo;
#endif

extern void ODBIInit( section *sect )
/***********************************/
{
    DBISize = sizeof( dbgheader );
    Master.signature = DBG_SIGNATURE;
    Master.exe_major_ver = EXE_MAJOR_VERSION;
    Master.exe_minor_ver = EXE_MINOR_VERSION;
    Master.obj_major_ver = 0;
    Master.obj_minor_ver = 0;
    DBISourceLang = LangAlloc( 1, "C" );
    DBISourceLang->next = NULL;
    _PermAlloc( sect->dbg_info, sizeof( debug_info ) );
    memset( sect->dbg_info, 0, sizeof( debug_info ) );  //assumes NULL == 0
#ifdef _INT_DEBUG
    memset( &TraceInfo, 0, sizeof( TraceInfo ) );
#endif
}

extern void ODBIInitModule( mod_entry *mod )
/******************************************/
{
    if( CurrSect->dbg_info == NULL )
        return;
    _PermAlloc( mod->d.o, sizeof( odbimodinfo ) );
    memset( mod->d.o, 0, sizeof( odbimodinfo ) );
}

static void DumpInfo( debug_info *dinfo, void *data, unsigned len )
/*****************************************************************/
{
    PutInfo( dinfo->DBIWrite, data, len );
    dinfo->DBIWrite += len;
}

static bool FindMatch( byte len, void *buff, unsigned *offset )
/*************************************************************/
// returns FALSE if not found
{
    snamelist * node;

    node = DBISourceLang;
    *offset = 0;
    while( node != NULL ) {
        if( node->len == len ) {
            if( memicmp( buff, node->name, len ) == 0 ) {
                return( TRUE );
            }
        }
        *offset += node->len + 1;     // +1 for NULLCHAR
        node = node->next;
    }
    return( FALSE );
}

static snamelist * LangAlloc( byte len, void *buff )
/**************************************************/
{
    snamelist *node;

    _PermAlloc( node, sizeof( snamelist ) + len );
    node->len = len;
    memcpy( node->name, buff, len );
    node->name[len] = '\0';
    return( node );
}

extern void ODBIP1Source( byte major, byte minor, char *name, int len )
/*********************************************************************/
{
    snamelist * node;

    if( Master.obj_major_ver == 0 )
        Master.obj_major_ver = major;
    if( major != Master.obj_major_ver ) {
        LnkMsg( LOC+WRN+MSG_CANT_USE_LOCALS, NULL );
        CurrMod->modinfo &= ~( DBI_TYPE | DBI_LOCAL );
    }
    if( minor > Master.obj_minor_ver ) {
        Master.obj_minor_ver = minor;
    }
    if( !FindMatch( len, name, &CurrMod->d.o->dbisourceoffset ) ) {
        node = LangAlloc( len, name );
        node->next = DBISourceLang->next;
        DBISourceLang->next = node;        // keep "C" the first entry.
    }
}

static void DoAddLocal( dbi_section * dbi, offset length )
/********************************************************/
{
    if( ( dbi->size == 0 ) || ( dbi->size + length > DEMAND_INFO_SPLIT ) ) {
        dbi->curr += sizeof( unsigned_32 );
        dbi->size = 0;
    }
    dbi->size += length;
#ifdef _INT_DEBUG
    TraceInfo.sizeadded += length;
#endif
}

extern void ODBIAddLocal( unsigned_16 info, offset length )
/*********************************************************/
{
    debug_info          *dinfo;

    dinfo = CurrSect->dbg_info;
    if( dinfo == NULL )
        return;
    if( info == MS_TYPE ) {
        DEBUG(( DBG_DBGINFO, "adding type info %h", length ));
        DoAddLocal( &dinfo->typelinks, length );
    } else if( info == MS_LOCAL ) {
        DEBUG(( DBG_DBGINFO, "adding local info %h", length ));
        DoAddLocal( &dinfo->locallinks, length );
    }
}

extern void ODBIP1ModuleScanned( void )
/*************************************/
{
    debug_info          *dinfo;

    dinfo = CurrSect->dbg_info;
    if( dinfo == NULL )
        return;
    dinfo->typelinks.size = 0;
    dinfo->locallinks.size = 0;
}

static void DoGenLocal( dbi_section *dsect, dbi_section * dlink,
                        demanddata * dmod, offset length )
/**************************************************************/
{
    unsigned_32 spot;

    if( ( dmod->size == 0 )
        || ( dmod->size + length > DEMAND_INFO_SPLIT ) ) {
        spot = dsect->start + ( dsect->curr - dsect->init );
        PutInfo( dlink->curr, &spot, sizeof( unsigned_32 ) );
        dmod->num++;
        if( dmod->size == 0 ) {
            dmod->offset = dlink->start + ( dlink->curr - dlink->init );
        } else {
            dmod->size = 0;
        }
        dlink->curr += sizeof( unsigned_32 );
    }
    dsect->curr += length;
    dmod->size += length;
#ifdef _INT_DEBUG
    TraceInfo.sizegenned += length;
#endif
}

extern void ODBIGenLocal( segdata *sdata )
/****************************************/
{
    debug_info          *dinfo;
    odbimodinfo         *minfo;

    dinfo = CurrSect->dbg_info;
    if( dinfo == NULL )
        return;
    if( sdata->isdead )
        return;
    minfo = CurrMod->d.o;
    if( sdata->u.leader->dbgtype == MS_TYPE ) {
        DEBUG(( DBG_DBGINFO, "genning type info %h", sdata->length ));
        DoGenLocal( &dinfo->type, &dinfo->typelinks, &minfo->types,
                    sdata->length );
    } else if( sdata->u.leader->dbgtype == MS_LOCAL ) {
        DEBUG(( DBG_DBGINFO, "genning local info %h", sdata->length ));
        DoGenLocal( &dinfo->local, &dinfo->locallinks, &minfo->locals,
                    sdata->length );
    }
}

static void ODBIAddLines( segdata * seg, void *lines, unsigned size,
                          bool is32bit )
/******************************************************************/
{
    unsigned            lineqty;
    unsigned_32         linesize;
    debug_info          *dinfo;

    lines = lines;
    seg = seg;
    dinfo = CurrSect->dbg_info;
    lineqty = CalcLineQty( size, is32bit );
    linesize = lineqty * sizeof( ln_off_386 ) + sizeof( lineseg );
    dinfo->line.curr += linesize;
    DoAddLocal( &dinfo->linelinks, linesize );
}

extern void ODBIP1ModuleFinished( mod_entry *obj )
/************************************************/
{
    debug_info          *dinfo;

    dinfo = CurrSect->dbg_info;
    if( ( dinfo == NULL ) || !( obj->modinfo & DBI_ALL ) )
        return;
    if( MOD_NOT_DEBUGGABLE( obj ) )
        return;
    CurrMod = obj;
    if( CurrMod->modinfo & DBI_LINE ) {
        DBILineWalk( obj->lines, ODBIAddLines );
    }
    Ring2Walk( obj->publist, DBIModGlobal );
    dinfo->mod.curr += strlen( obj->name ) + sizeof( modinfo );
    dinfo->linelinks.size = 0;
}

extern void ODBIDefClass( class_entry *cl, unsigned_32 size )
/***********************************************************/
{
    debug_info *dinfo;

    dinfo = CurrSect->dbg_info;
    if( dinfo == NULL )
        return;
    if( cl->flags & CLASS_MS_TYPE ) {
        dinfo->type.curr += size;
        dinfo->TypeClass = cl;
    } else if( cl->flags & CLASS_MS_LOCAL ) {
        dinfo->local.curr += size;
        dinfo->LocalClass = cl;
    }
}

static int ODBISymIsForGlobalDebugging( symbol *sym, mod_entry *currMod )
/***********************************************************************/
{
    return( !( CurrMod->modinfo & DBI_ONLY_EXPORTS )
        && ( ( CurrMod->modinfo & DBI_STATICS ) || !( sym->info & SYM_STATIC ) ) );
}

extern void ODBIAddGlobal( symbol *sym )
/**************************************/
{
    debug_info      *dinfo;
    unsigned        add;

    dinfo = CurrSect->dbg_info;
    if( dinfo == NULL )
        return;
    if( ODBISymIsForGlobalDebugging( sym, CurrMod ) ) {
        add = strlen( sym->name );
        if( add > 255 ) {
            LnkMsg( WRN+MSG_SYMBOL_NAME_TOO_LONG, "s", sym->name );
            add = 255;
        }
        dinfo->global.curr += add + sizeof( gblinfo );
    }
}

extern void ODBIAddrSectStart( section *sect )
/********************************************/
{
    debug_info      *dptr;

    dptr = sect->dbg_info;
    if( dptr == NULL )
        return;
    if( ( dptr->local.curr > 0 )
        || ( dptr->type.curr > 0 )
        || ( dptr->line.curr > 0 ) ) {
        dptr->linelinks.curr += sizeof( unsigned_32 );
    }
    dptr->locallinks.start = sizeof( sectheader );
    dptr->locallinks.size = dptr->locallinks.curr;
    dptr->locallinks.curr = DBIAlloc( dptr->locallinks.curr );
    dptr->locallinks.init = dptr->locallinks.curr;

    dptr->typelinks.start = dptr->locallinks.start + dptr->locallinks.size;
    dptr->typelinks.size = dptr->typelinks.curr;
    dptr->typelinks.curr = DBIAlloc( dptr->typelinks.curr );
    dptr->typelinks.init = dptr->typelinks.curr;

    dptr->linelinks.start = dptr->typelinks.start + dptr->typelinks.size;
    dptr->linelinks.size = dptr->linelinks.curr;
    dptr->linelinks.curr = DBIAlloc( dptr->linelinks.curr );
    dptr->linelinks.init = dptr->linelinks.curr;

    dptr->local.start = dptr->linelinks.start + dptr->linelinks.size;
    dptr->local.size = dptr->local.curr;
    dptr->local.init = dptr->local.curr;

    dptr->type.start = dptr->local.start + dptr->local.size;
    dptr->type.size = dptr->type.curr;
    dptr->type.init = dptr->type.curr;

    dptr->line.start = dptr->type.start + dptr->type.size;
    dptr->line.size = dptr->line.curr;
    dptr->line.curr = DBIAlloc( dptr->line.curr );
    dptr->line.init = dptr->line.curr;

    dptr->mod.start = dptr->line.start + dptr->line.size;
    dptr->mod.size = dptr->mod.curr;
    dptr->mod.curr = DBIAlloc( dptr->mod.curr );
    dptr->mod.init = dptr->mod.curr;

    dptr->global.start = dptr->mod.start + dptr->mod.size;
    dptr->addr.start = dptr->global.start + dptr->global.curr;
    dptr->global.size = 0;
    dptr->global.curr = DBIAlloc( dptr->global.curr );
    dptr->global.init = dptr->global.curr;

    dptr->addr.curr = DBIAlloc( dptr->addr.size );
    dptr->addr.init = dptr->addr.curr;

    dptr->DBIWrite = dptr->global.curr;
    dptr->modnum = -1;

    AllocDBIClasses( sect->classlist );
}

static bool AllocASeg( void *leader, void *group )
/************************************************/
{
    ((seg_leader *)leader)->group = group;
    return( FALSE );
}

static void AllocDBIClasses( class_entry *class )
/***********************************************/
/* Allocate all classes in the list */
{
    group_entry *group;

    while( class != NULL ) {
        if( class->flags & CLASS_DEBUG_INFO ) {
            group = AllocGroup( AutoGrpName, &DBIGroups );
            group->grp_addr.seg = 0;
            RingLookup( class->segs, AllocASeg, group );
        }
        class = class->next_class;
    }

⌨️ 快捷键说明

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