Browse Source

started implementation of IL rewriting for event tracking

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5194 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 16 years ago
parent
commit
d22bed612a
  1. 10
      src/AddIns/Misc/Profiler/Hook/Callback.cpp
  2. 1
      src/AddIns/Misc/Profiler/Hook/CorProfilerCallbackImpl.h
  3. 5
      src/AddIns/Misc/Profiler/Hook/Hook.def
  4. 1
      src/AddIns/Misc/Profiler/Hook/Hook.vcxproj
  5. 399
      src/AddIns/Misc/Profiler/Hook/Profiler.cpp
  6. 37
      src/AddIns/Misc/Profiler/Hook/Profiler.h
  7. 44
      src/AddIns/Misc/Profiler/Hook/ProfilerMetaData.cpp
  8. 4
      src/AddIns/Misc/Profiler/Hook/ProfilerMetaData.h
  9. 22
      src/AddIns/Misc/Profiler/Hook/constants.cpp
  10. 30
      src/AddIns/Misc/Profiler/Hook/global.h
  11. 35
      src/AddIns/Misc/Profiler/Hook/main.cpp
  12. 4
      src/AddIns/Misc/Profiler/Hook/main.h

10
src/AddIns/Misc/Profiler/Hook/Callback.cpp

@ -27,11 +27,11 @@ void _declspec(naked) FunctionEnterNaked(FunctionID functionID, UINT_PTR clientD @@ -27,11 +27,11 @@ void _declspec(naked) FunctionEnterNaked(FunctionID functionID, UINT_PTR clientD
// esp + 0 -> saved edx
// + 4 -> saved ecx
// + 8 -> saved eax
// + 12 -> saved esi
// + 16 -> return address
// + 20 -> functionID \
// + 24 -> clientData |- parameters for FunctionEnterNaked
// + 28 -> ... /
// + 12 -> return address
// + 16 -> functionID \
// + 20 -> clientData |- parameters for FunctionEnterNaked
// + 24 -> frameInfo |
// + 28 -> argumentInfo /
sub esp, FrameSize
// eax, ecx and edx are scratch registers in stdcall, so we need to save those

1
src/AddIns/Misc/Profiler/Hook/CorProfilerCallbackImpl.h

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
#include "cor.h"
#include "corprof.h"
#include "corhdr.h"
class CCorProfilerCallbackImpl : public ICorProfilerCallback2
{

5
src/AddIns/Misc/Profiler/Hook/Hook.def

@ -1,4 +1,7 @@ @@ -1,4 +1,7 @@
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
rdtsc
rdtsc
DeactivateProfiler
ActivateProfiler
LogEvent

1
src/AddIns/Misc/Profiler/Hook/Hook.vcxproj

@ -183,6 +183,7 @@ @@ -183,6 +183,7 @@
<ClCompile Include="allocator.cpp" />
<ClCompile Include="Callback.cpp" />
<ClCompile Include="CircularBuffer.cpp" />
<ClCompile Include="constants.cpp" />
<ClCompile Include="CorProfilerCallbackImpl.cpp" />
<ClCompile Include="EventWaitHandle.cpp" />
<ClCompile Include="FunctionInfo.cpp" />

399
src/AddIns/Misc/Profiler/Hook/Profiler.cpp

@ -175,10 +175,10 @@ int getNewPosFunctionID() { @@ -175,10 +175,10 @@ int getNewPosFunctionID() {
// this function is called by the CLR when a function has been mapped to an ID
UINT_PTR CProfiler::FunctionMapper(FunctionID functionID, BOOL *)
{
return profiler.MapFunction(functionID);
return profiler.MapFunction(functionID, nullptr);
}
UINT_PTR CProfiler::MapFunction(FunctionID functionID)
UINT_PTR CProfiler::MapFunction(FunctionID functionID, const WCHAR **sigOutput)
{
mapFunctionCriticalSection.Enter();
int clientData = 0;
@ -194,6 +194,8 @@ UINT_PTR CProfiler::MapFunction(FunctionID functionID) @@ -194,6 +194,8 @@ UINT_PTR CProfiler::MapFunction(FunctionID functionID)
// send to host
std::wstring signature = sigReader->Parse(functionID);
if (sigOutput != nullptr)
*sigOutput = sigReader->fullName.c_str();
LogString(L"map %d %Id %s", clientData, functionID, signature.c_str());
} else {
DebugWriteLine(L"using old ID");
@ -236,6 +238,7 @@ CProfiler::CProfiler() @@ -236,6 +238,7 @@ CProfiler::CProfiler()
this->pICorProfilerInfo = nullptr;
this->pICorProfilerInfo2 = nullptr;
this->sigReader = nullptr;
this->active = true;
}
// ---- ICorProfilerCallback IMPLEMENTATION ------------------
@ -245,7 +248,7 @@ STDMETHODIMP CProfiler::Initialize(IUnknown *pICorProfilerInfoUnk) @@ -245,7 +248,7 @@ STDMETHODIMP CProfiler::Initialize(IUnknown *pICorProfilerInfoUnk)
{
#ifdef DEBUG
MessageBox(nullptr, TEXT("CProfiler::Initialize - Attach debugger now!"), TEXT("Attach debugger"), MB_OK);
// __debugbreak(); // __asm int 3; replacement on x64 and Itanium
//__debugbreak();
#endif
// Have to disable the profiler, if this process starts other .NET processes (e. g. run a project in SharpDevelop)
@ -387,7 +390,10 @@ void CProfiler::LogString(WCHAR *pszFmtString, ...) @@ -387,7 +390,10 @@ void CProfiler::LogString(WCHAR *pszFmtString, ...)
HRESULT CProfiler::SetEventMask()
{
DWORD eventMask = COR_PRF_MONITOR_ENTERLEAVE | COR_PRF_MONITOR_THREADS | COR_PRF_MONITOR_FUNCTION_UNLOADS | COR_PRF_MONITOR_CLR_EXCEPTIONS | COR_PRF_MONITOR_EXCEPTIONS;
DWORD eventMask = COR_PRF_MONITOR_ENTERLEAVE | COR_PRF_MONITOR_THREADS |
COR_PRF_MONITOR_FUNCTION_UNLOADS | COR_PRF_MONITOR_CLR_EXCEPTIONS |
COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_MONITOR_JIT_COMPILATION |
COR_PRF_MONITOR_MODULE_LOADS;
return pICorProfilerInfo->SetEventMask(eventMask);
}
@ -593,4 +599,389 @@ STDMETHODIMP CProfiler::ExceptionCatcherLeave() @@ -593,4 +599,389 @@ STDMETHODIMP CProfiler::ExceptionCatcherLeave()
{
DebugWriteLine(L"ExceptionCatcherLeave");
return S_OK;
}
STDMETHODIMP CProfiler::JITCompilationStarted(FunctionID functionID, BOOL /*fIsSafeToBlock*/)
{
WCHAR *name;
int nameId = MapFunction(functionID, (const WCHAR **)(&name));
for (int i = 0; i < CONSOLE_GROUP_LENGTH; i++) {
if (wcsstr(consoleGroupList[i], name) != nullptr)
Rewrite(functionID, 0x1, nameId, name);
}
for (int i = 0; i < WINFORMS_GROUP_LENGTH; i++) {
if (wcsstr(winFormsGroupList[i], name) != nullptr)
Rewrite(functionID, 0x2, nameId, name);
}
for (int i = 0; i < WPF_GROUP_LENGTH; i++) {
if (wcsstr(wpfGroupList[i], name) != nullptr)
Rewrite(functionID, 0x3, nameId, name);
}
return S_OK;
}
void CProfiler::Activate()
{
}
void CProfiler::Deactivate()
{
}
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, WCHAR *name)
{
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 + 64);
allocator->Release();
if (codeBuf == nullptr)
return;
int newLength = 0;
if (((COR_ILMETHOD_TINY *)header)->IsTiny()) {
COR_ILMETHOD_TINY *method = (COR_ILMETHOD_TINY *)header;
if (method->GetCodeSize() + sizeof(activateCall) + sizeof(loggerCall) + sizeof(deactivateCall) + 2 < MAX_CODE_SIZE_TINY) {
LogString(L"is tiny!");
// Copy the header elements.
memcpy(&codeBuf[0], method, TINY_HEADER_SIZE);
newLength = TINY_HEADER_SIZE;
SetInjectionCode(metaData, codeBuf, &newLength, activateCall, loggerCall, deactivateCall, type, nameId, name);
// 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 {
LogString(L"is tiny but exceeds!");
ConvertToFat((byte *)codeBuf, &newLength);
SetInjectionCode(metaData, codeBuf, &newLength, activateCall, loggerCall, deactivateCall, type, nameId, name);
// 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()) {
LogString(L"is 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);
int diff = newLength;
// insert new code
SetInjectionCode(metaData, codeBuf, &newLength, activateCall, loggerCall, deactivateCall, type, nameId, name);
diff = newLength - diff;
// 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(), diff);
} else {
DebugWriteLine(L"neither fat nor tiny ... invalid header???");
}
if (codeBuf != nullptr && newLength > 0) {
hr = pICorProfilerInfo2->SetILFunctionBody(moduleID, token, codeBuf);
}
}
void CProfiler::SetInjectionCode(IMetaDataImport *metaData, byte *buffer, int *size,
mdMethodDef activateCall, mdMethodDef loggerCall, mdMethodDef deactivateCall,
int type, int nameId, WCHAR *name)
{
HRESULT hr = S_OK;
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_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);
}
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;
}
/// <summary>
/// Moves all offsets in SEH section tables by the given count of bytes.
/// </summary>
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, 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:
if (pIMetaDataEmit != nullptr)
pIMetaDataEmit->Release();
if (asmMetaData != nullptr)
asmMetaData->Release();
return S_OK;
}

37
src/AddIns/Misc/Profiler/Hook/Profiler.h

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// </file>
#pragma once
#include "CorProfilerCallbackImpl.h"
#include <rpc.h>
#include <rpcndr.h>
@ -16,6 +17,11 @@ @@ -16,6 +17,11 @@
#include "CircularBuffer.h"
#include "CriticalSection.h"
// Disable: conditional expression is constant (C4127)
#pragma warning (disable: 4127)
#include "corhlpr.h"
#pragma warning (default: 4127)
#include <map>
typedef IID CLSID;
@ -25,6 +31,8 @@ MIDL_DEFINE_GUID(CLSID, CLSID_Profiler,0xE7E2C111,0x3471,0x4AC7,0xB2,0x78,0x11,0 @@ -25,6 +31,8 @@ MIDL_DEFINE_GUID(CLSID, CLSID_Profiler,0xE7E2C111,0x3471,0x4AC7,0xB2,0x78,0x11,0
class ThreadInfo;
class HandlerInfo;
struct ThreadLocalData;
typedef std::map<FunctionID, int> TFunctionIDMap;
@ -36,6 +44,9 @@ typedef std::pair<ThreadID, ThreadInfo*> TThreadIDPair; @@ -36,6 +44,9 @@ typedef std::pair<ThreadID, ThreadInfo*> TThreadIDPair;
typedef std::map<DWORD, ThreadInfo*> TUThreadIDMap;
typedef std::pair<DWORD, ThreadInfo*> TUThreadIDPair;
typedef std::map<ModuleID, HandlerInfo> TMethodTokenMap;
typedef std::pair<ModuleID, HandlerInfo> TMethodTokenPair;
// CProfiler
class CProfiler : public CCorProfilerCallbackImpl
{
@ -80,15 +91,23 @@ public: @@ -80,15 +91,23 @@ public:
// UNLOAD EVENTS
STDMETHOD(FunctionUnloadStarted)(FunctionID functionID);
// JITTER EVENTS
STDMETHOD(JITCompilationStarted)(FunctionID functionID, BOOL fIsSafeToBlock);
// MODULE EVENTS
STDMETHOD(ModuleLoadFinished)(ModuleID moduleID, HRESULT hrStatus);
CProfiler();
// mapping functions
static UINT_PTR _stdcall FunctionMapper(FunctionID functionId, BOOL *pbHookFunction);
UINT_PTR MapFunction(FunctionID functionID);
UINT_PTR MapFunction(FunctionID functionID, const WCHAR **name);
FunctionInfo *CreateNewRoot();
void MovedRootChild(FunctionInfo *newRootChild);
void CProfiler::EnterLock(ThreadLocalData *);
void EnterLock(ThreadLocalData *);
void Deactivate();
void Activate();
// logging function
void LogString(WCHAR* pszFmtString, ... );
@ -104,17 +123,25 @@ private: @@ -104,17 +123,25 @@ private:
CriticalSection rootElementCriticalSection;
CriticalSection mapFunctionCriticalSection;
CriticalSection threadMapCriticalSection;
CriticalSection methodMapCriticalSection;
CEventWaitHandle *accessEventHandle;
SignatureReader *sigReader;
TFunctionIDMap functionIDMap;
TThreadIDMap threadIDMap;
TUThreadIDMap unmanagedThreadIDMap;
TMethodTokenMap methodMap;
bool active;
// function to set up our event mask
HRESULT SetEventMask();
void Rewrite(FunctionID functionID, int type, int nameId, WCHAR *name);
void ConvertToFat(byte *target, int *size);
void FixSEHSections(const COR_ILMETHOD_SECT *sections, int offset);
void SetInjectionCode(IMetaDataImport *, byte *buffer, int *size, mdMethodDef activateCall, mdMethodDef loggerCall, mdMethodDef deactivateCall, int type, int nameId, WCHAR *name);
bool CreateMethod(IMetaDataEmit *, const WCHAR *, PCCOR_SIGNATURE, mdMethodDef *, mdToken);
int InitializeCommunication();
};
DWORD WINAPI ExecuteHostCommand( LPVOID lpParam );
void DetachFromThread(ThreadLocalData *data);
void DetachFromThread(ThreadLocalData *data);

44
src/AddIns/Misc/Profiler/Hook/ProfilerMetaData.cpp

@ -66,6 +66,15 @@ std::wstring SignatureReader::Parse(FunctionID functionID) @@ -66,6 +66,15 @@ std::wstring SignatureReader::Parse(FunctionID functionID)
this->className << L"+";
}
std::wstring name = className.str();
AppendEscapedString(name);
this->output << L".";
AppendEscapedString(szFunction);
this->fullName = this->output.str();
this->output.str(L"");
if (SUCCEEDED(hr)) {
this->data = (unsigned char *)signature;
this->dataLength = sigLength;
@ -158,10 +167,7 @@ bool SignatureReader::ReadMethodDefSig(byte head) @@ -158,10 +167,7 @@ bool SignatureReader::ReadMethodDefSig(byte head)
this->output << L" ";
this->output << '"';
std::wstring name = className.str();
AppendEscapedString(name);
this->output << L".";
AppendEscapedString(szFunction);
this->output << fullName;
this->output << '"';
this->output << L" ";
@ -565,20 +571,30 @@ bool SignatureReader::IsNetInternal(FunctionID fid) @@ -565,20 +571,30 @@ bool SignatureReader::IsNetInternal(FunctionID fid)
mdToken funcToken;
HRESULT hr = S_OK;
IMetaDataAssemblyImport *asmMetaData;
const void *publicKey;
ULONG pKLength;
hr = profilerInfo->GetTokenAndMetaDataFromFunction(fid, IID_IMetaDataAssemblyImport, (LPUNKNOWN *) &asmMetaData, &funcToken);
if (SUCCEEDED(hr) && asmMetaData != nullptr)
return IsFrameworkAssembly(asmMetaData);
return false;
}
bool IsFrameworkAssembly(IMetaDataAssemblyImport *asmMetaData)
{
mdAssembly assembly;
const void *publicKey;
ULONG pKLength;
HRESULT hr = asmMetaData->GetAssemblyFromScope(&assembly);
if (SUCCEEDED(hr)) {
mdAssembly assembly;
hr = asmMetaData->GetAssemblyFromScope(&assembly);
if (SUCCEEDED(hr)) {
WCHAR assemblyName[NAME_BUFFER_SIZE];
ULONG assemblyNameLength;
WCHAR assemblyName[NAME_BUFFER_SIZE];
ULONG assemblyNameLength;
hr = asmMetaData->GetAssemblyProps(assembly, &publicKey, &pKLength, nullptr, assemblyName, NAME_BUFFER_SIZE, &assemblyNameLength, nullptr, nullptr);
const byte *b = (const byte *)publicKey;
hr = asmMetaData->GetAssemblyProps(assembly, &publicKey, &pKLength, nullptr, assemblyName, NAME_BUFFER_SIZE, &assemblyNameLength, nullptr, nullptr);
const byte *b = (const byte *)publicKey;
if (SUCCEEDED(hr)) {
if (pKLength == sizeof(mscorlibkey) && memcmp(mscorlibkey, b, sizeof(mscorlibkey)) == 0)
return true;
if (pKLength == sizeof(systemdrawingkey) && memcmp(systemdrawingkey, b, sizeof(systemdrawingkey)) == 0)

4
src/AddIns/Misc/Profiler/Hook/ProfilerMetaData.h

@ -110,5 +110,9 @@ public: @@ -110,5 +110,9 @@ public:
std::wstring Parse(FunctionID);
bool IsNetInternal(FunctionID);
SignatureReader(ICorProfilerInfo *);
std::wstring fullName;
};
bool IsFrameworkAssembly(IMetaDataAssemblyImport *asmMetaData);

22
src/AddIns/Misc/Profiler/Hook/constants.cpp

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="siegfriedpammer@gmail.com"/>
// <version>$Revision$</version>
// </file>
#include "global.h"
WCHAR *consoleGroupList[CONSOLE_GROUP_LENGTH] = {
L"System.Console.Write",
L"System.Console.WriteLine"
};
WCHAR *winFormsGroupList[WINFORMS_GROUP_LENGTH] = {
L"System.Windows.Forms.Control.OnClick",
L"System.Windows.Forms.Control.OnMouseClick"
};
WCHAR *wpfGroupList[WPF_GROUP_LENGTH] = {
L"dummy"
};

30
src/AddIns/Misc/Profiler/Hook/global.h

@ -13,6 +13,10 @@ @@ -13,6 +13,10 @@
#include "LightweightStack.h"
#include "LightweightList.h"
#define CONSOLE_GROUP_LENGTH 2
#define WINFORMS_GROUP_LENGTH 2
#define WPF_GROUP_LENGTH 1
extern fastAllocator stackAllocator;
extern SharedMemoryHeader *sharedMemoryHeader;
extern CProfiler profiler;
@ -20,6 +24,10 @@ extern HANDLE listMutex; @@ -20,6 +24,10 @@ extern HANDLE listMutex;
extern LightweightList *allThreadLocalDatas;
extern DWORD tls_index;
extern WCHAR *consoleGroupList[CONSOLE_GROUP_LENGTH];
extern WCHAR *winFormsGroupList[WINFORMS_GROUP_LENGTH];
extern WCHAR *wpfGroupList[WPF_GROUP_LENGTH];
struct StackEntry {
FunctionInfo *function;
ULONGLONG startTime;
@ -58,4 +66,24 @@ class ThreadInfo { @@ -58,4 +66,24 @@ class ThreadInfo {
this->unmanagedThreadId = 0;
this->managedThreadId = nullptr;
}
};
};
class HandlerInfo {
public:
mdMethodDef deactivator;
mdMethodDef activator;
mdMethodDef logger;
HandlerInfo(mdMethodDef activator, mdMethodDef deactivator, mdMethodDef logger)
{
this->activator = activator;
this->deactivator = deactivator;
this->logger = logger;
}
};
const COR_SIGNATURE rgSig[] = { IMAGE_CEE_CS_CALLCONV_DEFAULT, 0, ELEMENT_TYPE_VOID };
const COR_SIGNATURE loggerSig[] = { IMAGE_CEE_CS_CALLCONV_DEFAULT, 4, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I4, ELEMENT_TYPE_I4, ELEMENT_TYPE_STRING, ELEMENT_TYPE_STRING };
const COR_SIGNATURE getNameSig[] = { IMAGE_CEE_CS_CALLCONV_HASTHIS, 0, ELEMENT_TYPE_STRING };

35
src/AddIns/Misc/Profiler/Hook/main.cpp

@ -41,4 +41,39 @@ ThreadLocalData::ThreadLocalData() @@ -41,4 +41,39 @@ ThreadLocalData::ThreadLocalData()
STDAPI rdtsc(ULONGLONG *tsc) {
*tsc = __rdtsc();
return S_OK;
}
extern "C" {
void __stdcall DeactivateProfiler()
{
profiler.LogString(L"DeactivateProfiler called!");
profiler.Deactivate();
}
void __stdcall ActivateProfiler()
{
profiler.LogString(L"ActivateProfiler called!");
profiler.Activate();
}
void __stdcall LogEvent(int type, int id, WCHAR *controlName, WCHAR *controlText)
{
WCHAR *format = L"";
switch (type) {
case 0:
format = L"event %d %d --";
break;
case 1:
format = L"event %d %d --";
break;
case 2:
format = L"event %d %d -name:\"%s\"text:\"%s\"-";
break;
case 3:
break;
}
DebugWriteLine(format, type, id, controlName, controlText);
}
}

4
src/AddIns/Misc/Profiler/Hook/main.h

@ -58,6 +58,10 @@ inline void* _InterlockedCompareExchangePointer(void* volatile *Destination, voi @@ -58,6 +58,10 @@ inline void* _InterlockedCompareExchangePointer(void* volatile *Destination, voi
{
return ((PVOID)(LONG_PTR)_InterlockedCompareExchange((LONG volatile *)Destination, (LONG)(LONG_PTR)ExChange, (LONG)(LONG_PTR)Comparand));
}
#define HOOK_MODULE_NAME L"Hook32.dll"
#else
#define HOOK_MODULE_NAME L"Hook64.dll"
#endif
#undef InterlockedCompareExchangePointer

Loading…
Cancel
Save