mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
982 lines
34 KiB
982 lines
34 KiB
/*++
|
|
|
|
Module Description:
|
|
|
|
CAP.H
|
|
|
|
include files, symbol definitions and function prototypes for
|
|
CAP.DLL
|
|
|
|
Revision History:
|
|
|
|
2-Feb-95 a-robw (Bob Watson)
|
|
Added this header
|
|
Removed dependencies on Nt... functions so CAP.DLL will
|
|
run on Windows95 systems. This includes:
|
|
|
|
getting process information from PSAPI.DLL rather than
|
|
the direct NT functions
|
|
replacing KdPrint & DbgPrint calls with variations of
|
|
OutputDebugString
|
|
replaced Rtl Functions with internal versions doing the
|
|
same thing since these functions aren't available on
|
|
Windows95
|
|
|
|
10-Feb-95 a-robw (Bob Watson)
|
|
udpated comments about data structure arrangement
|
|
|
|
--*/
|
|
|
|
#define LAST_CODE_SYMBOL_HACK // There is a bug in imagehlp.dll which
|
|
// doesn't properly set the
|
|
// RvaToLastByteOfCode field in the coff
|
|
// symbols header struture. This hacks
|
|
// around our usage of this.
|
|
|
|
#define CAIRO // for Cairo uses
|
|
#define KERNEL32_IMPORT_HACK // so imports from kernel32 can be capped
|
|
// the problem is that the ldr* function that
|
|
// calls into cap for the process detach has
|
|
// called through penter() and can't get back
|
|
// unless the threadblock is not removed
|
|
|
|
//#define OLE_IMPORT_HACK // 'cause I don't want double entries when i've
|
|
// compiled with cap and I haven't implemented
|
|
// a way to turn off imports from certain dll's
|
|
|
|
#ifdef MIPS
|
|
// #define DEBUG_CAP 1
|
|
#undef USE_COMMNOT
|
|
#define ENABLE_MIPS_TOPLEVEL_CALIB
|
|
#define ENABLE_MIPS_CALIB
|
|
|
|
extern void _asm(char *, ...);
|
|
#endif
|
|
|
|
|
|
#ifdef i386
|
|
// #define SPEEDUP_INIT
|
|
#define OMAP_XLATE
|
|
#endif
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntcsrsrv.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#ifdef i386
|
|
#include <setjmpex.h>
|
|
#endif
|
|
|
|
#include <excpt.h>
|
|
#include <windows.h>
|
|
#include <tchar.h>
|
|
|
|
#include <imagehlp.h>
|
|
#include <psapi.h>
|
|
|
|
#include "capexp.h"
|
|
|
|
|
|
/*** CAP.H - Public defines and structure definitions for Call Profiler tool.
|
|
*
|
|
*
|
|
* Title:
|
|
* CallProf include file used by CAP.c
|
|
*
|
|
* Copyright (c) 1991, Microsoft Corporation.
|
|
* Reza Baghai.
|
|
*
|
|
*
|
|
* Modification History:
|
|
* 91.09.18 RezaB -- Created
|
|
* 92.03.01 RezaB -- Modified for Client/Server profiling capability
|
|
* 93.06.01 HoiV -- Modified for MIPS and Alpha
|
|
*/
|
|
|
|
|
|
/* * * * * * * * C o m m o n M i s c . D e f i n e s * * * * * * * */
|
|
|
|
#define Naked _declspec (naked) // For asm functions
|
|
|
|
#ifndef MAXLONGLONG
|
|
#define MAXLONGLONG 0x7fffffffffffffff
|
|
#endif
|
|
|
|
#ifdef PRINTDBG
|
|
|
|
void CapDbgPrint (PCH Format, ...);
|
|
|
|
#define INFOPrint(_x_) if (gfGlobalDebFlag & INFO_FLAG) CapDbgPrint _x_
|
|
#define SETUPPrint(_x_) if (gfGlobalDebFlag & SETUP_FLAG) CapDbgPrint _x_
|
|
#define DETAILPrint(_x_) if (gfGlobalDebFlag & DETAIL_FLAG) CapDbgPrint _x_
|
|
|
|
#define OutputCapDebugString(xx) OutputDebugString(xx)
|
|
|
|
#else
|
|
|
|
#define INFOPrint(_x_)
|
|
#define SETUPPrint(_x_)
|
|
#define DETAILPrint(_x_)
|
|
|
|
#define OutputCapDebugString(xx)
|
|
|
|
#endif
|
|
|
|
#define SETUP_FLAG 0x00000001L // Misc
|
|
#define INFO_FLAG 0x00000002L // Debug
|
|
#define DETAIL_FLAG 0x00000004L // Flags
|
|
|
|
#define MEMSIZE 32*1024*1024 // 32 MB virtual memory for data -
|
|
// initially 256K RESERVED - will be
|
|
// COMMITTED more as needed.
|
|
|
|
#define ONE_MILLION 1000000L // Defined for readability
|
|
#define MAX_PATCHES 300 // Limit on num of patchable dlls
|
|
#define MAX_THREADS 200 // Limit on num of profilable threads
|
|
#define PAGE_SIZE 4096 // 4K pages
|
|
#define PATCHFILESZ 3*PAGE_SIZE // DLL patch file maximum size
|
|
#define COMMIT_SIZE 64*PAGE_SIZE // Mem chunk to be commited at a time
|
|
#define BUFFER_SIZE 4*PAGE_SIZE // buffer size for writing to file
|
|
#define NUM_ITERATIONS 1000 // Number of iterations used to
|
|
// calculate overheads
|
|
#define MAXSTRLEN 40
|
|
#define DEFNAMELENGTH 40
|
|
#define MINNAMELENGTH 20
|
|
#define MAXNAMELENGTH 2048
|
|
#define FILENAMELENGTH 256
|
|
|
|
#define INI_DELIM '=' // Delimiter between fields in
|
|
// CAP.INI file
|
|
#define COMMENT_CHAR '#' // Comment character
|
|
#define COMPOBJ "COMPOBJ.DLL"
|
|
#define OLEUNINITIALIZE "OleUninitialize@0"
|
|
#define LOADLIBRARYW "LoadLibraryW"
|
|
#define CAP_INI "CAP.INI" // Current directory cap.ini
|
|
#define STUB_SIGNATURE 0xfefe55aa // Mips Patch Stub signature
|
|
#define MIPS_STUB_MARK 20 / 4 // 5 inst from delay inst to signature
|
|
#define STKSIZE 0x40 // BUGBUG changed when penter changes
|
|
#define PENTER_RAOFS 0x14 // BUGBUG changed when penter changes
|
|
#define PENTER_STACK_SIZE STKSIZE / 4 //
|
|
#define MAX_PARENT_STACK 640 // Should be plenty (bytes)
|
|
#define MAX_DLL_NAMELEN 15 // Should be changed once OFS is
|
|
// long)
|
|
#define CAPDLL "CAP.DLL"
|
|
#define CRTDLL "CRTDLL.DLL"
|
|
#define KERNEL32 "KERNEL32.DLL"
|
|
#define CAIROCRT "CAIROCRT.DLL"
|
|
|
|
#define PATCHEXELIST "[EXES]"
|
|
#define PATCHIMPORTLIST "[PATCH IMPORTS]"
|
|
#define PATCHCALLERLIST "[PATCH CALLERS]"
|
|
#define NAMELENGTH "[NAME LENGTH]"
|
|
#define GLOBALSEMNAME "CAPGlobalSem"
|
|
#define DONEEVENTNAME "CAPDoneEvent"
|
|
#define DUMPEVENTNAME "CAPDumpEvent"
|
|
#define CLEAREVENTNAME "CAPClearEvent"
|
|
#define PAUSEEVENTNAME "CAPPauseEvent"
|
|
#define DATASECNAME "CAPData"
|
|
#define PROFOBJSNAME "CAPProfObjs"
|
|
#define CAPINI "\\cap.ini"
|
|
|
|
#define CHRONOSECNAME "ChronoData"
|
|
#define CHRONO_FUNCS_SIZE PAGE_SIZE
|
|
#define CHRONO_SECTION "CHRONO FUNCS"
|
|
#define EXCLUDE_SECTION "EXCLUDE FUNCS"
|
|
#define OUTPUTFILE_SECTION "OUTPUT FILE"
|
|
#define EXCLUDE_FUNCS_SIZE PAGE_SIZE
|
|
#define MAX_NESTING 1024
|
|
#define CAP_FLAGS "[CAP FLAGS]"
|
|
#define EXCEL_DELIM '~'
|
|
#define PROFILE_OFF "PROFILE=OFF"
|
|
#define DUMPBINARY_ON "DUMPBINARY=ON"
|
|
#define CAPTHREAD_OFF "CAPTHREAD=OFF"
|
|
#define LOADLIBRARY_ON "LOADLIBRARY=ON"
|
|
#define SETJUMP_ON "SETJUMP=ON"
|
|
#define UNDECORATE_OFF "UNDECORATENAME=OFF"
|
|
#define EXCEL_ON "EXCELAWARE=ON"
|
|
#define CHRONOCOLLECT_ON "CHRONOCOLLECT=ON"
|
|
#define REGULARDUMP_OFF "REGULARDUMP=OFF"
|
|
#define CHRONODUMP_ON "CHRONODUMP=ON"
|
|
#define SLOWSYMBOLS_OFF "SLOWSYMBOLS=OFF"
|
|
#define PER_THREAD_MEMORY "PERTHREADMEM="
|
|
#define PER_THREAD_MEMORY_CHAR 13
|
|
#define EMPTY_STRING '%'
|
|
|
|
#ifdef i386
|
|
#define NOP_OPCODE 0x90
|
|
#define CALL_OPCODE 0xe8
|
|
#endif
|
|
|
|
#if 0
|
|
#define CURTHDBLK(x) ((PTHDBLK)(x->Instrumentation[0]))
|
|
#define CLIENTTHDBLK(x) ((PTHDBLK)(x->Instrumentation[1]))
|
|
#define CAPUSAGE(x) ((ULONG)(x->Instrumentation[2]))
|
|
#else
|
|
#define SETCURTHDBLK(p) (TlsSetValue(TlsThdBlk, (p)))
|
|
#define GETCURTHDBLK() ((PTHDBLK)TlsGetValue(TlsThdBlk))
|
|
#define ISCLIENT() ((BOOL)TlsGetValue(TlsClient))
|
|
#define SETCLIENT() (TlsSetValue(TlsClient, (LPVOID)TRUE))
|
|
#define RESETCLIENT() (TlsSetValue(TlsClient, (LPVOID)FALSE))
|
|
#define ISCAPINUSE() ((BOOL)TlsGetValue(TlsCapInUse))
|
|
#define SETCAPINUSE() (TlsSetValue(TlsCapInUse, (LPVOID)TRUE))
|
|
#define RESETCAPINUSE() (TlsSetValue(TlsCapInUse, (LPVOID)FALSE))
|
|
#endif
|
|
|
|
#define MKPDATACELL(base, offset) ((PDATACELL)((PBYTE)base + offset))
|
|
#define MKPPROFBLK(offset) ((PPROFBLK)((PBYTE)pulProfBlkBase + (offset)))
|
|
#define MKPSYMBLK(offset) ((PSYMINFO)((PBYTE)pulProfBlkBase + (offset)))
|
|
#define MKPSYMBOL(offset) ((PTCHAR)((PBYTE)pulProfBlkBase + (offset)))
|
|
|
|
|
|
|
|
/* * * * * * * * * * G l o b a l D e c l a r a t i o n s * * * * * * * * */
|
|
|
|
//
|
|
// Structure for holding a symbol definition. It holds the symbol's address
|
|
// an an offset to its name. Use the macro MKPSYMBOL to convert the offset
|
|
// to a name pointer.
|
|
//
|
|
typedef UNALIGNED struct _syminfo
|
|
{
|
|
ULONG ulAddr;
|
|
ULONG ulSymOff;
|
|
} SYMINFO, *PSYMINFO;
|
|
|
|
|
|
#ifdef i386
|
|
//
|
|
// Data structure for saving information when a setjmp call is made
|
|
// this will allow us to resume processing at the cell referenced by
|
|
// the ulCurCell.
|
|
//
|
|
typedef struct tagjmpinfo
|
|
{
|
|
int *jmpBuf[4];
|
|
ULONG ulCurCell[4];
|
|
INT nJmpCnt;
|
|
} JMPINFO, *PJMPINFO;
|
|
|
|
#endif
|
|
|
|
// Profile block states
|
|
typedef enum
|
|
{
|
|
BLKSTATE_EMPTY, // Not used
|
|
BLKSTATE_ASSIGNED, // Assigned to module, but not loaded
|
|
BLKSTATE_LOADED // Symbol definitions loaded
|
|
} PROFBLK_STATE;
|
|
|
|
//
|
|
// Profile Block - CAP maintains a PROFBLK for each profiled module. It
|
|
// contains the module name and address range, and an offset to an array
|
|
// of SYMINFO structs for the symbols in the module. Use the macro MKPSYMBLK
|
|
// to convert the offset to an array pointer. The PROFBLKs are kept in a linked
|
|
// list, with field ulNxtBlk containing an offset to the next block. The offset
|
|
// is converted to a pointer via the macro MKPPROFBLK.
|
|
//
|
|
typedef UNALIGNED struct _profblk
|
|
{
|
|
PVOID ImageBase; // actual base in image header
|
|
PULONG CodeStart;
|
|
ULONG CodeLength;
|
|
PROFBLK_STATE State;
|
|
ULONG ulSym;
|
|
INT iSymCnt;
|
|
ULONG ulNxtBlk;
|
|
TCHAR atchImageName[1];
|
|
} PROFBLK, *PPROFBLK;
|
|
|
|
|
|
typedef enum
|
|
{
|
|
CLEARED,
|
|
RESTART,
|
|
T1,
|
|
T2
|
|
} TIMESTATE;
|
|
|
|
//
|
|
// Data Cell - A data cell is a node in the call tree that is built as the
|
|
// profiled modules execute. Each node represents one caller-callee link. The
|
|
// node maintains statistics on the link (number of calls, longest, shortest,
|
|
// etc.). It points back to its caller, forward to its callees, and laterally
|
|
// to the other functions that have the same caller. The links are stored as
|
|
// offsets that are converted to pointers via the macro MKPDATACELL.
|
|
//
|
|
typedef UNALIGNED struct _datacell
|
|
{
|
|
LONGLONG liStartCount;
|
|
LONGLONG liFirstTime;
|
|
LONGLONG liMaxTime;
|
|
LONGLONG liMinTime;
|
|
LONGLONG liTotTime;
|
|
TIMESTATE ts; // Time State
|
|
DWORD ulSymbolAddr;
|
|
DWORD ulCallRetAddr;
|
|
int nCalls;
|
|
int nNestedCalls;
|
|
int nTmpNestedCalls;
|
|
ULONG ulParentCell; // Parent Cell (who called me)
|
|
ULONG ulNestedCell; // Nested Cell (Child - I call him)
|
|
ULONG ulNextCell; // Next on the same level Cell
|
|
ULONG ulProfBlkOff; // offset to our ProfBlock
|
|
|
|
} DATACELL, *PDATACELL;
|
|
|
|
|
|
typedef UNALIGNED struct _chronocell
|
|
{
|
|
LONGLONG liElapsed;
|
|
LONGLONG liCallees;
|
|
DWORD ulSymbolAddr;
|
|
DWORD ulCallRetAddr;
|
|
int nNestedCalls;
|
|
int nRepetitions;
|
|
UNALIGNED struct _chronocell * pPreviousChronoCell;
|
|
|
|
} CHRONOCELL, *PCHRONOCELL;
|
|
|
|
|
|
typedef UNALIGNED struct _thdblk
|
|
{
|
|
LONGLONG liStopCount;
|
|
LONGLONG liWasteCount;
|
|
DWORD dwLOCALVAR;
|
|
DWORD dwLOCALEBP;
|
|
DWORD dwPATCHEDADDR;
|
|
DWORD dwSYMBOLADDR;
|
|
DWORD dwCALLRETADDR;
|
|
#ifdef i386
|
|
JMPINFO jmpinfo;
|
|
#endif
|
|
ULONG ulRootCell;
|
|
ULONG ulCurCell;
|
|
PCHRONOCELL pChronoHeadCell; // Chrono Head Cell for this thread
|
|
PCHRONOCELL pCurrentChronoCell; // Currently used ChronoCell
|
|
PCHRONOCELL pLastChronoCell; // To use the same cell if identical
|
|
ULONG ulNestedCalls; // Current nested depth for this thread
|
|
ULONG aulDepth [ MAX_NESTING ];
|
|
ULONG ulTotalChronoCells; // Total of all cells in this thread
|
|
ULONG ulChronoOffset;
|
|
ULONG ulMemOff; // offset to next THDBLK
|
|
|
|
} THDBLK, *PTHDBLK;
|
|
|
|
|
|
|
|
typedef UNALIGNED struct _sectioninfo
|
|
{
|
|
PTHDBLK pthdblk;
|
|
HANDLE hMapObject;
|
|
HANDLE hChronoMapObject;
|
|
DWORD hPid;
|
|
DWORD hTid;
|
|
DWORD hClientPid;
|
|
DWORD hClientTid;
|
|
ULONG ulRootCell;
|
|
|
|
} SECTIONINFO, *PSECTIONINFO;
|
|
|
|
|
|
typedef struct _patchcode
|
|
{
|
|
#ifdef i386
|
|
|
|
#ifdef OVER_OPTIMIZATION
|
|
|
|
BYTE bCallOp; // CALL CAP!_penter
|
|
DWORD dw_penter;
|
|
BYTE bMoveEAXOp; // MOV EAX, ImportAddr
|
|
DWORD dwImportAddr;
|
|
WORD wJmpEAXOp; // JMP EAX
|
|
DWORD OurSignature; // FEFE55AA
|
|
|
|
#else
|
|
|
|
BYTE bMoveEAX1Op; // MOV EAX, ImportAddr
|
|
DWORD dwImportAddr1; //
|
|
BYTE bPushEAXOp; // PUSH EAX
|
|
|
|
BYTE bMoveEAX2Op; // MOV EAX, _penter
|
|
DWORD dw_penter; //
|
|
WORD wJmpEAXOp; // JMP EAX
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef MIPS
|
|
|
|
#ifdef MIPS_VC40_INTERFACE
|
|
DWORD Or_t9_ra; // or t9, ra, zero (1) + 0
|
|
DWORD Lui_t0_penter; // lui t0, xxxx (2) + 1
|
|
DWORD Ori_t0_penter; // ori t0, xxxx (3) + 2
|
|
DWORD Jalr_t0; // jalr t0 (4) + 3
|
|
DWORD Nop_1; // nop (5) + 4
|
|
DWORD Or_ra_t9; // or ra, t9, zero (6) + 5
|
|
DWORD Lui_t0; // lui t0, xxxx (7) + 6
|
|
DWORD Ori_t0; // ori t0, xxxx (8) + 7
|
|
DWORD Jr_t0; // jr t0 (9) + 8
|
|
DWORD Nop_2; // nop (A) + 9
|
|
DWORD OurSignature; // FEFE55AA (B) + A
|
|
#else
|
|
// We can afford just 8 bytes as a stack frame since penter() does
|
|
// not take any parameter.
|
|
DWORD Addiu_sp_sp_imm; // addiu sp, sp, -8 (1) + 0
|
|
DWORD Sw_ra_sp; // sw ra, 4(sp) (2) + 1
|
|
DWORD Lui_t0_ra; // lui t0, xxxx (&penter) (3) + 2
|
|
DWORD Ori_t0_ra; // ori t0, xxxx (&penter) (4) + 3
|
|
DWORD Jalr_t0; // jalr t0 (5) + 4
|
|
DWORD Addiu_r0_r0; // addiu $0, $0, 0x1804 (6) + 5
|
|
DWORD Lw_ra_sp; // lw ra, 4(sp) (7) + 6
|
|
DWORD Lui_t0; // lui t0, xxxx (8) + 7
|
|
DWORD Ori_t0; // ori t0, t0, xxxx (9) + 8
|
|
DWORD Jr_t0; // jr t0 (A) + 9
|
|
DWORD Delay_Inst; // addiu sp, sp, 8 (B) + A
|
|
DWORD OurSignature; // FEFE55AA (C) + B
|
|
#endif // MIPS_VC40_INTERFACE
|
|
|
|
#endif
|
|
|
|
#ifdef ALPHA
|
|
DWORD Lda_sp_sp_imm; // Lda sp, -0x10(sp) (1) + 0
|
|
DWORD Stq_v0_sp; // Stq v0, 0x08(sp) (3) + 2
|
|
DWORD Ldah_t12_ra; // Ldah t12, xxxx (&penter) (4) + 3
|
|
DWORD Lda_t12_ra; // Lda t12, xxxx (&penter) (5) + 4
|
|
DWORD Jsr_t12; // Jsr v0, (t12) (6) + 5
|
|
DWORD Ldq_v0_sp; // Ldq v0, 0x08(sp) (8) + 7
|
|
DWORD Lda_sp_sp; // Lda sp, 0x10(sp) (9) + 8
|
|
DWORD Ldah_t12; // Ldah t12, yyyy (A) + 9
|
|
DWORD Lda_t12; // Lda t12, yyyy (B) + A
|
|
DWORD Jmp_t12; // Jmp zero, (t12) (C) + B
|
|
DWORD Bis_0; // Bis zero, zero, zero (D) + C
|
|
DWORD OurSignature; // FEFE55AA (E) + D
|
|
#endif
|
|
|
|
#ifdef PPC
|
|
PVOID EntryPoint ; // FuncDesc
|
|
DWORD TOC ;
|
|
DWORD addis_UH_penter ; // addis r11,r0,UH (1) + 0
|
|
DWORD ori_LH_penter ; // ori r12,r11,LH (2) + 1
|
|
DWORD lwz_r11_0r12 ; // lwz r11,0(r12) (3) + 2
|
|
DWORD mtctr_r11 ; // mtctr r11 (4) + 3
|
|
DWORD mflr_r0 ; // mflr r0 (5) + 4
|
|
DWORD bctrl ; // bctrl (6) + 5
|
|
DWORD mtlr_r0 ; // mtlr r0 (7) + 6
|
|
DWORD addis_UH_ep ; // addis r11,r0,UH (8) + 7
|
|
DWORD ori_LH_ep ; // ori r12,r11,LH (9) + 8
|
|
DWORD lwz_r11_0r12_ ; // lwz r11,0(r12) (A) + 9
|
|
DWORD mtctr_r11_ ; // mtctr r11 (B) + A
|
|
DWORD lwz_r2_4r12 ; // lwz r11,4(r12) (C) + B
|
|
DWORD bctr ; // bctr (D + C
|
|
DWORD OurSignature ; // FEFE55AA (E) + D
|
|
#endif
|
|
|
|
} PATCHCODE;
|
|
typedef PATCHCODE * PPATCHCODE;
|
|
|
|
|
|
typedef struct _patchdllsec {
|
|
|
|
PVOID pSec; // Ptr to patch code section after MapView
|
|
|
|
} PATCHDLLSEC;
|
|
typedef PATCHDLLSEC * PPATCHDLLSEC;
|
|
|
|
|
|
typedef UNALIGNED struct _MODULE_INFO
|
|
{
|
|
LIST_ENTRY Entry;
|
|
ULONG ImageStart;
|
|
ULONG ImageEnd;
|
|
HANDLE Section;
|
|
PVOID MappedBase;
|
|
UNICODE_STRING BaseName;
|
|
PWSTR FileName;
|
|
WCHAR Path[ MAX_PATH ];
|
|
|
|
} MODULE_INFO, *PMODULE_INFO;
|
|
|
|
typedef UNALIGNED struct _LINENO_INFO
|
|
{
|
|
PCHAR FileName;
|
|
USHORT LineNo;
|
|
|
|
} LINENO_INFORMATION, *PLINENO_INFORMATION;
|
|
|
|
typedef UNALIGNED struct _BINFILE_HEADER_INFO
|
|
{
|
|
LONGLONG liIncompleteTicks;
|
|
char ptchProfilingBinaryName[FILENAMELENGTH];
|
|
SYSTEMTIME SysTime; // 4 DWORDS
|
|
ULONG ulCalibTime;
|
|
ULONG ulCalibNestedTime;
|
|
int iTotalThreads;
|
|
ULONG ulCairoFlags;
|
|
|
|
} BINFILE_HEADER_INFO;
|
|
|
|
typedef UNALIGNED struct _PROFBLOCK_INFO
|
|
{
|
|
PVOID ImageBase; // actual base in image header
|
|
PULONG CodeStart;
|
|
ULONG CodeLength;
|
|
CHAR pImageName[20];
|
|
|
|
} PROFBLOCK_INFO;
|
|
|
|
typedef UNALIGNED struct _BINFILE_THREAD_INFO
|
|
{
|
|
DWORD hPid;
|
|
DWORD hTid;
|
|
DWORD hClientPid;
|
|
DWORD hClientTid;
|
|
ULONG ulTotalCells;
|
|
|
|
} BINFILE_THREAD_INFO;
|
|
|
|
typedef UNALIGNED struct _BINFILE_CELL_INFO
|
|
{
|
|
LONGLONG liElapsed;
|
|
LONGLONG liCallees;
|
|
DWORD ulSymbolAddr;
|
|
DWORD ulCallRetAddr;
|
|
int nNestedCalls;
|
|
int nRepetitions;
|
|
|
|
} BINFILE_CELL_INFO;
|
|
|
|
#ifdef PPC
|
|
typedef struct _FD
|
|
{
|
|
ULONG EntryPoint;
|
|
ULONG TOC;
|
|
|
|
} FD;
|
|
typedef FD * PFD;
|
|
#endif
|
|
|
|
/* * * * E x t e r n a l F u n c t i o n D e c l a r a t i o n s * * * */
|
|
|
|
|
|
extern void __cdecl SaveAllRegs (void);
|
|
extern void __cdecl RestoreAllRegs (void);
|
|
extern void __cdecl CalHelper1(void);
|
|
extern void __cdecl CalHelper2(void);
|
|
|
|
|
|
typedef void * (__cdecl * Alloc_t) (unsigned int);
|
|
typedef void (__cdecl * Free_t) (void *);
|
|
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
//
|
|
// The following block diagram describes the format of a Profile Block
|
|
// This is from looking at the code.
|
|
//
|
|
// +-------------------------+
|
|
// | PVOID pulProfBlkShared | Unused field (only used by the CAP threads)
|
|
// +-------------------------+
|
|
// | PVOID pulProfBlkBase | ---------------------------------------------+
|
|
// +=========================+ |
|
|
// +=========================+ <----------------------------------------+ |
|
|
// | PVOID ImageBase | this whole block is one ProfBlk | |
|
|
// +-------------------------+ | |
|
|
// | PULONG CodeStart | | |
|
|
// +-------------------------+ | |
|
|
// | ULONG CodeLength | | |
|
|
// +-------------------------+ | |
|
|
// | INT State | | |
|
|
// +-------------------------+ (ulSym is offset from pulProfBlkBase) | |
|
|
// | ULONG ulSym | Offset to SYMINFO Table -----------+ | |
|
|
// +-------------------------+ | | |
|
|
// | int iSymCnt | | | |
|
|
// +-------------------------+ | | |
|
|
// | ULONG ulNxtBlk | Offset to next ProfBlk -----------+--+ | |
|
|
// +-------------------------+ ----- | | | |
|
|
// | TCHAR atchImageName[0] | ^ | | | |
|
|
// ~ ~ | | | | |
|
|
// | Length of ImageName | | | |
|
|
// ~ ~ | (n) TCHAR | | | |
|
|
// | TCHAR atchImageName[n] | | | | | |
|
|
// +-------------------------+ ----- | | | |
|
|
// +-------------------------+ <-----------------------------------+ | | |
|
|
// | SYMINFO: ULONG ulAddr | | | |
|
|
// | [0] ULONG ulSymOff +-----------------------------------+ | | |
|
|
// ~ ~ (ulSymOff is offset from | | | |
|
|
// pulProfBlkBase) | | | |
|
|
// ~ ~ | | | |
|
|
// | SYMINFO: | | | | |
|
|
// | [n] | | | | |
|
|
// +-------------------------+ | | | |
|
|
// | SymbolName[0][...] | <---------------------------------+ | | |
|
|
// +-------------------------+ | | |
|
|
// | SymbolName[1][...] | | | |
|
|
// +-------------------------+ | | |
|
|
// | ... | | | |
|
|
// ~ ~ | | |
|
|
// | | |
|
|
// ~ ~ | | |
|
|
// | | | | |
|
|
// +-------------------------+ | | |
|
|
// | SymbolName[n][...] | | | |
|
|
// +=========================+ <--------------------------------------+--+ |
|
|
// +=========================+ |
|
|
// ... |
|
|
// ... |
|
|
// ... |
|
|
// +=========================+ |
|
|
// +=========================+ |
|
|
// |
|
|
// Last ProfBlk <--------------------------------------------+
|
|
|
|
|
|
/* * * * * * * * * * * * * I N C L U D E F I L E S * * * * * * * * * * */
|
|
|
|
#ifdef ALPHA
|
|
typedef double DWORDLONG;
|
|
#define INST_SIZE 4
|
|
#endif
|
|
|
|
#ifdef _PPC_
|
|
#define SaveAllRegs() // Not Used, a place holder
|
|
#define RestoreAllRegs() // Not Used, a place holder
|
|
PTHDBLK get_pthdblk(void);
|
|
ULONG GetTOC(void);
|
|
#endif
|
|
|
|
/* * * * * * * * * * G L O B A L D E C L A R A T I O N S * * * * * * * * */
|
|
|
|
|
|
/* * * * * * * * * * F U N C T I O N P R O T O T Y P E S * * * * * * * * */
|
|
|
|
BOOL _cdecl LibMain (HANDLE hDLL,
|
|
DWORD dwReason,
|
|
LPVOID lpReserved);
|
|
|
|
BOOL WINAPI CallProfMain (IN HANDLE DllHandle, ULONG Reason,
|
|
IN PCONTEXT Context OPTIONAL);
|
|
|
|
BOOL DoDllInitializations (void);
|
|
|
|
#ifdef MIPS // Setup Mips [jal _penter] instruction to be
|
|
// at the right place
|
|
|
|
BOOL PatchEntryRoutine (ULONG ulAddr,
|
|
PVOID ImageBase,
|
|
ULONG ulPenterAddress,
|
|
BOOL fDisablePenter);
|
|
|
|
#endif
|
|
|
|
void PrePenter (PTHDBLK pthdblk);
|
|
|
|
|
|
DWORD PostPenter (void);
|
|
|
|
void RecordInfo (PDATACELL pCur,
|
|
PCHRONOCELL pChronoCell,
|
|
PTHDBLK pthdblk);
|
|
|
|
ULONG GetNxtCell (PTHDBLK pthdblk);
|
|
|
|
ULONG GetNewCell (PTHDBLK pthdblk);
|
|
|
|
INT UnprotectThunkFilter (PVOID pThunkAddress,
|
|
PEXCEPTION_POINTERS pXcptPtr);
|
|
|
|
INT AccessXcptFilter (ULONG ulXcptNo,
|
|
PEXCEPTION_POINTERS pXcptPtr,
|
|
ULONG ulCommitSz);
|
|
|
|
void GetNewThdBlk (void);
|
|
|
|
void ClearProfiledInfo (void);
|
|
|
|
void ClearRoutineInfo (PTHDBLK pthdblk, ULONG uldatacell,
|
|
LONGLONG liRootStartTicks);
|
|
|
|
void DumpProfiledInfo (PTCHAR ptchDumpExt);
|
|
void DumpProfiledBinary (PTCHAR);
|
|
|
|
int CalcIncompleteCalls (PTHDBLK pthdblk, ULONG uldatacell, int TreeDepth);
|
|
|
|
void DumpRoutineInfo (PTHDBLK pthdblk, ULONG uldatacell,
|
|
int iDepth, PTCHAR ptchDumpFile,
|
|
LPSTR lpstrbuff);
|
|
|
|
LONGLONG GetCalleesInfo (PTHDBLK pthdblk, ULONG uldatacell,
|
|
int * piCalls, int * piNestedCalls);
|
|
|
|
void AdjustTime (PLONGLONG Time, PTCHAR Kchar);
|
|
|
|
PTCHAR GetFunctionName (ULONG ulFuncAddr,
|
|
ULONG ulProfBlkOff,
|
|
ULONG * ulCorrectAddr);
|
|
|
|
void PreTopLevelCalib (PTHDBLK pthdblk, PDATACELL pDataCell);
|
|
|
|
void PostTopLevelCalib (PTHDBLK pthdblk);
|
|
|
|
void DoCalibrations (void);
|
|
|
|
PTHDBLK CreateDataSec (DWORD hPid, DWORD hTid,
|
|
DWORD hServerPid, DWORD hServerTid);
|
|
|
|
DWORD DumpThread (PVOID pvArg);
|
|
|
|
DWORD ClearThread (PVOID pvArg);
|
|
|
|
DWORD PauseThread (PVOID pvArg);
|
|
|
|
void DoDllCleanups (void);
|
|
|
|
BOOL PatchDll (PTCHAR ptchPatchImports,
|
|
PTCHAR ptchPatchCallers,
|
|
BOOL bCallersToPatch,
|
|
PTCHAR ptchDllName,
|
|
PVOID pvImageBase);
|
|
|
|
PIMAGE_SECTION_HEADER
|
|
GetSectionListFromAddress(
|
|
IN PULONG pulAddress,
|
|
OUT int *cNumberOfSections,
|
|
OUT PVOID *ppvCalleeImageBase);
|
|
|
|
BOOL IsCodeAddress (IN PULONG pulAddress,
|
|
IN PIMAGE_SECTION_HEADER pSection,
|
|
IN int cNumberOfSections,
|
|
IN PVOID pvImageBase);
|
|
|
|
PBOOL GetCodeSectionTable (IN PIMAGE_DEBUG_INFORMATION pImageDbgInfo,
|
|
OUT int *cNumberOfSections);
|
|
|
|
PPROFBLK SetupProfiling (LPCTSTR ptchFileName);
|
|
void SetupLibProfiling (LPCSTR ImageName, BOOL fFirstLevelCall);
|
|
|
|
void GetSymbols (PPROFBLK pProfBlk, PTCHAR ptchImageName,
|
|
PIMAGE_DEBUG_INFORMATION pImageDbgInfo);
|
|
|
|
int SymCompare (PSYMINFO, PSYMINFO);
|
|
void SymSort (SYMINFO syminfo[], INT iLeft, INT iRight);
|
|
int SymBCompare (PDWORD, PSYMINFO);
|
|
PSYMINFO SymBSearch (DWORD dwAddr, SYMINFO syminfoCur[], INT n);
|
|
void SymSwap (SYMINFO syminfo[], INT i, INT j);
|
|
BOOL GetCoffDebugDirectory(PIMAGE_DEBUG_DIRECTORY *pDbgDir,
|
|
ULONG ulDbgDirSz);
|
|
#ifdef i386
|
|
void CAP_LongJmp (jmp_buf jmpBuf, int nRet);
|
|
void CAP_SetJmp (jmp_buf jmpBuf);
|
|
#endif
|
|
|
|
HANDLE CAP_LoadLibraryA (LPCSTR lpName);
|
|
HANDLE CAP_LoadLibraryExA (LPCSTR lpName,
|
|
HANDLE hFile,
|
|
DWORD dwFlags);
|
|
#ifndef _CHICAGO_
|
|
HANDLE CAP_LoadLibraryW (LPCWSTR lpName);
|
|
HANDLE CAP_LoadLibraryExW (LPCWSTR lpName,
|
|
HANDLE hFile,
|
|
DWORD dwFlags);
|
|
#endif // !_CHICAGO_
|
|
void CAP_GetLibSyms (LPCSTR lpName, BOOL fMainLib);
|
|
|
|
void SetCapUsage (DWORD dwValue);
|
|
|
|
void SetSymbolSearchPath (void);
|
|
|
|
void DumpFuncCalls (PTHDBLK pthdblk, LPSTR lpstrBuff);
|
|
void GetTotalRuntime (PTHDBLK pthdblk);
|
|
void DumpChronoFuncs (PTHDBLK pthdblk, LPSTR lpstrBuff);
|
|
void DumpChronoEntry (PTHDBLK pthdblk,
|
|
LPSTR lpstrBuff,
|
|
PCHRONOCELL * ppChronoCell,
|
|
BOOL fDumpAll);
|
|
|
|
void penter (void);
|
|
|
|
void DummyRtn (void);
|
|
|
|
|
|
#undef UNICODE
|
|
#undef _UNICODE
|
|
|
|
// RTL replacement functions
|
|
|
|
VOID CapInitUnicodeString (
|
|
PUNICODE_STRING DestinationString,
|
|
PCWSTR SourceString
|
|
);
|
|
|
|
LONG
|
|
CapUnicodeStringToAnsiString (
|
|
PANSI_STRING DestinationString,
|
|
PUNICODE_STRING SourceString,
|
|
BOOLEAN AllocateDestinationString
|
|
);
|
|
|
|
HANDLE GetCurrentCapProcess ();
|
|
|
|
#if DBG
|
|
//
|
|
// Don't do anything for the checked builds, let it be controlled from the
|
|
// sources file.
|
|
|
|
#define PRINTDBG 1
|
|
|
|
#else
|
|
|
|
#undef PRINTDBG
|
|
|
|
#endif
|
|
|
|
#ifndef GLOBALS
|
|
|
|
//------------------------------------------------------------------------
|
|
// Shared Global Variables
|
|
//------------------------------------------------------------------------
|
|
|
|
/* * * * * * * * * * * G L O B A L V A R I A B L E S * * * * * * * * * */
|
|
|
|
extern char * VERSION;
|
|
|
|
extern DWORD TlsThdBlk; // indexes into Thread Local Storage
|
|
extern DWORD TlsClient;
|
|
extern DWORD TlsCapInUse;
|
|
|
|
extern ULONG ulThdStackSize;
|
|
extern HANDLE hProfMapObject;
|
|
|
|
extern ULONG ulLocProfBlkOff;
|
|
extern PULONG pulProfBlkBase;
|
|
extern PULONG pulProfBlkShared;
|
|
|
|
extern PATCHDLLSEC aPatchDllSec [MAX_PATCHES];
|
|
extern int iPatchCnt; // Number of DLLs being patched
|
|
|
|
extern SECTIONINFO aSecInfo [MAX_THREADS];
|
|
extern int iThdCnt; // Number of thread being profiled
|
|
|
|
extern HANDLE hThisProcess;
|
|
extern HANDLE hLocalSem;
|
|
extern HANDLE hGlobalSem;
|
|
extern HANDLE hDoneEvent;
|
|
extern HANDLE hDumpEvent;
|
|
extern HANDLE hClearEvent;
|
|
extern HANDLE hPauseEvent;
|
|
extern HANDLE hDumpThread;
|
|
extern HANDLE hClearThread;
|
|
extern HANDLE hPauseThread;
|
|
extern PCH pDumpStack;
|
|
extern PCH pClearStack;
|
|
extern PCH pPauseStack;
|
|
extern CLIENT_ID DumpClientId;
|
|
extern CLIENT_ID ClearClientId;
|
|
extern CLIENT_ID PauseClientId;
|
|
|
|
extern LPTSTR ptchBaseAppImageName;
|
|
extern LPTSTR ptchFullAppImageName;
|
|
|
|
extern HANDLE hOutFile;
|
|
extern TCHAR atchOutFileName[FILENAMELENGTH];
|
|
extern TCHAR atchFuncName[MAXNAMELENGTH];
|
|
extern int cChars;
|
|
|
|
extern LONGLONG liTimerFreq;
|
|
extern LONGLONG liCalibTicks;
|
|
extern ULONG ulCalibTime;
|
|
extern LONGLONG liCalibNestedTicks;
|
|
extern ULONG ulCalibNestedTime;
|
|
extern LONGLONG liRestartTicks;
|
|
extern LONGLONG liWasteOverheadSavRes;
|
|
extern LONGLONG liWasteOverhead;
|
|
extern LONGLONG liIncompleteTicks;
|
|
extern LONGLONG liTotalRunTime;
|
|
|
|
extern BOOL fProfiling;
|
|
extern BOOL fPaused;
|
|
extern DWORD dwDUMMYVAR;
|
|
extern TEB teb;
|
|
|
|
extern TCHAR atchPatchBuffer [PATCHFILESZ+1];
|
|
|
|
extern SECURITY_ATTRIBUTES SecAttributes;
|
|
extern SECURITY_DESCRIPTOR SecDescriptor;
|
|
extern BOOL fInThread;
|
|
extern BOOL fPatchImage;
|
|
|
|
#ifdef i386
|
|
extern FARPROC longjmpaddr;
|
|
extern FARPROC setjmpaddr;
|
|
#endif
|
|
|
|
extern FARPROC GetLastErrorAddr;
|
|
extern FARPROC loadlibAaddr;
|
|
extern FARPROC loadlibExAaddr;
|
|
#ifndef _CHICAGO_
|
|
extern FARPROC loadlibWaddr;
|
|
extern FARPROC loadlibExWaddr;
|
|
#endif // !_CHICAGO_
|
|
|
|
extern PTCHAR ptchPatchExes;
|
|
extern PTCHAR ptchPatchImports;
|
|
extern PTCHAR ptchPatchCallers;
|
|
extern BOOL bCallersToPatch;
|
|
|
|
extern PTCHAR ptchNameLength; // 053193 Add
|
|
extern int iNameLength; // 053193 Add
|
|
|
|
extern LPSTR lpSymbolSearchPath;
|
|
|
|
extern ULONG gfGlobalDebFlag;
|
|
|
|
extern BOOL fCsrSS;
|
|
extern BOOL fCalibration; // Default
|
|
extern BOOL fDllInit; // value
|
|
extern BOOL fUndecorateName; // for our flags
|
|
extern BOOL fDumpBinary;
|
|
extern BOOL fCapThreadOn;
|
|
extern BOOL fLoadLibraryOn;
|
|
extern BOOL fSetJumpOn;
|
|
extern BOOL fRegularDump;
|
|
extern BOOL fChronoCollect;
|
|
extern BOOL fChronoDump;
|
|
extern BOOL fSecondChanceTranslation;
|
|
extern unsigned long ulPerThdAllocSize;
|
|
|
|
extern CHAR cExcelDelimiter; // Delimiter for Excel
|
|
|
|
// This is for DumpChronoFuncs
|
|
extern TCHAR ptchChronoFuncs[CHRONO_FUNCS_SIZE];
|
|
extern TCHAR ptchExcludeFuncs[EXCLUDE_FUNCS_SIZE];
|
|
|
|
// This is for an optional output file
|
|
extern TCHAR ptchOutputFile[FILENAMELENGTH];
|
|
|
|
// This Flag is added to indicate if initialization is successful or not
|
|
// HWC 11/12/93
|
|
extern BOOL gfInitializationOK;
|
|
|
|
|
|
#if defined(MIPS) || defined(ALPHA) || defined(_PPC_)
|
|
extern PATCHCODE PatchStub;
|
|
#endif
|
|
|
|
#ifdef MIPS //---------------------- Mips only -------------------------
|
|
#define CURRENT_INST(ofs) *(pulRoutineAddr + ofs)
|
|
#define MAX_INST_SEARCH 60 // Reduced from 100, to keep offset below 255
|
|
|
|
#define DEBUG_BREAK 0x00000016
|
|
#define JAL_INSTR 0x0c000000
|
|
#define SW_RA 0xafbf0000
|
|
#define ADDIU_SP 0x27bd0000
|
|
#define JR_RA 0x03e00008
|
|
#define NOP 0x00000000
|
|
#define INST_SIZE 4
|
|
#endif //---------------------- Mips only -------------------------
|
|
#endif
|