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