dbgcv.c

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

C
748
字号
/****************************************************************************
*
*                            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:  routines for producing codeview information in the load file
*
****************************************************************************/


#include <string.h>
#include "linkstd.h"
#include "alloc.h"
#include "cv4w.h"
#include "virtmem.h"
#include "objnode.h"
#include "objcalc.h"
#include "dbgcomm.h"
#include "loadqnx.h"    // for ToQNXIndex
#include "ring.h"
#include "dbgcv.h"
#include "msg.h"
#include "wlnkmsg.h"
#include "specials.h"

typedef struct cvmodinfo {
    unsigned_32 pubsize;
    virt_mem    segloc;
    unsigned_16 numlines;
    unsigned_16 modidx;
    unsigned_16 numsegs;
} cvmodinfo;

#pragma pack( 1 );

// Cheesy implementation of sstSrcModule structures.
// Only allow one file and one segment.
typedef struct {
    unsigned_32 start;
    unsigned_32 end;
} offset_range;

typedef struct {
    unsigned_16         cFile;
    unsigned_16         cSeg;
    unsigned_32         baseSrcFile[1];
    offset_range        range[1];
    unsigned_16         seg[1];
    unsigned_16         pad;
} cheesy_module_header;

typedef struct {
    unsigned_16         cSeg;
    unsigned_16         pad;
    unsigned_32         baseSrcLn[1];
    offset_range        range[1];
    unsigned_8          name[1];        /* variable sized */
} cheesy_file_table;

typedef struct {
    unsigned_16         Seg;
    unsigned_16         cPair;
//  unsigned_32         offset[];
//  unsigned_32         linenumber[];
} cheesy_mapping_table;

#pragma pack();

// global information needed to keep track of line number information

typedef struct {
    virt_mem            linestart;
    virt_mem            offbase;
    virt_mem            numbase;
    offset_range        range;
    unsigned_32         prevaddr;
    unsigned_16         seg;
    unsigned_8          needsort : 1;
} cvlineinfo;

// split codeview up into a number of different "sections" to keep track
// of where we write bits of the information.

enum {
    CVSECT_MODULE,
    CVSECT_MISC,
    CVSECT_MODDIR,
    CVSECT_DIRECTORY,
    NUM_CV_SECTS
};

// keeps track of where to write bits of information.  Also used in pass 1
// to collect sizes of different blocks.

static virt_mem SectAddrs[NUM_CV_SECTS];

// the codeview information is just one big memory block.  This is the start
// of it, and the length of it

static virt_mem         CVBase;
       unsigned_32      CVSize; // external linkage since NT wants to know.

static unsigned         TempIndex;
static cvlineinfo       LineInfo;

static bool     CVStoreLines( segdata *, mod_entry * );
static void     GenSrcModHeader( void );

extern void CVInit( void )
/************************/
// called just after command file parsing
{
    memset( SectAddrs, 0, sizeof( virt_mem ) * NUM_CV_SECTS );
    memset( &LineInfo, 0, sizeof( cvlineinfo ) );
    TempIndex = 0;
}

extern void CVInitModule( mod_entry *obj )
/****************************************/
// called before pass 1 is done on the module
{
    _PermAlloc( obj->d.cv, sizeof( cvmodinfo ) );
    memset( obj->d.cv, 0, sizeof( cvmodinfo ) );
}

static void DumpInfo( unsigned sect, void *data, unsigned_32 len )
/****************************************************************/
{
    PutInfo( SectAddrs[sect], data, len );
    SectAddrs[sect] += len;
}

static segment GetCVSegment( seg_leader *seg )
/********************************************/
{
    int                 index;
    group_entry *       group;

    if( ( seg == NULL ) || ( seg->group == NULL ) ) {
        return( 0 );
    }
    if( FmtData.type & ( MK_REAL_MODE | MK_FLAT | MK_ID_SPLIT ) ) {
        index = 1;
        for( group = Groups; group != NULL; group = group->next_group ) {
            if( group == seg->group )
                return( index );
            index++;
        }
    } else if( FmtData.type & MK_QNX ) {
        return( ToQNXIndex( seg->seg_addr.seg ) );
    } else {
        return( seg->seg_addr.seg );
    }
    return( 0 );
}

static void AddSubSection( bool ismodule )
/****************************************/
{
    unsigned    sect;

    if( ismodule ) {
        sect = CVSECT_MODDIR;
    } else {
        sect = CVSECT_DIRECTORY;
    }
    SectAddrs[sect] += sizeof( cv_directory_entry );
}

static void GenSubSection( sst sect, unsigned_32 size )
/*****************************************************/
// generate a subsection entry
{
    cv_directory_entry  entry;

    entry.subsection = sect;
    if( CurrMod == NULL ) {
        entry.iMod = 0xFFFF;
    } else {
        entry.iMod = CurrMod->d.cv->modidx;
    }
    entry.cb = size;
    if( sect == sstModule ) {
        entry.lfo = SectAddrs[CVSECT_MODULE] - CVBase;
        DumpInfo( CVSECT_MODDIR, &entry, sizeof( cv_directory_entry ) );
    } else {
        entry.lfo = SectAddrs[CVSECT_MISC] - CVBase;
        DumpInfo( CVSECT_DIRECTORY, &entry, sizeof( cv_directory_entry ) );
    }
}

extern void CVP1ModuleScanned( void )
/***********************************/
{
}

static void CVAddLines( segdata * seg, void *line, unsigned size, bool is32bit )
/******************************************************************************/
// called during pass 1 linnum processing
{
    seg = seg;
    line = line;
    CurrMod->d.cv->numlines += CalcLineQty( size, is32bit );
}

extern void CVP1ModuleFinished( mod_entry *obj )
/**********************************************/
// calculate size of the sstModule
{
    byte        namelen;
    unsigned_32 temp;

    if( MOD_NOT_DEBUGGABLE( obj ) )
        return;
    TempIndex++;
    CurrMod = obj;
    obj->d.cv->modidx = TempIndex;
    if( CurrMod->modinfo & DBI_LINE ) {
        DBILineWalk( obj->lines, CVAddLines );
    }
    Ring2Walk( obj->publist, DBIModGlobal );
    namelen = strlen( obj->name );
    SectAddrs[CVSECT_MODULE] += sizeof( cv_sst_module ) + namelen + 1
                                - sizeof( cv_seginfo );
    AddSubSection( TRUE );
    if( obj->d.cv->pubsize > 0 ) {
        AddSubSection( FALSE );
        SectAddrs[CVSECT_MISC] += sizeof( unsigned_32 );
        obj->d.cv->pubsize += sizeof( unsigned_32 );
    }
    if( obj->d.cv->numlines > 0 ) {
        AddSubSection( FALSE );
        temp = sizeof( cheesy_module_header );
        temp += ROUND_UP( sizeof( cheesy_file_table ) + namelen, 4 );
        temp += sizeof( cheesy_mapping_table );
        temp += ROUND_UP( obj->d.cv->numlines
                    * ( sizeof( unsigned_32 ) + sizeof( unsigned_16 ) ), 4 );
        SectAddrs[CVSECT_MISC] += temp;
    }
}

extern void CVAddModule( mod_entry *obj, section *sect )
/******************************************************/
// called just before publics have been assigned addresses between p1 & p2
{
    unsigned_32         sig;
    cv_sst_module       mod;
    unsigned_32         size;
    byte                namelen;

    sect = sect;
    if( obj->d.cv->pubsize > 0 ) {
        GenSubSection( sstPublicSym, obj->d.cv->pubsize );
        sig = 1;
        DumpInfo( CVSECT_MISC, &sig, sizeof( unsigned_32 ) );
    }
    namelen = strlen( obj->name );
    size = sizeof( cv_sst_module ) + namelen + 1
                + ( obj->d.cv->numsegs - 1 ) * sizeof( cv_seginfo );
    GenSubSection( sstModule, size );
    mod.ovlNumber = 0;
    mod.iLib = 0;
    mod.cSeg = obj->d.cv->numsegs;
    mod.Style = CV_DEBUG_STYLE;
    DumpInfo( CVSECT_MODULE, &mod, sizeof( cv_sst_module ) - sizeof( cv_seginfo ) );
    obj->d.cv->segloc = SectAddrs[CVSECT_MODULE];
    SectAddrs[CVSECT_MODULE] += sizeof( cv_seginfo ) * obj->d.cv->numsegs;
    DumpInfo( CVSECT_MODULE, &namelen, 1 );
    DumpInfo( CVSECT_MODULE, obj->name, namelen );
}

static int RelocCompare( virt_mem a, virt_mem b )
/***********************************************/
{
    unsigned_32 a32;
    unsigned_32 b32;

    GET32INFO( a, a32 );
    GET32INFO( b, b32 );
    return( (signed_32)a32 - b32 );
}

static void SwapRelocs( virt_mem a, virt_mem b )
/**********************************************/
{
    unsigned    diffa;
    unsigned    diffb;
    unsigned_16 a16;
    unsigned_16 b16;
    unsigned_32 a32;
    unsigned_32 b32;

    GET32INFO( a, a32 );
    GET32INFO( b, b32 );
    PUT32INFO( a, b32 );
    PUT32INFO( b, a32 );
    diffa = ( a - LineInfo.offbase ) / sizeof( unsigned_32 );
    diffa *= sizeof( unsigned_16 );
    diffa += LineInfo.numbase;
    diffb = ( b - LineInfo.offbase ) / sizeof( unsigned_32 );
    diffb *= sizeof( unsigned_16 );
    diffb += LineInfo.numbase;
    GET16INFO( diffa, a16 );
    GET16INFO( diffb, b16 );
    PUT16INFO( diffa, b16 );
    PUT16INFO( diffb, a16 );
}

static void SortRelocs( void )
/****************************/
{
    LineInfo.offbase -= CurrMod->d.cv->numlines * sizeof( unsigned_32 );
    LineInfo.numbase -= CurrMod->d.cv->numlines * sizeof( unsigned_16 );
    VMemQSort( LineInfo.offbase, CurrMod->d.cv->numlines, sizeof( unsigned_32 ),
                SwapRelocs, RelocCompare );
}

extern void CVGenModule( void )
/*****************************/
// generate an sstSrcModule
{
    if( LineInfo.needsort ) {
        SortRelocs();
    }
    GenSrcModHeader();
}

extern void CVAddLocal( unsigned_16 info, offset length )
/*******************************************************/
// called during pass 1 final segment processing.
{
    if( length > 0xFFFF ) {
        LnkMsg( WRN+LOC+MSG_DEBUG_TOO_LARGE, "s", "Codeview" );
    }
    if( info != NOT_DEBUGGING_INFO ) {
        AddSubSection( FALSE );
    }
}

extern void CVAddGlobal( symbol *sym )
/************************************/
// called during pass 1 symbol definition
{
    unsigned    size;

    if( !( sym->info & SYM_STATIC ) ) {
        if( ( sym->p.seg == NULL )
            || IS_SYM_IMPORTED( sym )
            || sym->p.seg->is32bit ) {
            size = sizeof( s_pub32 );
        } else {
            size = sizeof( s_pub16 );
        }

⌨️ 快捷键说明

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