PageRenderTime 66ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/SimpleProfiler/ProfilerCallback.cpp

http://simple-assembly-explorer.googlecode.com/
C++ | 3763 lines | 2653 code | 656 blank | 454 comment | 465 complexity | 68615634c6ae5989cfe5c63df722da55 MD5 | raw file
Possible License(s): GPL-3.0, MIT, CC-BY-SA-3.0
  1. // ==++==
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // ==--==
  6. /****************************************************************************************
  7. * File:
  8. * ProfilerCallBack.cpp
  9. *
  10. * Description:
  11. * Implements ICorProfilerCallback. Logs every event of interest to a file on disc.
  12. *
  13. ***************************************************************************************/
  14. #undef _WIN32_WINNT
  15. #define _WIN32_WINNT 0x0403
  16. #include <windows.h>
  17. #include <share.h>
  18. #include "basehlp.h"
  19. #include "basehlp.hpp"
  20. #include "ProfilerInfo.h"
  21. #include "ProfilerCallback.h"
  22. ProfilerCallback *g_pCallbackObject; // global reference to callback object
  23. /***************************************************************************************
  24. ******************** ********************
  25. ******************** Global Functions Used for Thread Support ********************
  26. ******************** ********************
  27. ***************************************************************************************/
  28. /* static __stdcall */
  29. DWORD __stdcall ThreadStub( void *pObject )
  30. {
  31. ((ProfilerCallback *)pObject)->_ThreadStubWrapper();
  32. return 0;
  33. } // _GCThreadStub
  34. /***************************************************************************************
  35. ******************** ********************
  36. ******************** Global Functions Used by Function Hooks ********************
  37. ******************** ********************
  38. ***************************************************************************************/
  39. //
  40. // The functions EnterStub, LeaveStub and TailcallStub are wrappers. The use of
  41. // of the extended attribute "__declspec( naked )" does not allow a direct call
  42. // to a profiler callback (e.g., ProfilerCallback::Enter( functionID )).
  43. //
  44. // The enter/leave function hooks must necessarily use the extended attribute
  45. // "__declspec( naked )". Please read the corprof.idl for more details.
  46. //
  47. EXTERN_C void __stdcall EnterStub(FunctionID functionID,
  48. UINT_PTR clientData,
  49. COR_PRF_FRAME_INFO frameInfo,
  50. COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo)
  51. {
  52. ProfilerCallback::Enter( functionID, clientData, frameInfo, argumentInfo );
  53. } // EnterStub
  54. EXTERN_C void __stdcall LeaveStub( FunctionID functionID, COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange )
  55. {
  56. ProfilerCallback::Leave( functionID, retvalRange );
  57. } // LeaveStub
  58. EXTERN_C void __stdcall TailcallStub( FunctionID functionID )
  59. {
  60. ProfilerCallback::Tailcall( functionID );
  61. } // TailcallStub
  62. #ifdef _X86_
  63. void __declspec( naked ) EnterNaked2(FunctionID funcId,
  64. UINT_PTR clientData,
  65. COR_PRF_FRAME_INFO frameInfo,
  66. COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo)
  67. {
  68. __asm
  69. {
  70. PUSH EBP
  71. MOV EBP, ESP
  72. PUSH EAX
  73. PUSH ECX
  74. PUSH EDX
  75. }
  76. EnterStub(funcId, clientData, frameInfo, argumentInfo);
  77. __asm
  78. {
  79. POP EDX
  80. POP ECX
  81. POP EAX
  82. MOV ESP, EBP
  83. POP EBP
  84. RET 10H
  85. }
  86. } // EnterNaked
  87. void __declspec( naked ) LeaveNaked2(FunctionID funcId,
  88. UINT_PTR clientData,
  89. COR_PRF_FRAME_INFO frameInfo,
  90. COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange)
  91. {
  92. __asm
  93. {
  94. PUSH EBP
  95. MOV EBP, ESP
  96. PUSH EAX
  97. PUSH ECX
  98. PUSH EDX
  99. }
  100. LeaveStub(funcId, retvalRange);
  101. __asm
  102. {
  103. POP EDX
  104. POP ECX
  105. POP EAX
  106. MOV ESP, EBP
  107. POP EBP
  108. RET 10H
  109. }
  110. } // LeaveNaked
  111. void __declspec( naked ) TailcallNaked2(FunctionID funcId,
  112. UINT_PTR clientData,
  113. COR_PRF_FRAME_INFO frameInfo)
  114. {
  115. __asm
  116. {
  117. push eax
  118. push ecx
  119. push edx
  120. push [esp + 16]
  121. call TailcallStub
  122. pop edx
  123. pop ecx
  124. pop eax
  125. ret 12
  126. }
  127. } // TailcallNaked
  128. #elif defined(_AMD64_)
  129. // these are linked in AMD64 assembly (amd64\asmhelpers.asm)
  130. EXTERN_C void EnterNaked2(FunctionID funcId,
  131. UINT_PTR clientData,
  132. COR_PRF_FRAME_INFO frameInfo,
  133. COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo);
  134. EXTERN_C void LeaveNaked2(FunctionID funcId,
  135. UINT_PTR clientData,
  136. COR_PRF_FRAME_INFO frameInfo,
  137. COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange);
  138. EXTERN_C void TailcallNaked2(FunctionID funcId,
  139. UINT_PTR clientData,
  140. COR_PRF_FRAME_INFO frameInfo);
  141. #endif // _X86_
  142. /***************************************************************************************
  143. ******************** ********************
  144. ******************** ProfilerCallBack Implementation ********************
  145. ******************** ********************
  146. ***************************************************************************************/
  147. /* public */
  148. ProfilerCallback::ProfilerCallback() :
  149. PrfInfo(),
  150. m_path( NULL ),
  151. m_status_path( NULL),
  152. m_refCount( 0 ),
  153. m_stream( NULL ),
  154. m_dwShutdown( 0 ),
  155. m_bShutdown( FALSE ),
  156. m_dwProcessId( NULL ),
  157. m_filter( NULL ),
  158. m_filterLen( 0 ),
  159. m_pGCHost( NULL ),
  160. m_includeSystem( FALSE ),
  161. m_traceEvent( FALSE ),
  162. m_traceParameter( FALSE )
  163. {
  164. HRESULT hr = S_OK;
  165. //TEXT_OUTLN( "Turning off profiling for child processes" )
  166. SetEnvironmentVariableW(L"Cor_Enable_Profiling", L"0x0");
  167. //
  168. // initializations
  169. //
  170. if (!InitializeCriticalSectionAndSpinCount( &m_criticalSection, 10000 ))
  171. hr = E_FAIL;
  172. if (!InitializeCriticalSectionAndSpinCount( &g_criticalSection, 10000 ))
  173. hr = E_FAIL;
  174. g_pCallbackObject = this;
  175. m_dwProcessId = GetCurrentProcessId();
  176. //
  177. // define in which mode you will operate
  178. //
  179. strcpy_s( m_logFileName, ARRAY_LEN(m_logFileName), FILENAME );
  180. _ProcessEnvVariables();
  181. if (SUCCEEDED(hr) )
  182. {
  183. //
  184. // open the correct file stream fo dump the logging information
  185. //
  186. m_stream = _fsopen((m_path != NULL) ? m_path : m_logFileName, "a+", _SH_DENYWR);
  187. hr = ( m_stream == NULL ) ? E_FAIL : S_OK;
  188. if ( SUCCEEDED( hr ))
  189. {
  190. setvbuf(m_stream, NULL, _IOFBF, 32768);
  191. LogToAnyInternal( "SimpleProfiler\n");
  192. }
  193. else {
  194. TEXT_OUTLN( "Unable to open log file - No log will be produced" );
  195. }
  196. }
  197. if(FAILED(hr))
  198. {
  199. m_dwEventMask = COR_PRF_MONITOR_NONE;
  200. }
  201. } // ctor
  202. /* public */
  203. ProfilerCallback::~ProfilerCallback()
  204. {
  205. LogToAnyInternal( "~SimpleProfiler\n");
  206. if ( m_path != NULL )
  207. {
  208. delete[] m_path;
  209. m_path = NULL;
  210. }
  211. if ( m_filter != NULL )
  212. {
  213. delete[] m_filter;
  214. m_filter = NULL;
  215. }
  216. if ( m_stream != NULL )
  217. {
  218. fflush( m_stream );
  219. fclose( m_stream );
  220. m_stream = NULL;
  221. }
  222. m_pFunctionTable.clear();
  223. m_pClassTable.clear();
  224. DeleteCriticalSection( &m_criticalSection );
  225. DeleteCriticalSection( &g_criticalSection );
  226. g_pCallbackObject = NULL;
  227. m_pFunctionTable.clear();
  228. m_pClassTable.clear();
  229. m_pClassNameTable.clear();
  230. m_pModuleTable.clear();
  231. } // dtor
  232. /* public */
  233. ULONG ProfilerCallback::AddRef()
  234. {
  235. return InterlockedIncrement( &m_refCount );
  236. } // ProfilerCallback::AddRef
  237. /* public */
  238. ULONG ProfilerCallback::Release()
  239. {
  240. long refCount;
  241. refCount = InterlockedDecrement( &m_refCount );
  242. if ( refCount == 0 )
  243. delete this;
  244. return refCount;
  245. } // ProfilerCallback::Release
  246. /* public */
  247. HRESULT ProfilerCallback::QueryInterface( REFIID riid, void **ppInterface )
  248. {
  249. if ( riid == IID_IUnknown )
  250. *ppInterface = static_cast<IUnknown *>( this );
  251. else if ( riid == IID_ICorProfilerCallback )
  252. *ppInterface = static_cast<ICorProfilerCallback *>( this );
  253. else if ( riid == IID_ICorProfilerCallback2 )
  254. *ppInterface = static_cast<ICorProfilerCallback2 *>( this );
  255. else
  256. {
  257. *ppInterface = NULL;
  258. return E_NOINTERFACE;
  259. }
  260. reinterpret_cast<IUnknown *>( *ppInterface )->AddRef();
  261. return S_OK;
  262. } // ProfilerCallback::QueryInterface
  263. /* public static */
  264. HRESULT ProfilerCallback::CreateObject( REFIID riid, void **ppInterface )
  265. {
  266. HRESULT hr = E_NOINTERFACE;
  267. *ppInterface = NULL;
  268. if ( (riid == IID_IUnknown)
  269. || (riid == IID_ICorProfilerCallback2)
  270. || (riid == IID_ICorProfilerCallback) )
  271. {
  272. ProfilerCallback *pProfilerCallback;
  273. pProfilerCallback = new ProfilerCallback();
  274. if ( pProfilerCallback != NULL )
  275. {
  276. hr = S_OK;
  277. pProfilerCallback->AddRef();
  278. *ppInterface = static_cast<ICorProfilerCallback *>( pProfilerCallback );
  279. }
  280. else
  281. hr = E_OUTOFMEMORY;
  282. }
  283. return hr;
  284. } // ProfilerCallback::CreateObject
  285. IGCHost *GetGCHost()
  286. {
  287. ICorRuntimeHost *pCorHost = NULL;
  288. CoInitializeEx(NULL, COINIT_MULTITHREADED);
  289. HRESULT hr = CoCreateInstance( CLSID_CorRuntimeHost,
  290. NULL,
  291. CLSCTX_INPROC_SERVER,
  292. IID_ICorRuntimeHost,
  293. (void**)&pCorHost );
  294. if (SUCCEEDED(hr))
  295. {
  296. IGCHost *pGCHost = NULL;
  297. hr = pCorHost->QueryInterface(IID_IGCHost, (void**)&pGCHost);
  298. if (SUCCEEDED(hr))
  299. return pGCHost;
  300. else
  301. printf("Could not QueryInterface hr = %x\n", hr);
  302. }
  303. else
  304. printf("Could not CoCreateInstanceEx hr = %x\n", hr);
  305. return NULL;
  306. }
  307. /* public */
  308. HRESULT ProfilerCallback::Initialize( IUnknown *pICorProfilerInfoUnk )
  309. {
  310. HRESULT hr;
  311. hr = pICorProfilerInfoUnk->QueryInterface( IID_ICorProfilerInfo,
  312. (void **)&m_pProfilerInfo );
  313. if ( SUCCEEDED( hr ) )
  314. {
  315. hr = pICorProfilerInfoUnk->QueryInterface( IID_ICorProfilerInfo2,
  316. (void **)&m_pProfilerInfo2 );
  317. }else{
  318. Failure( "QueryInterface for ICorProfilerInfo FAILED" );
  319. }
  320. if ( SUCCEEDED( hr ) )
  321. {
  322. //printf("event mask = %x\n", m_dwEventMask);
  323. hr = m_pProfilerInfo2->SetEventMask( m_dwEventMask );
  324. if ( SUCCEEDED( hr ) )
  325. {
  326. #if defined(_X86_)
  327. hr = m_pProfilerInfo2->SetEnterLeaveFunctionHooks2( EnterNaked2,
  328. LeaveNaked2,
  329. TailcallNaked2 );
  330. #elif defined(_AMD64_)
  331. hr = m_pProfilerInfo2->SetEnterLeaveFunctionHooks2( (FunctionEnter2 *)EnterNaked2,
  332. (FunctionLeave2 *)LeaveNaked2,
  333. (FunctionTailcall2 *)TailcallNaked2 );
  334. #else
  335. hr = m_pProfilerInfo2->SetEnterLeaveFunctionHooks2( (FunctionEnter2 *)&EnterStub,
  336. (FunctionLeave2 *)&LeaveStub,
  337. (FunctionTailcall2 *)&TailcallStub );
  338. #endif // defined(_X86_) || defined(_AMD64_)
  339. if ( SUCCEEDED( hr ) )
  340. {
  341. Sleep(100); // Give the threads a chance to read any signals that are already set.
  342. }
  343. else
  344. Failure( "ICorProfilerInfo::SetEnterLeaveFunctionHooks() FAILED" );
  345. }
  346. else
  347. Failure( "SetEventMask for Profiler FAILED" );
  348. }
  349. else
  350. {
  351. Failure( "QueryInterface for ICorProfilerInfo2 FAILED" );
  352. Failure( "Allocation for Profiler FAILED" );
  353. }
  354. if(m_traceEvent) {
  355. LogToAny("Initialize\n");
  356. }
  357. return S_OK;
  358. } // ProfilerCallback::Initialize
  359. /* public */
  360. HRESULT ProfilerCallback::Shutdown()
  361. {
  362. m_dwShutdown++;
  363. if(m_traceEvent) {
  364. LogToAny("Shutdown\n");
  365. }
  366. return S_OK;
  367. } // ProfilerCallback::Shutdown
  368. /* public */
  369. HRESULT ProfilerCallback::DllDetachShutdown()
  370. {
  371. //
  372. // If no shutdown occurs during DLL_DETACH, release the callback
  373. // interface pointer. This scenario will more than likely occur
  374. // with any interop related program (e.g., a program that is
  375. // comprised of both managed and unmanaged components).
  376. //
  377. m_dwShutdown++;
  378. if ( (m_dwShutdown == 1) && (g_pCallbackObject != NULL) )
  379. {
  380. g_pCallbackObject->Release();
  381. g_pCallbackObject = NULL;
  382. }
  383. return S_OK;
  384. } // ProfilerCallback::DllDetachShutdown
  385. /* public */
  386. __forceinline void ProfilerCallback::Enter( FunctionID functionID,
  387. UINT_PTR clientData,
  388. COR_PRF_FRAME_INFO frameInfo,
  389. COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo )
  390. {
  391. FunctionInfo *pFunctionInfo = NULL;
  392. pFunctionInfo = g_pCallbackObject->m_pFunctionTable[functionID];
  393. if(pFunctionInfo != NULL && g_pCallbackObject->_IsNeedToLog(pFunctionInfo->m_name) &&
  394. (g_pCallbackObject->m_traceEvent || g_pCallbackObject->m_traceParameter)
  395. )
  396. {
  397. g_pCallbackObject->LogToAny("> %S",
  398. pFunctionInfo->m_name);
  399. if(g_pCallbackObject->m_traceParameter)
  400. {
  401. g_pCallbackObject->LogToAny("(");
  402. HRESULT hr;
  403. mdMethodDef methodDef;
  404. IMetaDataImport *mdi = NULL;
  405. hr = g_pCallbackObject->m_pProfilerInfo->GetTokenAndMetaDataFromFunction(
  406. functionID,
  407. IID_IMetaDataImport,
  408. (IUnknown**) &mdi,
  409. &methodDef);
  410. // output parameter list
  411. if(SUCCEEDED(hr) && mdi)
  412. {
  413. hr = g_pCallbackObject->TraceParameterList( pFunctionInfo,
  414. argumentInfo, g_pCallbackObject->m_pProfilerInfo2, mdi);
  415. }
  416. g_pCallbackObject->LogToAny(") %S", pFunctionInfo->m_pReturnInfo->m_typeName);
  417. if(mdi) mdi->Release();
  418. }
  419. g_pCallbackObject->LogToAny("\n");
  420. }
  421. } // ProfilerCallback::Enter
  422. // ----------------------------------------------------------------------------
  423. HRESULT ProfilerCallback::TraceParameterList(
  424. FunctionInfo* pFunctionInfo,
  425. COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo,
  426. ICorProfilerInfo2 *cpi,
  427. IMetaDataImport *mdi)
  428. {
  429. HRESULT hr = S_OK;
  430. if(pFunctionInfo->m_argCount == 0) return hr;
  431. // output parameters
  432. int offset = argumentInfo->numRanges - pFunctionInfo->m_argCount;
  433. for(ULONG i = 0;
  434. i < pFunctionInfo->m_argCount;
  435. i++)
  436. {
  437. hr = TraceParameter(
  438. &(argumentInfo->ranges[i + offset]), pFunctionInfo->m_ppParamInfo[i], cpi, mdi);
  439. if(i < pFunctionInfo->m_argCount - 1) LogToAny(", ");
  440. }
  441. return hr;
  442. }
  443. // ----------------------------------------------------------------------------
  444. HRESULT ProfilerCallback::TraceParameter(
  445. COR_PRF_FUNCTION_ARGUMENT_RANGE *range,
  446. ParameterInfo *pParameterInfo,
  447. ICorProfilerInfo2 *cpi,
  448. IMetaDataImport *mdi)
  449. {
  450. HRESULT hr = S_OK;
  451. // get argument direction
  452. PWCHAR direction;
  453. if(!pParameterInfo->m_isByRef)
  454. direction = L"";
  455. else if(IsPdOut(pParameterInfo->m_attributes) != 0)
  456. direction = L"out ";
  457. else
  458. direction = L"ref ";
  459. // output
  460. LogToAny("%S%S %S", direction, pParameterInfo->m_typeName, pParameterInfo->m_name);
  461. // no out parameters on enter
  462. if(IsPdOut(pParameterInfo->m_attributes) == 0)
  463. {
  464. LogToAny("=");
  465. hr = TraceValue(
  466. pParameterInfo->m_isByRef ? *(PUINT_PTR)(range->startAddress) : range->startAddress,
  467. cpi, mdi,
  468. pParameterInfo);
  469. }
  470. return hr;
  471. }
  472. // ----------------------------------------------------------------------------
  473. HRESULT ProfilerCallback::TraceValue(
  474. UINT_PTR startAddress,
  475. ICorProfilerInfo2 *cpi,
  476. IMetaDataImport *mdi,
  477. ParameterInfo *pParameterInfo)
  478. {
  479. /*if(pParameterInfo->m_def == mdTokenNil || pParameterInfo->m_def == 0xffffffff)
  480. {
  481. LogToAny("?");
  482. return S_OK;
  483. }*/
  484. if(pParameterInfo->m_isArray) {
  485. return TraceArray(*(PUINT_PTR)(startAddress), cpi, mdi, pParameterInfo);
  486. }
  487. switch(pParameterInfo->m_type)
  488. {
  489. case ELEMENT_TYPE_STRING:
  490. return TraceString(*(PUINT_PTR)startAddress, cpi);
  491. case ELEMENT_TYPE_BOOLEAN:
  492. return TraceBoolean(startAddress);
  493. case ELEMENT_TYPE_CHAR:
  494. return TraceChar(startAddress);
  495. case ELEMENT_TYPE_I1:
  496. return TraceSByte(startAddress);
  497. case ELEMENT_TYPE_U1:
  498. return TraceByte(startAddress);
  499. case ELEMENT_TYPE_I2:
  500. return TraceShort(startAddress);
  501. case ELEMENT_TYPE_U2:
  502. return TraceUShort(startAddress);
  503. case ELEMENT_TYPE_I4:
  504. return TraceInt(startAddress);
  505. case ELEMENT_TYPE_U4:
  506. return TraceUInt(startAddress);
  507. case ELEMENT_TYPE_I8:
  508. return TraceLong(startAddress);
  509. case ELEMENT_TYPE_U8:
  510. return TraceULong(startAddress);
  511. case ELEMENT_TYPE_R4:
  512. return TraceFloat(startAddress);
  513. case ELEMENT_TYPE_R8:
  514. return TraceDouble(startAddress);
  515. case ELEMENT_TYPE_VALUETYPE:
  516. return TraceStruct(startAddress, cpi, mdi, pParameterInfo, NULL, NULL, mdTokenNil);
  517. case ELEMENT_TYPE_CLASS:
  518. return TraceClass(*(PUINT_PTR)(startAddress), cpi, mdi, pParameterInfo);
  519. case ELEMENT_TYPE_OBJECT:
  520. return TraceObject(startAddress, cpi, mdi, pParameterInfo);
  521. /*
  522. case ELEMENT_TYPE_PTR:
  523. case ELEMENT_TYPE_ARRAY:
  524. case ELEMENT_TYPE_I:
  525. case ELEMENT_TYPE_U:
  526. case ELEMENT_TYPE_OBJECT:
  527. case ELEMENT_TYPE_SZARRAY:
  528. case ELEMENT_TYPE_FNPTR:
  529. case ELEMENT_TYPE_MAX:
  530. case ELEMENT_TYPE_END:
  531. case ELEMENT_TYPE_BYREF:
  532. case ELEMENT_TYPE_PINNED:
  533. case ELEMENT_TYPE_SENTINEL:
  534. case ELEMENT_TYPE_CMOD_OPT:
  535. case ELEMENT_TYPE_MODIFIER:
  536. case ELEMENT_TYPE_CMOD_REQD:
  537. case ELEMENT_TYPE_TYPEDBYREF:
  538. */
  539. case ELEMENT_TYPE_VOID:
  540. break;
  541. default:
  542. LogToAny("?");
  543. break;
  544. }
  545. return S_OK;
  546. }
  547. // ----------------------------------------------------------------------------
  548. HRESULT ProfilerCallback::TraceObject(
  549. UINT_PTR startAddress,
  550. ICorProfilerInfo2 *cpi,
  551. IMetaDataImport *mdiRef,
  552. ParameterInfo *pParameterInfo)
  553. {
  554. //__asm { int 3 }
  555. bool traced = false;
  556. ObjectID oid = *(ObjectID *)startAddress;
  557. ClassID classId = NULL;
  558. HRESULT hr = cpi->GetClassFromObject(oid, &classId);
  559. if(SUCCEEDED(hr)) {
  560. ClassInfo *pClassInfo = m_pClassTable[classId];
  561. if(pClassInfo != NULL) {
  562. CorElementType type;
  563. type = _GetElementTypeFromClassName(pClassInfo->m_name);
  564. if(type <= ELEMENT_TYPE_R8 || type == ELEMENT_TYPE_I || type == ELEMENT_TYPE_U || type == ELEMENT_TYPE_END) {
  565. ULONG32 bufferOffset = 0;
  566. hr = cpi->GetBoxClassLayout(classId, &bufferOffset);
  567. if(SUCCEEDED(hr)) {
  568. oid = oid + bufferOffset;
  569. if(type == ELEMENT_TYPE_END) {
  570. type = ELEMENT_TYPE_VALUETYPE;
  571. }
  572. }else{
  573. if(type == ELEMENT_TYPE_END) {
  574. type = ELEMENT_TYPE_CLASS;
  575. hr = S_OK;
  576. }
  577. }
  578. }
  579. if(SUCCEEDED(hr)) {
  580. switch(type)
  581. {
  582. case ELEMENT_TYPE_STRING:
  583. hr = TraceString(oid, cpi);traced = true;break;
  584. case ELEMENT_TYPE_BOOLEAN:
  585. hr = TraceBoolean(oid);traced = true;break;
  586. case ELEMENT_TYPE_CHAR:
  587. hr = TraceChar(oid);traced = true;break;
  588. case ELEMENT_TYPE_I1:
  589. hr = TraceSByte(oid);traced = true;break;
  590. case ELEMENT_TYPE_U1:
  591. hr = TraceByte(oid);traced = true;break;
  592. case ELEMENT_TYPE_I2:
  593. hr = TraceShort(oid);traced = true;break;
  594. case ELEMENT_TYPE_U2:
  595. hr = TraceUShort(oid);traced = true;break;
  596. case ELEMENT_TYPE_I4:
  597. hr = TraceInt(oid);traced = true;break;
  598. case ELEMENT_TYPE_U4:
  599. hr = TraceUInt(oid);traced = true;break;
  600. case ELEMENT_TYPE_I8:
  601. hr = TraceLong(oid);traced = true;break;
  602. case ELEMENT_TYPE_U8:
  603. hr = TraceULong(oid);traced = true;break;
  604. case ELEMENT_TYPE_R4:
  605. hr = TraceFloat(oid);traced = true;break;
  606. case ELEMENT_TYPE_R8:
  607. hr = TraceDouble(oid);traced = true;break;
  608. case ELEMENT_TYPE_VALUETYPE:
  609. hr = TraceStruct(oid, cpi, mdiRef, pParameterInfo, NULL, classId, pClassInfo->m_classToken);traced = true;break;
  610. case ELEMENT_TYPE_CLASS:
  611. hr = TraceClass(oid, cpi, mdiRef, pParameterInfo);traced = true;break;
  612. default:
  613. hr = E_FAIL; break;
  614. }//end switch
  615. }
  616. if(!traced) LogToAny("?");
  617. LogToAny("(%S)", pClassInfo->m_name);
  618. }//end pClassInfo!=NULL
  619. }
  620. return hr;
  621. }
  622. // ----------------------------------------------------------------------------
  623. HRESULT ProfilerCallback::TraceArray(
  624. ObjectID oid,
  625. ICorProfilerInfo2 *cpi,
  626. IMetaDataImport *mdiRef,
  627. ParameterInfo *pParameterInfo)
  628. {
  629. ULONG32 dim = 1;
  630. ULONG32 *dimSizes = new ULONG32[dim];
  631. int *dimLowerBounds = new int[dim];
  632. BYTE **ppData = new BYTE*[dim];
  633. //__asm { int 3 }
  634. HRESULT hr = cpi->GetArrayObjectInfo(oid, dim, dimSizes, dimLowerBounds, ppData);
  635. if(SUCCEEDED(hr)) {
  636. ULONG32 dimSize = dimSizes[0];
  637. ULONG32 dimLowerBound = dimLowerBounds[0];
  638. BYTE *pData = ppData[0];
  639. LogToAny("{");
  640. for(ULONG32 i=dimLowerBound; i<dimSize; i++) {
  641. switch(pParameterInfo->m_type) {
  642. case ELEMENT_TYPE_STRING:
  643. TraceString(*(ObjectID *)pData, cpi);
  644. pData += sizeof(ObjectID);
  645. break;
  646. case ELEMENT_TYPE_BOOLEAN:
  647. TraceBoolean((UINT_PTR)pData);
  648. pData += sizeof(bool);
  649. break;
  650. case ELEMENT_TYPE_CHAR:
  651. TraceChar((UINT_PTR)pData);
  652. pData += sizeof(WCHAR);
  653. break;
  654. case ELEMENT_TYPE_I1:
  655. TraceSByte((UINT_PTR)pData);
  656. pData += sizeof(char);
  657. break;
  658. case ELEMENT_TYPE_U1:
  659. TraceByte((UINT_PTR)pData);
  660. pData += sizeof(unsigned char);
  661. break;
  662. case ELEMENT_TYPE_I2:
  663. TraceShort((UINT_PTR)pData);
  664. pData += sizeof(short);
  665. break;
  666. case ELEMENT_TYPE_U2:
  667. TraceUShort((UINT_PTR)pData);
  668. pData += sizeof(unsigned short);
  669. break;
  670. case ELEMENT_TYPE_I4:
  671. TraceInt((UINT_PTR)pData);
  672. pData += sizeof(int);
  673. break;
  674. case ELEMENT_TYPE_U4:
  675. TraceUInt((UINT_PTR)pData);
  676. pData += sizeof(unsigned int);
  677. break;
  678. case ELEMENT_TYPE_I8:
  679. TraceLong((UINT_PTR)pData);
  680. pData += sizeof(long long);
  681. break;
  682. case ELEMENT_TYPE_U8:
  683. TraceULong((UINT_PTR)pData);
  684. pData += sizeof(unsigned long long);
  685. break;
  686. case ELEMENT_TYPE_R4:
  687. TraceFloat((UINT_PTR)pData);
  688. pData += sizeof(float);
  689. break;
  690. case ELEMENT_TYPE_R8:
  691. TraceDouble((UINT_PTR)pData);
  692. pData += sizeof(double);
  693. break;
  694. case ELEMENT_TYPE_VALUETYPE:
  695. {
  696. ULONG size = 0;
  697. TraceStruct((UINT_PTR)pData, cpi, mdiRef, pParameterInfo, &size, NULL, mdTokenNil);
  698. if(size < 0) {
  699. LogToAny("Cannot determine struct size.");
  700. break;
  701. }else{
  702. pData += size; // how to get size of struct?
  703. }
  704. }
  705. break;
  706. case ELEMENT_TYPE_CLASS:
  707. TraceClass(*(ObjectID *)pData, cpi, mdiRef, pParameterInfo);
  708. pData += sizeof(ObjectID);
  709. break;
  710. case ELEMENT_TYPE_OBJECT:
  711. TraceObject((UINT_PTR)pData, cpi, mdiRef, pParameterInfo);
  712. pData += sizeof(ObjectID);
  713. break;
  714. default:
  715. LogToAny("?");
  716. break;
  717. }
  718. if(i<dimSize-1) LogToAny(",");
  719. }
  720. LogToAny("}");
  721. }
  722. return hr;
  723. }
  724. // ----------------------------------------------------------------------------
  725. HRESULT ProfilerCallback::TraceULong(UINT_PTR startAddress)
  726. {
  727. LogToAny("%u", *(unsigned long long *)startAddress);
  728. return S_OK;
  729. }
  730. // ----------------------------------------------------------------------------
  731. HRESULT ProfilerCallback::TraceLong(UINT_PTR startAddress)
  732. {
  733. LogToAny("%d", *(long long *)startAddress);
  734. return S_OK;
  735. }
  736. // ----------------------------------------------------------------------------
  737. HRESULT ProfilerCallback::TraceUInt(UINT_PTR startAddress)
  738. {
  739. LogToAny("%u", *(unsigned int *)startAddress);
  740. return S_OK;
  741. }
  742. // ----------------------------------------------------------------------------
  743. HRESULT ProfilerCallback::TraceInt(UINT_PTR startAddress)
  744. {
  745. LogToAny("%d", *(int *)startAddress);
  746. return S_OK;
  747. }
  748. // ----------------------------------------------------------------------------
  749. HRESULT ProfilerCallback::TraceUShort(UINT_PTR startAddress)
  750. {
  751. LogToAny("%u", *(unsigned short *)startAddress);
  752. return S_OK;
  753. }
  754. // ----------------------------------------------------------------------------
  755. HRESULT ProfilerCallback::TraceShort(UINT_PTR startAddress)
  756. {
  757. LogToAny("%d", *(short *)startAddress);
  758. return S_OK;
  759. }
  760. // ----------------------------------------------------------------------------
  761. HRESULT ProfilerCallback::TraceByte(UINT_PTR startAddress)
  762. {
  763. LogToAny("%u", *(unsigned char *)startAddress);
  764. return S_OK;
  765. }
  766. // ----------------------------------------------------------------------------
  767. HRESULT ProfilerCallback::TraceSByte(UINT_PTR startAddress)
  768. {
  769. LogToAny("%d", *(char *)startAddress);
  770. return S_OK;
  771. }
  772. // ----------------------------------------------------------------------------
  773. HRESULT ProfilerCallback::TraceChar(UINT_PTR startAddress)
  774. {
  775. LogToAny("'%c'", *(char*)startAddress);
  776. return S_OK;
  777. }
  778. // ----------------------------------------------------------------------------
  779. HRESULT ProfilerCallback::TraceBoolean(UINT_PTR startAddress)
  780. {
  781. if((*(bool*)startAddress))
  782. {
  783. LogToAny("true");
  784. }else{
  785. LogToAny("false");
  786. }
  787. return S_OK;
  788. }
  789. // ----------------------------------------------------------------------------
  790. HRESULT ProfilerCallback::TraceFloat(UINT_PTR startAddress)
  791. {
  792. LogToAny("%f", *(float*)startAddress);
  793. return S_OK;
  794. }
  795. // ----------------------------------------------------------------------------
  796. HRESULT ProfilerCallback::TraceDouble(UINT_PTR startAddress)
  797. {
  798. LogToAny("%f", *(double*)startAddress);
  799. return S_OK;
  800. }
  801. // ----------------------------------------------------------------------------
  802. HRESULT ProfilerCallback::TraceString(
  803. ObjectID oid,
  804. ICorProfilerInfo2 *cpi)
  805. {
  806. if(oid == mdTokenNil || oid == 0xffffffff)
  807. {
  808. LogToAny("null");
  809. return S_OK;
  810. }
  811. //if(oid <= 0xFF) { // how to check whether ObjectID is valid?
  812. // LogToAny("?");
  813. // return S_OK;
  814. //}
  815. // get string
  816. ULONG bufferOffset=0;
  817. ULONG stringLengthOffset=0;
  818. ULONG bufferLengthOffset=0;
  819. HRESULT hr = cpi->GetStringLayout(&bufferLengthOffset, &stringLengthOffset, &bufferOffset);
  820. if(SUCCEEDED(hr))
  821. {
  822. __try {
  823. LPWSTR buffer = (LPWSTR) (oid + bufferOffset);
  824. DWORD bufferLength = *((DWORD *)(oid + bufferLengthOffset));
  825. DWORD stringLength = *((DWORD *)(oid + stringLengthOffset));
  826. LogToAny("\"%S\"", buffer);
  827. }__except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())){
  828. LogToAny("?");
  829. }
  830. }else{
  831. LogToAny("?");
  832. }
  833. return hr;
  834. }
  835. int ProfilerCallback::ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
  836. if (code == EXCEPTION_ACCESS_VIOLATION) {
  837. return EXCEPTION_EXECUTE_HANDLER;
  838. } else {
  839. return EXCEPTION_CONTINUE_SEARCH;
  840. };
  841. }
  842. // ----------------------------------------------------------------------------
  843. HRESULT ProfilerCallback::TraceClass(
  844. ObjectID oid,
  845. ICorProfilerInfo2 *cpi,
  846. IMetaDataImport *mdiRef,
  847. ParameterInfo *pParameterInfo)
  848. {
  849. //__asm { int 3 }
  850. HRESULT hr = S_OK;
  851. int fieldCnt = 0;
  852. IMetaDataImport *mdi = mdiRef;
  853. // get class for object
  854. ClassID classId = NULL;
  855. hr = cpi->GetClassFromObject(oid, &classId);
  856. ClassInfo *pClassInfo = NULL;
  857. if(SUCCEEDED(hr)) {
  858. pClassInfo = m_pClassTable[classId];
  859. }
  860. if(pClassInfo==NULL) {
  861. LogToAny("?");
  862. return E_FAIL;
  863. }
  864. LogToAny("{");
  865. bool isRef = (pParameterInfo->m_moduleId != pClassInfo->m_moduleID);
  866. if(isRef) {
  867. ModuleInfo *pModuleInfo = m_pModuleTable[pClassInfo->m_moduleID];
  868. if(pModuleInfo != NULL) {
  869. mdi = pModuleInfo->GetMDI();
  870. }
  871. }
  872. if(SUCCEEDED(hr) && classId != NULL)
  873. {
  874. ULONG fieldOffsetCount = 0;
  875. hr = cpi->GetClassLayout(
  876. classId,
  877. NULL, 0, &fieldOffsetCount, NULL);
  878. if(fieldOffsetCount != 0) {
  879. COR_FIELD_OFFSET* fieldOffset = new COR_FIELD_OFFSET[fieldOffsetCount];
  880. hr = cpi->GetClassLayout(
  881. classId,
  882. fieldOffset, fieldOffsetCount, &fieldOffsetCount, NULL);
  883. // output fields
  884. if(SUCCEEDED(hr))
  885. {
  886. for(ULONG i=0; i < fieldOffsetCount; i++)
  887. {
  888. ParameterInfo *pFieldParam = new ParameterInfo(fieldOffset[i].ridOfField);
  889. // get field name and prepare type info from metadata
  890. PCCOR_SIGNATURE sigBlob;
  891. ULONG sigBlobSize;
  892. hr = mdi->GetFieldProps(
  893. fieldOffset[i].ridOfField, NULL,
  894. pFieldParam->m_name, MAX_LENGTH, // get field name
  895. NULL, NULL, // acutal size of name, not relevant here
  896. &sigBlob, &sigBlobSize, // field metadata
  897. NULL, NULL, NULL);
  898. // get type and typename
  899. if(SUCCEEDED(hr))
  900. {
  901. // make sure metadata describes a field and move forward in metadata
  902. if(*sigBlob++ == IMAGE_CEE_CS_CALLCONV_FIELD)
  903. {}
  904. // get kind of type (primitive, class, ...) and type name
  905. pFieldParam->m_type = GetType(sigBlob, pFieldParam->m_isByRef, pFieldParam->m_typeDef, pFieldParam->m_isArray);
  906. hr = GetTypeName(pFieldParam->m_typeName, MAX_LENGTH, pFieldParam->m_type, pFieldParam->m_typeDef, mdi);
  907. if(SUCCEEDED(hr) && pFieldParam->m_isArray)
  908. wcscat_s(pFieldParam->m_name, L"[]");
  909. }
  910. // output
  911. if(SUCCEEDED(hr))
  912. {
  913. if(fieldCnt++ > 0)
  914. LogToAny(", ");
  915. LogToAny("%S %S=", pFieldParam->m_typeName, pFieldParam->m_name);
  916. if(pClassInfo->IsValidField(mdi, fieldOffset[i].ridOfField)) {
  917. switch(pFieldParam->m_type) {
  918. case ELEMENT_TYPE_VALUETYPE:
  919. case ELEMENT_TYPE_CLASS:
  920. LogToAny("?");
  921. break;
  922. default:
  923. TraceValue(
  924. oid + fieldOffset[i].ulOffset,
  925. cpi, mdi, pFieldParam);
  926. break;
  927. }
  928. }else{
  929. LogToAny("?");
  930. }
  931. }
  932. if(pFieldParam != NULL)
  933. delete pFieldParam;
  934. }
  935. }else{
  936. LogToAny("err=0x%p", hr);
  937. }
  938. if(fieldOffset)
  939. delete [] fieldOffset;
  940. } //end of numFields != 0
  941. }//end
  942. LogToAny("}");
  943. return hr;
  944. }
  945. HRESULT ProfilerCallback::GetStructParamInfo(ICorProfilerInfo2 *cpi,
  946. IMetaDataImport **mdiRef,
  947. ParameterInfo *pParameterInfo,
  948. ClassID &classId,
  949. mdTypeDef &typeDef)
  950. {
  951. HRESULT hr = S_OK;
  952. typeDef = pParameterInfo->m_typeDef;
  953. bool isRef = (TypeFromToken( typeDef ) == mdtTypeRef);
  954. classId = NULL;
  955. // get class id
  956. if(isRef) {
  957. ClassInfo *pClassInfo = m_pClassNameTable[Hash(pParameterInfo->m_typeName)];
  958. if(pClassInfo != NULL) {
  959. classId = pClassInfo->m_id;
  960. }
  961. IMetaDataImport *pMetaDataImportRef = NULL;
  962. mdTypeDef classToken;
  963. hr = (*mdiRef)->ResolveTypeRef(typeDef, IID_IMetaDataImport, (IUnknown **)&pMetaDataImportRef, &classToken);
  964. if (hr == S_OK)
  965. {
  966. *mdiRef = pMetaDataImportRef;
  967. typeDef = classToken;
  968. }
  969. }else{
  970. hr = cpi->GetClassFromToken(pParameterInfo->m_moduleId, typeDef, &classId);
  971. if(!SUCCEEDED(hr))
  972. classId = NULL;
  973. }
  974. return hr;
  975. }
  976. HRESULT ProfilerCallback::TraceStruct(
  977. UINT_PTR startAddress,
  978. ICorProfilerInfo2 *cpi,
  979. IMetaDataImport *mdiRef,
  980. ParameterInfo *pParameterInfo,
  981. ULONG *pcSize,
  982. ClassID classIdIn,
  983. mdTypeDef typeDefIn
  984. )
  985. {
  986. HRESULT hr = S_OK;
  987. int fieldCnt = 0;
  988. mdTypeDef typeDef = pParameterInfo->m_typeDef;
  989. IMetaDataImport *mdi = mdiRef;
  990. ClassID classId = NULL;
  991. if(classIdIn != NULL && typeDefIn != mdTokenNil) {
  992. classId = classIdIn;
  993. typeDef = typeDefIn;
  994. }else{
  995. hr = GetStructParamInfo(cpi, &mdi, pParameterInfo, classId, typeDef);
  996. }
  997. ClassInfo *pClassInfo = NULL;
  998. if(classId != NULL) {
  999. pClassInfo = m_pClassTable[classId];
  1000. }
  1001. if(pClassInfo == NULL) {
  1002. LogToAny("?");
  1003. return E_FAIL;
  1004. }
  1005. ULONG structSize = 0;
  1006. LogToAny("{");
  1007. {
  1008. ULONG fieldOffsetCount = 0;
  1009. if(SUCCEEDED(hr)) {
  1010. hr = cpi->GetClassLayout(
  1011. classId,
  1012. NULL, 0, &fieldOffsetCount, NULL);
  1013. }
  1014. if(SUCCEEDED(hr) && fieldOffsetCount != 0) {
  1015. //__asm { int 3 }
  1016. COR_FIELD_OFFSET* fieldOffset = new COR_FIELD_OFFSET[fieldOffsetCount];
  1017. hr = cpi->GetClassLayout(
  1018. classId,
  1019. fieldOffset, fieldOffsetCount, &fieldOffsetCount, NULL);
  1020. // output fields
  1021. if(SUCCEEDED(hr))
  1022. {
  1023. for(ULONG i=0; i < fieldOffsetCount; i++)
  1024. {
  1025. ParameterInfo *pFieldParam = new ParameterInfo(fieldOffset[i].ridOfField);
  1026. // get field name and prepare type info from metadata
  1027. PCCOR_SIGNATURE sigBlob;
  1028. ULONG sigBlobSize;
  1029. hr = mdi->GetFieldProps(
  1030. fieldOffset[i].ridOfField, NULL,
  1031. pFieldParam->m_name, MAX_LENGTH, // get field name
  1032. NULL, NULL, // acutal size of name, not relevant here
  1033. &sigBlob, &sigBlobSize, // field metadata
  1034. NULL, NULL, NULL);
  1035. // get type and typename
  1036. if(SUCCEEDED(hr))
  1037. {
  1038. // make sure metadata describes a field and move forward in metadata
  1039. if(*sigBlob++ == IMAGE_CEE_CS_CALLCONV_FIELD)
  1040. {}
  1041. // get kind of type (primitive, class, ...) and type name
  1042. pFieldParam->m_type = GetType(sigBlob, pFieldParam->m_isByRef, pFieldParam->m_typeDef, pFieldParam->m_isArray);
  1043. hr = GetTypeName(pFieldParam->m_typeName, MAX_LENGTH, pFieldParam->m_type, pFieldParam->m_typeDef, mdi);
  1044. if(SUCCEEDED(hr) && pFieldParam->m_isArray)
  1045. wcscat_s(pFieldParam->m_name, L"[]");
  1046. }
  1047. // output
  1048. if(SUCCEEDED(hr))
  1049. {
  1050. ULONG typeSize = GetElementTypeSize(pFieldParam->m_type);
  1051. if(typeSize < 0)
  1052. structSize = -1;
  1053. if(structSize>=0)
  1054. structSize += typeSize;
  1055. if(fieldCnt++ > 0)
  1056. LogToAny(", ");
  1057. LogToAny("%S %S=", pFieldParam->m_typeName, pFieldParam->m_name);
  1058. //__asm { int 3 }
  1059. if(pClassInfo->IsValidField(mdi, fieldOffset[i].ridOfField)) {
  1060. switch(pFieldParam->m_type) {
  1061. case ELEMENT_TYPE_VALUETYPE:
  1062. case ELEMENT_TYPE_CLASS:
  1063. LogToAny("?");
  1064. break;
  1065. default:
  1066. TraceValue(
  1067. startAddress + fieldOffset[i].ulOffset,
  1068. cpi, mdi, pFieldParam);
  1069. break;
  1070. }
  1071. }else{
  1072. LogToAny("?");
  1073. }
  1074. }
  1075. }
  1076. }else{
  1077. LogToAny("err=0x%p", hr);
  1078. }
  1079. } //end of numFields != 0
  1080. else if(!SUCCEEDED(hr)) {
  1081. LogToAny("err=0x%p", hr);
  1082. }
  1083. }
  1084. LogToAny("}");
  1085. if(pcSize != NULL) *pcSize = structSize;
  1086. return hr;
  1087. }
  1088. // ----------------------------------------------------------------------------
  1089. CorElementType ProfilerCallback::GetType(
  1090. PCCOR_SIGNATURE& sigBlob,
  1091. bool &isByRef,
  1092. mdTypeDef &typeDef,
  1093. bool &isArray)
  1094. {
  1095. CorElementType type = (CorElementType) *sigBlob++;
  1096. isByRef = (ELEMENT_TYPE_BYREF == type);
  1097. if(isByRef)
  1098. type = (CorElementType) *sigBlob++;
  1099. isArray = (ELEMENT_TYPE_SZARRAY == type);
  1100. if(isArray)
  1101. type = (CorElementType) *sigBlob++;
  1102. typeDef = mdTypeDefNil;
  1103. if(ELEMENT_TYPE_VALUETYPE == type || ELEMENT_TYPE_CLASS == type)
  1104. {
  1105. sigBlob += CorSigUncompressToken(sigBlob, &typeDef);
  1106. }
  1107. return type;
  1108. }
  1109. // ----------------------------------------------------------------------------
  1110. HRESULT ProfilerCallback::GetTypeName(
  1111. PWCHAR name,
  1112. ULONG size,
  1113. CorElementType type,
  1114. mdTypeDef typeDef,
  1115. IMetaDataImport *mdi)
  1116. {
  1117. HRESULT hr = S_OK;
  1118. switch(type)
  1119. {
  1120. case ELEMENT_TYPE_VALUETYPE:
  1121. case ELEMENT_TYPE_CLASS:
  1122. if ( TypeFromToken( typeDef ) == mdtTypeRef )
  1123. {
  1124. hr = mdi->GetTypeRefProps(
  1125. typeDef, NULL,
  1126. name, MAX_LENGTH, NULL);
  1127. }
  1128. else
  1129. {
  1130. hr = mdi->GetTypeDefProps(
  1131. typeDef,
  1132. name, MAX_LENGTH, NULL, NULL, NULL);
  1133. }
  1134. if(!SUCCEEDED(hr))
  1135. {
  1136. name[0] = '\0';
  1137. }
  1138. break;
  1139. default:
  1140. {
  1141. _GetNameFromElementType(type, name, size);
  1142. }
  1143. break;
  1144. }
  1145. return hr;
  1146. }
  1147. /* public */
  1148. __forceinline void ProfilerCallback::Leave( FunctionID functionID, COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange )
  1149. {
  1150. FunctionInfo *pFunctionInfo = NULL;
  1151. pFunctionInfo = g_pCallbackObject->m_pFunctionTable[functionID];
  1152. if(pFunctionInfo != NULL && g_pCallbackObject->_IsNeedToLog(pFunctionInfo->m_name) &&
  1153. (g_pCallbackObject->m_traceEvent || g_pCallbackObject->m_traceParameter)
  1154. )
  1155. {
  1156. g_pCallbackObject->LogToAny("< %S",
  1157. pFunctionInfo->m_name);
  1158. if(g_pCallbackObject->m_traceParameter)
  1159. {
  1160. g_pCallbackObject->LogToAny(" %S",
  1161. pFunctionInfo->m_pReturnInfo->m_typeName);
  1162. HRESULT hr;
  1163. mdMethodDef methodDef;
  1164. IMetaDataImport *mdi = NULL;
  1165. if(pFunctionInfo->m_pReturnInfo->m_type != ELEMENT_TYPE_VOID)
  1166. {
  1167. hr = g_pCallbackObject->m_pProfilerInfo->GetTokenAndMetaDataFromFunction(
  1168. functionID,
  1169. IID_IMetaDataImport,
  1170. (IUnknown**) &mdi,
  1171. &methodDef);
  1172. if(SUCCEEDED(hr) && mdi != NULL) {
  1173. g_pCallbackObject->LogToAny("=");
  1174. hr = g_pCallbackObject->TraceValue(
  1175. pFunctionInfo->m_pReturnInfo->m_isByRef ? *(PUINT_PTR)(retvalRange->startAddress) : retvalRange->startAddress,
  1176. g_pCallbackObject->m_pProfilerInfo2, mdi,
  1177. pFunctionInfo->m_pReturnInfo);
  1178. }
  1179. }
  1180. }
  1181. g_pCallbackObject->LogToAny("\n");
  1182. }
  1183. } // ProfilerCallback::Leave
  1184. /* public */
  1185. void ProfilerCallback::Tailcall( FunctionID functionID )
  1186. {
  1187. ///////////////////////////////////////////////////////////////////////////
  1188. Synchronize guard( g_pCallbackObject->m_criticalSection );
  1189. ///////////////////////////////////////////////////////////////////////////
  1190. if(g_pCallbackObject->m_traceEvent) {
  1191. g_pCallbackObject->LogToAny("Tailcall: FunctionID=0x%p\n", functionID);
  1192. }
  1193. } // ProfilerCallback::Tailcall
  1194. /* public */
  1195. HRESULT ProfilerCallback::ModuleLoadFinished( ModuleID moduleID,
  1196. HRESULT hrStatus )
  1197. {
  1198. ///////////////////////////////////////////////////////////////////////////
  1199. Synchronize guard( m_criticalSection );
  1200. ///////////////////////////////////////////////////////////////////////////
  1201. try
  1202. {
  1203. if(SUCCEEDED(hrStatus)) {
  1204. AddModule(moduleID);
  1205. }
  1206. }
  1207. catch ( BaseException *exception )
  1208. {
  1209. exception->ReportFailure();
  1210. delete exception;
  1211. Failure();
  1212. }
  1213. if(m_traceEvent) {
  1214. ModuleInfo *pModuleInfo = m_pModuleTable[moduleID];
  1215. if(pModuleInfo != NULL)
  1216. LogToAny( "ModuleLoadFinished: ModuleID=0x%p, Name=%S, Address=0x%p\n",
  1217. moduleID,
  1218. pModuleInfo->m_name,
  1219. pModuleInfo->m_loadAddress
  1220. );
  1221. }
  1222. return S_OK;
  1223. } // ProfilerCallback::ModuleLoadFinished
  1224. /* public */
  1225. HRESULT ProfilerCallback::JITCompilationStarted( FunctionID functionID,
  1226. BOOL fIsSafeToBlock )
  1227. {
  1228. ///////////////////////////////////////////////////////////////////////////
  1229. Synchronize guard( m_criticalSection );
  1230. ///////////////////////////////////////////////////////////////////////////
  1231. try
  1232. {
  1233. AddFunction( functionID );
  1234. }
  1235. catch ( BaseException *exception )
  1236. {
  1237. exception->ReportFailure();
  1238. delete exception;
  1239. Failure();
  1240. }
  1241. if(m_traceEvent) {
  1242. FunctionInfo *pFunctionInfo = m_pFunctionTable[functionID];
  1243. if(pFunctionInfo != NULL)
  1244. LogToAny("JITCompilationStarted: FunctionID=0x%p, Name=%S\n", functionID, pFunctionInfo->m_name);
  1245. }
  1246. return S_OK;
  1247. } // ProfilerCallback::JITCompilationStarted
  1248. /* public */
  1249. HRESULT ProfilerCallback::JITCachedFunctionSearchStarted( FunctionID functionID,
  1250. BOOL *pbUseCachedFunction )
  1251. {
  1252. ///////////////////////////////////////////////////////////////////////////
  1253. Synchronize guard( m_criticalSection );
  1254. ///////////////////////////////////////////////////////////////////////////
  1255. // use the pre-jitted function
  1256. *pbUseCachedFunction = TRUE;
  1257. try
  1258. {
  1259. AddFunction( functionID );
  1260. }
  1261. catch ( BaseException *exception )
  1262. {
  1263. exception->ReportFailure();
  1264. delete exception;
  1265. Failure();
  1266. }
  1267. if(m_traceEvent) {
  1268. FunctionInfo *pFunctionInfo = m_pFunctionTable[functionID];
  1269. if(pFunctionInfo != NULL)
  1270. LogToAny("JITCachedFunctionSearchStarted: FunctionID=0x%p, Name=%S\n", functionID, pFunctionInfo->m_name);
  1271. }
  1272. return S_OK;
  1273. } // ProfilerCallback::JITCachedFunctionSearchStarted
  1274. /* public */
  1275. HRESULT ProfilerCallback::JITCompilationFinished( FunctionID functionID,
  1276. HRESULT hrStatus,
  1277. BOOL fIsSafeToBlock )
  1278. {
  1279. ///////////////////////////////////////////////////////////////////////////
  1280. Synchronize guard( m_criticalSection );
  1281. ///////////////////////////////////////////////////////////////////////////
  1282. if(m_traceEvent) {
  1283. LogToAny("JITCompilationFinished: FunctionID=0x%p\n", functionID);
  1284. }
  1285. return S_OK;
  1286. } // ProfilerCallback::JITCompilationFinished
  1287. /* public */
  1288. HRESULT ProfilerCallback::JITCachedFunctionSearchFinished( FunctionID functionID,
  1289. COR_PRF_JIT_CACHE result )
  1290. {
  1291. ///////////////////////////////////////////////////////////////////////////
  1292. Synchronize guard( m_criticalSection );
  1293. ///////////////////////////////////////////////////////////////////////////
  1294. if(m_traceEvent) {
  1295. LogToAny("JITCachedFunctionSearchFinished: FunctionID=0x%p\n", functionID);
  1296. }
  1297. return S_OK;
  1298. } // ProfilerCallback::JITCachedFunctionSearchFinished
  1299. /* public */
  1300. HRESULT ProfilerCallback::ExceptionUnwindFunctionEnter( FunctionID functionID )
  1301. {
  1302. ///////////////////////////////////////////////////////////////////////////
  1303. Synchronize guard( g_pCallbackObject->m_criticalSection );
  1304. ///////////////////////////////////////////////////////////////////////////
  1305. if(m_traceEvent) {
  1306. LogToAny("ExceptionUnwindFunctionEnter: FunctionID=0x%p\n", functionID);
  1307. }
  1308. return S_OK;
  1309. } // ProfilerCallback::ExceptionUnwindFunctionEnter
  1310. /* public */
  1311. HRESULT ProfilerCallback::ExceptionUnwindFunctionLeave( )
  1312. {
  1313. ///////////////////////////////////////////////////////////////////////////
  1314. Synchronize guard( m_criticalSection );
  1315. ///////////////////////////////////////////////////////////////////////////
  1316. if(m_traceEvent) {
  1317. LogToAny("ExceptionUnwindFunctionLeave\n");
  1318. }
  1319. return S_OK;
  1320. } // ProfilerCallback::ExceptionUnwindFunctionLeave
  1321. /* public */
  1322. HRESULT ProfilerCallback::ThreadCreated( ThreadID threadID )
  1323. {
  1324. ///////////////////////////////////////////////////////////////////////////
  1325. Synchronize guard( g_pCallbackObject->m_criticalSection );
  1326. ///////////////////////////////////////////////////////////////////////////
  1327. if(m_traceEvent) {
  1328. HRESULT hr;
  1329. ThreadID myThreadID;
  1330. hr = m_pProfilerInfo->GetCurrentThreadID( &myThreadID );
  1331. if ( SUCCEEDED( hr ) )
  1332. {
  1333. if ( threadID == myThreadID )
  1334. {
  1335. DWORD win32ThreadID;
  1336. hr = m_pProfilerInfo->GetThreadInfo( threadID, &win32ThreadID );
  1337. if ( SUCCEEDED( hr ) )
  1338. {
  1339. LogToAny("ThreadCreated: ThreadID=%0xp, Win32ThreadID=0x%p\n", threadID, win32ThreadID);
  1340. }
  1341. else
  1342. {
  1343. _THROW_EXCEPTION( "ICorProfilerInfo::GetThreadInfo() FAILED" )
  1344. }
  1345. }
  1346. else
  1347. _THROW_EXCEPTION( "Thread ID's do not match FAILED" )
  1348. }
  1349. else
  1350. _THROW_EXCEPTION( "ICorProfilerInfo::GetCurrentThreadID() FAILED" )
  1351. }
  1352. return S_OK;
  1353. } // ProfilerCallback::ThreadCreated
  1354. /* public */
  1355. HRESULT ProfilerCallback::ThreadDestroyed( ThreadID threadID )
  1356. {
  1357. ///////////////////////////////////////////////////////////////////////////
  1358. Synchronize guard( g_pCallbackObject->m_criticalSection );
  1359. ///////////////////////////////////////////////////////////////////////////
  1360. if(m_traceEvent)
  1361. {
  1362. LogToAny("ThreadDestroyed: ThreadID=%Id\n", threadID);
  1363. }
  1364. return S_OK;
  1365. } // ProfilerCallback::ThreadDestroyed
  1366. /* public */
  1367. HRESULT ProfilerCallback::ThreadAssignedToOSThread( ThreadID managedThreadID,
  1368. DWORD osThreadID )
  1369. {
  1370. ///////////////////////////////////////////////////////////////////////////
  1371. Synchronize guard( g_pCallbackObject->m_criticalSection );
  1372. ///////////////////////////////////////////////////////////////////////////
  1373. if(m_traceEvent) {
  1374. LogToAny("ThreadAssignedToOSThread: ThreadID=0x%p, OSThreadID=0x%p\n", managedThreadID, osThreadID);
  1375. }
  1376. return S_OK;
  1377. } // ProfilerCallback::ThreadAssignedToOSThread
  1378. /* public */
  1379. HRESULT ProfilerCallback::UnmanagedToManagedTransition( FunctionID functionID,
  1380. COR_PRF_TRANSITION_REASON reason )
  1381. {
  1382. ///////////////////////////////////////////////////////////////////////////
  1383. Synchronize guard( m_criticalSection );
  1384. ///////////////////////////////////////////////////////////////////////////
  1385. if ( m_traceEvent && reason == COR_PRF_TRANSITION_RETURN )
  1386. {
  1387. LogToAny("UnmanagedToManagedTransition: FunctionID=0x%p\n", functionID);
  1388. }
  1389. return S_OK;
  1390. } // ProfilerCallback::UnmanagedToManagedTransition
  1391. /* public */
  1392. HRESULT ProfilerCallback::ManagedToUnmanagedTransition( FunctionID functionID,
  1393. COR_PRF_TRANSITION_REASON reason )
  1394. {
  1395. ///////////////////////////////////////////////////////////////////////////
  1396. Synchronize guard( m_criticalSection );
  1397. ///////////////////////////////////////////////////////////////////////////
  1398. if ( m_traceEvent && reason == COR_PRF_TRANSITION_CALL )
  1399. {
  1400. LogToAny("ManagedToUnmanagedTransition: FunctiondID=0x%p\n", functionID);
  1401. }
  1402. return S_OK;
  1403. } // ProfilerCallback::ManagedToUnmanagedTransition
  1404. HRESULT ProfilerCallback::ObjectAllocated( ObjectID objectID,
  1405. ClassID classID )
  1406. {
  1407. ///////////////////////////////////////////////////////////////////////////
  1408. Synchronize guard( m_criticalSection );
  1409. ///////////////////////////////////////////////////////////////////////////
  1410. if(m_traceEvent) {
  1411. LogToAny("ObjectAllocated: ObjectID=0x%p, ClassID=0x%p\n", objectID, classID);
  1412. }
  1413. return S_OK;
  1414. } // ProfilerCallback::ObjectAllocated
  1415. /* public */
  1416. HRESULT ProfilerCallback::ObjectReferences( ObjectID objectID,
  1417. ClassID classID,
  1418. ULONG objectRefs,
  1419. ObjectID objectRefIDs[] )
  1420. {
  1421. ///////////////////////////////////////////////////////////////////////////
  1422. Synchronize guard( m_criticalSection );
  1423. ///////////////////////////////////////////////////////////////////////////
  1424. if(m_traceEvent) {
  1425. LogToAny("ObjectReferences: ObjectID=0x%p, ClassID=0x%p", objectID, classID);
  1426. }
  1427. return S_OK;
  1428. } // ProfilerCallback::ObjectReferences
  1429. /* public */
  1430. HRESULT ProfilerCallback::RootReferences( ULONG rootRefs,
  1431. ObjectID rootRefIDs[] )
  1432. {
  1433. ///////////////////////////////////////////////////////////////////////////
  1434. Synchronize guard( m_criticalSection );
  1435. ///////////////////////////////////////////////////////////////////////////
  1436. if(m_traceEvent) {
  1437. LogToAny("RootReferences: 0x%p\n", rootRefs);
  1438. }
  1439. return S_OK;
  1440. } // ProfilerCallback::RootReferences
  1441. /* public */
  1442. HRESULT ProfilerCallback::RuntimeSuspendStarted( COR_PRF_SUSPEND_REASON suspendReason )
  1443. {
  1444. ///////////////////////////////////////////////////////////////////////////
  1445. Synchronize guard( g_pCallbackObject->m_criticalSection );
  1446. ///////////////////////////////////////////////////////////////////////////
  1447. //if we are shutting down , terminate all the threads
  1448. if ( suspendReason == COR_PRF_SUSPEND_FOR_SHUTDOWN )
  1449. {
  1450. m_bShutdown = TRUE;
  1451. }
  1452. if(m_traceEvent) {
  1453. LogToAny("RuntimeSuspendStarted: %d\n", suspendReason);
  1454. }
  1455. return S_OK;
  1456. } // ProfilerCallback::RuntimeSuspendStarted
  1457. /* public */
  1458. HRESULT ProfilerCallback::RuntimeResumeFinished()
  1459. {
  1460. ///////////////////////////////////////////////////////////////////////////
  1461. Synchronize guard( m_criticalSection );
  1462. ///////////////////////////////////////////////////////////////////////////
  1463. if(m_traceEvent) {
  1464. LogToAny( "RuntimeResumeFinished\n");
  1465. }
  1466. return S_OK;
  1467. } // ProfilerCallback::RuntimeResumeFinished
  1468. /***************************************************************************************
  1469. ******************** ********************
  1470. ******************** Callbacks With Default Implementation ********************
  1471. ******************** ********************
  1472. ***************************************************************************************/
  1473. /* public */
  1474. HRESULT ProfilerCallback::AppDomainCreationStarted( AppDomainID appDomainID )
  1475. {
  1476. if(m_traceEvent) {
  1477. LogToAny("AppDomainCreationStarted: DomainID=0x%p\n", appDomainID);
  1478. }
  1479. return S_OK;
  1480. } // ProfilerCallback::AppDomainCreationStarted
  1481. /* public */
  1482. HRESULT ProfilerCallback::AppDomainCreationFinished( AppDomainID appDomainID,
  1483. HRESULT hrStatus )
  1484. {
  1485. ///////////////////////////////////////////////////////////////////////////
  1486. Synchronize guard( m_criticalSection );
  1487. ///////////////////////////////////////////////////////////////////////////
  1488. if(m_traceEvent) {
  1489. ULONG size;
  1490. WCHAR name[2048];
  1491. ProcessID processId;
  1492. if(SUCCEEDED(m_pProfilerInfo->GetAppDomainInfo(appDomainID, 2048, &size, name, &processId)))
  1493. {
  1494. LogToAny("AppDomainCreationFinished: DomainID=0x%p, Name=%S, ProcessID=0x%p\n", appDomainID, name, processId);
  1495. }
  1496. }
  1497. return S_OK;
  1498. } // ProfilerCallback::AppDomainCreationFinished
  1499. /* public */
  1500. HRESULT ProfilerCallback::AppDomainShutdownStarted( AppDomainID appDomainID )
  1501. {
  1502. if(m_traceEvent) {
  1503. LogToAny("AppDomainShutdownStarted: DomainID=0x%p\n", appDomainID);
  1504. }
  1505. return S_OK;
  1506. } // ProfilerCallback::AppDomainShutdownStarted
  1507. /* public */
  1508. HRESULT ProfilerCallback::AppDomainShutdownFinished( AppDomainID appDomainID,
  1509. HRESULT hrStatus )
  1510. {
  1511. if(m_traceEvent) {
  1512. LogToAny("AppDomainShutdownFinished: DomainID=0x%p\n", appDomainID);
  1513. }
  1514. return S_OK;
  1515. } // ProfilerCallback::AppDomainShutdownFinished
  1516. /* public */
  1517. HRESULT ProfilerCallback::AssemblyLoadStarted( AssemblyID assemblyId )
  1518. {
  1519. if(m_traceEvent) {
  1520. LogToAny("AssemblyLoadStarted: AssemblyID=0x%p\n", assemblyId);
  1521. }
  1522. return S_OK;
  1523. } // ProfilerCallback::AssemblyLoadStarted
  1524. /* public */
  1525. HRESULT ProfilerCallback::AssemblyLoadFinished( AssemblyID assemblyId,
  1526. HRESULT hrStatus )
  1527. {
  1528. ///////////////////////////////////////////////////////////////////////////
  1529. Synchronize guard( m_criticalSection );
  1530. ///////////////////////////////////////////////////////////////////////////
  1531. if(m_traceEvent) {
  1532. ULONG size;
  1533. WCHAR name[2048];
  1534. ModuleID moduleId;
  1535. AppDomainID appDomainId;
  1536. if(SUCCEEDED(m_pProfilerInfo->GetAssemblyInfo(assemblyId, 2048, &size, name, &appDomainId, &moduleId)))
  1537. {
  1538. LogToAny("AssemblyLoadFinished: AssemblyID=0x%p, Name=%S, AppDomainID=0x%p, ModuleID=0x%p\n", assemblyId, name, appDomainId, moduleId);
  1539. }
  1540. }
  1541. return S_OK;
  1542. } // ProfilerCallback::AssemblyLoadFinished
  1543. /* public */
  1544. HRESULT ProfilerCallback::AssemblyUnloadStarted( AssemblyID assemblyId )
  1545. {
  1546. if(m_traceEvent) {
  1547. LogToAny("AssemblyUnloadStarted: AssemblyID=0x%p\n", assemblyId);
  1548. }
  1549. return S_OK;
  1550. } // ProfilerCallback::AssemblyUnLoadStarted
  1551. /* public */
  1552. HRESULT ProfilerCallback::AssemblyUnloadFinished( AssemblyID assemblyId,
  1553. HRESULT hrStatus )
  1554. {
  1555. if(m_traceEvent) {
  1556. LogToAny("AssemblyUnloadFinished: AssemblyID=0x%p\n", assemblyId);
  1557. }
  1558. return S_OK;
  1559. } // ProfilerCallback::AssemblyUnLoadFinished
  1560. /* public */
  1561. HRESULT ProfilerCallback::ModuleLoadStarted( ModuleID moduleID )
  1562. {
  1563. if(m_traceEvent) {
  1564. LogToAny("ModuleLoadStarted: ModuleID=0x%p\n", moduleID);
  1565. }
  1566. return S_OK;
  1567. } // ProfilerCallback::ModuleLoadStarted
  1568. /* public */
  1569. HRESULT ProfilerCallback::ModuleUnloadStarted( ModuleID moduleID )
  1570. {
  1571. if(m_traceEvent) {
  1572. LogToAny("ModuleUnloadStarted: ModuleID=0x%p\n", moduleID);
  1573. }
  1574. return S_OK;
  1575. } // ProfilerCallback::ModuleUnloadStarted
  1576. /* public */
  1577. HRESULT ProfilerCallback::ModuleUnloadFinished( ModuleID moduleID,
  1578. HRESULT hrStatus )
  1579. {
  1580. if(m_traceEvent) {
  1581. LogToAny("ModuleUnloadFinished: ModuleID=0x%p\n", moduleID);
  1582. }
  1583. try
  1584. {
  1585. if(SUCCEEDED(hrStatus)) {
  1586. RemoveModule(moduleID);
  1587. }
  1588. }
  1589. catch ( BaseException *exception )
  1590. {
  1591. exception->ReportFailure();
  1592. delete exception;
  1593. Failure();
  1594. }
  1595. return S_OK;
  1596. } // ProfilerCallback::ModuleUnloadFinished
  1597. /* public */
  1598. HRESULT ProfilerCallback::ModuleAttachedToAssembly( ModuleID moduleID,
  1599. AssemblyID assemblyID )
  1600. {
  1601. if(m_traceEvent) {
  1602. LogToAny("ModuleAttachedToAssembly: ModuleID=0x%p, AssemblyID=0x%p\n", moduleID, assemblyID);
  1603. }
  1604. return S_OK;
  1605. } // ProfilerCallback::ModuleAttachedToAssembly
  1606. /* public */
  1607. HRESULT ProfilerCallback::ClassLoadStarted( ClassID classID )
  1608. {
  1609. if(m_traceEvent) {
  1610. LogToAny("ClassLoadStarted: ClassID=0x%p\n", classID);
  1611. }
  1612. return S_OK;
  1613. } // ProfilerCallback::ClassLoadStarted
  1614. /* public */
  1615. HRESULT ProfilerCallback::ClassLoadFinished( ClassID classID,
  1616. HRESULT hrStatus )
  1617. {
  1618. ///////////////////////////////////////////////////////////////////////////
  1619. Synchronize guard( m_criticalSection );
  1620. ///////////////////////////////////////////////////////////////////////////
  1621. try
  1622. {
  1623. if(SUCCEEDED(hrStatus)) {
  1624. AddClass(classID);
  1625. }
  1626. }
  1627. catch ( BaseException *exception )
  1628. {
  1629. exception->ReportFailure();
  1630. delete exception;
  1631. Failure();
  1632. }
  1633. if(m_traceEvent)
  1634. {
  1635. ClassInfo *pClassInfo = m_pClassTable[classID];
  1636. if(pClassInfo != NULL)
  1637. LogToAny("ClassLoadFinished: ClassID=0x%p, Name=%S, ModuleID=%p, Token=%p\n", classID, pClassInfo->m_name, pClassInfo->m_moduleID, pClassInfo->m_classToken);
  1638. }
  1639. return S_OK;
  1640. } // ProfilerCallback::ClassLoadFinished
  1641. /* public */
  1642. HRESULT ProfilerCallback::ClassUnloadStarted( ClassID classID )
  1643. {
  1644. if(m_traceEvent) {
  1645. LogToAny("ClassUnloadStarted: ClassID=0x%p\n", classID);
  1646. }
  1647. return S_OK;
  1648. } // ProfilerCallback::ClassUnloadStarted
  1649. HRESULT ProfilerCallback::ClassUnloadFinished( ClassID classID,
  1650. HRESULT hrStatus )
  1651. {
  1652. if(m_traceEvent) {
  1653. ClassInfo *pClassInfo = m_pClassTable[classID];
  1654. if(pClassInfo != NULL)
  1655. LogToAny("ClassUnloadFinished: ClassID=0x%p, Name=%S, ModuleID=%p, Token=%p\n", classID, pClassInfo->m_name, pClassInfo->m_moduleID, pClassInfo->m_classToken);
  1656. }
  1657. try
  1658. {
  1659. if(SUCCEEDED(hrStatus)) {
  1660. RemoveClass(classID);
  1661. }
  1662. }
  1663. catch ( BaseException *exception )
  1664. {
  1665. exception->ReportFailure();
  1666. delete exception;
  1667. Failure();
  1668. }
  1669. return S_OK;
  1670. } // ProfilerCallback::ClassUnloadFinished
  1671. /* public */
  1672. HRESULT ProfilerCallback::FunctionUnloadStarted( FunctionID functionID )
  1673. {
  1674. if(m_traceEvent) {
  1675. LogToAny("FunctionUnloadStarted: FunctionID=0x%p\n", functionID);
  1676. }
  1677. return S_OK;
  1678. } // ProfilerCallback::FunctionUnloadStarted
  1679. /* public */
  1680. HRESULT ProfilerCallback::JITFunctionPitched( FunctionID functionID )
  1681. {
  1682. if(m_traceEvent) {
  1683. LogToAny("JITFunctionPitched: FunctionID=0x%p\n", functionID);
  1684. }
  1685. return S_OK;
  1686. } // ProfilerCallback::JITFunctionPitched
  1687. /* public */
  1688. HRESULT ProfilerCallback::JITInlining( FunctionID callerID,
  1689. FunctionID calleeID,
  1690. BOOL *pfShouldInline )
  1691. {
  1692. if(m_traceEvent) {
  1693. LogToAny("JITInlining: CallerID=0x%p, CalleeID=0x%p\n", callerID, calleeID);
  1694. }
  1695. return S_OK;
  1696. } // ProfilerCallback::JITInlining
  1697. /* public */
  1698. HRESULT ProfilerCallback::RemotingClientInvocationStarted()
  1699. {
  1700. if(m_traceEvent) {
  1701. LogToAny("RemotingClientInvocationStarted\n");
  1702. }
  1703. return S_OK;
  1704. } // ProfilerCallback::RemotingClientInvocationStarted
  1705. /* public */
  1706. HRESULT ProfilerCallback::RemotingClientSendingMessage( GUID *pCookie,
  1707. BOOL fIsAsync )
  1708. {
  1709. if(m_traceEvent) {
  1710. LogToAny("RemotingClientSendingMessage\n");
  1711. }
  1712. return S_OK;
  1713. } // ProfilerCallback::RemotingClientSendingMessage
  1714. /* public */
  1715. HRESULT ProfilerCallback::RemotingClientReceivingReply( GUID *pCookie,
  1716. BOOL fIsAsync )
  1717. {
  1718. if(m_traceEvent) {
  1719. LogToAny("RemotingClientReceivingReply\n");
  1720. }
  1721. return S_OK;
  1722. } // ProfilerCallback::RemotingClientReceivingReply
  1723. HRESULT ProfilerCallback::RemotingClientInvocationFinished()
  1724. {
  1725. if(m_traceEvent) {
  1726. LogToAny("RemotingClientInvocationFinished\n");
  1727. }
  1728. return S_OK;
  1729. } // ProfilerCallback::RemotingClientInvocationFinished
  1730. /* public */
  1731. HRESULT ProfilerCallback::RemotingServerReceivingMessage( GUID *pCookie,
  1732. BOOL fIsAsync )
  1733. {
  1734. if(m_traceEvent) {
  1735. LogToAny("RemotingServerReceivingMessage\n");
  1736. }
  1737. return S_OK;
  1738. } // ProfilerCallback::RemotingServerReceivingMessage
  1739. /* public */
  1740. HRESULT ProfilerCallback::RemotingServerInvocationStarted()
  1741. {
  1742. if(m_traceEvent) {
  1743. LogToAny("RemotingServerInvocationStarted\n");
  1744. }
  1745. return S_OK;
  1746. } // ProfilerCallback::RemotingServerInvocationStarted
  1747. /* public */
  1748. HRESULT ProfilerCallback::RemotingServerInvocationReturned()
  1749. {
  1750. if(m_traceEvent) {
  1751. LogToAny("RemotingServerInvocationReturned\n");
  1752. }
  1753. return S_OK;
  1754. } // ProfilerCallback::RemotingServerInvocationReturned
  1755. /* public */
  1756. HRESULT ProfilerCallback::RemotingServerSendingReply( GUID *pCookie,
  1757. BOOL fIsAsync )
  1758. {
  1759. if(m_traceEvent) {
  1760. LogToAny("RemotingServerSendingReply\n");
  1761. }
  1762. return S_OK;
  1763. } // ProfilerCallback::RemotingServerSendingReply
  1764. /* public */
  1765. HRESULT ProfilerCallback::RuntimeSuspendFinished()
  1766. {
  1767. if(m_traceEvent) {
  1768. LogToAny("RuntimeSuspendFinished\n");
  1769. }
  1770. return S_OK;
  1771. } // ProfilerCallback::RuntimeSuspendFinished
  1772. /* public */
  1773. HRESULT ProfilerCallback::RuntimeSuspendAborted()
  1774. {
  1775. if(m_traceEvent) {
  1776. LogToAny("RuntimeSuspendAborted\n");
  1777. }
  1778. return S_OK;
  1779. } // ProfilerCallback::RuntimeSuspendAborted
  1780. /* public */
  1781. HRESULT ProfilerCallback::RuntimeResumeStarted()
  1782. {
  1783. if(m_traceEvent) {
  1784. LogToAny("RuntimeResumeStarted\n");
  1785. }
  1786. return S_OK;
  1787. } // ProfilerCallback::RuntimeResumeStarted
  1788. /* public */
  1789. HRESULT ProfilerCallback::RuntimeThreadSuspended( ThreadID threadID )
  1790. {
  1791. if(m_traceEvent) {
  1792. LogToAny("RuntimeThreadSuspended: ThreadID=%Id\n", threadID);
  1793. }
  1794. return S_OK;
  1795. } // ProfilerCallback::RuntimeThreadSuspended
  1796. /* public */
  1797. HRESULT ProfilerCallback::RuntimeThreadResumed( ThreadID threadID )
  1798. {
  1799. if(m_traceEvent) {
  1800. LogToAny("RuntimeThreadResumed: ThreadID=%Id\n", threadID);
  1801. }
  1802. return S_OK;
  1803. } // ProfilerCallback::RuntimeThreadResumed
  1804. /* public */
  1805. HRESULT ProfilerCallback::MovedReferences( ULONG cmovedObjectIDRanges,
  1806. ObjectID oldObjectIDRangeStart[],
  1807. ObjectID newObjectIDRangeStart[],
  1808. ULONG cObjectIDRangeLength[] )
  1809. {
  1810. ///////////////////////////////////////////////////////////////////////////
  1811. Synchronize guard( m_criticalSection );
  1812. ///////////////////////////////////////////////////////////////////////////
  1813. if(m_traceEvent) {
  1814. LogToAny("MovedReferences\n");
  1815. }
  1816. return S_OK;
  1817. } // ProfilerCallback::MovedReferences
  1818. HRESULT ProfilerCallback::SurvivingReferences( ULONG cmovedObjectIDRanges,
  1819. ObjectID objectIDRangeStart[],
  1820. ULONG cObjectIDRangeLength[] )
  1821. {
  1822. ///////////////////////////////////////////////////////////////////////////
  1823. Synchronize guard( m_criticalSection );
  1824. ///////////////////////////////////////////////////////////////////////////
  1825. if(m_traceEvent) {
  1826. LogToAny("SurvivingReferences\n");
  1827. }
  1828. return S_OK;
  1829. } // ProfilerCallback::SurvivingReferences
  1830. /* public */
  1831. HRESULT ProfilerCallback::ObjectsAllocatedByClass( ULONG classCount,
  1832. ClassID classIDs[],
  1833. ULONG objects[] )
  1834. {
  1835. if(m_traceEvent) {
  1836. LogToAny("ObjectsAllocatedByClass: ClassCount=%u\n", classCount);
  1837. }
  1838. return S_OK;
  1839. } // ProfilerCallback::ObjectsAllocatedByClass
  1840. /* public */
  1841. HRESULT ProfilerCallback::ExceptionThrown( ObjectID thrownObjectID )
  1842. {
  1843. LogToAny("\nExceptionThrown: ObjectID=0x%p\n", thrownObjectID);
  1844. return S_OK;
  1845. } // ProfilerCallback::ExceptionThrown
  1846. /* public */
  1847. HRESULT ProfilerCallback::ExceptionSearchFunctionEnter( FunctionID functionID )
  1848. {
  1849. if(m_traceEvent) {
  1850. LogToAny("ExceptionSearchFunctionEnter: FunctionID=0x%p\n", functionID);
  1851. }
  1852. return S_OK;
  1853. } // ProfilerCallback::ExceptionSearchFunctionEnter
  1854. /* public */
  1855. HRESULT ProfilerCallback::ExceptionSearchFunctionLeave()
  1856. {
  1857. if(m_traceEvent) {
  1858. LogToAny("ExceptionSearchFunctionLeave\n");
  1859. }
  1860. return S_OK;
  1861. } // ProfilerCallback::ExceptionSearchFunctionLeave
  1862. /* public */
  1863. HRESULT ProfilerCallback::ExceptionSearchFilterEnter( FunctionID functionID )
  1864. {
  1865. if(m_traceEvent) {
  1866. LogToAny("ExceptionSearchFilterEnter: FunctionID=0x%p\n", functionID);
  1867. }
  1868. return S_OK;
  1869. } // ProfilerCallback::ExceptionSearchFilterEnter
  1870. /* public */
  1871. HRESULT ProfilerCallback::ExceptionSearchFilterLeave()
  1872. {
  1873. if(m_traceEvent) {
  1874. LogToAny("ExceptionSearchFilterLeave\n");
  1875. }
  1876. return S_OK;
  1877. } // ProfilerCallback::ExceptionSearchFilterLeave
  1878. /* public */
  1879. HRESULT ProfilerCallback::ExceptionSearchCatcherFound( FunctionID functionID )
  1880. {
  1881. if(m_traceEvent) {
  1882. LogToAny("ExceptionSearchCatcherFound: FunctionID=0x%p\n", functionID);
  1883. }
  1884. return S_OK;
  1885. } // ProfilerCallback::ExceptionSearchCatcherFound
  1886. /* public */
  1887. HRESULT ProfilerCallback::ExceptionCLRCatcherFound()
  1888. {
  1889. if(m_traceEvent) {
  1890. LogToAny("ExceptionCLRCatcherFound\n");
  1891. }
  1892. return S_OK;
  1893. }
  1894. /* public */
  1895. HRESULT ProfilerCallback::ExceptionCLRCatcherExecute()
  1896. {
  1897. if(m_traceEvent) {
  1898. LogToAny("ExceptionCLRCatcherExecute\n");
  1899. }
  1900. return S_OK;
  1901. }
  1902. /* public */
  1903. HRESULT ProfilerCallback::ExceptionOSHandlerEnter( FunctionID functionID )
  1904. {
  1905. if(m_traceEvent) {
  1906. LogToAny("ExceptionOSHandlerEnter: FunctionID=0x%p\n", functionID);
  1907. }
  1908. return S_OK;
  1909. } // ProfilerCallback::ExceptionOSHandlerEnter
  1910. /* public */
  1911. HRESULT ProfilerCallback::ExceptionOSHandlerLeave( FunctionID functionID )
  1912. {
  1913. if(m_traceEvent) {
  1914. LogToAny("ExceptionOSHandlerLeave: FunctionID=0x%p\n", functionID);
  1915. }
  1916. return S_OK;
  1917. } // ProfilerCallback::ExceptionOSHandlerLeave
  1918. /* public */
  1919. HRESULT ProfilerCallback::ExceptionUnwindFinallyEnter( FunctionID functionID )
  1920. {
  1921. if(m_traceEvent) {
  1922. LogToAny("ExceptionUnwindFinallyEnter: FunctionID=0x%p\n", functionID);
  1923. }
  1924. return S_OK;
  1925. } // ProfilerCallback::ExceptionUnwindFinallyEnter
  1926. /* public */
  1927. HRESULT ProfilerCallback::ExceptionUnwindFinallyLeave()
  1928. {
  1929. if(m_traceEvent) {
  1930. LogToAny("ExceptionUnwindFinallyLeave\n");
  1931. }
  1932. return S_OK;
  1933. } // ProfilerCallback::ExceptionUnwindFinallyLeave
  1934. /* public */
  1935. HRESULT ProfilerCallback::ExceptionCatcherEnter( FunctionID functionID,
  1936. ObjectID objectID )
  1937. {
  1938. if(m_traceEvent) {
  1939. LogToAny("ExceptionCatcherEnter: FunctionID=0x%p, ObjectID=0x%p\n", functionID, objectID);
  1940. }
  1941. return S_OK;
  1942. } // ProfilerCallback::ExceptionCatcherEnter
  1943. /* public */
  1944. HRESULT ProfilerCallback::ExceptionCatcherLeave()
  1945. {
  1946. if(m_traceEvent) {
  1947. LogToAny("ExceptionCatcherLeave\n");
  1948. }
  1949. return S_OK;
  1950. } // ProfilerCallback::ExceptionCatcherLeave
  1951. /* public */
  1952. HRESULT ProfilerCallback::COMClassicVTableCreated( ClassID wrappedClassID,
  1953. REFGUID implementedIID,
  1954. void *pVTable,
  1955. ULONG cSlots )
  1956. {
  1957. ///////////////////////////////////////////////////////////////////////////
  1958. Synchronize guard( m_criticalSection );
  1959. ///////////////////////////////////////////////////////////////////////////
  1960. if(m_traceEvent) {
  1961. LogToAny("COMClassicVTableCreated: WrappedClassID=0x%p\n", wrappedClassID);
  1962. }
  1963. return S_OK;
  1964. } // ProfilerCallback::COMClassicWrapperCreated
  1965. /* public */
  1966. HRESULT ProfilerCallback::COMClassicVTableDestroyed( ClassID wrappedClassID,
  1967. REFGUID implementedIID,
  1968. void *pVTable )
  1969. {
  1970. if(m_traceEvent) {
  1971. LogToAny("COMClassicVTableDestroyed: ClassID=0x%p\n", wrappedClassID);
  1972. }
  1973. return S_OK;
  1974. } // ProfilerCallback::COMClassicWrapperDestroyed
  1975. /* public */
  1976. HRESULT ProfilerCallback::ThreadNameChanged(
  1977. /* [in] */ ThreadID threadId,
  1978. /* [in] */ ULONG cchName,
  1979. /* [in] */ WCHAR name[ ])
  1980. {
  1981. if(m_traceEvent) {
  1982. LogToAny("ThreadNameChanged: ThreadID=%Id, Name=%S\n", threadId, name);
  1983. }
  1984. return S_OK;
  1985. } // ProfilerCallback::ThreadNameChanged
  1986. /* public */
  1987. HRESULT ProfilerCallback::FinalizeableObjectQueued(
  1988. /* [in] */ DWORD finalizerFlags,
  1989. /* [in] */ ObjectID objectID)
  1990. {
  1991. ///////////////////////////////////////////////////////////////////////////
  1992. Synchronize guard( m_criticalSection );
  1993. ///////////////////////////////////////////////////////////////////////////
  1994. if(m_traceEvent) {
  1995. LogToAny("FinalizeableObjectQueued: FinalizerFlags=%u, ObjectID=0x%p\n", finalizerFlags, objectID);
  1996. }
  1997. return S_OK;
  1998. }
  1999. /* public */
  2000. HRESULT ProfilerCallback::RootReferences2(
  2001. /* [in] */ ULONG cRootRefs,
  2002. /* [size_is][in] */ ObjectID rootRefIds[ ],
  2003. /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ],
  2004. /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ],
  2005. /* [size_is][in] */ UINT_PTR rootIds[ ])
  2006. {
  2007. ///////////////////////////////////////////////////////////////////////////
  2008. Synchronize guard( m_criticalSection );
  2009. ///////////////////////////////////////////////////////////////////////////
  2010. if(m_traceEvent) {
  2011. LogToAny("RootReferences2: 0x%p\n", cRootRefs);
  2012. }
  2013. return S_OK;
  2014. }
  2015. /* public */
  2016. HRESULT ProfilerCallback::HandleCreated(
  2017. /* [in] */ UINT_PTR handleId,
  2018. /* [in] */ ObjectID initialObjectId)
  2019. {
  2020. ///////////////////////////////////////////////////////////////////////////
  2021. Synchronize guard( m_criticalSection );
  2022. ///////////////////////////////////////////////////////////////////////////
  2023. if(m_traceEvent) {
  2024. LogToAny("HandleCreated: HandleID=0x%p\n", handleId);
  2025. }
  2026. return S_OK;
  2027. }
  2028. /* public */
  2029. HRESULT ProfilerCallback::HandleDestroyed(
  2030. /* [in] */ UINT_PTR handleId)
  2031. {
  2032. ///////////////////////////////////////////////////////////////////////////
  2033. Synchronize guard( m_criticalSection );
  2034. ///////////////////////////////////////////////////////////////////////////
  2035. if(m_traceEvent) {
  2036. LogToAny("HandleDestroyed: HandleID=0x%p\n", handleId);
  2037. }
  2038. return S_OK;
  2039. }
  2040. bool ProfilerCallback::_IsNeedToLog(WCHAR *pFilter)
  2041. {
  2042. if(m_includeSystem == FALSE)
  2043. {
  2044. if(_wcsnicmp(pFilter, L"System.", ARRAY_LEN(L"System.") - 1) == 0) return false;
  2045. if(_wcsnicmp(pFilter, L"Microsoft.", ARRAY_LEN(L"Microsoft.") - 1) == 0) return false;
  2046. }
  2047. //LogToAny("DEBUG: %S %S %d\n", pFilter, m_filter, m_filterLen);
  2048. if(m_filter != NULL && m_filterLen >= 2)
  2049. {
  2050. //int cmp = _wcsnicmp(pClassName, m_filter, m_filterLen);
  2051. //LogToAny("SP_CLASS: %S %S %d %d\n", pClassName, m_filter, cmp, m_filterLen-1);
  2052. //if(cmp==0) return true;
  2053. //else return false;
  2054. if(wcsstr(pFilter, m_filter) == NULL) return false;
  2055. }
  2056. return true;
  2057. }
  2058. HRESULT ProfilerCallback::GarbageCollectionStarted(
  2059. /* [in] */int cGenerations,
  2060. /*[in, size_is(cGenerations), length_is(cGenerations)]*/ BOOL generationCollected[],
  2061. /*[in]*/ COR_PRF_GC_REASON reason)
  2062. {
  2063. ///////////////////////////////////////////////////////////////////////////
  2064. Synchronize guard( m_criticalSection );
  2065. ///////////////////////////////////////////////////////////////////////////
  2066. LogToAny("GarbageCollectionStarted\n");
  2067. return S_OK;
  2068. }
  2069. /*
  2070. * The CLR calls GarbageCollectionFinished after a garbage
  2071. * collection has completed and all GC callbacks have been
  2072. * issued for it.
  2073. */
  2074. HRESULT ProfilerCallback::GarbageCollectionFinished()
  2075. {
  2076. ///////////////////////////////////////////////////////////////////////////
  2077. Synchronize guard( m_criticalSection );
  2078. ///////////////////////////////////////////////////////////////////////////
  2079. LogToAny("GarbageCollectionFinished\n");
  2080. return S_OK;
  2081. }
  2082. /***************************************************************************************
  2083. ******************** ********************
  2084. ******************** Private Functions ********************
  2085. ******************** ********************
  2086. ***************************************************************************************/
  2087. /* public */
  2088. void ProfilerCallback::_ProcessEnvVariables()
  2089. {
  2090. char buffer[4*MAX_LENGTH];
  2091. //
  2092. // look if the user specified another path to save the output file
  2093. //
  2094. buffer[0] = '\0';
  2095. if ( GetEnvironmentVariableA( SP_LOG_PATH, buffer, MAX_LENGTH ) > 0 )
  2096. {
  2097. // room for buffer chars + '\' + logfilename chars + '\0':
  2098. size_t len = ARRAY_LEN(buffer) + ARRAY_LEN(m_logFileName);
  2099. m_path = new char[len];
  2100. if ( m_path != NULL )
  2101. {
  2102. sprintf_s( m_path, len, "%s\\%s", buffer, m_logFileName );
  2103. len = ARRAY_LEN(buffer) + ARRAY_LEN(STATUS_FILENAME);
  2104. m_status_path = new char[len];
  2105. sprintf_s( m_status_path, len, "%s\\%s", buffer, STATUS_FILENAME );
  2106. }
  2107. }
  2108. buffer[0] = '\0';
  2109. m_includeSystem = FALSE;
  2110. if (GetEnvironmentVariableA(SP_INCLUDE_SYSTEM, buffer, MAX_LENGTH) > 0)
  2111. {
  2112. if(_stricmp("1", buffer) == 0)
  2113. {
  2114. m_includeSystem = TRUE;
  2115. }
  2116. }
  2117. buffer[0] = '\0';
  2118. m_traceEvent = FALSE;
  2119. if (GetEnvironmentVariableA(SP_TRACE_EVENT, buffer, MAX_LENGTH) > 0)
  2120. {
  2121. if(_stricmp("1", buffer) == 0)
  2122. {
  2123. m_traceEvent = TRUE;
  2124. }
  2125. }
  2126. buffer[0] = '\0';
  2127. m_traceParameter = FALSE;
  2128. if (GetEnvironmentVariableA(SP_TRACE_PARAMETER, buffer, MAX_LENGTH) > 0)
  2129. {
  2130. if(_stricmp("1", buffer) == 0)
  2131. {
  2132. m_traceParameter = TRUE;
  2133. }
  2134. }
  2135. if(m_traceEvent == TRUE) {
  2136. m_dwEventMask = (DWORD) COR_PRF_ALL;
  2137. }
  2138. else {
  2139. m_dwEventMask = (DWORD) (
  2140. COR_PRF_MONITOR_CLASS_LOADS |
  2141. COR_PRF_MONITOR_MODULE_LOADS |
  2142. COR_PRF_MONITOR_ENTERLEAVE |
  2143. COR_PRF_ENABLE_FUNCTION_ARGS |
  2144. COR_PRF_ENABLE_FUNCTION_RETVAL |
  2145. COR_PRF_MONITOR_JIT_COMPILATION |
  2146. COR_PRF_DISABLE_OPTIMIZATIONS |
  2147. COR_PRF_DISABLE_INLINING //|
  2148. //COR_PRF_MONITOR_ASSEMBLY_LOADS |
  2149. //COR_PRF_MONITOR_APPDOMAIN_LOADS |
  2150. //COR_PRF_MONITOR_THREADS
  2151. );
  2152. }
  2153. //
  2154. // in which class you are interested in
  2155. //
  2156. buffer[0] = '\0';
  2157. if( GetEnvironmentVariableA( SP_FILTER, buffer, MAX_LENGTH ) > 0)
  2158. {
  2159. //
  2160. // if the env variable does not exist copy to it the null
  2161. // string otherwise copy its value
  2162. //
  2163. //__asm { int 3 }
  2164. const size_t len = ARRAY_LEN(buffer) + 1;
  2165. m_filter = new WCHAR[len];
  2166. if ( m_filter != NULL )
  2167. {
  2168. _snwprintf_s( m_filter, len, len-1, L"%S", buffer );
  2169. m_filterLen = (int) wcslen(m_filter);
  2170. }
  2171. else
  2172. {
  2173. //
  2174. // some error has happened, do not monitor anything
  2175. //
  2176. printf( "Memory Allocation Error in ProfilerCallback .ctor\n" );
  2177. printf( "**** No Profiling Will Take place **** \n" );
  2178. m_dwEventMask = (DWORD) COR_PRF_MONITOR_NONE;
  2179. }
  2180. }
  2181. } // ProfilerCallback::_ProcessEnvVariables
  2182. /* private */
  2183. ULONG ProfilerCallback::GetElementTypeSize( CorElementType elementType )
  2184. {
  2185. ULONG size = 0;
  2186. switch ( elementType )
  2187. {
  2188. case ELEMENT_TYPE_BOOLEAN:
  2189. size = sizeof(bool);
  2190. break;
  2191. case ELEMENT_TYPE_CHAR:
  2192. case ELEMENT_TYPE_I1:
  2193. case ELEMENT_TYPE_U1:
  2194. size = 1;
  2195. break;
  2196. case ELEMENT_TYPE_I2:
  2197. case ELEMENT_TYPE_U2:
  2198. size = 2;
  2199. break;
  2200. case ELEMENT_TYPE_I4:
  2201. case ELEMENT_TYPE_U4:
  2202. size = 4;
  2203. break;
  2204. case ELEMENT_TYPE_I8:
  2205. case ELEMENT_TYPE_U8:
  2206. size = 8;
  2207. break;
  2208. case ELEMENT_TYPE_R4:
  2209. size = 4;
  2210. break;
  2211. case ELEMENT_TYPE_R8:
  2212. size = 8;
  2213. break;
  2214. case ELEMENT_TYPE_STRING:
  2215. size = sizeof(ObjectID);
  2216. break;
  2217. case ELEMENT_TYPE_PTR:
  2218. size = sizeof(INT_PTR);
  2219. break;
  2220. case ELEMENT_TYPE_CLASS:
  2221. size = sizeof(ObjectID);
  2222. break;
  2223. case ELEMENT_TYPE_I:
  2224. size = sizeof(INT_PTR);
  2225. break;
  2226. case ELEMENT_TYPE_U:
  2227. size = sizeof(UINT_PTR);
  2228. break;
  2229. case ELEMENT_TYPE_ARRAY:
  2230. case ELEMENT_TYPE_VALUETYPE:
  2231. case ELEMENT_TYPE_OBJECT:
  2232. case ELEMENT_TYPE_SZARRAY:
  2233. case ELEMENT_TYPE_VOID:
  2234. case ELEMENT_TYPE_FNPTR:
  2235. case ELEMENT_TYPE_MAX:
  2236. case ELEMENT_TYPE_END:
  2237. case ELEMENT_TYPE_BYREF:
  2238. case ELEMENT_TYPE_PINNED:
  2239. case ELEMENT_TYPE_SENTINEL:
  2240. case ELEMENT_TYPE_CMOD_OPT:
  2241. case ELEMENT_TYPE_MODIFIER:
  2242. case ELEMENT_TYPE_CMOD_REQD:
  2243. case ELEMENT_TYPE_TYPEDBYREF:
  2244. default:
  2245. size = -1;
  2246. break;
  2247. }
  2248. return size;
  2249. } // ProfilerCallback::GetElementTypeSize
  2250. /* private */
  2251. HRESULT ProfilerCallback::_GetNameFromElementType( CorElementType elementType, __out_ecount(buflen) WCHAR *buffer, size_t buflen )
  2252. {
  2253. HRESULT hr = S_OK;
  2254. switch ( elementType )
  2255. {
  2256. case ELEMENT_TYPE_BOOLEAN:
  2257. //wcscpy_s( buffer, buflen, L"System.Boolean" );
  2258. wcscpy_s( buffer, buflen, L"bool" );
  2259. break;
  2260. case ELEMENT_TYPE_CHAR:
  2261. //wcscpy_s( buffer, buflen, L"System.Char" );
  2262. wcscpy_s( buffer, buflen, L"char" );
  2263. break;
  2264. case ELEMENT_TYPE_I1:
  2265. //wcscpy_s( buffer, buflen, L"System.SByte" );
  2266. wcscpy_s( buffer, buflen, L"sbyte" );
  2267. break;
  2268. case ELEMENT_TYPE_U1:
  2269. //wcscpy_s( buffer, buflen, L"System.Byte" );
  2270. wcscpy_s( buffer, buflen, L"byte" );
  2271. break;
  2272. case ELEMENT_TYPE_I2:
  2273. //wcscpy_s( buffer, buflen, L"System.Int16" );
  2274. wcscpy_s( buffer, buflen, L"short" );
  2275. break;
  2276. case ELEMENT_TYPE_U2:
  2277. //wcscpy_s( buffer, buflen, L"System.UInt16" );
  2278. wcscpy_s( buffer, buflen, L"ushort" );
  2279. break;
  2280. case ELEMENT_TYPE_I4:
  2281. //wcscpy_s( buffer, buflen, L"System.Int32" );
  2282. wcscpy_s( buffer, buflen, L"int" );
  2283. break;
  2284. case ELEMENT_TYPE_U4:
  2285. //wcscpy_s( buffer, buflen, L"System.UInt32" );
  2286. wcscpy_s( buffer, buflen, L"uint" );
  2287. break;
  2288. case ELEMENT_TYPE_I8:
  2289. //wcscpy_s( buffer, buflen, L"System.Int64" );
  2290. wcscpy_s( buffer, buflen, L"long" );
  2291. break;
  2292. case ELEMENT_TYPE_U8:
  2293. //wcscpy_s( buffer, buflen, L"System.UInt64" );
  2294. wcscpy_s( buffer, buflen, L"ulong" );
  2295. break;
  2296. case ELEMENT_TYPE_R4:
  2297. //wcscpy_s( buffer, buflen, L"System.Single" );
  2298. wcscpy_s( buffer, buflen, L"float" );
  2299. break;
  2300. case ELEMENT_TYPE_R8:
  2301. //wcscpy_s( buffer, buflen, L"System.Double" );
  2302. wcscpy_s( buffer, buflen, L"double" );
  2303. break;
  2304. case ELEMENT_TYPE_STRING:
  2305. //wcscpy_s( buffer, buflen, L"System.String" );
  2306. wcscpy_s( buffer, buflen, L"string" );
  2307. break;
  2308. case ELEMENT_TYPE_PTR:
  2309. //wcscpy_s( buffer, buflen, L"System.IntPtr" );
  2310. wcscpy_s( buffer, buflen, L"IntPtr" );
  2311. break;
  2312. case ELEMENT_TYPE_VALUETYPE:
  2313. wcscpy_s( buffer, buflen, L"struct" );
  2314. break;
  2315. case ELEMENT_TYPE_CLASS:
  2316. wcscpy_s( buffer, buflen, L"class" );
  2317. break;
  2318. case ELEMENT_TYPE_ARRAY:
  2319. //wcscpy_s( buffer, buflen, L"System.Array" );
  2320. wcscpy_s( buffer, buflen, L"Array" );
  2321. break;
  2322. case ELEMENT_TYPE_I:
  2323. wcscpy_s( buffer, buflen, L"INT_PTR" );
  2324. break;
  2325. case ELEMENT_TYPE_U:
  2326. wcscpy_s( buffer, buflen, L"UINT_PTR" );
  2327. break;
  2328. case ELEMENT_TYPE_OBJECT:
  2329. //wcscpy_s( buffer, buflen, L"System.Object" );
  2330. wcscpy_s( buffer, buflen, L"object" );
  2331. break;
  2332. case ELEMENT_TYPE_SZARRAY:
  2333. //wcscpy_s( buffer, buflen, L"System.Array" );
  2334. wcscpy_s( buffer, buflen, L"Array" );
  2335. break;
  2336. case ELEMENT_TYPE_VOID:
  2337. wcscpy_s( buffer, buflen, L"void" );
  2338. break;
  2339. break;
  2340. case ELEMENT_TYPE_FNPTR:
  2341. case ELEMENT_TYPE_MAX:
  2342. case ELEMENT_TYPE_END:
  2343. case ELEMENT_TYPE_BYREF:
  2344. case ELEMENT_TYPE_PINNED:
  2345. case ELEMENT_TYPE_SENTINEL:
  2346. case ELEMENT_TYPE_CMOD_OPT:
  2347. case ELEMENT_TYPE_MODIFIER:
  2348. case ELEMENT_TYPE_CMOD_REQD:
  2349. case ELEMENT_TYPE_TYPEDBYREF:
  2350. default:
  2351. wcscpy_s( buffer, buflen, L"?" );
  2352. break;
  2353. }
  2354. return hr;
  2355. } // ProfilerCallback::_GetNameFromElementType
  2356. CorElementType ProfilerCallback::_GetElementTypeFromClassName(WCHAR *className)
  2357. {
  2358. if(_wcsnicmp(className, L"System.Boolean", ARRAY_LEN(L"System.Boolean") - 1) == 0)
  2359. return ELEMENT_TYPE_BOOLEAN;
  2360. if(_wcsnicmp(className, L"System.Char", ARRAY_LEN(L"System.Char") - 1) == 0)
  2361. return ELEMENT_TYPE_CHAR;
  2362. if(_wcsnicmp(className, L"System.SByte", ARRAY_LEN(L"System.SByte") - 1) == 0)
  2363. return ELEMENT_TYPE_I1;
  2364. if(_wcsnicmp(className, L"System.Byte", ARRAY_LEN(L"System.Byte") - 1) == 0)
  2365. return ELEMENT_TYPE_U1;
  2366. if(_wcsnicmp(className, L"System.Int16", ARRAY_LEN(L"System.Int16") - 1) == 0)
  2367. return ELEMENT_TYPE_I2;
  2368. if(_wcsnicmp(className, L"System.UInt16", ARRAY_LEN(L"System.UInt16") - 1) == 0)
  2369. return ELEMENT_TYPE_U2;
  2370. if(_wcsnicmp(className, L"System.Int32", ARRAY_LEN(L"System.Int32") - 1) == 0)
  2371. return ELEMENT_TYPE_I4;
  2372. if(_wcsnicmp(className, L"System.UInt32", ARRAY_LEN(L"System.UInt32") - 1) == 0)
  2373. return ELEMENT_TYPE_U4;
  2374. if(_wcsnicmp(className, L"System.Int64", ARRAY_LEN(L"System.Int64") - 1) == 0)
  2375. return ELEMENT_TYPE_I8;
  2376. if(_wcsnicmp(className, L"System.UInt64", ARRAY_LEN(L"System.UInt64") - 1) == 0)
  2377. return ELEMENT_TYPE_U8;
  2378. if(_wcsnicmp(className, L"System.Single", ARRAY_LEN(L"System.Single") - 1) == 0)
  2379. return ELEMENT_TYPE_R4;
  2380. if(_wcsnicmp(className, L"System.Double", ARRAY_LEN(L"System.Double") - 1) == 0)
  2381. return ELEMENT_TYPE_I8;
  2382. if(_wcsnicmp(className, L"System.String", ARRAY_LEN(L"System.String") - 1) == 0)
  2383. return ELEMENT_TYPE_STRING;
  2384. if(_wcsnicmp(className, L"System.IntPtr", ARRAY_LEN(L"System.IntPtr") - 1) == 0)
  2385. return ELEMENT_TYPE_PTR;
  2386. return ELEMENT_TYPE_END;
  2387. /*
  2388. case ELEMENT_TYPE_ARRAY;
  2389. case ELEMENT_TYPE_VALUETYPE:
  2390. case ELEMENT_TYPE_CLASS:
  2391. case ELEMENT_TYPE_I:
  2392. case ELEMENT_TYPE_U:
  2393. case ELEMENT_TYPE_OBJECT:
  2394. case ELEMENT_TYPE_SZARRAY:
  2395. case ELEMENT_TYPE_VOID:
  2396. case ELEMENT_TYPE_FNPTR:
  2397. case ELEMENT_TYPE_MAX:
  2398. case ELEMENT_TYPE_END:
  2399. case ELEMENT_TYPE_BYREF:
  2400. case ELEMENT_TYPE_PINNED:
  2401. case ELEMENT_TYPE_SENTINEL:
  2402. case ELEMENT_TYPE_CMOD_OPT:
  2403. case ELEMENT_TYPE_MODIFIER:
  2404. case ELEMENT_TYPE_CMOD_REQD:
  2405. case ELEMENT_TYPE_TYPEDBYREF:
  2406. */
  2407. } // ProfilerCallback::_GetElementTypeFromClassName
  2408. /* public */
  2409. bool ProfilerCallback::LogEnabled()
  2410. {
  2411. if(m_status_path == NULL) return false;
  2412. DWORD sz = GetFileAttributesA(m_status_path);
  2413. return sz != 0xFFFFFFFF;
  2414. }
  2415. void ProfilerCallback::LogToAnyInternal(const char *format, ... )
  2416. {
  2417. if(m_stream == NULL) return;
  2418. ///////////////////////////////////////////////////////////////////////////
  2419. Synchronize guard( m_criticalSection );
  2420. ///////////////////////////////////////////////////////////////////////////
  2421. {
  2422. va_list args;
  2423. va_start( args, format );
  2424. vfprintf( m_stream, format, args );
  2425. }
  2426. }
  2427. void ProfilerCallback::LogToAny( const char *format, ... )
  2428. {
  2429. if(m_stream == NULL) return;
  2430. if(!LogEnabled()) return;
  2431. ///////////////////////////////////////////////////////////////////////////
  2432. Synchronize guard( m_criticalSection );
  2433. ///////////////////////////////////////////////////////////////////////////
  2434. {
  2435. va_list args;
  2436. va_start( args, format );
  2437. vfprintf( m_stream, format, args );
  2438. }
  2439. } // ProfilerCallback::LogToAny
  2440. /* public */
  2441. void ProfilerCallback::_ThreadStubWrapper()
  2442. {
  2443. m_pGCHost = GetGCHost();
  2444. //
  2445. // loop and listen for a ForceGC event
  2446. //
  2447. while( TRUE )
  2448. {
  2449. DWORD dwResult;
  2450. //
  2451. // wait until someone signals an event from the GUI or the profiler
  2452. //
  2453. dwResult = WaitForMultipleObjects( SENTINEL_HANDLE, m_hArray, FALSE, INFINITE );
  2454. if ( dwResult >= WAIT_OBJECT_0 && dwResult < WAIT_OBJECT_0 + SENTINEL_HANDLE)
  2455. {
  2456. ///////////////////////////////////////////////////////////////////////////
  2457. Synchronize guard( g_criticalSection );
  2458. ///////////////////////////////////////////////////////////////////////////
  2459. //
  2460. // reset the event
  2461. //
  2462. ObjHandles type = (ObjHandles)(dwResult - WAIT_OBJECT_0);
  2463. ResetEvent( m_hArray[type] );
  2464. //
  2465. // FALSE: indicates a ForceGC event arriving from the GUI
  2466. // TRUE: indicates that the thread has to terminate
  2467. // in both cases you need to send to the GUI an event to let it know
  2468. // what the deal is
  2469. //
  2470. if ( m_bShutdown == FALSE )
  2471. {
  2472. //
  2473. // what type do you have ?
  2474. //
  2475. switch( type )
  2476. {
  2477. case GC_HANDLE:
  2478. //
  2479. // force the GC and do not worry about the result
  2480. //
  2481. if ( m_pProfilerInfo != NULL )
  2482. {
  2483. // dump the GC info on the next GC
  2484. m_pProfilerInfo->ForceGC();
  2485. }
  2486. break;
  2487. case TRIGGER_GC_HANDLE:
  2488. //
  2489. // force the GC and do not worry about the result
  2490. //
  2491. if ( m_pProfilerInfo != NULL )
  2492. {
  2493. m_pProfilerInfo->ForceGC();
  2494. }
  2495. break;
  2496. case OBJ_HANDLE:
  2497. //
  2498. // you need to update the set event mask, given the previous state
  2499. //
  2500. if ( m_pProfilerInfo != NULL )
  2501. {
  2502. // flush the log file
  2503. fflush(m_stream);
  2504. }
  2505. break;
  2506. case CALL_HANDLE:
  2507. {
  2508. // flush the log file
  2509. fflush(m_stream);
  2510. }
  2511. break;
  2512. default:
  2513. TEXT_OUTLN( !"Valid Option" );
  2514. }
  2515. }
  2516. else
  2517. {
  2518. //
  2519. // Terminate
  2520. //
  2521. break;
  2522. }
  2523. }
  2524. else
  2525. {
  2526. Failure( " WaitForSingleObject TimedOut " );
  2527. break;
  2528. }
  2529. }
  2530. } // ProfilerCallback::_ThreadStubWrapper
  2531. void ProfilerCallback::Failure( const char *message )
  2532. {
  2533. if ( message == NULL )
  2534. message = "\n\n**** SEVERE FAILURE: TURNING OFF APPLICABLE PROFILING EVENTS ****\n\n";
  2535. //
  2536. // Display the error message and discontinue monitoring CLR events, except the
  2537. // IMMUTABLE ones. Turning off the IMMUTABLE events can cause crashes. The only
  2538. // place that we can safely enable or disable immutable events is the Initialize
  2539. // callback.
  2540. //
  2541. LogToAny( message );
  2542. LogToAny("\n");
  2543. m_pProfilerInfo->SetEventMask( (m_dwEventMask & (DWORD)COR_PRF_MONITOR_IMMUTABLE) );
  2544. } // ProfilerCallback::Failure
  2545. /*--------------------------------------------------------------------------------------------------*/
  2546. /* public */
  2547. /* throws BaseException */
  2548. void ProfilerCallback::AddModule( ModuleID moduleID )
  2549. {
  2550. if ( moduleID != NULL )
  2551. {
  2552. ModuleInfo *pModuleInfo;
  2553. pModuleInfo = m_pModuleTable[moduleID];
  2554. if ( pModuleInfo == NULL )
  2555. {
  2556. pModuleInfo = new ModuleInfo( m_pProfilerInfo2, moduleID );
  2557. if ( pModuleInfo != NULL )
  2558. {
  2559. try
  2560. {
  2561. ULONG dummy;
  2562. HRESULT hr = m_pProfilerInfo->GetModuleInfo( moduleID,
  2563. &pModuleInfo->m_loadAddress,
  2564. MAX_LENGTH,
  2565. &dummy,
  2566. pModuleInfo->m_name,
  2567. NULL );
  2568. if(SUCCEEDED(hr))
  2569. m_pModuleTable[moduleID] = pModuleInfo;
  2570. else
  2571. delete pModuleInfo;
  2572. }
  2573. catch(BaseException *exception)
  2574. {
  2575. delete pModuleInfo;
  2576. throw;
  2577. }
  2578. }
  2579. else
  2580. _THROW_EXCEPTION( "Allocation for ModuleInfo Object FAILED" )
  2581. }
  2582. }
  2583. else
  2584. _THROW_EXCEPTION( "ModuleID is NULL" )
  2585. } // ProfilerCallback::AddFunction
  2586. /* public */
  2587. /* throws BaseException */
  2588. void ProfilerCallback::RemoveModule( ModuleID moduleID )
  2589. {
  2590. if ( moduleID != NULL )
  2591. {
  2592. ModuleInfo *pModuleInfo;
  2593. pModuleInfo = m_pModuleTable[moduleID];
  2594. if ( pModuleInfo != NULL ) {
  2595. m_pModuleTable[moduleID] = NULL;
  2596. delete pModuleInfo;
  2597. }
  2598. else
  2599. _THROW_EXCEPTION( "Module was not found in the Module Table" )
  2600. }
  2601. else
  2602. _THROW_EXCEPTION( "ModuleID is NULL" )
  2603. } // ProfilerCallback::RemoveFunction
  2604. /* public */
  2605. /* throws BaseException */
  2606. void ProfilerCallback::AddFunction( FunctionID functionID )
  2607. {
  2608. if ( functionID != NULL )
  2609. {
  2610. FunctionInfo *pFunctionInfo;
  2611. pFunctionInfo = m_pFunctionTable[functionID];
  2612. if ( pFunctionInfo == NULL )
  2613. {
  2614. pFunctionInfo = new FunctionInfo( functionID );
  2615. if ( pFunctionInfo != NULL )
  2616. {
  2617. try
  2618. {
  2619. HRESULT hr = _GetFunctionInfo( &pFunctionInfo );
  2620. if(SUCCEEDED(hr))
  2621. m_pFunctionTable[functionID] = pFunctionInfo;
  2622. else
  2623. delete pFunctionInfo;
  2624. }
  2625. catch(BaseException *exception)
  2626. {
  2627. delete pFunctionInfo;
  2628. throw;
  2629. }
  2630. }
  2631. else
  2632. _THROW_EXCEPTION( "Allocation for FunctionInfo Object FAILED" )
  2633. }
  2634. }
  2635. else
  2636. _THROW_EXCEPTION( "FunctionID is NULL" )
  2637. } // ProfilerCallback::AddFunction
  2638. /* public */
  2639. /* throws BaseException */
  2640. void ProfilerCallback::RemoveFunction( FunctionID functionID )
  2641. {
  2642. if ( functionID != NULL )
  2643. {
  2644. FunctionInfo *pFunctionInfo;
  2645. pFunctionInfo = m_pFunctionTable[functionID];
  2646. if ( pFunctionInfo != NULL ) {
  2647. m_pFunctionTable[functionID] = NULL;
  2648. delete pFunctionInfo;
  2649. }
  2650. else
  2651. _THROW_EXCEPTION( "Function was not found in the Function Table" )
  2652. }
  2653. else
  2654. _THROW_EXCEPTION( "FunctionID is NULL" )
  2655. } // ProfilerCallback::RemoveFunction
  2656. /* public */
  2657. /* throws BaseException */
  2658. void ProfilerCallback::AddClass( ClassID classID )
  2659. {
  2660. if ( classID != NULL )
  2661. {
  2662. ClassInfo *pClassInfo;
  2663. HRESULT hr = S_OK;
  2664. pClassInfo = m_pClassTable[classID];
  2665. if ( pClassInfo == NULL )
  2666. {
  2667. pClassInfo = new ClassInfo( classID );
  2668. if ( pClassInfo != NULL )
  2669. {
  2670. //
  2671. // we have 2 cases
  2672. // case 1: class is an array
  2673. // case 2: class is a real class
  2674. //
  2675. ULONG rank = 0;
  2676. CorElementType elementType;
  2677. ClassID realClassID = NULL;
  2678. WCHAR ranks[MAX_LENGTH];
  2679. bool finalizable = false;
  2680. // case 1
  2681. hr = m_pProfilerInfo->IsArrayClass( classID, &elementType, &realClassID, &rank );
  2682. if ( hr == S_OK )
  2683. {
  2684. ClassID prevClassID;
  2685. ranks[0] = '\0';
  2686. do
  2687. {
  2688. prevClassID = realClassID;
  2689. _snwprintf_s( ranks, ARRAY_LEN(ranks), ARRAY_LEN(ranks)-1, L"%s[]", ranks);
  2690. hr = m_pProfilerInfo->IsArrayClass( prevClassID, &elementType, &realClassID, &rank );
  2691. if ( (hr == S_FALSE) || (FAILED(hr)) || (realClassID == NULL) )
  2692. {
  2693. //
  2694. // before you break set the realClassID to the value that it was before the
  2695. // last unsuccessful call
  2696. //
  2697. realClassID = prevClassID;
  2698. break;
  2699. }
  2700. }
  2701. while ( TRUE );
  2702. if ( SUCCEEDED( hr ) )
  2703. {
  2704. if(SUCCEEDED(GetNameFromClassIDEx(classID, pClassInfo->m_name, pClassInfo->m_moduleID, pClassInfo->m_classToken)))
  2705. {
  2706. m_pClassTable[classID] = pClassInfo;
  2707. m_pClassNameTable[Hash(pClassInfo->m_name)] = pClassInfo;
  2708. //LogToAny("DEBUG1: %S,%p,%p,%S\n", pClassInfo->m_name, classID, m_pClassNameTable[pClassInfo->m_name]->m_id, m_pClassNameTable[pClassInfo->m_name]->m_name);
  2709. }else{
  2710. delete pClassInfo;
  2711. }
  2712. }
  2713. else
  2714. Failure( "ERROR: Looping for Locating the ClassID FAILED" );
  2715. }
  2716. // case 2
  2717. else if ( hr == S_FALSE )
  2718. {
  2719. if(SUCCEEDED(GetNameFromClassIDEx(classID, pClassInfo->m_name, pClassInfo->m_moduleID, pClassInfo->m_classToken)))
  2720. {
  2721. m_pClassTable[classID] = pClassInfo;
  2722. m_pClassNameTable[Hash(pClassInfo->m_name)] = pClassInfo;
  2723. //LogToAny("DEBUG2: %S,%p,%p,%S\n", pClassInfo->m_name, classID, m_pClassNameTable[pClassInfo->m_name]->m_id, m_pClassNameTable[pClassInfo->m_name]->m_name);
  2724. }else{
  2725. delete pClassInfo;
  2726. }
  2727. }
  2728. else
  2729. Failure( "ERROR: ICorProfilerInfo::IsArrayClass() FAILED" );
  2730. }
  2731. else
  2732. Failure( "ERROR: Allocation for ClassInfo FAILED" );
  2733. }//end of pClassInfo == NULL
  2734. }
  2735. else
  2736. _THROW_EXCEPTION( "ClassID is NULL" )
  2737. } // ProfilerCallback::AddFunction
  2738. /* public */
  2739. /* throws BaseException */
  2740. void ProfilerCallback::RemoveClass( ClassID classID )
  2741. {
  2742. if ( classID != NULL )
  2743. {
  2744. ClassInfo *pClassInfo;
  2745. pClassInfo = m_pClassTable[classID];
  2746. if ( pClassInfo != NULL ) {
  2747. m_pClassTable[classID] = NULL;
  2748. m_pClassNameTable[Hash(pClassInfo->m_name)] = NULL;
  2749. delete pClassInfo;
  2750. }
  2751. else
  2752. _THROW_EXCEPTION( "Class was not found in the Class Table" )
  2753. }
  2754. else
  2755. _THROW_EXCEPTION( "ClassID is NULL" )
  2756. } // ProfilerCallback::RemoveFunction
  2757. DECLSPEC
  2758. /* static public */
  2759. HRESULT ProfilerCallback::_GetFunctionInfo( FunctionInfo **ppFunctionInfo )
  2760. {
  2761. HRESULT hr = E_FAIL; // assume success
  2762. FunctionInfo *pFunctionInfo = (*ppFunctionInfo);
  2763. FunctionID functionID = pFunctionInfo->m_id;
  2764. WCHAR *functionName = pFunctionInfo->m_name;
  2765. if ( functionID != NULL )
  2766. {
  2767. mdToken funcToken = mdTypeDefNil;
  2768. IMetaDataImport *pMDImport = NULL;
  2769. WCHAR funName[MAX_LENGTH] = L"UNKNOWN";
  2770. //
  2771. // Get the MetadataImport interface and the metadata token
  2772. //
  2773. hr = m_pProfilerInfo->GetTokenAndMetaDataFromFunction( functionID,
  2774. IID_IMetaDataImport,
  2775. (IUnknown **)&pMDImport,
  2776. &funcToken );
  2777. if ( SUCCEEDED( hr ) )
  2778. {
  2779. mdTypeDef classToken = mdTypeDefNil;
  2780. DWORD methodAttr = 0;
  2781. PCCOR_SIGNATURE sigBlob = NULL;
  2782. ULONG sigBytes;
  2783. hr = pMDImport->GetMethodProps( funcToken,
  2784. &classToken,
  2785. funName,
  2786. MAX_LENGTH,
  2787. 0,
  2788. &methodAttr,
  2789. &sigBlob,
  2790. &sigBytes,
  2791. NULL,
  2792. NULL );
  2793. if ( SUCCEEDED( hr ) )
  2794. {
  2795. // get class id
  2796. WCHAR className[MAX_LENGTH] = L"UNKNOWN";
  2797. ClassID classId = 0;
  2798. if (m_pProfilerInfo2 != NULL)
  2799. {
  2800. hr = m_pProfilerInfo2->GetFunctionInfo2(functionID,
  2801. 0,
  2802. &classId,
  2803. &(pFunctionInfo->m_moduleId),
  2804. &(pFunctionInfo->m_methodDef),
  2805. 0,
  2806. NULL,
  2807. NULL);
  2808. if (!SUCCEEDED(hr))
  2809. classId = 0;
  2810. }
  2811. if (classId == 0)
  2812. {
  2813. hr = m_pProfilerInfo->GetFunctionInfo(functionID,
  2814. &classId,
  2815. &(pFunctionInfo->m_moduleId),
  2816. &(pFunctionInfo->m_methodDef));
  2817. }
  2818. //get class name
  2819. if (SUCCEEDED(hr) && classId != 0)
  2820. {
  2821. hr = GetNameFromClassID(classId, className);
  2822. }
  2823. else if (classToken != mdTypeDefNil)
  2824. {
  2825. ULONG classGenericArgCount = 0;
  2826. hr = GetClassName(pMDImport, classToken, className, NULL, &classGenericArgCount);
  2827. }
  2828. _snwprintf_s( functionName, MAX_LENGTH, MAX_LENGTH-1, L"%s::%s", className, funName );
  2829. //pFunctionInfo->m_moduleId and m_methodDef init after classID inited
  2830. //so all functions use these fields need to put after classID initialization
  2831. // calling convention, argument count and return type
  2832. ULONG callConv = IMAGE_CEE_CS_CALLCONV_MAX;
  2833. sigBlob += CorSigUncompressData(sigBlob, &callConv);
  2834. sigBlob += CorSigUncompressData(sigBlob, &(pFunctionInfo->m_argCount));
  2835. ParameterInfo *pReturn = new ParameterInfo(0);
  2836. pReturn->m_moduleId = pFunctionInfo->m_moduleId;
  2837. pReturn->m_type = g_pCallbackObject->GetType(sigBlob,
  2838. pReturn->m_isByRef,
  2839. pReturn->m_typeDef,
  2840. pReturn->m_isArray);
  2841. hr = g_pCallbackObject->GetTypeName(pReturn->m_typeName, MAX_LENGTH,
  2842. pReturn->m_type,
  2843. pReturn->m_typeDef,
  2844. pMDImport);
  2845. if(SUCCEEDED(hr) && pReturn->m_isArray)
  2846. wcscat_s(pReturn->m_typeName, L"[]");
  2847. pFunctionInfo->m_pReturnInfo = pReturn;
  2848. // get parameters
  2849. if(SUCCEEDED(hr) && m_traceParameter && pFunctionInfo->m_argCount>0) {
  2850. HCORENUM paramEnum = NULL;
  2851. mdParamDef* paramDefs = new mdParamDef[pFunctionInfo->m_argCount];
  2852. ULONG numParams = 0;
  2853. hr = pMDImport->EnumParams(
  2854. &paramEnum,
  2855. pFunctionInfo->m_methodDef,
  2856. paramDefs,
  2857. pFunctionInfo->m_argCount, &numParams);
  2858. if(paramEnum)
  2859. pMDImport->CloseEnum(paramEnum);
  2860. pFunctionInfo->m_ppParamInfo = new ParameterInfo*[pFunctionInfo->m_argCount];
  2861. for(ULONG i = 0;
  2862. sigBlob != NULL && i < pFunctionInfo->m_argCount;
  2863. i++)
  2864. {
  2865. ParameterInfo *pParamInfo = new ParameterInfo(paramDefs[i]);
  2866. pParamInfo->m_moduleId = pFunctionInfo->m_moduleId;
  2867. // get parameter name and attributes (for direction in/out/ref)
  2868. HRESULT hr = pMDImport->GetParamProps(
  2869. paramDefs[i], NULL, NULL,
  2870. pParamInfo->m_name, MAX_LENGTH, NULL,
  2871. &(pParamInfo->m_attributes), NULL, NULL, NULL);
  2872. // get parameter type and type name
  2873. if(SUCCEEDED(hr))
  2874. {
  2875. pParamInfo->m_type = GetType(sigBlob,
  2876. pParamInfo->m_isByRef,
  2877. pParamInfo->m_typeDef,
  2878. pParamInfo->m_isArray);
  2879. hr = GetTypeName(pParamInfo->m_typeName, MAX_LENGTH,
  2880. pParamInfo->m_type,
  2881. pParamInfo->m_typeDef,
  2882. pMDImport);
  2883. if(SUCCEEDED(hr) && pParamInfo->m_isArray)
  2884. wcscat_s(pParamInfo->m_typeName, L"[]");
  2885. }
  2886. pFunctionInfo->m_ppParamInfo[i] = pParamInfo;
  2887. }
  2888. if(paramDefs)
  2889. delete [] paramDefs;
  2890. }
  2891. }
  2892. pMDImport->Release();
  2893. }
  2894. }
  2895. //
  2896. // This corresponds to an unmanaged frame
  2897. //
  2898. else
  2899. {
  2900. hr = S_OK;
  2901. }
  2902. return hr;
  2903. } // ProfilerCallback::GetFunctionProperties
  2904. static void StrAppend(__out_ecount(cchBuffer) char *buffer, const char *str, size_t cchBuffer)
  2905. {
  2906. size_t bufLen = strlen(buffer) + 1;
  2907. if (bufLen <= cchBuffer)
  2908. strncat_s(buffer, cchBuffer, str, cchBuffer-bufLen);
  2909. }
  2910. /* public */
  2911. HRESULT ProfilerCallback::GetNameFromClassID( ClassID classID, WCHAR className[] )
  2912. {
  2913. ModuleID moduleID;
  2914. mdTypeDef classToken;
  2915. return GetNameFromClassIDEx(classID, className, moduleID, classToken);
  2916. }
  2917. /* public */
  2918. HRESULT ProfilerCallback::GetNameFromClassIDEx( ClassID classID, WCHAR className[], ModuleID &moduleID, mdTypeDef &classToken )
  2919. {
  2920. HRESULT hr = E_FAIL;
  2921. if ( m_pProfilerInfo != NULL )
  2922. {
  2923. hr = m_pProfilerInfo->GetClassIDInfo( classID,
  2924. &moduleID,
  2925. &classToken );
  2926. if ( SUCCEEDED( hr ) )
  2927. {
  2928. IMetaDataImport *pMDImport = NULL;
  2929. hr = m_pProfilerInfo->GetModuleMetaData( moduleID,
  2930. (ofRead | ofWrite),
  2931. IID_IMetaDataImport,
  2932. (IUnknown **)&pMDImport );
  2933. if ( SUCCEEDED( hr ) )
  2934. {
  2935. if ( classToken != mdTypeDefNil )
  2936. {
  2937. ClassID *classTypeArgs = NULL;
  2938. ULONG32 classTypeArgCount = 0;
  2939. #ifdef mdGenericPar
  2940. if (m_pProfilerInfo2 != NULL)
  2941. {
  2942. hr = m_pProfilerInfo2->GetClassIDInfo2(classID,
  2943. NULL,
  2944. NULL,
  2945. NULL,
  2946. 0,
  2947. &classTypeArgCount,
  2948. NULL);
  2949. if (SUCCEEDED(hr) && classTypeArgCount > 0)
  2950. {
  2951. classTypeArgs = (ClassID *)_alloca(classTypeArgCount*sizeof(classTypeArgs[0]));
  2952. hr = m_pProfilerInfo2->GetClassIDInfo2(classID,
  2953. NULL,
  2954. NULL,
  2955. NULL,
  2956. classTypeArgCount,
  2957. &classTypeArgCount,
  2958. classTypeArgs);
  2959. }
  2960. if (!SUCCEEDED(hr))
  2961. classTypeArgs = NULL;
  2962. }
  2963. #endif // mdGenericPar
  2964. DWORD dwTypeDefFlags = 0;
  2965. ULONG genericArgCount = 0;
  2966. hr = GetClassName(pMDImport, classToken, className, classTypeArgs, &genericArgCount);
  2967. if ( FAILED( hr ) )
  2968. Failure( "_GetClassNameHelper() FAILED" );
  2969. }
  2970. else
  2971. Failure( ("The class token is mdTypeDefNil, class does NOT have MetaData info") );
  2972. pMDImport->Release ();
  2973. }
  2974. else
  2975. {
  2976. // Failure( "IProfilerInfo::GetModuleMetaData() => IMetaDataImport FAILED" );
  2977. wcscpy_s(className, MAX_LENGTH, L"???");
  2978. hr = S_OK;
  2979. }
  2980. }
  2981. else
  2982. Failure( "ICorProfilerInfo::GetClassIDInfo() FAILED" );
  2983. }
  2984. else
  2985. Failure( "ICorProfilerInfo Interface has NOT been Initialized" );
  2986. return hr;
  2987. } // ProfilerCallback::GetNameFromClassIDEx
  2988. DECLSPEC
  2989. /* static public */
  2990. HRESULT ProfilerCallback::GetClassName(IMetaDataImport *pMDImport, mdToken classToken, WCHAR className[], ClassID *classTypeArgs, ULONG *totalGenericArgCount)
  2991. {
  2992. DWORD dwTypeDefFlags = 0;
  2993. HRESULT hr = S_OK;
  2994. hr = pMDImport->GetTypeDefProps( classToken,
  2995. className,
  2996. MAX_LENGTH,
  2997. NULL,
  2998. &dwTypeDefFlags,
  2999. NULL );
  3000. if ( FAILED( hr ) )
  3001. {
  3002. return hr;
  3003. }
  3004. *totalGenericArgCount = 0;
  3005. if (IsTdNested(dwTypeDefFlags))
  3006. {
  3007. // printf("%S is a nested class\n", className);
  3008. mdToken enclosingClass = mdTokenNil;
  3009. hr = pMDImport->GetNestedClassProps(classToken, &enclosingClass);
  3010. if ( FAILED( hr ) )
  3011. {
  3012. return hr;
  3013. }
  3014. // printf("Enclosing class for %S is %d\n", className, enclosingClass);
  3015. hr = GetClassName(pMDImport, enclosingClass, className, classTypeArgs, totalGenericArgCount);
  3016. // printf("Enclosing class name %S\n", className);
  3017. if (FAILED(hr))
  3018. return hr;
  3019. size_t length = wcslen(className);
  3020. if (length + 2 < MAX_LENGTH)
  3021. {
  3022. className[length++] = '.';
  3023. hr = pMDImport->GetTypeDefProps( classToken,
  3024. className + length,
  3025. (ULONG)(MAX_LENGTH - length),
  3026. NULL,
  3027. NULL,
  3028. NULL );
  3029. if ( FAILED( hr ) )
  3030. {
  3031. return hr;
  3032. }
  3033. // printf("%S is a nested class\n", className);
  3034. }
  3035. }
  3036. WCHAR *backTick = wcschr(className, L'`');
  3037. if (backTick != NULL)
  3038. {
  3039. *backTick = L'\0';
  3040. ULONG genericArgCount = wcstoul(backTick+1, NULL, 10);
  3041. if (genericArgCount >0)
  3042. {
  3043. char typeArgText[MAX_LENGTH];
  3044. typeArgText[0] = '\0';
  3045. StrAppend(typeArgText, "<", MAX_LENGTH);
  3046. for (ULONG i = *totalGenericArgCount; i < *totalGenericArgCount + genericArgCount; i++)
  3047. {
  3048. if (i != *totalGenericArgCount)
  3049. StrAppend(typeArgText, ",", MAX_LENGTH);
  3050. AppendTypeArgName(i, classTypeArgs, NULL, FALSE, typeArgText, MAX_LENGTH);
  3051. }
  3052. StrAppend(typeArgText, ">", MAX_LENGTH);
  3053. *totalGenericArgCount += genericArgCount;
  3054. _snwprintf_s(className, MAX_LENGTH, MAX_LENGTH-1, L"%s%S", className, typeArgText);
  3055. }
  3056. }
  3057. return hr;
  3058. }
  3059. void ProfilerCallback::AppendTypeArgName(ULONG argIndex, ClassID *actualClassTypeArgs, ClassID *actualMethodTypeArgs, BOOL methodFormalArg, __out_ecount(cchBuffer) char *buffer, size_t cchBuffer)
  3060. {
  3061. char argName[MAX_LENGTH];
  3062. argName[0] = '\0';
  3063. ClassID classId = 0;
  3064. if (methodFormalArg && actualMethodTypeArgs != NULL)
  3065. classId = actualMethodTypeArgs[argIndex];
  3066. if (!methodFormalArg && actualClassTypeArgs != NULL)
  3067. classId = actualClassTypeArgs[argIndex];
  3068. if (classId != 0)
  3069. {
  3070. WCHAR className[MAX_LENGTH];
  3071. HRESULT hr = GetNameFromClassID(classId, className);
  3072. if (SUCCEEDED(hr))
  3073. _snprintf_s( argName, ARRAY_LEN(argName), ARRAY_LEN(argName)-1, "%S", className);
  3074. }
  3075. if (argName[0] == '\0')
  3076. {
  3077. char argStart = methodFormalArg ? 'M' : 'T';
  3078. if (argIndex <= 6)
  3079. {
  3080. // the first 7 parameters are printed as M, N, O, P, Q, R, S
  3081. // or as T, U, V, W, X, Y, Z
  3082. sprintf_s( argName, ARRAY_LEN(argName), "%c", argIndex + argStart);
  3083. }
  3084. else
  3085. {
  3086. // everything after that as M7, M8, ... or T7, T8, ...
  3087. sprintf_s( argName, ARRAY_LEN(argName), "%c%u", argStart, argIndex);
  3088. }
  3089. }
  3090. StrAppend( buffer, argName, cchBuffer);
  3091. }
  3092. long ProfilerCallback::Hash(PWCHAR str)
  3093. {
  3094. const char *locName = "English_America";
  3095. locale loc ( locName, LC_ALL );
  3096. size_t len = wcslen(str);
  3097. long r = use_facet< collate<wchar_t> > ( loc ).
  3098. hash (str, &str[len-1 ]);
  3099. return r;
  3100. }
  3101. /***************************************************************************************
  3102. ******************** ********************
  3103. ******************** DllMain/ClassFactory ********************
  3104. ******************** ********************
  3105. ***************************************************************************************/
  3106. #include "dllmain.hpp"
  3107. // End of File