From a526e7d5fbae3aacf2ff7c8b8a5270a867e34958 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 17 Oct 2010 08:02:26 +0200 Subject: [PATCH] splitting profiler source: moved rewriting part to new file --- src/AddIns/Analysis/Profiler/Hook/Hook.vcproj | 2 + .../Analysis/Profiler/Hook/Hook.vcxproj | 1 + .../Profiler/Hook/Profiler.Rewriting.cpp | 411 ++++++++++++++++++ .../Analysis/Profiler/Hook/Profiler.cpp | 395 ----------------- 4 files changed, 414 insertions(+), 395 deletions(-) create mode 100644 src/AddIns/Analysis/Profiler/Hook/Profiler.Rewriting.cpp diff --git a/src/AddIns/Analysis/Profiler/Hook/Hook.vcproj b/src/AddIns/Analysis/Profiler/Hook/Hook.vcproj index c2aa01f645..94b5a711b9 100644 --- a/src/AddIns/Analysis/Profiler/Hook/Hook.vcproj +++ b/src/AddIns/Analysis/Profiler/Hook/Hook.vcproj @@ -291,6 +291,8 @@ RelativePath="main.cpp"> + + \ No newline at end of file diff --git a/src/AddIns/Analysis/Profiler/Hook/Profiler.Rewriting.cpp b/src/AddIns/Analysis/Profiler/Hook/Profiler.Rewriting.cpp new file mode 100644 index 0000000000..5fe3745760 --- /dev/null +++ b/src/AddIns/Analysis/Profiler/Hook/Profiler.Rewriting.cpp @@ -0,0 +1,411 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +#include "main.h" +#include "global.h" +#include "Profiler.h" +#include "windows.h" +#include "CircularBuffer.h" +#include "allocator.h" +#include "FunctionInfo.h" +#include "LightweightList.h" +#include "Callback.h" +#include + +const ULONG FAT_HEADER_SIZE = 0xC; /* 12 bytes = WORD + WORD + DWORD + DWORD */ +const ULONG TINY_HEADER_SIZE = 0x1; /* 1 byte */ +const ULONG MAX_CODE_SIZE_TINY = 0x40; /* 64 bytes */ +const WORD DEFAULT_MAX_STACK = 0x8; /* default stack depth in slots */ + +void CProfiler::Rewrite(FunctionID functionID, int type, int nameId) { + ModuleID moduleID; + mdToken token; + HRESULT hr = S_OK; + + hr = pICorProfilerInfo2->GetFunctionInfo(functionID, 0, &moduleID, &token); + + if (!SUCCEEDED(hr)) + return; + + LPCBYTE header; + ULONG length; + + hr = pICorProfilerInfo2->GetILFunctionBody(moduleID, token, &header, &length); + + if (!SUCCEEDED(hr)) + return; + + IMethodMalloc *allocator = nullptr; + + hr = pICorProfilerInfo2->GetILFunctionBodyAllocator(moduleID, &allocator); + + if (!SUCCEEDED(hr) || allocator == nullptr) + return; + + methodMapCriticalSection.Enter(); + TMethodTokenMap::iterator it = this->methodMap.find(moduleID); + + mdMethodDef deactivateCall = nullptr; + mdMethodDef activateCall = nullptr; + mdMethodDef loggerCall = nullptr; + + if (it != this->methodMap.end()) { + deactivateCall = it->second.deactivator; + activateCall = it->second.activator; + loggerCall = it->second.logger; + } + + methodMapCriticalSection.Leave(); + + if (deactivateCall == nullptr || activateCall == nullptr || loggerCall == nullptr) + return; + + IMetaDataImport *metaData = nullptr; + hr = pICorProfilerInfo->GetModuleMetaData(moduleID, ofRead, IID_IMetaDataImport, (LPUNKNOWN *) &metaData); + + if (!SUCCEEDED(hr) || metaData == nullptr) + return; + + byte *codeBuf = 0; + + codeBuf = (byte *)allocator->Alloc(length + 128); + allocator->Release(); + + if (codeBuf == nullptr) + return; + + int newLength = 0; + + unsigned char newCode[64] = { 0 }; + + int injectionLen = SetInjectionCode(metaData, newCode, &newLength, activateCall, loggerCall, deactivateCall, type, nameId); + + assert(injectionLen == newLength); + + DebugWriteLine(L"rewrite size %d", injectionLen); + + if (((COR_ILMETHOD_TINY *)header)->IsTiny()) { + COR_ILMETHOD_TINY *method = (COR_ILMETHOD_TINY *)header; + + if (method->GetCodeSize() + injectionLen < MAX_CODE_SIZE_TINY) { + DebugWriteLine(L"rewrite normal"); + // Copy the header elements. + memcpy(&codeBuf[0], method, TINY_HEADER_SIZE); + newLength = TINY_HEADER_SIZE; + + // copy new code + memcpy(&codeBuf[newLength], + &newCode[0], + injectionLen); + + newLength += injectionLen; + + // copy old code + memcpy(&codeBuf[newLength], + &header[TINY_HEADER_SIZE], + length - TINY_HEADER_SIZE); + + newLength += (length - TINY_HEADER_SIZE); + + // update code size in header + // LLLLLLUU + // 2 upper bits are the tiny header 6 lower bits are length + codeBuf[0] = (byte)((newLength - 1) << 2 | 0x2); + } else { + DebugWriteLine(L"rewrite convert"); + ConvertToFat((byte *)codeBuf, &newLength); + + // copy new code + memcpy(&codeBuf[newLength], + &newCode[0], + injectionLen); + + newLength += injectionLen; + + // copy old code + memcpy(&codeBuf[newLength], &header[TINY_HEADER_SIZE], length - TINY_HEADER_SIZE); + newLength += (length - TINY_HEADER_SIZE); + + COR_ILMETHOD_FAT *target = (COR_ILMETHOD_FAT *)codeBuf; + target->CodeSize = newLength - FAT_HEADER_SIZE; + } + } else if (((COR_ILMETHOD_FAT *)header)->IsFat()) { + DebugWriteLine(L"rewrite fat"); + COR_ILMETHOD_FAT *method = (COR_ILMETHOD_FAT *)header; + COR_ILMETHOD_FAT *target = (COR_ILMETHOD_FAT *)codeBuf; + + // Copy the header elements. + newLength = FAT_HEADER_SIZE; + memcpy(&codeBuf[0], method, newLength); + + // copy new code + memcpy(&codeBuf[newLength], + &newCode[0], + injectionLen); + + newLength += injectionLen; + + // Copy the remainder of the method body. + memcpy(&codeBuf[newLength], &header[FAT_HEADER_SIZE], length - FAT_HEADER_SIZE); + newLength += (length - FAT_HEADER_SIZE); + + // Reset the size of the code in the header itself. + target->CodeSize = newLength - FAT_HEADER_SIZE; + + // Increase MaxStack to allow our injection code to run. + target->MaxStack = (method->MaxStack > 8) ? method->MaxStack : 8; + + // Fix SEH sections + FixSEHSections(target->GetSect(), injectionLen); + } else { + DebugWriteLine(L"neither fat nor tiny ... invalid header???"); + } + + if (codeBuf != nullptr && newLength > 0) { + hr = pICorProfilerInfo2->SetILFunctionBody(moduleID, token, codeBuf); + } +} + +int CProfiler::SetInjectionCode(IMetaDataImport *metaData, byte *buffer, int *size, + mdMethodDef activateCall, mdMethodDef loggerCall, mdMethodDef deactivateCall, + int type, int nameId) { + HRESULT hr = S_OK; + + int start = *size; + + buffer[(*size)++] = 0x28; //call + *(mdMethodDef*)(&buffer[*size]) = deactivateCall; + *size += sizeof(deactivateCall); + + buffer[(*size)++] = 0x20; //ldc.i4 + *(int*)(&buffer[*size]) = type; + *size += sizeof(type); + buffer[(*size)++] = 0x20; //ldc.i4 + *(int*)(&buffer[*size]) = nameId; + *size += sizeof(nameId); + + mdTypeDef controlType = 0; + mdMethodDef getNameToken = 0; + mdMethodDef getTextToken = 0; + + switch (type) { + case 1: // Console + buffer[(*size)++] = 0x14; //ldnull + buffer[(*size)++] = 0x14; //ldnull + break; + case 2: // Windows Forms + buffer[(*size)++] = 0x14; //ldnull + buffer[(*size)++] = 0x14; //ldnull + break; + /* + hr = metaData->FindTypeDefByName(L"System.Windows.Forms.Control", nullptr, &controlType); + + if (!SUCCEEDED(hr) || controlType == 0) { + DebugWriteLine(L"FindTypeDefByName failed"); + buffer[(*size)++] = 0x14; //ldnull + buffer[(*size)++] = 0x14; //ldnull + break; + } + + hr = metaData->FindMethod(controlType, L"get_Name", getNameSig, sizeof(getNameSig), &getNameToken); + + if (!SUCCEEDED(hr) || getNameToken == 0) { + DebugWriteLine(L"FindMethod failed"); + buffer[(*size)++] = 0x14; //ldnull + buffer[(*size)++] = 0x14; //ldnull + break; + } + + hr = metaData->FindMethod(controlType, L"get_Text", getNameSig, sizeof(getNameSig), &getTextToken); + + if (!SUCCEEDED(hr) || getTextToken == 0) { + DebugWriteLine(L"FindMethod failed"); + buffer[(*size)++] = 0x14; //ldnull + buffer[(*size)++] = 0x14; //ldnull + break; + } + + buffer[(*size)++] = 0x02; //ldarg.0 + buffer[(*size)++] = 0x28; //call + *(mdMethodDef*)(&buffer[*size]) = getNameToken; + *size += sizeof(getNameToken); + + buffer[(*size)++] = 0x02; //ldarg.0 + buffer[(*size)++] = 0x6F; //callvirt + *(mdMethodDef*)(&buffer[*size]) = getTextToken; + *size += sizeof(getTextToken); + break;*/ + case 3: // WPF + buffer[(*size)++] = 0x14; //ldnull + buffer[(*size)++] = 0x14; //ldnull + break; + } + + buffer[(*size)++] = 0x28; //call + *(mdMethodDef*)(&buffer[*size]) = loggerCall; + *size += sizeof(loggerCall); + + buffer[(*size)++] = 0x28; //call + *(mdMethodDef*)(&buffer[*size]) = activateCall; + *size += sizeof(activateCall); + + return *size - start; +} + +void CProfiler::ConvertToFat(byte *target, int *size) { + COR_ILMETHOD_FAT *targetTable = (COR_ILMETHOD_FAT *)target; + memset(targetTable, 0, FAT_HEADER_SIZE); + targetTable->Flags = CorILMethod_FatFormat; + targetTable->Size = FAT_HEADER_SIZE / sizeof(DWORD); + targetTable->MaxStack = DEFAULT_MAX_STACK; + *size = FAT_HEADER_SIZE; +} + +/// +/// Moves all offsets in SEH section tables by the given count of bytes. +/// +void CProfiler::FixSEHSections(const COR_ILMETHOD_SECT *sections, int offset) { + while (sections) { + if (sections->Kind() == CorILMethod_Sect_EHTable) { + COR_ILMETHOD_SECT_EH *peh = (COR_ILMETHOD_SECT_EH *) sections; + if (peh->IsFat()) { + COR_ILMETHOD_SECT_EH_FAT *pFat = (COR_ILMETHOD_SECT_EH_FAT*) peh; + + for (unsigned int i = 0; i < peh->EHCount(); i++) { + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT *pfeh = &pFat->Clauses[i]; + + if (pfeh->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) + pfeh->FilterOffset += offset; + + pfeh->HandlerOffset += offset; + pfeh->TryOffset += offset; + } + } else { + COR_ILMETHOD_SECT_EH_SMALL *pSmall = (COR_ILMETHOD_SECT_EH_SMALL *) peh; + + for (unsigned int i = 0; i < peh->EHCount(); i++) { + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL *pseh = &pSmall->Clauses[i]; + + if (pseh->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) + pseh->FilterOffset += offset; + + pseh->TryOffset += offset; + pseh->HandlerOffset += offset; + } + } + } + sections = sections->Next(); + } +} + +bool CProfiler::CreateMethod(IMetaDataEmit *emitter, const WCHAR *name, PCCOR_SIGNATURE sig, mdMethodDef *methodDefinition, mdToken moduleRef) { + HRESULT hr = emitter->DefineMethod(mdTokenNil, name, mdPublic | mdStatic | mdPinvokeImpl, sig, sizeof(sig), 0, miIL | miManaged, methodDefinition); + + if (!SUCCEEDED(hr)) + return false; + + hr = emitter->DefinePinvokeMap(*methodDefinition, pmNoMangle | pmCallConvStdcall, name, moduleRef); + + if (!SUCCEEDED(hr)) + return false; + + return true; +} + +STDMETHODIMP CProfiler::ModuleLoadFinished(ModuleID moduleID, HRESULT /*hrStatus*/) { + HRESULT hr = S_OK; + + IMetaDataEmit *pIMetaDataEmit = nullptr; + IMetaDataAssemblyImport *asmMetaData = nullptr; + + hr = pICorProfilerInfo->GetModuleMetaData(moduleID, ofRead | ofWrite, IID_IMetaDataEmit, (LPUNKNOWN *) &pIMetaDataEmit); + + if (!SUCCEEDED(hr) || pIMetaDataEmit == nullptr) + goto CLEANUP; + + hr = pICorProfilerInfo->GetModuleMetaData(moduleID, ofRead | ofWrite, IID_IMetaDataAssemblyImport, (LPUNKNOWN *) &asmMetaData); + + if (!SUCCEEDED(hr) || asmMetaData == nullptr) + goto CLEANUP; + + mdToken moduleRef; + hr = pIMetaDataEmit->DefineModuleRef(HOOK_MODULE_NAME, &moduleRef); + + if (!SUCCEEDED(hr)) + goto CLEANUP; + + mdMethodDef deactivator; + if (!CreateMethod(pIMetaDataEmit, L"DeactivateProfiler", rgSig, &deactivator, moduleRef)) + goto CLEANUP; + + mdMethodDef activator; + if (!CreateMethod(pIMetaDataEmit, L"ActivateProfiler", rgSig, &activator, moduleRef)) + goto CLEANUP; + + mdMethodDef logger; + hr = pIMetaDataEmit->DefineMethod(mdTokenNil, L"LogEvent", mdPublic | mdStatic | mdPinvokeImpl, loggerSig, sizeof(loggerSig), 0, miIL | miManaged, &logger); + + if (!SUCCEEDED(hr)) + goto CLEANUP; + + hr = pIMetaDataEmit->DefinePinvokeMap(logger, pmNoMangle | pmCallConvStdcall | pmCharSetUnicode, L"LogEvent", moduleRef); + + if (!SUCCEEDED(hr)) + goto CLEANUP; + + { + methodMapCriticalSection.Enter(); + TMethodTokenMap::iterator it = this->methodMap.find(moduleID); + if (it == this->methodMap.end()) { + this->methodMap.insert(TMethodTokenPair(moduleID, HandlerInfo(activator, deactivator, logger))); + } + methodMapCriticalSection.Leave(); + } + +CLEANUP: + #ifdef DEBUG + if (!SUCCEEDED(hr)) { + MessageBox(nullptr, TEXT("Crashed in ModuleLoadFinished"), TEXT("Crash!"), MB_OK); + __debugbreak(); + } + #endif + + if (pIMetaDataEmit != nullptr) + pIMetaDataEmit->Release(); + + if (asmMetaData != nullptr) + asmMetaData->Release(); + + return S_OK; +} + +STDMETHODIMP CProfiler::JITCompilationStarted(FunctionID functionID, BOOL /*fIsSafeToBlock*/) { + WCHAR *name; + int nameId = (int)MapFunction(functionID, (const WCHAR **)(&name)); + + if (name == nullptr) + return S_OK; + + for (int i = 0; i < CONSOLE_GROUP_LENGTH; i++) { + if (wcsstr(consoleGroupList[i], name) != nullptr) { + DebugWriteLine(L"Rewriting %s", name); + Rewrite(functionID, 0x1, nameId); + } + } + + for (int i = 0; i < WINFORMS_GROUP_LENGTH; i++) { + if (wcsstr(winFormsGroupList[i], name) != nullptr) { + DebugWriteLine(L"Rewriting %s", name); + Rewrite(functionID, 0x2, nameId); + } + } + + for (int i = 0; i < WPF_GROUP_LENGTH; i++) { + if (wcsstr(wpfGroupList[i], name) != nullptr) { + DebugWriteLine(L"Rewriting %s", name); + Rewrite(functionID, 0x3, nameId); + } + } + + return S_OK; +} \ No newline at end of file diff --git a/src/AddIns/Analysis/Profiler/Hook/Profiler.cpp b/src/AddIns/Analysis/Profiler/Hook/Profiler.cpp index abc189e0d4..88cf77d3ce 100644 --- a/src/AddIns/Analysis/Profiler/Hook/Profiler.cpp +++ b/src/AddIns/Analysis/Profiler/Hook/Profiler.cpp @@ -495,37 +495,6 @@ STDMETHODIMP CProfiler::ExceptionUnwindFunctionLeave() { return S_OK; } -STDMETHODIMP CProfiler::JITCompilationStarted(FunctionID functionID, BOOL /*fIsSafeToBlock*/) { - WCHAR *name; - int nameId = (int)MapFunction(functionID, (const WCHAR **)(&name)); - - if (name == nullptr) - return S_OK; - - for (int i = 0; i < CONSOLE_GROUP_LENGTH; i++) { - if (wcsstr(consoleGroupList[i], name) != nullptr) { - DebugWriteLine(L"Rewriting %s", name); - Rewrite(functionID, 0x1, nameId); - } - } - - for (int i = 0; i < WINFORMS_GROUP_LENGTH; i++) { - if (wcsstr(winFormsGroupList[i], name) != nullptr) { - DebugWriteLine(L"Rewriting %s", name); - Rewrite(functionID, 0x2, nameId); - } - } - - for (int i = 0; i < WPF_GROUP_LENGTH; i++) { - if (wcsstr(wpfGroupList[i], name) != nullptr) { - DebugWriteLine(L"Rewriting %s", name); - Rewrite(functionID, 0x3, nameId); - } - } - - return S_OK; -} - void CProfiler::Activate() { ThreadLocalData *data = getThreadLocalData(); data->active = true; @@ -534,368 +503,4 @@ void CProfiler::Activate() { void CProfiler::Deactivate() { ThreadLocalData *data = getThreadLocalData(); data->active = false; -} - -const ULONG FAT_HEADER_SIZE = 0xC; /* 12 bytes = WORD + WORD + DWORD + DWORD */ -const ULONG TINY_HEADER_SIZE = 0x1; /* 1 byte */ -const ULONG MAX_CODE_SIZE_TINY = 0x40; /* 64 bytes */ -const WORD DEFAULT_MAX_STACK = 0x8; /* default stack depth in slots */ - -void CProfiler::Rewrite(FunctionID functionID, int type, int nameId) { - ModuleID moduleID; - mdToken token; - HRESULT hr = S_OK; - - hr = pICorProfilerInfo2->GetFunctionInfo(functionID, 0, &moduleID, &token); - - if (!SUCCEEDED(hr)) - return; - - LPCBYTE header; - ULONG length; - - hr = pICorProfilerInfo2->GetILFunctionBody(moduleID, token, &header, &length); - - if (!SUCCEEDED(hr)) - return; - - IMethodMalloc *allocator = nullptr; - - hr = pICorProfilerInfo2->GetILFunctionBodyAllocator(moduleID, &allocator); - - if (!SUCCEEDED(hr) || allocator == nullptr) - return; - - methodMapCriticalSection.Enter(); - TMethodTokenMap::iterator it = this->methodMap.find(moduleID); - - mdMethodDef deactivateCall = nullptr; - mdMethodDef activateCall = nullptr; - mdMethodDef loggerCall = nullptr; - - if (it != this->methodMap.end()) { - deactivateCall = it->second.deactivator; - activateCall = it->second.activator; - loggerCall = it->second.logger; - } - - methodMapCriticalSection.Leave(); - - if (deactivateCall == nullptr || activateCall == nullptr || loggerCall == nullptr) - return; - - IMetaDataImport *metaData = nullptr; - hr = pICorProfilerInfo->GetModuleMetaData(moduleID, ofRead, IID_IMetaDataImport, (LPUNKNOWN *) &metaData); - - if (!SUCCEEDED(hr) || metaData == nullptr) - return; - - byte *codeBuf = 0; - - codeBuf = (byte *)allocator->Alloc(length + 128); - allocator->Release(); - - if (codeBuf == nullptr) - return; - - int newLength = 0; - - unsigned char newCode[64] = { 0 }; - - int injectionLen = SetInjectionCode(metaData, newCode, &newLength, activateCall, loggerCall, deactivateCall, type, nameId); - - assert(injectionLen == newLength); - - DebugWriteLine(L"rewrite size %d", injectionLen); - - if (((COR_ILMETHOD_TINY *)header)->IsTiny()) { - COR_ILMETHOD_TINY *method = (COR_ILMETHOD_TINY *)header; - - if (method->GetCodeSize() + injectionLen < MAX_CODE_SIZE_TINY) { - DebugWriteLine(L"rewrite normal"); - // Copy the header elements. - memcpy(&codeBuf[0], method, TINY_HEADER_SIZE); - newLength = TINY_HEADER_SIZE; - - // copy new code - memcpy(&codeBuf[newLength], - &newCode[0], - injectionLen); - - newLength += injectionLen; - - // copy old code - memcpy(&codeBuf[newLength], - &header[TINY_HEADER_SIZE], - length - TINY_HEADER_SIZE); - - newLength += (length - TINY_HEADER_SIZE); - - // update code size in header - // LLLLLLUU - // 2 upper bits are the tiny header 6 lower bits are length - codeBuf[0] = (byte)((newLength - 1) << 2 | 0x2); - } else { - DebugWriteLine(L"rewrite convert"); - ConvertToFat((byte *)codeBuf, &newLength); - - // copy new code - memcpy(&codeBuf[newLength], - &newCode[0], - injectionLen); - - newLength += injectionLen; - - // copy old code - memcpy(&codeBuf[newLength], &header[TINY_HEADER_SIZE], length - TINY_HEADER_SIZE); - newLength += (length - TINY_HEADER_SIZE); - - COR_ILMETHOD_FAT *target = (COR_ILMETHOD_FAT *)codeBuf; - target->CodeSize = newLength - FAT_HEADER_SIZE; - } - } else if (((COR_ILMETHOD_FAT *)header)->IsFat()) { - DebugWriteLine(L"rewrite fat"); - COR_ILMETHOD_FAT *method = (COR_ILMETHOD_FAT *)header; - COR_ILMETHOD_FAT *target = (COR_ILMETHOD_FAT *)codeBuf; - - // Copy the header elements. - newLength = FAT_HEADER_SIZE; - memcpy(&codeBuf[0], method, newLength); - - // copy new code - memcpy(&codeBuf[newLength], - &newCode[0], - injectionLen); - - newLength += injectionLen; - - // Copy the remainder of the method body. - memcpy(&codeBuf[newLength], &header[FAT_HEADER_SIZE], length - FAT_HEADER_SIZE); - newLength += (length - FAT_HEADER_SIZE); - - // Reset the size of the code in the header itself. - target->CodeSize = newLength - FAT_HEADER_SIZE; - - // Increase MaxStack to allow our injection code to run. - target->MaxStack = (method->MaxStack > 8) ? method->MaxStack : 8; - - // Fix SEH sections - FixSEHSections(target->GetSect(), injectionLen); - } else { - DebugWriteLine(L"neither fat nor tiny ... invalid header???"); - } - - if (codeBuf != nullptr && newLength > 0) { - hr = pICorProfilerInfo2->SetILFunctionBody(moduleID, token, codeBuf); - } -} - -int CProfiler::SetInjectionCode(IMetaDataImport *metaData, byte *buffer, int *size, - mdMethodDef activateCall, mdMethodDef loggerCall, mdMethodDef deactivateCall, - int type, int nameId) { - HRESULT hr = S_OK; - - int start = *size; - - buffer[(*size)++] = 0x28; //call - *(mdMethodDef*)(&buffer[*size]) = deactivateCall; - *size += sizeof(deactivateCall); - - buffer[(*size)++] = 0x20; //ldc.i4 - *(int*)(&buffer[*size]) = type; - *size += sizeof(type); - buffer[(*size)++] = 0x20; //ldc.i4 - *(int*)(&buffer[*size]) = nameId; - *size += sizeof(nameId); - - mdTypeDef controlType = 0; - mdMethodDef getNameToken = 0; - mdMethodDef getTextToken = 0; - - switch (type) { - case 1: // Console - buffer[(*size)++] = 0x14; //ldnull - buffer[(*size)++] = 0x14; //ldnull - break; - case 2: // Windows Forms - hr = metaData->FindTypeDefByName(L"System.Windows.Forms.Control", nullptr, &controlType); - - if (!SUCCEEDED(hr) || controlType == 0) { - DebugWriteLine(L"FindTypeDefByName failed"); - buffer[(*size)++] = 0x14; //ldnull - buffer[(*size)++] = 0x14; //ldnull - break; - } - - hr = metaData->FindMethod(controlType, L"get_Name", getNameSig, sizeof(getNameSig), &getNameToken); - - if (!SUCCEEDED(hr) || getNameToken == 0) { - DebugWriteLine(L"FindMethod failed"); - buffer[(*size)++] = 0x14; //ldnull - buffer[(*size)++] = 0x14; //ldnull - break; - } - - hr = metaData->FindMethod(controlType, L"get_Text", getNameSig, sizeof(getNameSig), &getTextToken); - - if (!SUCCEEDED(hr) || getTextToken == 0) { - DebugWriteLine(L"FindMethod failed"); - buffer[(*size)++] = 0x14; //ldnull - buffer[(*size)++] = 0x14; //ldnull - break; - } - - buffer[(*size)++] = 0x02; //ldarg.0 - buffer[(*size)++] = 0x28; //call - *(mdMethodDef*)(&buffer[*size]) = getNameToken; - *size += sizeof(getNameToken); - - buffer[(*size)++] = 0x02; //ldarg.0 - buffer[(*size)++] = 0x6F; //callvirt - *(mdMethodDef*)(&buffer[*size]) = getTextToken; - *size += sizeof(getTextToken); - - break; - case 3: // WPF - buffer[(*size)++] = 0x14; //ldnull - buffer[(*size)++] = 0x14; //ldnull - break; - } - - buffer[(*size)++] = 0x28; //call - *(mdMethodDef*)(&buffer[*size]) = loggerCall; - *size += sizeof(loggerCall); - - buffer[(*size)++] = 0x28; //call - *(mdMethodDef*)(&buffer[*size]) = activateCall; - *size += sizeof(activateCall); - - return *size - start; -} - -void CProfiler::ConvertToFat(byte *target, int *size) { - COR_ILMETHOD_FAT *targetTable = (COR_ILMETHOD_FAT *)target; - memset(targetTable, 0, FAT_HEADER_SIZE); - targetTable->Flags = CorILMethod_FatFormat; - targetTable->Size = FAT_HEADER_SIZE / sizeof(DWORD); - targetTable->MaxStack = DEFAULT_MAX_STACK; - *size = FAT_HEADER_SIZE; -} - -/// -/// Moves all offsets in SEH section tables by the given count of bytes. -/// -void CProfiler::FixSEHSections(const COR_ILMETHOD_SECT *sections, int offset) { - while (sections) { - if (sections->Kind() == CorILMethod_Sect_EHTable) { - COR_ILMETHOD_SECT_EH *peh = (COR_ILMETHOD_SECT_EH *) sections; - if (peh->IsFat()) { - COR_ILMETHOD_SECT_EH_FAT *pFat = (COR_ILMETHOD_SECT_EH_FAT*) peh; - - for (unsigned int i = 0; i < peh->EHCount(); i++) { - IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT *pfeh = &pFat->Clauses[i]; - - if (pfeh->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) - pfeh->FilterOffset += offset; - - pfeh->HandlerOffset += offset; - pfeh->TryOffset += offset; - } - } else { - COR_ILMETHOD_SECT_EH_SMALL *pSmall = (COR_ILMETHOD_SECT_EH_SMALL *) peh; - - for (unsigned int i = 0; i < peh->EHCount(); i++) { - IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL *pseh = &pSmall->Clauses[i]; - - if (pseh->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) - pseh->FilterOffset += offset; - - pseh->TryOffset += offset; - pseh->HandlerOffset += offset; - } - } - } - sections = sections->Next(); - } -} - -bool CProfiler::CreateMethod(IMetaDataEmit *emitter, const WCHAR *name, PCCOR_SIGNATURE sig, mdMethodDef *methodDefinition, mdToken moduleRef) { - HRESULT hr = emitter->DefineMethod(mdTokenNil, name, mdPublic | mdStatic | mdPinvokeImpl, sig, sizeof(sig), 0, miIL | miManaged, methodDefinition); - - if (!SUCCEEDED(hr)) - return false; - - hr = emitter->DefinePinvokeMap(*methodDefinition, pmNoMangle | pmCallConvStdcall, name, moduleRef); - - if (!SUCCEEDED(hr)) - return false; - - return true; -} - -STDMETHODIMP CProfiler::ModuleLoadFinished(ModuleID moduleID, HRESULT /*hrStatus*/) { - HRESULT hr = S_OK; - - IMetaDataEmit *pIMetaDataEmit = nullptr; - IMetaDataAssemblyImport *asmMetaData = nullptr; - - hr = pICorProfilerInfo->GetModuleMetaData(moduleID, ofRead | ofWrite, IID_IMetaDataEmit, (LPUNKNOWN *) &pIMetaDataEmit); - - if (!SUCCEEDED(hr) || pIMetaDataEmit == nullptr) - goto CLEANUP; - - hr = pICorProfilerInfo->GetModuleMetaData(moduleID, ofRead | ofWrite, IID_IMetaDataAssemblyImport, (LPUNKNOWN *) &asmMetaData); - - if (!SUCCEEDED(hr) || asmMetaData == nullptr) - goto CLEANUP; - - mdToken moduleRef; - hr = pIMetaDataEmit->DefineModuleRef(HOOK_MODULE_NAME, &moduleRef); - - if (!SUCCEEDED(hr)) - goto CLEANUP; - - mdMethodDef deactivator; - if (!CreateMethod(pIMetaDataEmit, L"DeactivateProfiler", rgSig, &deactivator, moduleRef)) - goto CLEANUP; - - mdMethodDef activator; - if (!CreateMethod(pIMetaDataEmit, L"ActivateProfiler", rgSig, &activator, moduleRef)) - goto CLEANUP; - - mdMethodDef logger; - hr = pIMetaDataEmit->DefineMethod(mdTokenNil, L"LogEvent", mdPublic | mdStatic | mdPinvokeImpl, loggerSig, sizeof(loggerSig), 0, miIL | miManaged, &logger); - - if (!SUCCEEDED(hr)) - goto CLEANUP; - - hr = pIMetaDataEmit->DefinePinvokeMap(logger, pmNoMangle | pmCallConvStdcall | pmCharSetUnicode, L"LogEvent", moduleRef); - - if (!SUCCEEDED(hr)) - goto CLEANUP; - - { - methodMapCriticalSection.Enter(); - TMethodTokenMap::iterator it = this->methodMap.find(moduleID); - if (it == this->methodMap.end()) { - this->methodMap.insert(TMethodTokenPair(moduleID, HandlerInfo(activator, deactivator, logger))); - } - methodMapCriticalSection.Leave(); - } - -CLEANUP: - #ifdef DEBUG - if (!SUCCEEDED(hr)) { - MessageBox(nullptr, TEXT("Crashed in ModuleLoadFinished"), TEXT("Crash!"), MB_OK); - __debugbreak(); - } - #endif - - if (pIMetaDataEmit != nullptr) - pIMetaDataEmit->Release(); - - if (asmMetaData != nullptr) - asmMetaData->Release(); - - return S_OK; } \ No newline at end of file