PageRenderTime 174ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/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

Large files files are truncated, but you can click here to view the full file

  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. //////////////////////////////////////////////////////////…

Large files files are truncated, but you can click here to view the full file