Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
a629ba49
Commit
a629ba49
authored
May 07, 2012
by
Vincent Povirk
Committed by
Alexandre Julliard
May 09, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mscoree: Implement vtable fixups.
parent
f0be44c8
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
237 additions
and
3 deletions
+237
-3
corruntimehost.c
dlls/mscoree/corruntimehost.c
+229
-3
metahost.c
dlls/mscoree/metahost.c
+1
-0
mscoree_main.c
dlls/mscoree/mscoree_main.c
+3
-0
mscoree_private.h
dlls/mscoree/mscoree_private.h
+4
-0
No files found.
dlls/mscoree/corruntimehost.c
View file @
a629ba49
...
...
@@ -19,6 +19,7 @@
#define COBJMACROS
#include <assert.h>
#include <stdarg.h>
#include "windef.h"
...
...
@@ -39,6 +40,7 @@
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
mscoree
);
...
...
@@ -52,6 +54,21 @@ struct DomainEntry
MonoDomain
*
domain
;
};
static
HANDLE
dll_fixup_heap
;
/* using a separate heap so we can have execute permission */
static
struct
list
dll_fixups
;
struct
dll_fixup
{
struct
list
entry
;
int
done
;
HMODULE
dll
;
void
*
thunk_code
;
/* pointer into dll_fixup_heap */
VTableFixup
*
fixup
;
void
*
vtable
;
void
*
tokens
;
/* pointer into process heap */
};
static
HRESULT
RuntimeHost_AddDomain
(
RuntimeHost
*
This
,
MonoDomain
**
result
)
{
struct
DomainEntry
*
entry
;
...
...
@@ -803,19 +820,207 @@ static void get_utf8_args(int *argc, char ***argv)
HeapFree
(
GetProcessHeap
(),
0
,
argvw
);
}
#if __i386__
# define CAN_FIXUP_VTABLE 1
#include "pshpack1.h"
struct
vtable_fixup_thunk
{
/* sub $0x4,%esp */
BYTE
i1
[
3
];
/* mov fixup,(%esp) */
BYTE
i2
[
3
];
struct
dll_fixup
*
fixup
;
/* mov function,%eax */
BYTE
i3
;
void
(
CDECL
*
function
)(
struct
dll_fixup
*
);
/* call *%eax */
BYTE
i4
[
2
];
/* pop %eax */
BYTE
i5
;
/* jmp *vtable_entry */
BYTE
i6
[
2
];
void
*
vtable_entry
;
};
static
const
struct
vtable_fixup_thunk
thunk_template
=
{
{
0x83
,
0xec
,
0x04
},
{
0xc7
,
0x04
,
0x24
},
NULL
,
0xb8
,
NULL
,
{
0xff
,
0xd0
},
0x58
,
{
0xff
,
0x25
},
NULL
};
#include "poppack.h"
#else
/* !defined(__i386__) */
# define CAN_FIXUP_VTABLE 0
struct
vtable_fixup_thunk
{
struct
dll_fixup
*
fixup
;
void
(
CDECL
*
function
)(
struct
dll_fixup
*
fixup
);
void
*
vtable_entry
;
};
static
const
struct
vtable_fixup_thunk
thunk_template
=
{
0
};
#endif
static
void
CDECL
ReallyFixupVTable
(
struct
dll_fixup
*
fixup
)
{
HRESULT
hr
=
S_OK
;
WCHAR
filename
[
MAX_PATH
];
ICLRRuntimeInfo
*
info
=
NULL
;
RuntimeHost
*
host
;
char
*
filenameA
;
MonoImage
*
image
=
NULL
;
MonoAssembly
*
assembly
=
NULL
;
MonoImageOpenStatus
status
=
0
;
MonoDomain
*
domain
;
if
(
fixup
->
done
)
return
;
/* It's possible we'll have two threads doing this at once. This is
* considered preferable to the potential deadlock if we use a mutex. */
GetModuleFileNameW
(
fixup
->
dll
,
filename
,
MAX_PATH
);
TRACE
(
"%p,%p,%s
\n
"
,
fixup
,
fixup
->
dll
,
debugstr_w
(
filename
));
filenameA
=
WtoA
(
filename
);
if
(
!
filenameA
)
hr
=
E_OUTOFMEMORY
;
if
(
SUCCEEDED
(
hr
))
hr
=
get_runtime_info
(
filename
,
NULL
,
NULL
,
0
,
0
,
FALSE
,
&
info
);
if
(
SUCCEEDED
(
hr
))
hr
=
ICLRRuntimeInfo_GetRuntimeHost
(
info
,
&
host
);
if
(
SUCCEEDED
(
hr
))
hr
=
RuntimeHost_GetDefaultDomain
(
host
,
&
domain
);
if
(
SUCCEEDED
(
hr
))
{
host
->
mono
->
mono_thread_attach
(
domain
);
image
=
host
->
mono
->
mono_image_open_from_module_handle
(
fixup
->
dll
,
filenameA
,
1
,
&
status
);
}
if
(
image
)
assembly
=
host
->
mono
->
mono_assembly_load_from
(
image
,
filenameA
,
&
status
);
if
(
assembly
)
{
int
i
;
/* Mono needs an image that belongs to an assembly. */
image
=
host
->
mono
->
mono_assembly_get_image
(
assembly
);
if
(
fixup
->
fixup
->
type
&
COR_VTABLE_32BIT
)
{
DWORD
*
vtable
=
fixup
->
vtable
;
DWORD
*
tokens
=
fixup
->
tokens
;
for
(
i
=
0
;
i
<
fixup
->
fixup
->
count
;
i
++
)
{
TRACE
(
"%x
\n
"
,
tokens
[
i
]);
vtable
[
i
]
=
PtrToUint
(
host
->
mono
->
mono_marshal_get_vtfixup_ftnptr
(
image
,
tokens
[
i
],
fixup
->
fixup
->
type
));
}
}
fixup
->
done
=
1
;
}
if
(
info
!=
NULL
)
ICLRRuntimeHost_Release
(
info
);
HeapFree
(
GetProcessHeap
(),
0
,
filenameA
);
if
(
!
fixup
->
done
)
{
ERR
(
"unable to fixup vtable, hr=%x, status=%d
\n
"
,
hr
,
status
);
/* If we returned now, we'd get an infinite loop. */
assert
(
0
);
}
}
static
void
FixupVTableEntry
(
HMODULE
hmodule
,
VTableFixup
*
vtable_fixup
)
{
/* We can't actually generate code for the functions without loading mono,
* and loading mono inside DllMain is a terrible idea. So we make thunks
* that call ReallyFixupVTable, which will load the runtime and fill in the
* vtable, then do an indirect jump using the (now filled in) vtable. Note
* that we have to keep the thunks around forever, as one of them may get
* called while we're filling in the table, and we can never be sure all
* threads are clear. */
struct
dll_fixup
*
fixup
;
fixup
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
fixup
));
fixup
->
dll
=
hmodule
;
fixup
->
thunk_code
=
HeapAlloc
(
dll_fixup_heap
,
0
,
sizeof
(
struct
vtable_fixup_thunk
)
*
vtable_fixup
->
count
);
fixup
->
fixup
=
vtable_fixup
;
fixup
->
vtable
=
(
BYTE
*
)
hmodule
+
vtable_fixup
->
rva
;
fixup
->
done
=
0
;
if
(
vtable_fixup
->
type
&
COR_VTABLE_32BIT
)
{
DWORD
*
vtable
=
fixup
->
vtable
;
DWORD
*
tokens
;
int
i
;
struct
vtable_fixup_thunk
*
thunks
=
fixup
->
thunk_code
;
if
(
sizeof
(
void
*
)
>
4
)
ERR
(
"32-bit fixup in 64-bit mode; broken image?
\n
"
);
tokens
=
fixup
->
tokens
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
tokens
)
*
vtable_fixup
->
count
);
memcpy
(
tokens
,
vtable
,
sizeof
(
*
tokens
)
*
vtable_fixup
->
count
);
for
(
i
=
0
;
i
<
vtable_fixup
->
count
;
i
++
)
{
memcpy
(
&
thunks
[
i
],
&
thunk_template
,
sizeof
(
thunk_template
));
thunks
[
i
].
fixup
=
fixup
;
thunks
[
i
].
function
=
ReallyFixupVTable
;
thunks
[
i
].
vtable_entry
=
&
vtable
[
i
];
vtable
[
i
]
=
PtrToUint
(
&
thunks
[
i
]);
}
}
else
{
ERR
(
"unsupported vtable fixup flags %x
\n
"
,
vtable_fixup
->
type
);
HeapFree
(
dll_fixup_heap
,
0
,
fixup
->
thunk_code
);
HeapFree
(
GetProcessHeap
(),
0
,
fixup
);
return
;
}
list_add_tail
(
&
dll_fixups
,
&
fixup
->
entry
);
}
static
void
FixupVTable
(
HMODULE
hmodule
)
{
ASSEMBLY
*
assembly
;
HRESULT
hr
;
VTableFixup
*
vtable_fixups
;
ULONG
vtable_fixup_count
;
ULONG
vtable_fixup_count
,
i
;
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
"
);
if
(
CAN_FIXUP_VTABLE
)
for
(
i
=
0
;
i
<
vtable_fixup_count
;
i
++
)
FixupVTableEntry
(
hmodule
,
&
vtable_fixups
[
i
]);
else
if
(
vtable_fixup_count
)
FIXME
(
"cannot fixup vtable; expect a crash
\n
"
);
assembly_release
(
assembly
);
}
...
...
@@ -909,11 +1114,32 @@ BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
FixupVTable
(
hinstDLL
);
break
;
case
DLL_PROCESS_DETACH
:
/* FIXME: clean up the vtables */
break
;
}
return
TRUE
;
}
/* called from DLL_PROCESS_ATTACH */
void
runtimehost_init
(
void
)
{
dll_fixup_heap
=
HeapCreate
(
HEAP_CREATE_ENABLE_EXECUTE
,
0
,
0
);
list_init
(
&
dll_fixups
);
}
/* called from DLL_PROCESS_DETACH */
void
runtimehost_uninit
(
void
)
{
struct
dll_fixup
*
fixup
,
*
fixup2
;
HeapDestroy
(
dll_fixup_heap
);
LIST_FOR_EACH_ENTRY_SAFE
(
fixup
,
fixup2
,
&
dll_fixups
,
struct
dll_fixup
,
entry
)
{
HeapFree
(
GetProcessHeap
(),
0
,
fixup
->
tokens
);
HeapFree
(
GetProcessHeap
(),
0
,
fixup
);
}
}
HRESULT
RuntimeHost_Construct
(
const
CLRRuntimeInfo
*
runtime_version
,
loaded_mono
*
loaded_mono
,
RuntimeHost
**
result
)
{
...
...
dlls/mscoree/metahost.c
View file @
a629ba49
...
...
@@ -177,6 +177,7 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result)
LOAD_MONO_FUNCTION
(
mono_jit_exec
);
LOAD_MONO_FUNCTION
(
mono_jit_init
);
LOAD_MONO_FUNCTION
(
mono_jit_set_trace_options
);
LOAD_MONO_FUNCTION
(
mono_marshal_get_vtfixup_ftnptr
);
LOAD_MONO_FUNCTION
(
mono_object_get_domain
);
LOAD_MONO_FUNCTION
(
mono_object_new
);
LOAD_MONO_FUNCTION
(
mono_object_unbox
);
...
...
dlls/mscoree/mscoree_main.c
View file @
a629ba49
...
...
@@ -227,10 +227,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
case
DLL_WINE_PREATTACH
:
return
FALSE
;
/* prefer native version */
case
DLL_PROCESS_ATTACH
:
runtimehost_init
();
DisableThreadLibraryCalls
(
hinstDLL
);
break
;
case
DLL_PROCESS_DETACH
:
expect_no_runtimes
();
if
(
lpvReserved
)
break
;
/* process is terminating */
runtimehost_uninit
();
break
;
}
return
TRUE
;
...
...
dlls/mscoree/mscoree_private.h
View file @
a629ba49
...
...
@@ -159,6 +159,7 @@ struct loaded_mono
int
(
CDECL
*
mono_jit_exec
)(
MonoDomain
*
domain
,
MonoAssembly
*
assembly
,
int
argc
,
char
*
argv
[]);
MonoDomain
*
(
CDECL
*
mono_jit_init
)(
const
char
*
file
);
int
(
CDECL
*
mono_jit_set_trace_options
)(
const
char
*
options
);
void
*
(
CDECL
*
mono_marshal_get_vtfixup_ftnptr
)(
MonoImage
*
image
,
DWORD
token
,
WORD
type
);
MonoDomain
*
(
CDECL
*
mono_object_get_domain
)(
MonoObject
*
obj
);
MonoObject
*
(
CDECL
*
mono_object_new
)(
MonoDomain
*
domain
,
MonoClass
*
klass
);
void
*
(
CDECL
*
mono_object_unbox
)(
MonoObject
*
obj
);
...
...
@@ -200,4 +201,7 @@ extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) D
extern
HRESULT
create_monodata
(
REFIID
riid
,
LPVOID
*
ppObj
)
DECLSPEC_HIDDEN
;
extern
void
runtimehost_init
(
void
);
extern
void
runtimehost_uninit
(
void
);
#endif
/* __MSCOREE_PRIVATE__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment