1

I am building a .Net Profiler for some custom requirement where I need to capture the exception details even though it got handled properly in the code. To do so-

  • I have implemented ICorProfilerCallback
  • SetEventsMask for COR_PRF_MONITOR_EXCEPTIONS
  • Implemented the ExceptionThrown callback

So far so good, I am getting callback for every exception being thrown. However, it gives OjbectID that is a pointer to the actual exception object. I want more details like the message, call stack, etc. about the exception.

How do I get object details from ObjectID?

valiano
  • 16,433
  • 7
  • 64
  • 79
Hitesh
  • 1,067
  • 1
  • 10
  • 27
  • Wrong approach, using ICorDebug is best. Start from the mdbg v4 sample. – Hans Passant Oct 05 '17 at 13:11
  • @HansPassant Loading both the ICorDebug and ICorProfiler is not really recommended and if the OP is looking to avoid the runtime changes that are implied by loading the ICorDebug it makes sense to use the ICorProfiler interfaces. In fact, this is what the VS Profiler does. Admittedly, if the OP doesn't really need to profile, then yes the ICorDebug interfaces are more convenient for this. – linuxuser27 Oct 05 '17 at 14:42
  • @Hitesh Look for the ICorProfilerInfo interface. There are many options on it, unclear about what specific data you are after, but you can get a bunch of information from it. – linuxuser27 Oct 05 '17 at 14:42
  • @linuxuser27, I am already using ICorProfiler for IL Rewriting. I have to continue with it. – Hitesh Oct 05 '17 at 16:08
  • @linuxuser27, as I have mentioned, I want error message, call stack, etc. – Hitesh Oct 05 '17 at 16:10

1 Answers1

1

As @HansPassant mentioned, what you are doing smells like a debugger feature more than a profiler. However, you can do what you want using the profiler if that is a hard requirement - I believe IL re-writing is possible via the ICorDebug interfaces, but I am a profiler dev and haven't used the debugger interfaces as much.

David Broman's blog has a great description of taking a managed stack walk using the ICorProfilerInfo2 interface. In order to get the native parts you need to do a lot more work.

Navigating the object instance is also done via the ICorProfilerInfo2 interface.

  1. Get the class ID of the object using ICorProfilerInfo::GetClassFromObject()

  2. Using the class ID get the class layout via ICorProfilerInfo2::GetClassLayout()

    • You will need to parse the object metadata to determine which field you want.
  3. Index into the object to grab the desired data.

valiano
  • 16,433
  • 7
  • 64
  • 79
linuxuser27
  • 7,183
  • 1
  • 26
  • 22
  • Interesting, thanks for the response. Is it possible to get the exception object and pass to managed code through COM interface? Actually, I have some contextual data stored in CallContext in .Net. I have to log exception details along with contextual data. – Hitesh Oct 06 '17 at 01:45
  • 1
    @Hitesh: No, you can't call back into managed code from any profiler callbacks, doing so may result in deadlocks. (eg. the ExceptionThrown callback suspends GC until the callback returns, so that the ObjectID it just gave you will mean something; but if you call a managed method that performs a managed allocation, it may trigger a GC and BAM! you have a deadlock. Even if you try it and it works *today*, there is no guarantee that it will continue to work after the next update). – Brian Reichle Oct 07 '17 at 02:16
  • @BrianReichle, Okay. So, how do I read some contextual information stored in CallContext? And how do I read the error message, exception type, call stack from the exception, etc.? As mentioned in https://blogs.msdn.microsoft.com/davbr/2007/12/18/debugging-your-profiler-ii-sos-and-ids/, I tried converting ObjectId to _Exception object, but no luck. I am not able to get the object size as well using 'GetObjectSize' :( – Hitesh Oct 07 '17 at 06:37
  • Moreover, can't I suspend GC until my managed call execution gets over? – Hitesh Oct 07 '17 at 06:41