sampdos.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 339 行
C
339 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <ctype.h>
#include <string.h>
#include <process.h>
#include <dos.h>
#include <malloc.h>
#include <conio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "sample.h"
#include "smpstuff.h"
#include "wmsg.h"
#include "ovldbg.h"
char FAR_PTR *CommonAddr = NULL;
extern bool FirstSample;
typedef struct {
struct samp_block_prefix pref;
struct samp_ovl_load ovl;
} overlay_record_t;
typedef struct pblock {
seg envstring;
seg_offset commandln;
seg_offset fcb01;
seg_offset fcb02;
seg_offset startsssp;
seg_offset startcsip;
} pblock;
typedef struct {
void far *addr;
uint_16 sect;
} ovl_addr;
extern seg_offset far SysCallerAddr;
extern unsigned char far SysCaught;
extern unsigned char far SysNoDOS;
extern char FAR_PTR *MsgArray[ERR_LAST_MESSAGE-ERR_FIRST_MESSAGE+1];
unsigned OvlSize;
void FAR_PTR *OvlStruct;
int (far *OvlHandler)( unsigned req, void far *data );
int FirstHook = TRUE;
extern unsigned GetNumber( unsigned, unsigned, char **, unsigned );
extern void Output( char FAR_PTR *str );
extern void fatal( void );
extern void StartTimer( void );
extern void InstallDOSIntercepts( void );
extern void StopTimer( void );
extern void REPORT_TYPE report( void );
extern void RemoveDOSIntercepts( void );
extern void WriteCodeLoad( seg_offset ovl_tbl, char *name, samp_block_kinds );
extern void WriteAddrMap( seg map_start, seg load_start, off load_offset );
extern int SampWrite( void FAR_PTR *buff, unsigned len );
extern int AddInterrupt( unsigned );
extern void Usage( void );
extern void SetTimerRate( char ** );
extern void RecordCGraph( void );
extern seg GetPSP( void );
extern void DOSLoadProg( char *, pblock near *, void REPORT_TYPE (*)( void ) );
extern void DOSRunProg( seg_offset * );
extern void far ovl_handler( short );
void WriteOvl( unsigned req_ovl, char is_return, unsigned offset, unsigned seg )
{
overlay_record_t FAR_PTR *ovl;
struct {
struct samp_block_prefix pref;
struct samp_remap_sect remap;
} remap_blk;
ovl_addr xlat_addr;
unsigned size;
SamplerOff++;
if( FirstHook ) {
FirstHook = FALSE;
req_ovl = 0; /* first req_ovl is garbage */
SamplerOff--; /* start sampling after this routine */
}
size = ( sizeof( overlay_record_t ) - 1 ) + OvlSize;
ovl = OvlStruct;
ovl->pref.tick = CurrTick;
ovl->pref.length = size;
ovl->pref.kind = SAMP_OVL_LOAD;
ovl->ovl.req_section = req_ovl;
if( is_return ) {
ovl->ovl.req_section |= OVL_RETURN;
}
ovl->ovl.addr.segment = seg;
ovl->ovl.addr.offset = offset-1;
Info.d.count[ SAMP_OVL_LOAD ].size += size;
Info.d.count[ SAMP_OVL_LOAD ].number += 1;
OvlHandler( OVLDBG_GET_OVERLAY_STATE, ovl->ovl.ovl_map );
SampWrite( ovl, ovl->pref.length );
/* find out what overlays moved */
remap_blk.pref.tick = CurrTick;
remap_blk.pref.length = sizeof( remap_blk );
remap_blk.pref.kind = SAMP_REMAP_SECTION;
xlat_addr.sect = 0;
for(;;) {
if( !OvlHandler( OVLDBG_GET_MOVED_SECTION, &xlat_addr ) )
break;
remap_blk.remap.data[ 0 ].section = xlat_addr.sect;
remap_blk.remap.data[ 0 ].segment = FP_SEG( xlat_addr.addr );
Info.d.count[ SAMP_REMAP_SECTION ].size += remap_blk.pref.length;
Info.d.count[ SAMP_REMAP_SECTION ].number += 1;
SampWrite( &remap_blk, remap_blk.pref.length );
}
SamplerOff--;
}
void StopProg( void )
{
StopTimer();
RemoveDOSIntercepts();
}
void StartProg( char *cmd, char *prog, char *args )
{
struct SREGS segs;
seg_offset ovl_tbl;
struct ovl_header far *ovl;
pblock parms;
void REPORT_TYPE (*fn)( void );
void *ovl_struct;
cmd = cmd;
InstallDOSIntercepts();
StartTimer();
segread( (struct SREGS *)&segs );
parms.envstring = 0;
parms.commandln.segment = segs.ss;
parms.commandln.offset = (off) args;
parms.fcb01.segment = GetPSP();
parms.fcb01.offset = 0x5c; /* formatted parameter area 1 (FCB) */
parms.fcb02.segment = parms.fcb01.segment;
parms.fcb02.offset = 0x6c; /* formatted parameter area 2 (FCB) */
fn = (void REPORT_TYPE (*)( void )) report;
DOSLoadProg( prog, (pblock near *) &parms, fn );
/* Will load prog to memory ready to DOSRunProg.
Will also cause prog to chain to report after its execution.
*/
ovl_tbl.segment = 0;
ovl_tbl.offset = 0;
ovl = MK_FP( parms.startcsip.segment, parms.startcsip.offset );
if( ovl->signature == OVL_SIGNATURE ) {
OvlHandler = MK_FP( parms.startcsip.segment, ovl->handler_offset );
OvlSize = OvlHandler( OVLDBG_GET_STATE_SIZE, NULL );
ovl_struct = alloca( ( sizeof( overlay_record_t ) - 1 ) + OvlSize );
if( ovl_struct == NULL ) {
Output( MsgArray[MSG_SAMPLE_1-ERR_FIRST_MESSAGE] );
Output( "\r\n" );
fatal();
}
OvlStruct = ovl_struct;
OvlHandler( OVLDBG_GET_OVL_TBL_ADDR, &ovl_tbl );
ovl->hook = &ovl_handler;
SamplerOff++; /* don't time overlay initialization */
}
WriteCodeLoad( ovl_tbl, ExeName, SAMP_MAIN_LOAD );
WriteAddrMap( 0, GetPSP() + 0x10, 0 );
SampleIndex = 0;
SampleCount = 0;
CurrTick = 0L;
SysCaught = 0;
FirstSample = TRUE;
DOSRunProg( (seg_offset *)&parms.startsssp );
}
void RecordSample( union INTPACK FAR_PTR *r )
{
seg segment;
off offset;
if( SysCaught ) {
offset = SysCallerAddr.offset;
segment = SysCallerAddr.segment;
} else {
offset = r->x.ip;
segment = r->x.cs;
}
Samples->d.sample.sample[ SampleIndex ].offset = offset;
Samples->d.sample.sample[ SampleIndex ].segment = segment;
LastSampleIndex = SampleIndex;
++SampleIndex;
++SampleCount;
if( CallGraphMode ) {
RecordCGraph();
}
}
void GetCommArea( void )
{
if( CommonAddr == NULL ) { /* can't get the common region yet */
Comm.cgraph_top = 0;
Comm.top_ip = 0;
Comm.top_cs = 0;
Comm.pop_no = 0;
Comm.push_no = 0;
Comm.in_hook = 1; /* don't record this sample */
} else {
_fmemcpy(&Comm, CommonAddr, sizeof( Comm ) );
}
}
void GetNextAddr( void )
{
struct {
unsigned long ptr;
seg cs;
off ip;
} stack_entry;
if( CommonAddr == NULL ) {
CGraphOff = 0;
CGraphSeg = 0;
} else {
_fmemcpy( &stack_entry, (void FAR_PTR *) Comm.cgraph_top,
sizeof( stack_entry ) );
CGraphOff = stack_entry.ip;
CGraphSeg = stack_entry.cs;
Comm.cgraph_top = stack_entry.ptr;
}
}
void RememberComm( char FAR_PTR *address )
{
CommonAddr = address;
}
void ResetCommArea( void )
{
if( CommonAddr != NULL ) { /* reset common variables */
Comm.pop_no = 0;
Comm.push_no = 0;
_fmemcpy( CommonAddr + 9, &Comm.pop_no, 4 );
}
}
void SysDefaultOptions( void )
{
SysNoDOS = 0;
}
void SetInterruptWatch( char **cmd )
{
unsigned intr_num;
intr_num = GetNumber( 0x20, 0xff, cmd, 16 );
if( ( intr_num >= 0x34 ) && ( intr_num <= 0x3d ) ) {
Output( MsgArray[MSG_SAMPLE_2-ERR_FIRST_MESSAGE] );
Output( "\r\n" );
fatal();
}
if( intr_num != 0x21 ) { /* the DOS interrupt is already monitored */
if( AddInterrupt( intr_num ) ) {
Output( MsgArray[MSG_SAMPLE_3-ERR_FIRST_MESSAGE] );
Output( "\r\n" );
fatal();
}
}
}
void SysParseOptions( char c, char **cmd )
{
char buff[2];
switch( c ) {
case 'r':
SetTimerRate( cmd );
break;
case 'i':
SetInterruptWatch( cmd );
break;
case 'd':
SysNoDOS = 1;
break;
default:
Output( MsgArray[MSG_INVALID_OPTION-ERR_FIRST_MESSAGE] );
buff[0] = c;
buff[1] = '\0';
Output( buff );
Output( "\r\n" );
fatal();
break;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?