Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / CLR / February 2004

Tip: Looking for answers? Try searching our database.

DefineMethod causes TypeLoadException

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Brian Tyler - 09 Feb 2004 18:35 GMT
I am using the COM Profiling API to hook into the CLR and dynamically modify
the program. I have been successful with the modification of existing
methods, but now I want to add my own. To do this, inside the
ModuleLoadFinished() method, I add the following call to DefineMethod:

               COR_SIGNATURE signature[8];

               signature[0] = IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS |
                                     IMAGE_CEE_CS_CALLCONV_DEFAULT;
               signature[1] = 0;   // No Parameters
               signature[2] = ELEMENT_TYPE_VOID; // Retval
               ULONG signatureSize = 3;

               mdMethodDef methodToken = 0;
               CorMethodAttr methodFlags = (CorMethodAttr)(mdFamily |
mdHideBySig | mdVirtual );
               CorMethodImpl implFlags = (CorMethodImpl)(miIL | miManaged);
               hr = pIMetaDataEmit->DefineMethod(tokens[i],

L"abcdef",

methodFlags,

signature,

signatureSize,

0,

implFlags,

&methodToken);

where tokens[i] is the array of tokens returned from
IMetaDataImport::EnumTypeDefs(). This should inject into my test class a
simple "void abcdef()" method. According to the documentation and discussion
I have been able to find, this should be all I need to do until the
JITCompilationStarted() method, where I would provide the method body. But
when I run the program, before any call to JITCompilationStarted() for my
assembly, I get

Unhandled Exception: System.TypeLoadException: Could not load type Foo from
assembly CrashTest, Version=1.0.1500.21519, Culture=neutral,
PublicKeyToken=null because the method abcdef has no RVA.

I get this even if I change the RVA above (0) to some number - hoping to get
some other error, but it still reports no RVA. I've also tried providing a
method body by calling SetILFunctionBody() with a simple body immediately
after I define the MethodDef token, but to no avail.

Any ideas? Does anyone have any sample program that successfully injects a
method? The only one I could find that called DefineMethod() at all was on
MSDN, but then it was called within JITCompilationStarted(), which gives a
MissingMethod exception...

Brian
Jonathan Keljo [MS] - 09 Feb 2004 21:14 GMT
Hi Brian,
    Can you try creating the method body before calling DefineMethod, then
computing and passing the correct RVA to DefineMethod? (You can get the
module's base address using GetModuleInfo, and if you use the memory
allocator provided by GetILFunctionBodyAllocator for that module, you'll
ensure that the method body is actually above the base of the module in
memory.)

Let me know if that works,

Jonathan

This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
| From: "Brian Tyler" <brianmtyler@yahoo.com>
| Subject: DefineMethod causes TypeLoadException
[quoted text clipped - 8 lines]
| NNTP-Posting-Host: ip67.tonic.com 216.54.231.67
| Path:
cpmsftngxa07.phx.gbl!cpmsftngxa10.phx.gbl!TK2MSFTNGXA05.phx.gbl!TK2MSFTNGP08
.phx.gbl!TK2MSFTNGP11.phx.gbl
| Xref: cpmsftngxa07.phx.gbl microsoft.public.dotnet.framework.clr:9498
| X-Tomcat-NG: microsoft.public.dotnet.framework.clr
[quoted text clipped - 55 lines]
|
| Brian
Brian Tyler - 09 Feb 2004 22:53 GMT
Afraid not. Here is the complete ModuleLoadFinished() method. The
ICorProfilerInfo is stored in the like-named member variable and
GetModuleName() and GetModuleBaseAddress() are just wrappers around the
ICorProfilerInfo->GetModuleInfo() method. Also note the filter at the top
based on the module name to ensure I don't start messing with mscorlib or
something (in case you try to run this).

*DISCLAIMER: This is a hack-test program, there is no synchronization,
proper error recovery or other important bits!*

STDMETHODIMP CProfiler::ModuleLoadFinished(ModuleID moduleId,
                                          HRESULT hrStatus)
{
   try
   {
       std::wstring moduleName = GetModuleName(moduleId);
       std::wcerr << L"Module " << moduleName << L" has been loaded" <<
std::endl;

       if (::wcsicmp(moduleName.c_str(),
L"C:\\work\\dotnet\\simple\\CrashTest\\bin\\Debug\\CrashTest.exe") == 0)
       {
           IMetaDataImport* pIMetaDataImport = NULL;
           HRESULT hr = m_pICorProfilerInfo->GetModuleMetaData(moduleId,
                                                               ofRead,

IID_IMetaDataImport,

(IUnknown**)&pIMetaDataImport);
           if (FAILED(hr))
           {
               std::wcerr << L"GetModuleMetaData returned 0x" << std::hex
<< hr << std::endl;
           }
           assert(pIMetaDataImport != NULL);

           IMetaDataEmit* pIMetaDataEmit = NULL;
           hr = m_pICorProfilerInfo->GetModuleMetaData(moduleId,
                                                       ofRead | ofWrite,
                                                       IID_IMetaDataEmit,

(IUnknown**)&pIMetaDataEmit);
           if (FAILED(hr))
           {
               std::wcerr << L"GetModuleMetaData(2) returned 0x" <<
std::hex << hr << std::endl;
           }
           assert(pIMetaDataEmit != NULL);

           HCORENUM hEnum = 0;
           ULONG numTokens = 2048;
           mdTypeDef* tokens = new mdTypeDef[numTokens];
           hr = pIMetaDataImport->EnumTypeDefs(&hEnum,
                                               tokens,
                                               numTokens,
                                               &numTokens);
           if (FAILED(hr))
           {
               std::wcerr << L"EnumTypeDefs returned 0x" << std::hex << hr
<< std::endl;
           }

           pIMetaDataImport->CloseEnum( hEnum );

           for(ULONG i=0; i<numTokens; i++)
           {
               //
               // First let's generate a NOP IL Stream
               //
               BYTE data[2];

               // Flags_CodeSize (Tiny w/ 1 byte of IL)
               data[0] = CorILMethod_TinyFormat1 | (1 <<
(CorILMethod_FormatShift-1));
               // The IL: NOP
               data[1] = 0;

               // Now allocate the memory for it
               void* mem = NULL;
               ULONG codeRVA = 0;
               IMethodMalloc* mallocer = NULL;
               hr =
m_pICorProfilerInfo->GetILFunctionBodyAllocator(moduleId,

&mallocer);
               if (FAILED(hr))
               {
                   std::wcerr << L"GetILFunctionBodyAllocator returned 0x"
<< std::hex << hr << std::endl;
               }
               else
               {
                   mem = mallocer->Alloc(sizeof(data));
                   mallocer->Release();

                   const BYTE* baseAddress =
GetModuleBaseAddress(moduleId);
                   codeRVA = (ULONG)(((UINT_PTR)mem) -
((UINT_PTR)baseAddress));

                   ::memcpy(mem, data, sizeof(data));
               }

               //
               // Now the MethodDef
               //
               COR_SIGNATURE signature[8];

               signature[0] = IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS |
                              IMAGE_CEE_CS_CALLCONV_DEFAULT;
               signature[1] = 0;   // No Parameters
               signature[2] = ELEMENT_TYPE_VOID; // Retval
               ULONG signatureSize = 3;

               mdMethodDef methodToken = 0;
               CorMethodAttr methodFlags = (CorMethodAttr)(mdFamily |
mdHideBySig | mdVirtual );
               CorMethodImpl implFlags = (CorMethodImpl)(miIL | miManaged);
               hr = pIMetaDataEmit->DefineMethod(tokens[i],
                                                 L"abcdef",
                                                 methodFlags,
                                                 signature,
                                                 signatureSize,
                                                 codeRVA,
                                                 implFlags,
                                                 &methodToken);
               if (FAILED(hr))
               {
                   std::wcerr << L"EnumTypeDefs returned 0x" << std::hex <<
hr << std::endl;
               }
               else
               {
                   std::wcerr << L"Injected method into class @ 0x" <<
std::hex << codeRVA << std::endl;
               }

               //
               // Now that we have the token, let's put the IL in place
               //
               if (mem != NULL)
               {
                   hr = m_pICorProfilerInfo->SetILFunctionBody(moduleId,
methodToken, (BYTE*)mem);
                   if (FAILED(hr))
                   {
                       std::wcerr << L"SetILFunctionBody returned 0x" <<
std::hex << hr << std::endl;
                   }
               }
           }

           //
           // Cleanup
           //
           delete[] tokens;
           if (pIMetaDataImport != NULL)
           {
               pIMetaDataImport->Release();
           }

           if (pIMetaDataEmit != NULL)
           {
               pIMetaDataEmit->Release();
           }
       }
   }
   catch(...)
   {
       std::wcerr << L"Caught ... exception during Module Creation" <<
std::endl;
   }

   return S_OK;
}

> Hi Brian,
>      Can you try creating the method body before calling DefineMethod, then
[quoted text clipped - 23 lines]
> | NNTP-Posting-Host: ip67.tonic.com 216.54.231.67
> | Path:

cpmsftngxa07.phx.gbl!cpmsftngxa10.phx.gbl!TK2MSFTNGXA05.phx.gbl!TK2MSFTNGP08
> phx.gbl!TK2MSFTNGP11.phx.gbl
> | Xref: cpmsftngxa07.phx.gbl microsoft.public.dotnet.framework.clr:9498
[quoted text clipped - 61 lines]
> |
> | Brian

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.