0

In our .Net application, we want to keep track of a file that is getting opened through .Net Code. Any file that is getting opened, execution call always pass through an internal instance method FileStrem.Init(...) which available in mscorlib.

To inject our monitoring code into any .Net method, we have built a framework in C++ using ICorProfiler APIs provided by Microsoft. All it does is that on module load finished, read the existing IL from target method from the loaded module, build custom code using IL and inject it into the target method.

This framework works fine. We are able to inject our monitoring code into many methods including FileStream.Init(...) method in mscorlib for .Net 4.x. But the same injected code does not get invoked in .Net 2.x.

We are able to inject our code into any .Net DLL except mscorlib for .Net 2.x. Code is getting injected properly, but not getting invoked. I have verified the IL of FileStream.Init(...) after injecting the code; I can see my code is present. But, not sure why it is not getting invoked. However the same code works file with FileStream.Init(...) for .Net 4.x.

Here is the sample C++ code to inject through IL -

// Read existing IL
ModuleID modId = 0x2030202; // module id of mscorlib
mdToken tkMethodId = 0x2492333; // Method token for FileStream.Init(...)
LPCBYTE methodBodyIL;
pICorProfilerInfo->GetILFunctionBody(modId, tkMethodId, &methodBodyIL, NULL)

// build monitoring IL and inject it into the bytes read from FileStream.Init
InjectCode(&methodBodyIL)

// Update the injected method back to mscorlib in memory
pICorProfilerInfo->SetILFunctionBody(modId, tkMethodId, methodBodyIL)

Any idea why it is not working in mscorlib for .Net 2.x?

valiano
  • 16,433
  • 7
  • 64
  • 79
Hitesh
  • 1,067
  • 1
  • 10
  • 27
  • First question... Is it a 32 vs 64 bit problem? Some poorly done injections work only at 32 bits. Try printing `IntPtr.Size` or equivalent. – xanatos Jul 26 '18 at 10:01
  • It's 64bit. Injection happened in C++, where I don't have IntPtr.Size. However, I have verified the size and content of methodBodyIL before and after injection. That looks fine. In fact, the same is working for .Net 4.x – Hitesh Jul 26 '18 at 10:08
  • Are you relying on `COR_PRF_DISABLE_ALL_NGEN_IMAGES` to disable the ngen images? that flag wasn't introduced until .Net 4 and ngen images will interfere with what you are trying to do. – Brian Reichle Jul 26 '18 at 10:39
  • Yes, I have used COR_PRF_DISABLE_ALL_NGEN_IMAGES. What should I do now? – Hitesh Jul 26 '18 at 10:41
  • 1
    The solution back then was to use `COR_PRF_USE_PROFILE_IMAGES` and hope that no profiler enabled images were installed. – Brian Reichle Jul 26 '18 at 10:42
  • Thanks Brian, after setting COR_PRF_USE_PROFILE_IMAGES, it is working now with .Net 2.x as well. You can answer this question, I will accept it. – Hitesh Jul 27 '18 at 06:25

1 Answers1

0

You cant replace the body of a method if its covered by an ngen-ed image (mscorlib is normally ngen-ed). You might be using the COR_PRF_DISABLE_ALL_NGEN_IMAGES flag to disable ngen images, but that flag wasn't introduced until .NET 4 and so won't work for .NET 2.

In the .NET 2 days the common solution was to use COR_PRF_USE_PROFILE_IMAGES and hope the machine didn't have any ngen images generated with profiling support enabled.

Brian Reichle
  • 2,798
  • 2
  • 30
  • 34