Hi,
I am trying to instrument methods in mscorlib.dll and put method calls into my own proxy methods into them. Now, I know I cannot add AssemblyRefs from mscorlib.dll to my proxy.dll because mscorlib does not like that in SingleDomain mode.
So, I want to merge all the content of proxy.dll (all typedefs, methods, methodbodies, ect) into mscorlib.dll. It is very similar to what has been discussed in
http://social.msdn.microsoft.com/Forums/en-US/0338c6bf-81b5-44ff-8e43-8bdb9a44feb7/modify-systemexception-in-setilfunctionbody.
I tried IMetaDataEmit::Merge() to inject all metadata into mscorlib.dll (at ModuleLoadStarted/Finished profiler callback). However, I could not get it to work yet. Documentation is very sparse on that topic. My problem is that I get a AccessViolation when I call MergeEnd:
clr.dll!CMiniMdRW::GetFilterTable(void) Unknown clr.dll!NEWMERGER::Merge(enum MergeFlags,enum CorRefToDefCheck) Unknown clr.dll!RegMeta::MergeEnd(void) Unknown
Here is the disassebly from the debugger:
CMiniMdRW::GetFilterTable: 000007FEE8A7FA5C mov qword ptr [rsp+8],rbx 000007FEE8A7FA61 push rdi 000007FEE8A7FA62 sub rsp,20h 000007FEE8A7FA66 xor ebx,ebx 000007FEE8A7FA68 mov rdi,rcx --> 000007FEE8A7FA6B cmp qword ptr [rcx+18A0h],rbx 000007FEE8A7FA72 je CMiniMdRW::GetFilterTable+0C5Eh (07FEE8A806BAh) 000007FEE8A7FA78 mov rax,qword ptr [rdi+18A0h] 000007FEE8A7FA7F mov rbx,qword ptr [rsp+30h] 000007FEE8A7FA84 add rsp,20h 000007FEE8A7FA88 pop rdi 000007FEE8A7FA89 ret 000007FEE8A7FA8A nop 000007FEE8A7FA8B nop
rcx is 0. That means that the this-pointer is NULL, if I interpret it correctly.
This is what I do in ModuleLoadFinished callback (simplified):
// open scope and IMetaDataImport for proxy.dll which is loaded as raw file IMetaDataDispenserEx *pDisp; CoCreateInstance(CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER, IID_IMetaDataDispenserEx, (void **)&pDisp); IMetaDataImport *pImport; pDisp->OpenScopeOnMemory(pFileInMemory, fileSize, ofRead, IID_IMetaDataImport, (LPUNKNOWN*)&pImport); // get IMetaDataEmit for mscorlib.dll IMetaDataEmit2 * pEmit2; corProfilerInfo->GetModuleMetaData(moduleId, ( DWORD)( ofWrite | ofRead), IID_IMetaDataEmit2, (IUnknown **) &pEmit2); // do the merge MyTokenMapper mapper; // dummy mapper which implements IMapToken MyErrorHandler handler; // implements IUnknown, not sure what this one is supposed to do emit->Merge(import, &mapper, &handler); emit->MergeEnd(); // here, the crash happens
Can anyone tell me:
1. Why does it crash? What can I do differently?
2. I implemented IMapToken myself, but I do not get any callbacks to ::Map(). Isn't it supposed to give me a callback for each merge?
3. Is it recommended to use ::Merge() at all? Or would it be more wise to use IMetaDataEmit::Define...() and do the merge one by one?
Thanks!
-Christoph