locked
Profiler adding a new type field via IMetaDataEmit::DefineField results in "_CorExeMain failed"

    Question

  • m trying to add two new fields (one of type bool and one of type string) to System.String and System.Text.StringBuilder; I'm targeting .NET 1.1 and this is what' I'm doing :

    1. in ICorProfilerCallback::AssemblyLoadFinished if the assembly name is mscorlib get main module

    2. locate the types using IMetaDataImport::FindTypeDefByName

    3. for each type call IMetaDataEmit::DefineField with the following signatures:

    COR_SIGNATURE sig_bool[2] = { IMAGE_CEE_CS_CALLCONV_FIELD, ELEMENT_TYPE_BOOLEAN };

    COR_SIGNATURE sig_string[2]= { IMAGE_CEE_CS_CALLCONV_FIELD, ELEMENT_TYPE_STRING };

    The fields seems to be added OK (there is no error) but later when the main application assembly is loaded I get the following error: "Could not run the given program. _CorExeMain failed".

    Any ideas what I'm doing wrong? Is it there a way to get some logging out of CLR which will give more details about the error? I've tried moving the instrumentation code to ModuleLoadFinished but it makes no difference; if I don't add the string field the code "almost" works but the output of Console.WriteXXX shows garbage - for example if I try to print a string "hello" I can see "h<non-ASCII char>llo"  which makes me belive the string class layout is wrong and somehow the fields overlap.

    Thanks!

    Thursday, February 15, 2007 1:28 AM

Answers

  • Hello,

    The MetaData operation DefineField you are trying to perform on the CLR types (String and StringBuilder) won't work because the layout of those classes is known to the native part of the CLR and therefore cannot change. Any attempt to modify their layout will likely break many parts of CLR like COM interop, PInvoke interop, marshaling, serialization, etc. That's the reason why CLR fails with the error you are seeing.

    You would see similar errors if you try to use DefineField in your types that heavily use listed operations (e.g. PInvoke interop). The DefineField MetaData operation is considered to be invasive profiler operation and should be avoided for sensitive types.

    If you need to add information to these types per instance, I would suggest to keep that information in separate objects and use a hash table to associate your additional informational object with the original object instance. There are profiler-based products which use this technique and it performs well for them even for such objects like String/StringBuilder.

    I hope it helps,

    -Karel

    Tuesday, February 20, 2007 6:31 PM
    Moderator

All replies

  • Hello,

    The MetaData operation DefineField you are trying to perform on the CLR types (String and StringBuilder) won't work because the layout of those classes is known to the native part of the CLR and therefore cannot change. Any attempt to modify their layout will likely break many parts of CLR like COM interop, PInvoke interop, marshaling, serialization, etc. That's the reason why CLR fails with the error you are seeing.

    You would see similar errors if you try to use DefineField in your types that heavily use listed operations (e.g. PInvoke interop). The DefineField MetaData operation is considered to be invasive profiler operation and should be avoided for sensitive types.

    If you need to add information to these types per instance, I would suggest to keep that information in separate objects and use a hash table to associate your additional informational object with the original object instance. There are profiler-based products which use this technique and it performs well for them even for such objects like String/StringBuilder.

    I hope it helps,

    -Karel

    Tuesday, February 20, 2007 6:31 PM
    Moderator
  • Thanks for replying Karel ! Currently I'm using something like you've suggested combined with custom methods added via DefineMethod; can you comment on the safety of adding methods to mscorlib types ?

    Thanks!

    Paul

    Tuesday, February 20, 2007 8:52 PM
  • Hi, Paul! Although adding fields is dangerous as Karel mentioned, adding methods should be ok.  However, be very careful not to have those methods reference types that live outside of mscorlib.dll.  This means no TypeRefs, AssemblyRefs, etc. may be added to mscorlib.dll.  The CLR assumes mscorlib.dll has no references (though other assemblies obviously reference mscorlib.dll).  If you break this assumption, bad things will happen at bad times.

    A similar pitfall to avoid is adding IL to mscorlib that would cause another assembly to load (even if not via a TypeRef).  When such code is executed early on in AppDomain initialization, the loader has trouble loading the other assembly, and you'll get exceptions.

    There have been recent discussions in this forum about IL rewriting inside mscorlib.dll and the dangers profiler writers have encountered.

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1153030&SiteID=1

    is one example.

    Tuesday, February 20, 2007 11:07 PM
    Owner