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
|
struct tagASSEMBLY
|
||||||
{
|
{
|
||||||
LPWSTR path;
|
int is_mapped_file;
|
||||||
|
|
||||||
|
/* mapped files */
|
||||||
|
LPWSTR path;
|
||||||
HANDLE hfile;
|
HANDLE hfile;
|
||||||
HANDLE hmap;
|
HANDLE hmap;
|
||||||
|
|
||||||
BYTE *data;
|
BYTE *data;
|
||||||
|
|
||||||
IMAGE_NT_HEADERS *nthdr;
|
IMAGE_NT_HEADERS *nthdr;
|
||||||
|
@ -89,6 +92,29 @@ static inline LPWSTR strdupW(LPCWSTR src)
|
||||||
return dest;
|
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)
|
static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
|
||||||
{
|
{
|
||||||
METADATAHDR *metadatahdr;
|
METADATAHDR *metadatahdr;
|
||||||
|
@ -97,7 +123,7 @@ static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
|
||||||
ULONG rva;
|
ULONG rva;
|
||||||
|
|
||||||
rva = assembly->corhdr->MetaData.VirtualAddress;
|
rva = assembly->corhdr->MetaData.VirtualAddress;
|
||||||
ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
|
ptr = assembly_rva_to_va(assembly, rva);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
|
@ -158,20 +184,24 @@ static HRESULT parse_pe_header(ASSEMBLY *assembly)
|
||||||
if (!datadirs)
|
if (!datadirs)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if (!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress ||
|
if (!assembly_datadir_get_data(assembly, &datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR], (void**)&assembly->corhdr))
|
||||||
!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)
|
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
return S_OK;
|
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)
|
HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
|
||||||
{
|
{
|
||||||
ASSEMBLY *assembly;
|
ASSEMBLY *assembly;
|
||||||
|
@ -183,6 +213,8 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
|
||||||
if (!assembly)
|
if (!assembly)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
assembly->is_mapped_file = 1;
|
||||||
|
|
||||||
assembly->path = strdupW(file);
|
assembly->path = strdupW(file);
|
||||||
if (!assembly->path)
|
if (!assembly->path)
|
||||||
{
|
{
|
||||||
|
@ -213,10 +245,7 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = parse_pe_header(assembly);
|
hr = parse_headers(assembly);
|
||||||
if (FAILED(hr)) goto failed;
|
|
||||||
|
|
||||||
hr = parse_clr_metadata(assembly);
|
|
||||||
if (FAILED(hr)) goto failed;
|
if (FAILED(hr)) goto failed;
|
||||||
|
|
||||||
*out = assembly;
|
*out = assembly;
|
||||||
|
@ -227,16 +256,43 @@ failed:
|
||||||
return hr;
|
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)
|
HRESULT assembly_release(ASSEMBLY *assembly)
|
||||||
{
|
{
|
||||||
if (!assembly)
|
if (!assembly)
|
||||||
return S_OK;
|
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->metadatahdr);
|
||||||
HeapFree(GetProcessHeap(), 0, assembly->path);
|
HeapFree(GetProcessHeap(), 0, assembly->path);
|
||||||
UnmapViewOfFile(assembly->data);
|
|
||||||
CloseHandle(assembly->hmap);
|
|
||||||
CloseHandle(assembly->hfile);
|
|
||||||
HeapFree(GetProcessHeap(), 0, assembly);
|
HeapFree(GetProcessHeap(), 0, assembly);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -248,3 +304,13 @@ HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
|
||||||
|
|
||||||
return S_OK;
|
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);
|
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)
|
__int32 WINAPI _CorExeMain(void)
|
||||||
{
|
{
|
||||||
int exit_code;
|
int exit_code;
|
||||||
|
@ -830,6 +850,8 @@ __int32 WINAPI _CorExeMain(void)
|
||||||
if (!filenameA)
|
if (!filenameA)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
FixupVTable(GetModuleHandleW(NULL));
|
||||||
|
|
||||||
hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
|
hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
@ -862,6 +884,22 @@ __int32 WINAPI _CorExeMain(void)
|
||||||
return exit_code;
|
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,
|
HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
|
||||||
loaded_mono *loaded_mono, RuntimeHost** result)
|
loaded_mono *loaded_mono, RuntimeHost** result)
|
||||||
{
|
{
|
||||||
|
|
|
@ -236,21 +236,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
return TRUE;
|
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)
|
__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));
|
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,
|
extern HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
|
||||||
LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN;
|
LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
typedef struct _VTableFixup {
|
||||||
|
DWORD rva;
|
||||||
|
WORD count;
|
||||||
|
WORD type;
|
||||||
|
} VTableFixup;
|
||||||
|
|
||||||
typedef struct tagASSEMBLY ASSEMBLY;
|
typedef struct tagASSEMBLY ASSEMBLY;
|
||||||
|
|
||||||
HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
|
extern void* assembly_rva_to_va(ASSEMBLY *assembly, ULONG rva) DECLSPEC_HIDDEN;
|
||||||
HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
|
extern HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
|
||||||
HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) 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 */
|
/* Mono embedding */
|
||||||
typedef struct _MonoDomain MonoDomain;
|
typedef struct _MonoDomain MonoDomain;
|
||||||
|
|
Loading…
Reference in New Issue