mscoree: Detect when a CLR DLL requests vtable fixups.

oldstable
Vincent Povirk 2011-10-20 13:23:35 -05:00 committed by Alexandre Julliard
parent 29893d8162
commit d2d1c6d824
4 changed files with 134 additions and 36 deletions

View File

@ -63,10 +63,13 @@ typedef struct tagCLRTABLE
struct tagASSEMBLY
{
LPWSTR path;
int is_mapped_file;
/* mapped files */
LPWSTR path;
HANDLE hfile;
HANDLE hmap;
BYTE *data;
IMAGE_NT_HEADERS *nthdr;
@ -89,6 +92,29 @@ static inline LPWSTR strdupW(LPCWSTR src)
return dest;
}
void* assembly_rva_to_va(ASSEMBLY *assembly, ULONG rva)
{
if (assembly->is_mapped_file)
return ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
else
return assembly->data + rva;
}
static ULONG assembly_datadir_get_data(ASSEMBLY *assembly,
IMAGE_DATA_DIRECTORY *datadir, void **data)
{
if (!datadir->VirtualAddress || !datadir->Size)
{
*data = NULL;
return 0;
}
else
{
*data = assembly_rva_to_va(assembly, datadir->VirtualAddress);
return datadir->Size;
}
}
static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
{
METADATAHDR *metadatahdr;
@ -97,7 +123,7 @@ static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
ULONG rva;
rva = assembly->corhdr->MetaData.VirtualAddress;
ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
ptr = assembly_rva_to_va(assembly, rva);
if (!ptr)
return E_FAIL;
@ -158,20 +184,24 @@ static HRESULT parse_pe_header(ASSEMBLY *assembly)
if (!datadirs)
return E_FAIL;
if (!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress ||
!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size)
{
return E_FAIL;
}
assembly->corhdr = ImageRvaToVa(assembly->nthdr, assembly->data,
datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress, NULL);
if (!assembly->corhdr)
if (!assembly_datadir_get_data(assembly, &datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR], (void**)&assembly->corhdr))
return E_FAIL;
return S_OK;
}
HRESULT parse_headers(ASSEMBLY *assembly)
{
HRESULT hr;
hr = parse_pe_header(assembly);
if (SUCCEEDED(hr))
hr = parse_clr_metadata(assembly);
return hr;
}
HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
{
ASSEMBLY *assembly;
@ -183,6 +213,8 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
if (!assembly)
return E_OUTOFMEMORY;
assembly->is_mapped_file = 1;
assembly->path = strdupW(file);
if (!assembly->path)
{
@ -213,10 +245,7 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
goto failed;
}
hr = parse_pe_header(assembly);
if (FAILED(hr)) goto failed;
hr = parse_clr_metadata(assembly);
hr = parse_headers(assembly);
if (FAILED(hr)) goto failed;
*out = assembly;
@ -227,16 +256,43 @@ failed:
return hr;
}
HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule)
{
ASSEMBLY *assembly;
HRESULT hr;
*out = NULL;
assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY));
if (!assembly)
return E_OUTOFMEMORY;
assembly->is_mapped_file = 0;
assembly->data = (BYTE*)hmodule;
hr = parse_headers(assembly);
if (SUCCEEDED(hr))
*out = assembly;
else
assembly_release(assembly);
return hr;
}
HRESULT assembly_release(ASSEMBLY *assembly)
{
if (!assembly)
return S_OK;
if (assembly->is_mapped_file)
{
UnmapViewOfFile(assembly->data);
CloseHandle(assembly->hmap);
CloseHandle(assembly->hfile);
}
HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
HeapFree(GetProcessHeap(), 0, assembly->path);
UnmapViewOfFile(assembly->data);
CloseHandle(assembly->hmap);
CloseHandle(assembly->hfile);
HeapFree(GetProcessHeap(), 0, assembly);
return S_OK;
@ -248,3 +304,13 @@ HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
return S_OK;
}
HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWORD *count)
{
ULONG size;
size = assembly_datadir_get_data(assembly, &assembly->corhdr->VTableFixups, (void**)fixups);
*count = size / sizeof(VTableFixup);
return S_OK;
}

View File

@ -803,6 +803,26 @@ static void get_utf8_args(int *argc, char ***argv)
HeapFree(GetProcessHeap(), 0, argvw);
}
static void FixupVTable(HMODULE hmodule)
{
ASSEMBLY *assembly;
HRESULT hr;
VTableFixup *vtable_fixups;
ULONG vtable_fixup_count;
hr = assembly_from_hmodule(&assembly, hmodule);
if (SUCCEEDED(hr))
{
hr = assembly_get_vtable_fixups(assembly, &vtable_fixups, &vtable_fixup_count);
if (vtable_fixup_count)
FIXME("vtable fixups are not implemented; expect a crash\n");
assembly_release(assembly);
}
else
ERR("failed to read CLR headers, hr=%x\n", hr);
}
__int32 WINAPI _CorExeMain(void)
{
int exit_code;
@ -830,6 +850,8 @@ __int32 WINAPI _CorExeMain(void)
if (!filenameA)
return -1;
FixupVTable(GetModuleHandleW(NULL));
hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
if (SUCCEEDED(hr))
@ -862,6 +884,22 @@ __int32 WINAPI _CorExeMain(void)
return exit_code;
}
BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
FIXME("(%p, %d, %p): stub\n", hinstDLL, fdwReason, lpvReserved);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
FixupVTable(hinstDLL);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
loaded_mono *loaded_mono, RuntimeHost** result)
{

View File

@ -236,21 +236,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return TRUE;
}
BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
FIXME("(%p, %d, %p): stub\n", hinstDLL, fdwReason, lpvReserved);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__int32 WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPWSTR imageName, LPWSTR loaderName, LPWSTR cmdLine)
{
TRACE("(%p, %u, %s, %s, %s)\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine));

View File

@ -27,11 +27,20 @@ extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj) DECLSPEC_HI
extern HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN;
typedef struct _VTableFixup {
DWORD rva;
WORD count;
WORD type;
} VTableFixup;
typedef struct tagASSEMBLY ASSEMBLY;
HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
extern void* assembly_rva_to_va(ASSEMBLY *assembly, ULONG rva) DECLSPEC_HIDDEN;
extern HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
extern HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule) DECLSPEC_HIDDEN;
extern HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
extern HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
extern HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWORD *count) DECLSPEC_HIDDEN;
/* Mono embedding */
typedef struct _MonoDomain MonoDomain;