mirror of
https://github.com/mpv-player/mpv
synced 2025-05-09 10:21:43 +02:00
- qtx (quicktime's macos emulation layer) debugging/emulation environment :)
- some fixes in loadlibrary, to allow multiple loads/lookups git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8270 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
dc18e7dcbe
commit
be4c25600b
@ -6,7 +6,7 @@ DEFINES=$(WIN32_PATH) -DMPLAYER -D__WINE__ -Ddbg_printf=__vprintf \
|
|||||||
|
|
||||||
LIB_OBJECTS= ldt_keeper.o pe_image.o module.o \
|
LIB_OBJECTS= ldt_keeper.o pe_image.o module.o \
|
||||||
ext.o win32.o driver.o pe_resource.o \
|
ext.o win32.o driver.o pe_resource.o \
|
||||||
resource.o registry.o elfdll.o afl.o vfl.o
|
resource.o registry.o elfdll.o afl.o vfl.o wrapper.o
|
||||||
|
|
||||||
# gcc-3.0 produces buggy code for acmStreamOpen() with
|
# gcc-3.0 produces buggy code for acmStreamOpen() with
|
||||||
# "-O3 -fomit-frame-pointer" or "-O2 -fomit-frame-pointer
|
# "-O3 -fomit-frame-pointer" or "-O2 -fomit-frame-pointer
|
||||||
|
408
loader/module.c
408
loader/module.c
@ -3,6 +3,13 @@
|
|||||||
*
|
*
|
||||||
* Copyright 1995 Alexandre Julliard
|
* Copyright 1995 Alexandre Julliard
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// define for quicktime calls debugging and/or MacOS-level emulation:
|
||||||
|
//#define EMU_QTX_API
|
||||||
|
|
||||||
|
// define for quicktime debugging (verbose logging):
|
||||||
|
//#define DEBUG_QTX_API
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -15,13 +22,15 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
#include "wine/windef.h"
|
#include "wine/windef.h"
|
||||||
#include "wine/winerror.h"
|
#include "wine/winerror.h"
|
||||||
#include "wine/heap.h"
|
#include "wine/heap.h"
|
||||||
#include "wine/module.h"
|
#include "wine/module.h"
|
||||||
#include "wine/pe_image.h"
|
#include "wine/pe_image.h"
|
||||||
#include "wine/debugtools.h"
|
#include "wine/debugtools.h"
|
||||||
|
|
||||||
|
#undef HAVE_LIBDL
|
||||||
|
|
||||||
#ifdef HAVE_LIBDL
|
#ifdef HAVE_LIBDL
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include "wine/elfdll.h"
|
#include "wine/elfdll.h"
|
||||||
@ -29,6 +38,12 @@
|
|||||||
#include "win32.h"
|
#include "win32.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
|
#ifdef EMU_QTX_API
|
||||||
|
#include "wrapper.h"
|
||||||
|
static int report_func(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags);
|
||||||
|
static int report_func_ret(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
//#undef TRACE
|
//#undef TRACE
|
||||||
//#define TRACE printf
|
//#define TRACE printf
|
||||||
|
|
||||||
@ -43,7 +58,8 @@ WINE_MODREF* MODULE_FindModule(LPCSTR m)
|
|||||||
TRACE("Module %s request\n", m);
|
TRACE("Module %s request\n", m);
|
||||||
if(list==NULL)
|
if(list==NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
while(strcmp(m, list->wm->filename))
|
// while(strcmp(m, list->wm->filename))
|
||||||
|
while(!strstr(list->wm->filename, m))
|
||||||
{
|
{
|
||||||
TRACE("%s: %x\n", list->wm->filename, list->wm->module);
|
TRACE("%s: %x\n", list->wm->filename, list->wm->module);
|
||||||
list=list->prev;
|
list=list->prev;
|
||||||
@ -295,6 +311,17 @@ static WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD fl
|
|||||||
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
||||||
pwm->refCount++;
|
pwm->refCount++;
|
||||||
|
|
||||||
|
#ifdef EMU_QTX_API
|
||||||
|
if(strstr(libname,"QuickTime.qts")){
|
||||||
|
void** ptr=0x62b75ca4;
|
||||||
|
fprintf(stderr,"QuickTime.qts entrypoint patched!!! old=%p\n",ptr[0]);
|
||||||
|
report_entry = report_func;
|
||||||
|
report_ret = report_func_ret;
|
||||||
|
wrapper_target=ptr[0];
|
||||||
|
ptr[0]=wrapper;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SetLastError( err ); /* restore last error */
|
SetLastError( err ); /* restore last error */
|
||||||
return pwm;
|
return pwm;
|
||||||
}
|
}
|
||||||
@ -344,6 +371,10 @@ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
|||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wm=MODULE_FindModule(libname);
|
||||||
|
if(wm) return wm->module;
|
||||||
|
|
||||||
// if(fs_installed==0)
|
// if(fs_installed==0)
|
||||||
// install_fs();
|
// install_fs();
|
||||||
|
|
||||||
@ -472,6 +503,337 @@ FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
|
|||||||
return MODULE_GetProcAddress( hModule, function, TRUE );
|
return MODULE_GetProcAddress( hModule, function, TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
|
||||||
|
struct ComponentParameters {
|
||||||
|
unsigned char flags; /* call modifiers: sync/async, deferred, immed, etc */
|
||||||
|
unsigned char paramSize; /* size in bytes of actual parameters passed to this call */
|
||||||
|
short what; /* routine selector, negative for Component management calls */
|
||||||
|
long params[1]; /* actual parameters for the indicated routine */
|
||||||
|
};
|
||||||
|
typedef struct ComponentParameters ComponentParameters;
|
||||||
|
|
||||||
|
static char* component_func(int what){
|
||||||
|
switch(what){
|
||||||
|
case -1: return "kComponentOpenSelect";
|
||||||
|
case -2: return "kComponentCloseSelect";
|
||||||
|
case -3: return "kComponentCanDoSelect";
|
||||||
|
case -4: return "kComponentVersionSelect";
|
||||||
|
case -5: return "kComponentRegisterSelect";
|
||||||
|
case -6: return "kComponentTargetSelect";
|
||||||
|
case -7: return "kComponentUnregisterSelect";
|
||||||
|
}
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* component_func_type(int type,int what){
|
||||||
|
if(type==1) switch(what){
|
||||||
|
case 0: return "kImageCodecGetCodecInfoSelect";
|
||||||
|
case 1: return "kImageCodecGetCompressionTimeSelect";
|
||||||
|
case 5: return "kImageCodecPreDecompressSelect";
|
||||||
|
case 6: return "kImageCodecBandDecompressSelect";
|
||||||
|
case 0x12: return "kImageCodecDisposeMemorySelect";
|
||||||
|
case 0x10: return "kImageCodecIsImageDescriptionEquivalentSelect";
|
||||||
|
case 0x14: return "kImageCodecNewImageBufferMemorySelect";
|
||||||
|
case 0x28: return "kImageCodecRequestGammaLevelSelect";
|
||||||
|
}
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int c_level=0;
|
||||||
|
|
||||||
|
static int dump_component(char* name,int type,void* _orig, ComponentParameters *params,void** glob){
|
||||||
|
int ( *orig)(ComponentParameters *params, void** glob) = _orig;
|
||||||
|
int ret,i;
|
||||||
|
|
||||||
|
if(params->what<0)
|
||||||
|
fprintf(stderr,"%*sComponentCall: %s flags=0x%X size=%d what=%d %s\n",3*c_level,"",name,params->flags, params->paramSize, params->what, component_func(params->what));
|
||||||
|
else
|
||||||
|
fprintf(stderr,"%*sComponentCall: %s flags=0x%X size=%d what=0x%X %s\n",3*c_level,"",name,params->flags, params->paramSize, params->what, component_func_type(type,params->what));
|
||||||
|
|
||||||
|
for(i=0;i<params->paramSize/4;i++)
|
||||||
|
fprintf(stderr,"%*s param[%d] = 0x%X\n",3*c_level,"",i,params->params[i]);
|
||||||
|
|
||||||
|
++c_level;
|
||||||
|
ret=orig(params,glob);
|
||||||
|
--c_level;
|
||||||
|
|
||||||
|
if(ret>=0x1000)
|
||||||
|
fprintf(stderr,"%*s return=0x%X\n",3*c_level,"",ret);
|
||||||
|
else
|
||||||
|
fprintf(stderr,"%*s return=%d\n",3*c_level,"",ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DECL_COMPONENT(sname,name,type) \
|
||||||
|
static void* real_ ## sname = NULL; \
|
||||||
|
static int fake_ ## sname(ComponentParameters *params,void** glob){ \
|
||||||
|
return dump_component(name,type,real_ ## sname, params, glob); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "qt_comp.h"
|
||||||
|
|
||||||
|
#undef DECL_COMPONENT
|
||||||
|
|
||||||
|
#include "qt_fv.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EMU_QTX_API
|
||||||
|
|
||||||
|
static u_int32_t ret_array[4096];
|
||||||
|
static int ret_i=0;
|
||||||
|
|
||||||
|
static int report_func(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
int i;
|
||||||
|
int* dptr;
|
||||||
|
void* pwrapper=NULL;
|
||||||
|
void* pptr=NULL;
|
||||||
|
char* pname=NULL;
|
||||||
|
int plen=-1;
|
||||||
|
// find the code:
|
||||||
|
|
||||||
|
dptr=0x62b67ae0;dptr+=2*((reg->eax>>16)&255);
|
||||||
|
// printf("FUNC: flag=%d ptr=%p\n",dptr[0],dptr[1]);
|
||||||
|
if(dptr[0]&255){
|
||||||
|
dptr=dptr[1];dptr+=4*(reg->eax&65535);
|
||||||
|
// printf("FUNC: ptr2=%p eax=%p edx=%p\n",dptr[1],dptr[0],dptr[2]);
|
||||||
|
pwrapper=dptr[1]; pptr=dptr[0]; plen=dptr[2];
|
||||||
|
} else {
|
||||||
|
pwrapper=0x62924910;
|
||||||
|
switch(dptr[1]){
|
||||||
|
case 0x629248d0:
|
||||||
|
dptr=0x62b672c0;dptr+=2*(reg->eax&65535);
|
||||||
|
// printf("FUNC: ptr2=%p eax=%p edx=%p\n",0x62924910,dptr[0],dptr[1]);
|
||||||
|
pptr=dptr[0]; plen=dptr[1];
|
||||||
|
break;
|
||||||
|
case 0x62924e40:
|
||||||
|
dptr=0x62b67c70;dptr+=2*(reg->eax&65535);
|
||||||
|
// printf("FUNC: ptr2=%p eax=%p edx=%p\n",0x62924910,dptr[0],dptr[1]);
|
||||||
|
pptr=dptr[0]; plen=dptr[1];
|
||||||
|
break;
|
||||||
|
case 0x62924e60:
|
||||||
|
dptr=0x62b68108;if(reg->eax&0x8000) dptr+=2*(reg->eax|0xffff0000); else dptr+=2*(reg->eax&65535);
|
||||||
|
// printf("FUNC: ptr2=%p eax=%p edx=%p\n",0x62924910,dptr[0],dptr[1]);
|
||||||
|
pptr=dptr[0]; plen=dptr[1];
|
||||||
|
break;
|
||||||
|
case 0x62924e80:
|
||||||
|
dptr=0x62b68108;if(reg->eax&0x8000) dptr+=2*(reg->eax|0xffff0000); else dptr+=2*(reg->eax&65535);
|
||||||
|
// printf("FUNC: ptr2=%p eax=%p edx=%p\n",0x62924910,dptr[0],dptr[1]);
|
||||||
|
pptr=dptr[0]; plen=dptr[1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("FUNC: unknown ptr & psize!\n");
|
||||||
|
pwrapper=dptr[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;qt_fv_list[i].name;i++){
|
||||||
|
if(qt_fv_list[i].id==reg->eax){
|
||||||
|
pname=qt_fv_list[i].name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("FUNC[%X/%s]: wrapper=%p func=%p len=%d\n",reg->eax,
|
||||||
|
pname?pname:"???",pwrapper,pptr,plen);
|
||||||
|
|
||||||
|
printf("FUNC: caller=%p ebx=%p\n",((u_int32_t *)stack_base)[0],reg->ebx);
|
||||||
|
|
||||||
|
if(pname)
|
||||||
|
printf("%*sENTER(%d): %s(",ret_i*2,"",ret_i,pname);
|
||||||
|
else
|
||||||
|
printf("%*sENTER(%d): %X(",ret_i*2,"",ret_i,reg->eax);
|
||||||
|
for (i=0;i<plen/4;i++){
|
||||||
|
unsigned int val=((u_int32_t *)stack_base)[1+i];
|
||||||
|
unsigned char* fcc=&val;
|
||||||
|
printf("%s0x%X", i?", ":"",val);
|
||||||
|
if(fcc[0]>=0x20 && fcc[0]<128 &&
|
||||||
|
fcc[1]>=0x20 && fcc[1]<128 &&
|
||||||
|
fcc[2]>=0x20 && fcc[2]<128 &&
|
||||||
|
fcc[3]>=0x20 && fcc[3]<128) printf("='%c%c%c%c'",fcc[3],fcc[2],fcc[1],fcc[0]);
|
||||||
|
else if(val>=8 && val<65536) printf("=%d",val);
|
||||||
|
}
|
||||||
|
printf(")\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// emulate some functions:
|
||||||
|
switch(reg->eax){
|
||||||
|
// memory management:
|
||||||
|
case 0x150011: //NewPtrClear
|
||||||
|
case 0x150012: //NewPtrSysClear
|
||||||
|
reg->eax=malloc(((u_int32_t *)stack_base)[1]);
|
||||||
|
memset(reg->eax,0,((u_int32_t *)stack_base)[1]);
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
case 0x15000F: //NewPtr
|
||||||
|
case 0x150010: //NewPtrSys
|
||||||
|
reg->eax=malloc(((u_int32_t *)stack_base)[1]);
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
case 0x15002f: //DisposePtr
|
||||||
|
if(((u_int32_t *)stack_base)[1]>=0x60000000)
|
||||||
|
printf("WARNING! Invalid Ptr handle!\n");
|
||||||
|
else
|
||||||
|
free(((u_int32_t *)stack_base)[1]);
|
||||||
|
reg->eax=0;
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
// mutexes:
|
||||||
|
case 0x1d0033: //QTMLCreateMutex
|
||||||
|
reg->eax=0xdeadbabe;
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
case 0x1d0034: //QTMLDestroyMutex
|
||||||
|
case 0x1d0035: //QTMLGrabMutex
|
||||||
|
case 0x1d0036: //QTMLReturnMutex
|
||||||
|
case 0x1d003d: //QTMLTryGrabMutex
|
||||||
|
reg->eax=0;
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
switch(reg->eax){
|
||||||
|
// case 0x00010000:
|
||||||
|
// printf("FUNC: ImageCodecInitialize/ImageCodecGetCodecInfo(ci=%p,&icap=%p)\n",((u_int32_t *)stack_base)[1],((u_int32_t *)stack_base)[4]);
|
||||||
|
// break;
|
||||||
|
case 0x00010003:
|
||||||
|
printf("FUNC: CountComponents(&desc=%p)\n",((u_int32_t *)stack_base)[1]);
|
||||||
|
break;
|
||||||
|
case 0x00010004:
|
||||||
|
printf("FUNC: FindNextComponent(prev=%p,&desc=%p)\n",((u_int32_t *)stack_base)[1],((u_int32_t *)stack_base)[2]);
|
||||||
|
break;
|
||||||
|
case 0x00010007:
|
||||||
|
printf("FUNC: OpenComponent(prev=%p)\n",((u_int32_t *)stack_base)[1]);
|
||||||
|
break;
|
||||||
|
case 0x0003008b:
|
||||||
|
printf("FUNC: QTNewGWorldFromPtr(&pts=%p,fourcc=%.4s,&rect=%p,x1=%p,x2=%p,x3=%p,plane=%p,stride=%d)\n",
|
||||||
|
((u_int32_t *)stack_base)[1],
|
||||||
|
&(((u_int32_t *)stack_base)[2]),
|
||||||
|
((u_int32_t *)stack_base)[3],
|
||||||
|
((u_int32_t *)stack_base)[4],
|
||||||
|
((u_int32_t *)stack_base)[5],
|
||||||
|
((u_int32_t *)stack_base)[6],
|
||||||
|
((u_int32_t *)stack_base)[7],
|
||||||
|
((u_int32_t *)stack_base)[8]);
|
||||||
|
break;
|
||||||
|
case 0x001c0018:
|
||||||
|
printf("FUNC: GetGWorldPixMap(gworld=%p)\n",((u_int32_t *)stack_base)[1]);
|
||||||
|
break;
|
||||||
|
case 0x00110001:
|
||||||
|
printf("FUNC: Gestalt(fourcc=%.4s, &ret=%p)\n",&(((u_int32_t *)stack_base)[1]),((u_int32_t *)stack_base)[2]);
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
int i;
|
||||||
|
for(i=0;qt_fv_list[i].name;i++){
|
||||||
|
if(qt_fv_list[i].id==reg->eax){
|
||||||
|
printf("FUNC: %s\n",qt_fv_list[i].name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print stack/reg information
|
||||||
|
printf("ENTER(%d) stack = %d bytes @ %p\n"
|
||||||
|
"eax = 0x%08x edx = 0x%08x ebx = 0x%08x ecx = 0x%08x\n"
|
||||||
|
"esp = 0x%08x ebp = 0x%08x esi = 0x%08x edi = 0x%08x\n"
|
||||||
|
"flags = 0x%08x\n", ret_i,
|
||||||
|
stack_size, stack_base,
|
||||||
|
reg->eax, reg->edx, reg->ebx, reg->ecx,
|
||||||
|
reg->esp, reg->ebp, reg->esi, reg->edi,
|
||||||
|
*flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// save ret addr:
|
||||||
|
ret_array[ret_i]=((u_int32_t *)stack_base)[0];
|
||||||
|
++ret_i;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// print first 7 longs in the stack (return address, arg[1], arg[2] ... )
|
||||||
|
printf("stack[] = { ");
|
||||||
|
for (i=0;i<7;i++) {
|
||||||
|
printf("%08x ", ((u_int32_t *)stack_base)[i]);
|
||||||
|
}
|
||||||
|
printf("}\n\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// // mess with function parameters
|
||||||
|
// ((u_int32_t *)stack_base)[1] = 0x66554433;
|
||||||
|
|
||||||
|
// // mess with return address...
|
||||||
|
// reg->eax = 0x11223344;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int report_func_ret(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
short err;
|
||||||
|
|
||||||
|
// restore ret addr:
|
||||||
|
--ret_i;
|
||||||
|
((u_int32_t *)stack_base)[0]=ret_array[ret_i];
|
||||||
|
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
printf("%*sLEAVE(%d): 0x%X",ret_i*2,"",ret_i, reg->eax);
|
||||||
|
err=reg->eax;
|
||||||
|
if(err && (reg->eax>>16)==0) printf(" = %d",err);
|
||||||
|
printf("\n");
|
||||||
|
fflush(stdout);
|
||||||
|
#else
|
||||||
|
// print stack/reg information
|
||||||
|
printf("LEAVE(%d) stack = %d bytes @ %p\n"
|
||||||
|
"eax = 0x%08x edx = 0x%08x ebx = 0x%08x ecx = 0x%08x\n"
|
||||||
|
"esp = 0x%08x ebp = 0x%08x esi = 0x%08x edi = 0x%08x\n"
|
||||||
|
"flags = 0x%08x\n", ret_i,
|
||||||
|
stack_size, stack_base,
|
||||||
|
reg->eax, reg->edx, reg->ebx, reg->ecx,
|
||||||
|
reg->esp, reg->ebp, reg->esi, reg->edi,
|
||||||
|
*flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// print first 7 longs in the stack (return address, arg[1], arg[2] ... )
|
||||||
|
printf("stack[] = { ");
|
||||||
|
for (i=0;i<7;i++) {
|
||||||
|
printf("%08x ", ((u_int32_t *)stack_base)[i]);
|
||||||
|
}
|
||||||
|
printf("}\n\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// // mess with function parameters
|
||||||
|
// ((u_int32_t *)stack_base)[1] = 0x66554433;
|
||||||
|
|
||||||
|
// // mess with return address...
|
||||||
|
// reg->eax = 0x11223344;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MODULE_GetProcAddress (internal)
|
* MODULE_GetProcAddress (internal)
|
||||||
*/
|
*/
|
||||||
@ -484,10 +846,17 @@ FARPROC MODULE_GetProcAddress(
|
|||||||
// WINE_MODREF *wm=local_wm;
|
// WINE_MODREF *wm=local_wm;
|
||||||
FARPROC retproc;
|
FARPROC retproc;
|
||||||
|
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
if (HIWORD(function))
|
if (HIWORD(function))
|
||||||
TRACE_(win32)("(%08lx,%s)\n",(DWORD)hModule,function);
|
fprintf(stderr,"XXX GetProcAddress(%08lx,%s)\n",(DWORD)hModule,function);
|
||||||
else
|
else
|
||||||
TRACE_(win32)("(%08lx,%p)\n",(DWORD)hModule,function);
|
fprintf(stderr,"XXX GetProcAddress(%08lx,%p)\n",(DWORD)hModule,function);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TRACE_(win32)("(%08lx,%s)\n",(DWORD)hModule,function);
|
||||||
|
// else
|
||||||
|
// TRACE_(win32)("(%08lx,%p)\n",(DWORD)hModule,function);
|
||||||
|
|
||||||
if (!wm) {
|
if (!wm) {
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
return (FARPROC)0;
|
return (FARPROC)0;
|
||||||
@ -497,7 +866,7 @@ FARPROC MODULE_GetProcAddress(
|
|||||||
case MODULE32_PE:
|
case MODULE32_PE:
|
||||||
retproc = PE_FindExportedFunction( wm, function, snoop );
|
retproc = PE_FindExportedFunction( wm, function, snoop );
|
||||||
if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
|
if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
|
||||||
return retproc;
|
break;
|
||||||
#ifdef HAVE_LIBDL
|
#ifdef HAVE_LIBDL
|
||||||
case MODULE32_ELF:
|
case MODULE32_ELF:
|
||||||
retproc = (FARPROC) dlsym( (void*) wm->module, function);
|
retproc = (FARPROC) dlsym( (void*) wm->module, function);
|
||||||
@ -509,6 +878,35 @@ FARPROC MODULE_GetProcAddress(
|
|||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
return (FARPROC)0;
|
return (FARPROC)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EMU_QTX_API
|
||||||
|
if (HIWORD(function) && retproc){
|
||||||
|
|
||||||
|
#ifdef DEBUG_QTX_API
|
||||||
|
#define DECL_COMPONENT(sname,name,type) \
|
||||||
|
if(!strcmp(function,name)){ \
|
||||||
|
fprintf(stderr,name "dispatcher catched -> %p\n",retproc); \
|
||||||
|
real_ ## sname = retproc; retproc = fake_ ## sname; \
|
||||||
|
}
|
||||||
|
#include "qt_comp.h"
|
||||||
|
#undef DECL_COMPONENT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!strcmp(function,"theQuickTimeDispatcher")
|
||||||
|
// || !strcmp(function,"_CallComponentFunctionWithStorage")
|
||||||
|
// || !strcmp(function,"_CallComponent")
|
||||||
|
){
|
||||||
|
fprintf(stderr,"theQuickTimeDispatcher catched -> %p\n",retproc);
|
||||||
|
report_entry = report_func;
|
||||||
|
report_ret = report_func_ret;
|
||||||
|
wrapper_target=retproc;
|
||||||
|
retproc=wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return retproc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acounter = 0;
|
static int acounter = 0;
|
||||||
|
27
loader/qt_comp.h
Normal file
27
loader/qt_comp.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
DECL_COMPONENT(sorenson3,"SMD_ComponentDispatch",1)
|
||||||
|
DECL_COMPONENT(sorenson,"SorensonYUV9Dispatcher",1)
|
||||||
|
DECL_COMPONENT(sorenson1,"SVD_ComponentDispatch",1)
|
||||||
|
DECL_COMPONENT(genericd,"GenericComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(stmedia,"STMediaComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(handlecd,"HandleComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(pcxcd,"PCExchangeComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(capcd,"CapComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(videocd,"VideoComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(soundcd,"SoundComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(scalingcd,"ScalingCodecDispatcher",0)
|
||||||
|
DECL_COMPONENT(formatcnv,"FormatConverterDispatch",0)
|
||||||
|
|
||||||
|
DECL_COMPONENT(basecd,"Base_CDComponentDispatch",1)
|
||||||
|
DECL_COMPONENT(ddcd,"DD_CDComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(fakergb,"FakeRGBDispatcher",0)
|
||||||
|
DECL_COMPONENT(rawcd,"RAW_CDComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(yuvsgi,"YUVSGI_CDComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(yuvs,"YUVS_CDComponentDispatch",0)
|
||||||
|
DECL_COMPONENT(yuvu,"YUVU_CDComponentDispatch",0)
|
||||||
|
|
||||||
|
DECL_COMPONENT(qdm2d,"QDM2Decompressor",0)
|
||||||
|
DECL_COMPONENT(mace3d,"Mace3DecompDispatch",0)
|
||||||
|
|
||||||
|
//DECL_COMPONENT(,"",0)
|
||||||
|
|
1586
loader/qt_fv.h
Normal file
1586
loader/qt_fv.h
Normal file
File diff suppressed because it is too large
Load Diff
83
loader/wrapper.S
Normal file
83
loader/wrapper.S
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
.section .data
|
||||||
|
.globl caller_return
|
||||||
|
caller_return:
|
||||||
|
.long 0
|
||||||
|
.globl report_entry
|
||||||
|
report_entry:
|
||||||
|
.long null_call
|
||||||
|
.globl report_ret
|
||||||
|
report_ret:
|
||||||
|
.long null_call
|
||||||
|
.global wrapper_target
|
||||||
|
wrapper_target:
|
||||||
|
.long null_call
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.globl null_call
|
||||||
|
.type null_call, @function
|
||||||
|
.align 16,0x90
|
||||||
|
null_call:
|
||||||
|
ret
|
||||||
|
.globl wrapper
|
||||||
|
.type wrapper, @function
|
||||||
|
.align 16,0x90
|
||||||
|
wrapper:
|
||||||
|
pusha # store registers (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI)
|
||||||
|
pushf # store flags
|
||||||
|
|
||||||
|
push %ebp # set up a stack frame
|
||||||
|
movl %esp, %ebp
|
||||||
|
|
||||||
|
leal 4(%ebp), %eax # push flags addr
|
||||||
|
push %eax
|
||||||
|
leal 8(%ebp), %eax # push registers addr
|
||||||
|
push %eax
|
||||||
|
|
||||||
|
leal 40(%ebp), %edx
|
||||||
|
movl (%ebp), %eax
|
||||||
|
subl %edx, %eax
|
||||||
|
push %eax
|
||||||
|
push %edx
|
||||||
|
|
||||||
|
call *report_entry # report entry
|
||||||
|
|
||||||
|
test %eax, %eax
|
||||||
|
jnz .Ldone
|
||||||
|
|
||||||
|
leave # restore %esp, %ebp
|
||||||
|
popf # restore flags
|
||||||
|
popa # restore registers
|
||||||
|
|
||||||
|
popl caller_return # switch return addresses
|
||||||
|
pushl $.Lwrapper_return
|
||||||
|
|
||||||
|
jmp *wrapper_target # wrapper_target should return at .Lwrapper_return
|
||||||
|
|
||||||
|
.align 16, 0x90
|
||||||
|
.Lwrapper_return:
|
||||||
|
pushl caller_return # restore the original return address
|
||||||
|
pusha # more for reference sake here
|
||||||
|
pushf
|
||||||
|
|
||||||
|
push %ebp # set up a stack frame
|
||||||
|
movl %esp, %ebp
|
||||||
|
|
||||||
|
leal 4(%ebp), %eax # push flags addr
|
||||||
|
push %eax
|
||||||
|
leal 8(%ebp), %eax # push registers addr
|
||||||
|
push %eax
|
||||||
|
|
||||||
|
leal 40(%ebp), %edx # push stack top address (relative to our entry)
|
||||||
|
movl (%ebp), %eax
|
||||||
|
subl %edx, %eax # calculate difference between entry and previous frame
|
||||||
|
push %eax
|
||||||
|
push %edx
|
||||||
|
|
||||||
|
call *report_ret # report the return information (same args)
|
||||||
|
.Ldone:
|
||||||
|
|
||||||
|
leave
|
||||||
|
popf
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
20
loader/wrapper.h
Normal file
20
loader/wrapper.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef _WRAPPER_H
|
||||||
|
#define _WRAPPER_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||||
|
} reg386_t;
|
||||||
|
|
||||||
|
typedef int (*wrapper_func_t)(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags);
|
||||||
|
|
||||||
|
extern wrapper_func_t report_entry, report_ret;
|
||||||
|
|
||||||
|
extern void (*wrapper_target)(void);
|
||||||
|
|
||||||
|
extern int wrapper(void);
|
||||||
|
extern int null_call(void);
|
||||||
|
|
||||||
|
#endif /* _WRAPPER_H */
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user