mscoree: Detect when a CLR DLL requests vtable fixups.
This commit is contained in:
parent
29893d8162
commit
d2d1c6d824
|
@ -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;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
|
||||
HeapFree(GetProcessHeap(), 0, assembly->path);
|
||||
if (assembly->is_mapped_file)
|
||||
{
|
||||
UnmapViewOfFile(assembly->data);
|
||||
CloseHandle(assembly->hmap);
|
||||
CloseHandle(assembly->hfile);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
|
||||
HeapFree(GetProcessHeap(), 0, assembly->path);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue