Reserve space for the PE header at the start of the .so file.
Store the export table inside the data section so that sections can be properly aligned. Build the relay function table directly in the .spec.c file. Moved relay debugging functions to relay386.c.
This commit is contained in:
parent
a1b2fc2a80
commit
246c360631
|
@ -7,33 +7,21 @@
|
|||
#ifndef __WINE_BUILTIN32_H
|
||||
#define __WINE_BUILTIN32_H
|
||||
|
||||
typedef void (*ENTRYPOINT32)();
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name; /* DLL name */
|
||||
const char* filename; /* DLL file name */
|
||||
int base; /* Ordinal base */
|
||||
int nb_funcs; /* Number of functions */
|
||||
int nb_names; /* Number of function names */
|
||||
int nb_imports; /* Number of imported DLLs */
|
||||
int fwd_size; /* Total size of forward names */
|
||||
const ENTRYPOINT32 *functions; /* Pointer to function table */
|
||||
const char * const *names; /* Pointer to names table */
|
||||
const unsigned short *ordinals; /* Pointer to ordinals table */
|
||||
const unsigned char *args; /* Pointer to argument lengths */
|
||||
const unsigned int *argtypes; /* Pointer to argument types bitmask */
|
||||
void *pe_header; /* Buffer for PE header */
|
||||
void *exports; /* Pointer to export directory */
|
||||
unsigned int exports_size; /* Total size of export directory */
|
||||
const char * const *imports; /* Pointer to imports */
|
||||
const ENTRYPOINT32 dllentrypoint;/* Pointer to LibMain function */
|
||||
void (*dllentrypoint)(); /* Pointer to entry point function */
|
||||
int characteristics;
|
||||
const void *rsrc; /* Resource descriptor */
|
||||
void *rsrc; /* Resource descriptor */
|
||||
} BUILTIN32_DESCRIPTOR;
|
||||
|
||||
extern ENTRYPOINT32 BUILTIN32_GetEntryPoint( char *buffer, void *relay,
|
||||
unsigned int *typemask );
|
||||
extern void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR *descr );
|
||||
extern void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr,
|
||||
int ordinal );
|
||||
extern void BUILTIN32_SwitchRelayDebug(int onoff);
|
||||
extern void BUILTIN32_Unimplemented( const char *dllname, const char *funcname );
|
||||
extern void RELAY_SetupDLL( const char *module );
|
||||
|
||||
#endif /* __WINE_BUILTIN32_H */
|
||||
|
|
|
@ -708,14 +708,19 @@ typedef HANDLE *PHANDLE;
|
|||
".long " __ASM_NAME(#fn) "\n\t" \
|
||||
".byte " #args ", " #args )
|
||||
#define DEFINE_REGS_ENTRYPOINT_0( name, fn ) \
|
||||
extern void WINAPI name(void); \
|
||||
_DEFINE_REGS_ENTRYPOINT( name, fn, 0 )
|
||||
#define DEFINE_REGS_ENTRYPOINT_1( name, fn, t1 ) \
|
||||
extern void WINAPI name( t1 a1 ); \
|
||||
_DEFINE_REGS_ENTRYPOINT( name, fn, 4 )
|
||||
#define DEFINE_REGS_ENTRYPOINT_2( name, fn, t1, t2 ) \
|
||||
extern void WINAPI name( t1 a1, t2 a2 ); \
|
||||
_DEFINE_REGS_ENTRYPOINT( name, fn, 8 )
|
||||
#define DEFINE_REGS_ENTRYPOINT_3( name, fn, t1, t2, t3 ) \
|
||||
extern void WINAPI name( t1 a1, t2 a2, t3 a3 ); \
|
||||
_DEFINE_REGS_ENTRYPOINT( name, fn, 12 )
|
||||
#define DEFINE_REGS_ENTRYPOINT_4( name, fn, t1, t2, t3, t4 ) \
|
||||
extern void WINAPI name( t1 a1, t2 a2, t3 a3, t4 a4 ); \
|
||||
_DEFINE_REGS_ENTRYPOINT( name, fn, 16 )
|
||||
|
||||
#endif /* __i386__ */
|
||||
|
@ -1619,9 +1624,9 @@ typedef struct _IMAGE_EXPORT_DIRECTORY {
|
|||
DWORD Base;
|
||||
DWORD NumberOfFunctions;
|
||||
DWORD NumberOfNames;
|
||||
LPDWORD *AddressOfFunctions;
|
||||
LPDWORD *AddressOfNames;
|
||||
LPWORD *AddressOfNameOrdinals;
|
||||
DWORD AddressOfFunctions;
|
||||
DWORD AddressOfNames;
|
||||
DWORD AddressOfNameOrdinals;
|
||||
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
|
||||
|
||||
/* Import name entry */
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "msdos.h"
|
||||
#include "color.h"
|
||||
#include "options.h"
|
||||
#include "builtin32.h"
|
||||
#include "debugtools.h"
|
||||
#include "debugdefs.h"
|
||||
#include "module.h"
|
||||
|
@ -111,7 +110,7 @@ void MAIN_ParseDebugOptions( const char *arg )
|
|||
extern char **debug_snoop_excludelist;
|
||||
|
||||
int i;
|
||||
int l, cls, dotracerelay = TRACE_ON(relay);
|
||||
int l, cls;
|
||||
|
||||
char *options = strdup(arg);
|
||||
|
||||
|
@ -214,10 +213,6 @@ void MAIN_ParseDebugOptions( const char *arg )
|
|||
}
|
||||
while((*options==',')&&(*(++options)));
|
||||
|
||||
/* special handling for relay debugging */
|
||||
if (dotracerelay != TRACE_ON(relay))
|
||||
BUILTIN32_SwitchRelayDebug( TRACE_ON(relay) );
|
||||
|
||||
if (!*options) return;
|
||||
|
||||
error:
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#ifdef HAVE_DL_API
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "windef.h"
|
||||
#include "wine/winbase16.h"
|
||||
|
@ -20,6 +23,8 @@
|
|||
#include "winuser.h"
|
||||
#include "builtin32.h"
|
||||
#include "elfdll.h"
|
||||
#include "file.h"
|
||||
#include "global.h"
|
||||
#include "neexe.h"
|
||||
#include "heap.h"
|
||||
#include "main.h"
|
||||
|
@ -34,18 +39,10 @@ DECLARE_DEBUG_CHANNEL(relay);
|
|||
|
||||
typedef struct
|
||||
{
|
||||
BYTE call; /* 0xe8 call callfrom32 (relative) */
|
||||
DWORD callfrom32 WINE_PACKED; /* RELAY_CallFrom32 relative addr */
|
||||
BYTE ret; /* 0xc2 ret $n or 0xc3 ret */
|
||||
WORD args; /* nb of args to remove from the stack */
|
||||
} DEBUG_ENTRY_POINT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const BYTE *restab;
|
||||
const DWORD nresources;
|
||||
const DWORD restabsize;
|
||||
const IMAGE_RESOURCE_DATA_ENTRY *entries;
|
||||
BYTE *restab;
|
||||
DWORD nresources;
|
||||
DWORD restabsize;
|
||||
IMAGE_RESOURCE_DATA_ENTRY *entries;
|
||||
} BUILTIN32_RESOURCE;
|
||||
|
||||
#define MAX_DLLS 60
|
||||
|
@ -54,8 +51,6 @@ static const BUILTIN32_DESCRIPTOR *builtin_dlls[MAX_DLLS];
|
|||
static HMODULE dll_modules[MAX_DLLS];
|
||||
static int nb_dlls;
|
||||
|
||||
extern void RELAY_CallFrom32();
|
||||
extern void RELAY_CallFrom32Regs();
|
||||
|
||||
/***********************************************************************
|
||||
* BUILTIN32_WarnSecondInstance
|
||||
|
@ -66,7 +61,8 @@ extern void RELAY_CallFrom32Regs();
|
|||
static void BUILTIN32_WarnSecondInstance( const char *name )
|
||||
{
|
||||
static const char * const warning_list[] =
|
||||
{ "comctl32", "comdlg32", "crtdll", "imagehlp", "msacm32", "shell32", NULL };
|
||||
{ "comctl32.dll", "comdlg32.dll", "crtdll.dll",
|
||||
"imagehlp.dll", "msacm32.dll", "shell32.dll", NULL };
|
||||
|
||||
const char * const *ptr = warning_list;
|
||||
|
||||
|
@ -111,10 +107,29 @@ void *BUILTIN32_dlopen( const char *name )
|
|||
int BUILTIN32_dlclose( void *handle )
|
||||
{
|
||||
#ifdef HAVE_DL_API
|
||||
return dlclose( handle );
|
||||
/* FIXME: should unregister descriptors first */
|
||||
/* return dlclose( handle ); */
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* fixup_rva_ptrs
|
||||
*
|
||||
* Adjust an array of pointers to make them into RVAs.
|
||||
*/
|
||||
static inline void fixup_rva_ptrs( void *array, void *base, int count )
|
||||
{
|
||||
void **ptr = (void **)array;
|
||||
while (count--)
|
||||
{
|
||||
if (*ptr) *ptr = (void *)((char *)*ptr - (char *)base);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* BUILTIN32_DoLoadImage
|
||||
*
|
||||
|
@ -122,29 +137,23 @@ int BUILTIN32_dlclose( void *handle )
|
|||
*/
|
||||
static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
|
||||
{
|
||||
|
||||
IMAGE_DATA_DIRECTORY *dir;
|
||||
IMAGE_DOS_HEADER *dos;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
IMAGE_SECTION_HEADER *sec;
|
||||
IMAGE_EXPORT_DIRECTORY *exp;
|
||||
IMAGE_IMPORT_DESCRIPTOR *imp;
|
||||
const BUILTIN32_RESOURCE *rsrc = descr->rsrc;
|
||||
LPVOID *funcs;
|
||||
LPSTR *names;
|
||||
LPSTR pfwd, rtab;
|
||||
DEBUG_ENTRY_POINT *debug;
|
||||
IMAGE_EXPORT_DIRECTORY *exports = descr->exports;
|
||||
INT i, size, nb_sections;
|
||||
BYTE *addr;
|
||||
BYTE *addr, *code_start, *data_start;
|
||||
BYTE* xcnlnk;
|
||||
DWORD xcnsize = 0;
|
||||
int page_size = VIRTUAL_GetPageSize();
|
||||
|
||||
/* Allocate the module */
|
||||
|
||||
nb_sections = 2; /* exports + code */
|
||||
if (descr->nb_imports) nb_sections++;
|
||||
nb_sections = 2; /* code + data */
|
||||
|
||||
if (!strcmp(descr->name, "KERNEL32")) {
|
||||
if (!strcmp(descr->filename, "kernel32.dll")) {
|
||||
nb_sections++;
|
||||
xcnsize = sizeof(DWORD);
|
||||
}
|
||||
|
@ -152,30 +161,33 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
|
|||
+ sizeof(IMAGE_NT_HEADERS)
|
||||
+ nb_sections * sizeof(IMAGE_SECTION_HEADER)
|
||||
+ (descr->nb_imports+1) * sizeof(IMAGE_IMPORT_DESCRIPTOR)
|
||||
+ sizeof(IMAGE_EXPORT_DIRECTORY)
|
||||
+ descr->nb_funcs * sizeof(LPVOID)
|
||||
+ descr->nb_names * sizeof(LPSTR)
|
||||
+ descr->fwd_size
|
||||
+ xcnsize);
|
||||
|
||||
#ifdef __i386__
|
||||
if (WARN_ON(relay) || TRACE_ON(relay))
|
||||
size += descr->nb_funcs * sizeof(DEBUG_ENTRY_POINT);
|
||||
#endif
|
||||
if (rsrc) size += rsrc->restabsize;
|
||||
addr = VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
if (!addr) return 0;
|
||||
dos = (IMAGE_DOS_HEADER *)addr;
|
||||
nt = (IMAGE_NT_HEADERS *)(dos + 1);
|
||||
sec = (IMAGE_SECTION_HEADER *)(nt + 1);
|
||||
imp = (IMAGE_IMPORT_DESCRIPTOR *)(sec + nb_sections);
|
||||
exp = (IMAGE_EXPORT_DIRECTORY *)(imp + descr->nb_imports + 1);
|
||||
funcs = (LPVOID *)(exp + 1);
|
||||
names = (LPSTR *)(funcs + descr->nb_funcs);
|
||||
pfwd = (LPSTR)(names + descr->nb_names);
|
||||
xcnlnk= pfwd + descr->fwd_size;
|
||||
rtab = xcnlnk + xcnsize;
|
||||
debug = (DEBUG_ENTRY_POINT *)(rtab + (rsrc ? rsrc->restabsize : 0));
|
||||
assert( size <= page_size );
|
||||
|
||||
if (descr->pe_header)
|
||||
{
|
||||
if ((addr = FILE_dommap( -1, descr->pe_header, 0, page_size, 0, 0,
|
||||
PROT_READ|PROT_WRITE, MAP_FIXED )) != descr->pe_header)
|
||||
{
|
||||
ERR("failed to map over PE header for %s at %p\n", descr->filename, descr->pe_header );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(addr = VirtualAlloc( NULL, page_size, MEM_COMMIT, PAGE_READWRITE ))) return 0;
|
||||
}
|
||||
|
||||
dos = (IMAGE_DOS_HEADER *)addr;
|
||||
nt = (IMAGE_NT_HEADERS *)(dos + 1);
|
||||
sec = (IMAGE_SECTION_HEADER *)(nt + 1);
|
||||
imp = (IMAGE_IMPORT_DESCRIPTOR *)(sec + nb_sections);
|
||||
xcnlnk = (char *)(imp + descr->nb_imports + 1);
|
||||
code_start = addr + page_size;
|
||||
|
||||
/* HACK! */
|
||||
data_start = code_start + page_size;
|
||||
|
||||
/* Build the DOS and NT headers */
|
||||
|
||||
|
@ -189,35 +201,41 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
|
|||
nt->FileHeader.Characteristics = descr->characteristics;
|
||||
|
||||
nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
|
||||
nt->OptionalHeader.SizeOfCode = 0x1000;
|
||||
nt->OptionalHeader.SizeOfCode = data_start - code_start;
|
||||
nt->OptionalHeader.SizeOfInitializedData = 0;
|
||||
nt->OptionalHeader.SizeOfUninitializedData = 0;
|
||||
nt->OptionalHeader.ImageBase = (DWORD)addr;
|
||||
nt->OptionalHeader.SectionAlignment = 0x1000;
|
||||
nt->OptionalHeader.FileAlignment = 0x1000;
|
||||
nt->OptionalHeader.SectionAlignment = page_size;
|
||||
nt->OptionalHeader.FileAlignment = page_size;
|
||||
nt->OptionalHeader.MajorOperatingSystemVersion = 1;
|
||||
nt->OptionalHeader.MinorOperatingSystemVersion = 0;
|
||||
nt->OptionalHeader.MajorSubsystemVersion = 4;
|
||||
nt->OptionalHeader.MinorSubsystemVersion = 0;
|
||||
nt->OptionalHeader.SizeOfImage = size;
|
||||
nt->OptionalHeader.SizeOfHeaders = (BYTE *)exp - addr;
|
||||
nt->OptionalHeader.SizeOfImage = page_size;
|
||||
nt->OptionalHeader.SizeOfHeaders = page_size;
|
||||
nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
|
||||
if (descr->dllentrypoint)
|
||||
nt->OptionalHeader.AddressOfEntryPoint = (DWORD)descr->dllentrypoint - (DWORD)addr;
|
||||
|
||||
/* Build the code section */
|
||||
|
||||
strcpy( sec->Name, ".code" );
|
||||
sec->SizeOfRawData = 0;
|
||||
#ifdef __i386__
|
||||
if (WARN_ON(relay) || TRACE_ON(relay))
|
||||
sec->SizeOfRawData += descr->nb_funcs * sizeof(DEBUG_ENTRY_POINT);
|
||||
#endif
|
||||
strcpy( sec->Name, ".text" );
|
||||
sec->SizeOfRawData = data_start - code_start;
|
||||
sec->Misc.VirtualSize = sec->SizeOfRawData;
|
||||
sec->VirtualAddress = (BYTE *)debug - addr;
|
||||
sec->PointerToRawData = (BYTE *)debug - addr;
|
||||
sec->VirtualAddress = code_start - addr;
|
||||
sec->PointerToRawData = code_start - addr;
|
||||
sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
|
||||
sec++;
|
||||
|
||||
/* Build the data section */
|
||||
|
||||
strcpy( sec->Name, ".data" );
|
||||
sec->SizeOfRawData = 0;
|
||||
sec->Misc.VirtualSize = sec->SizeOfRawData;
|
||||
sec->VirtualAddress = data_start - addr;
|
||||
sec->PointerToRawData = data_start - addr;
|
||||
sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
|
||||
IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
|
||||
sec++;
|
||||
|
||||
/* Build the import directory */
|
||||
|
@ -228,17 +246,6 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
|
|||
dir->VirtualAddress = (BYTE *)imp - addr;
|
||||
dir->Size = sizeof(*imp) * (descr->nb_imports + 1);
|
||||
|
||||
/* Build the imports section */
|
||||
strcpy( sec->Name, ".idata" );
|
||||
sec->Misc.VirtualSize = dir->Size;
|
||||
sec->VirtualAddress = (BYTE *)imp - addr;
|
||||
sec->SizeOfRawData = dir->Size;
|
||||
sec->PointerToRawData = (BYTE *)imp - addr;
|
||||
sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
|
||||
IMAGE_SCN_MEM_WRITE);
|
||||
sec++;
|
||||
|
||||
/* Build the imports */
|
||||
for (i = 0; i < descr->nb_imports; i++)
|
||||
{
|
||||
|
@ -250,138 +257,55 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
|
|||
}
|
||||
}
|
||||
|
||||
/* Build the export directory */
|
||||
|
||||
dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
|
||||
dir->VirtualAddress = (BYTE *)exp - addr;
|
||||
dir->Size = sizeof(*exp)
|
||||
+ descr->nb_funcs * sizeof(LPVOID)
|
||||
+ descr->nb_names * sizeof(LPSTR)
|
||||
+ descr->fwd_size;
|
||||
|
||||
/* Build the exports section */
|
||||
|
||||
strcpy( sec->Name, ".edata" );
|
||||
sec->Misc.VirtualSize = dir->Size;
|
||||
sec->VirtualAddress = (BYTE *)exp - addr;
|
||||
sec->SizeOfRawData = dir->Size;
|
||||
sec->PointerToRawData = (BYTE *)exp - addr;
|
||||
sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA |
|
||||
IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
|
||||
IMAGE_SCN_MEM_WRITE);
|
||||
|
||||
/* Build Wine's .so link section. Those sections are used by the wine debugger to
|
||||
* link a builtin PE header with the corresponding ELF module (from either a
|
||||
* shared library, or the main executable - wine emulator or any winelib program
|
||||
*/
|
||||
if (xcnsize)
|
||||
{
|
||||
sec++;
|
||||
strcpy( sec->Name, ".xcnlnk" );
|
||||
sec->Misc.VirtualSize = xcnsize;
|
||||
sec->VirtualAddress = (BYTE *)xcnlnk - addr;
|
||||
sec->SizeOfRawData = sec->Misc.VirtualSize;
|
||||
sec->PointerToRawData = (BYTE *)xcnlnk - addr;
|
||||
sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ);
|
||||
sec++;
|
||||
|
||||
*(const char**)xcnlnk = argv0;
|
||||
}
|
||||
|
||||
/* Build the resource directory */
|
||||
|
||||
if (rsrc)
|
||||
if (descr->rsrc)
|
||||
{
|
||||
BUILTIN32_RESOURCE *rsrc = descr->rsrc;
|
||||
IMAGE_RESOURCE_DATA_ENTRY *rdep;
|
||||
|
||||
/*
|
||||
* The resource directory has to be copied because it contains
|
||||
* RVAs. These would be invalid if the dll is instantiated twice.
|
||||
*/
|
||||
memcpy(rtab, rsrc->restab, rsrc->restabsize);
|
||||
|
||||
dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
|
||||
dir->VirtualAddress = (BYTE *)rtab - addr;
|
||||
dir->VirtualAddress = (BYTE *)rsrc->restab - addr;
|
||||
dir->Size = rsrc->restabsize;
|
||||
rdep = (IMAGE_RESOURCE_DATA_ENTRY *)((DWORD)rtab + (DWORD)rsrc->entries - (DWORD)rsrc->restab);
|
||||
for(i = 0; i < rsrc->nresources; i++)
|
||||
{
|
||||
rdep[i].OffsetToData += (DWORD)rsrc->restab - (DWORD)addr;
|
||||
}
|
||||
rdep = rsrc->entries;
|
||||
for (i = 0; i < rsrc->nresources; i++) rdep[i].OffsetToData += dir->VirtualAddress;
|
||||
}
|
||||
|
||||
/* Build the exports section data */
|
||||
/* Build the export directory */
|
||||
|
||||
exp->Name = ((BYTE *)descr->name) - addr; /*??*/
|
||||
exp->Base = descr->base;
|
||||
exp->NumberOfFunctions = descr->nb_funcs;
|
||||
exp->NumberOfNames = descr->nb_names;
|
||||
exp->AddressOfFunctions = (LPDWORD *)((BYTE *)funcs - addr);
|
||||
exp->AddressOfNames = (LPDWORD *)((BYTE *)names - addr);
|
||||
exp->AddressOfNameOrdinals = (LPWORD *)((BYTE *)descr->ordinals - addr);
|
||||
|
||||
/* Build the funcs table */
|
||||
|
||||
for (i = 0; i < descr->nb_funcs; i++, funcs++, debug++)
|
||||
if (exports)
|
||||
{
|
||||
BYTE args = descr->args[i];
|
||||
int j;
|
||||
dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
|
||||
dir->VirtualAddress = (BYTE *)exports - addr;
|
||||
dir->Size = descr->exports_size;
|
||||
|
||||
if (!descr->functions[i]) continue;
|
||||
fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
|
||||
fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames );
|
||||
fixup_rva_ptrs( &exports->Name, addr, 1 );
|
||||
fixup_rva_ptrs( &exports->AddressOfFunctions, addr, 1 );
|
||||
fixup_rva_ptrs( &exports->AddressOfNames, addr, 1 );
|
||||
fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 );
|
||||
|
||||
if (args == 0xfd) /* forward func */
|
||||
{
|
||||
strcpy( pfwd, (LPSTR)descr->functions[i] );
|
||||
*funcs = (LPVOID)((BYTE *)pfwd - addr);
|
||||
pfwd += strlen(pfwd) + 1;
|
||||
}
|
||||
else *funcs = (LPVOID)((BYTE *)descr->functions[i] - addr);
|
||||
|
||||
#ifdef __i386__
|
||||
if (!(WARN_ON(relay) || TRACE_ON(relay))) continue;
|
||||
for (j=0;j<descr->nb_names;j++)
|
||||
if (descr->ordinals[j] == i)
|
||||
break;
|
||||
if (j<descr->nb_names) {
|
||||
if (descr->names[j]) {
|
||||
char buffer[200];
|
||||
sprintf(buffer,"%s.%d: %s",descr->name,i,descr->names[j]);
|
||||
if (!RELAY_ShowDebugmsgRelay(buffer))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
switch(args)
|
||||
{
|
||||
case 0xfd: /* forward */
|
||||
case 0xff: /* stub or extern */
|
||||
break;
|
||||
default: /* normal function (stdcall or cdecl or register) */
|
||||
if (TRACE_ON(relay)) {
|
||||
debug->call = 0xe8; /* lcall relative */
|
||||
if (args & 0x40) /* register func */
|
||||
debug->callfrom32 = (DWORD)RELAY_CallFrom32Regs -
|
||||
(DWORD)&debug->ret;
|
||||
else
|
||||
debug->callfrom32 = (DWORD)RELAY_CallFrom32 -
|
||||
(DWORD)&debug->ret;
|
||||
} else {
|
||||
debug->call = 0xe9; /* ljmp relative */
|
||||
debug->callfrom32 = (DWORD)descr->functions[i] -
|
||||
(DWORD)&debug->ret;
|
||||
}
|
||||
debug->ret = (args & 0x80) ? 0xc3 : 0xc2; /*ret/ret $n*/
|
||||
debug->args = (args & 0x3f) * sizeof(int);
|
||||
*funcs = (LPVOID)((BYTE *)debug - addr);
|
||||
break;
|
||||
}
|
||||
#endif /* __i386__ */
|
||||
/* Setup relay debugging entry points */
|
||||
if (WARN_ON(relay) || TRACE_ON(relay)) RELAY_SetupDLL( addr );
|
||||
}
|
||||
|
||||
/* Build the names table */
|
||||
|
||||
for (i = 0; i < exp->NumberOfNames; i++, names++)
|
||||
if (descr->names[i])
|
||||
*names = (LPSTR)((BYTE *)descr->names[i] - addr);
|
||||
|
||||
return (HMODULE)addr;
|
||||
}
|
||||
|
||||
|
@ -429,7 +353,7 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
|
|||
{
|
||||
if (!(dll_modules[i] = BUILTIN32_DoLoadImage( builtin_dlls[i] ))) return NULL;
|
||||
}
|
||||
else BUILTIN32_WarnSecondInstance( builtin_dlls[i]->name );
|
||||
else BUILTIN32_WarnSecondInstance( builtin_dlls[i]->filename );
|
||||
|
||||
/* Create 16-bit dummy module */
|
||||
if ((hModule16 = MODULE_CreateDummyModule( dllname, dll_modules[i] )) < 32)
|
||||
|
@ -507,92 +431,6 @@ void BUILTIN32_UnloadLibrary(WINE_MODREF *wm)
|
|||
/* FIXME: do something here */
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* BUILTIN32_GetEntryPoint
|
||||
*
|
||||
* Return the name of the DLL entry point corresponding
|
||||
* to a relay entry point address. This is used only by relay debugging.
|
||||
*
|
||||
* This function _must_ return the real entry point to call
|
||||
* after the debug info is printed.
|
||||
*/
|
||||
ENTRYPOINT32 BUILTIN32_GetEntryPoint( char *buffer, void *relay,
|
||||
unsigned int *typemask )
|
||||
{
|
||||
const BUILTIN32_DESCRIPTOR *descr = NULL;
|
||||
int ordinal = 0, i;
|
||||
|
||||
/* First find the module */
|
||||
|
||||
for (i = 0; i < nb_dlls; i++)
|
||||
if (dll_modules[i])
|
||||
{
|
||||
IMAGE_SECTION_HEADER *sec = PE_SECTIONS(dll_modules[i]);
|
||||
DEBUG_ENTRY_POINT *debug =
|
||||
(DEBUG_ENTRY_POINT *)((DWORD)dll_modules[i] + sec[0].VirtualAddress);
|
||||
DEBUG_ENTRY_POINT *func = (DEBUG_ENTRY_POINT *)relay;
|
||||
descr = builtin_dlls[i];
|
||||
if (debug <= func && func < debug + descr->nb_funcs)
|
||||
{
|
||||
ordinal = func - debug;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!descr) return NULL;
|
||||
|
||||
/* Now find the function */
|
||||
|
||||
for (i = 0; i < descr->nb_names; i++)
|
||||
if (descr->ordinals[i] == ordinal) break;
|
||||
|
||||
sprintf( buffer, "%s.%d: %s", descr->name, ordinal + descr->base,
|
||||
(i < descr->nb_names) ? descr->names[i] : "@" );
|
||||
*typemask = descr->argtypes[ordinal];
|
||||
return descr->functions[ordinal];
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* BUILTIN32_SwitchRelayDebug
|
||||
*
|
||||
* FIXME: enhance to do it module relative.
|
||||
*/
|
||||
void BUILTIN32_SwitchRelayDebug(BOOL onoff)
|
||||
{
|
||||
const BUILTIN32_DESCRIPTOR *descr;
|
||||
IMAGE_SECTION_HEADER *sec;
|
||||
DEBUG_ENTRY_POINT *debug;
|
||||
int i, j;
|
||||
|
||||
#ifdef __i386__
|
||||
if (!(TRACE_ON(relay) || WARN_ON(relay)))
|
||||
return;
|
||||
for (j = 0; j < nb_dlls; j++)
|
||||
{
|
||||
if (!dll_modules[j]) continue;
|
||||
sec = PE_SECTIONS(dll_modules[j]);
|
||||
debug = (DEBUG_ENTRY_POINT *)((DWORD)dll_modules[j] + sec[1].VirtualAddress);
|
||||
descr = builtin_dlls[j];
|
||||
for (i = 0; i < descr->nb_funcs; i++,debug++) {
|
||||
if (!descr->functions[i]) continue;
|
||||
if ((descr->args[i]==0xff) || (descr->args[i]==0xfe))
|
||||
continue;
|
||||
if (onoff) {
|
||||
debug->call = 0xe8; /* lcall relative */
|
||||
debug->callfrom32 = (DWORD)RELAY_CallFrom32 -
|
||||
(DWORD)&debug->ret;
|
||||
} else {
|
||||
debug->call = 0xe9; /* ljmp relative */
|
||||
debug->callfrom32 = (DWORD)descr->functions[i] -
|
||||
(DWORD)&debug->ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* __i386__ */
|
||||
return;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* BUILTIN32_RegisterDLL
|
||||
*
|
||||
|
@ -610,19 +448,11 @@ void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR *descr )
|
|||
* This function is called for unimplemented 32-bit entry points (declared
|
||||
* as 'stub' in the spec file).
|
||||
*/
|
||||
void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr, int ordinal )
|
||||
void BUILTIN32_Unimplemented( const char *dllname, const char *funcname )
|
||||
{
|
||||
const char *func_name = "???";
|
||||
int i;
|
||||
|
||||
__RESTORE_ES; /* Just in case */
|
||||
|
||||
for (i = 0; i < descr->nb_names; i++)
|
||||
if (descr->ordinals[i] + descr->base == ordinal) break;
|
||||
if (i < descr->nb_names) func_name = descr->names[i];
|
||||
|
||||
MESSAGE( "No handler for Win32 routine %s.%d: %s",
|
||||
descr->name, ordinal, func_name );
|
||||
MESSAGE( "No handler for Win32 routine %s.%s", dllname, funcname );
|
||||
#ifdef __GNUC__
|
||||
MESSAGE( " (called from %p)", __builtin_return_address(1) );
|
||||
#endif
|
||||
|
|
|
@ -7,12 +7,15 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "winnt.h"
|
||||
#include "builtin32.h"
|
||||
#include "selectors.h"
|
||||
#include "stackframe.h"
|
||||
#include "syslevel.h"
|
||||
#include "main.h"
|
||||
#include "module.h"
|
||||
#include "process.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(relay);
|
||||
|
@ -62,6 +65,77 @@ int RELAY_ShowDebugmsgRelay(const char *func) {
|
|||
|
||||
#ifdef __i386__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE call; /* 0xe8 call callfrom32 (relative) */
|
||||
DWORD callfrom32 WINE_PACKED; /* RELAY_CallFrom32 relative addr */
|
||||
BYTE ret; /* 0xc2 ret $n or 0xc3 ret */
|
||||
WORD args; /* nb of args to remove from the stack */
|
||||
FARPROC orig; /* original entry point */
|
||||
DWORD argtypes; /* argument types */
|
||||
} DEBUG_ENTRY_POINT;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* find_exported_name
|
||||
*
|
||||
* Find the name of an exported function.
|
||||
*/
|
||||
static const char *find_exported_name( const char *module,
|
||||
IMAGE_EXPORT_DIRECTORY *exp, int ordinal )
|
||||
{
|
||||
int i;
|
||||
const char *ret = NULL;
|
||||
|
||||
WORD *ordptr = (WORD *)(module + exp->AddressOfNameOrdinals);
|
||||
for (i = 0; i < exp->NumberOfNames; i++, ordptr++)
|
||||
if (*ordptr + exp->Base == ordinal) break;
|
||||
if (i < exp->NumberOfNames)
|
||||
ret = module + ((DWORD*)(module + exp->AddressOfNames))[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_entry_point
|
||||
*
|
||||
* Get the name of the DLL entry point corresponding to a relay address.
|
||||
*/
|
||||
static void get_entry_point( char *buffer, DEBUG_ENTRY_POINT *relay )
|
||||
{
|
||||
IMAGE_DATA_DIRECTORY *dir;
|
||||
IMAGE_EXPORT_DIRECTORY *exp = NULL;
|
||||
DEBUG_ENTRY_POINT *debug;
|
||||
char *base = NULL;
|
||||
const char *name;
|
||||
int ordinal = 0;
|
||||
WINE_MODREF *wm;
|
||||
|
||||
/* First find the module */
|
||||
|
||||
for (wm = PROCESS_Current()->modref_list; wm; wm = wm->next)
|
||||
{
|
||||
if (wm->type != MODULE32_PE) continue;
|
||||
if (!(wm->flags & WINE_MODREF_INTERNAL)) continue;
|
||||
base = (char *)wm->module;
|
||||
dir = &PE_HEADER(base)->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
|
||||
if (!dir->Size) continue;
|
||||
exp = (IMAGE_EXPORT_DIRECTORY *)(base + dir->VirtualAddress);
|
||||
debug = (DEBUG_ENTRY_POINT *)((char *)exp + dir->Size);
|
||||
if (debug <= relay && relay < debug + exp->NumberOfFunctions)
|
||||
{
|
||||
ordinal = relay - debug;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now find the function */
|
||||
|
||||
name = find_exported_name( base, exp, ordinal + exp->Base );
|
||||
sprintf( buffer, "%s.%ld: %s", base + exp->Name, ordinal + exp->Base, name ? name : "@" );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RELAY_PrintArgs
|
||||
*/
|
||||
|
@ -94,29 +168,28 @@ static inline void RELAY_PrintArgs( int *args, int nb_args, unsigned int typemas
|
|||
* (esp+4) ret_addr
|
||||
* (esp) return addr to relay code
|
||||
*/
|
||||
int RELAY_CallFrom32( int ret_addr, ... )
|
||||
static int RELAY_CallFrom32( int ret_addr, ... )
|
||||
{
|
||||
int ret;
|
||||
char buffer[80];
|
||||
unsigned int typemask;
|
||||
FARPROC func;
|
||||
|
||||
int *args = &ret_addr + 1;
|
||||
/* Relay addr is the return address for this function */
|
||||
BYTE *relay_addr = (BYTE *)__builtin_return_address(0);
|
||||
WORD nb_args = *(WORD *)(relay_addr + 1) / sizeof(int);
|
||||
DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5);
|
||||
WORD nb_args = relay->args / sizeof(int);
|
||||
|
||||
get_entry_point( buffer, relay );
|
||||
|
||||
assert(TRACE_ON(relay));
|
||||
func = (FARPROC)BUILTIN32_GetEntryPoint( buffer, relay_addr - 5, &typemask );
|
||||
DPRINTF( "Call %s(", buffer );
|
||||
RELAY_PrintArgs( args, nb_args, typemask );
|
||||
RELAY_PrintArgs( args, nb_args, relay->argtypes );
|
||||
DPRINTF( ") ret=%08x fs=%04x\n", ret_addr, __get_fs() );
|
||||
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
|
||||
if (*relay_addr == 0xc3) /* cdecl */
|
||||
if (relay->ret == 0xc3) /* cdecl */
|
||||
{
|
||||
LRESULT (*cfunc)() = (LRESULT(*)())func;
|
||||
LRESULT (*cfunc)() = (LRESULT(*)())relay->orig;
|
||||
switch(nb_args)
|
||||
{
|
||||
case 0: ret = cfunc(); break;
|
||||
|
@ -159,6 +232,7 @@ int RELAY_CallFrom32( int ret_addr, ... )
|
|||
}
|
||||
else /* stdcall */
|
||||
{
|
||||
FARPROC func = relay->orig;
|
||||
switch(nb_args)
|
||||
{
|
||||
case 0: ret = func(); break;
|
||||
|
@ -225,14 +299,14 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context );
|
|||
DEFINE_REGS_ENTRYPOINT_0( RELAY_CallFrom32Regs, RELAY_DoCallFrom32Regs )
|
||||
void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
|
||||
{
|
||||
unsigned int typemask;
|
||||
char buffer[80];
|
||||
int* args;
|
||||
FARPROC func;
|
||||
BYTE *entry_point;
|
||||
|
||||
BYTE *relay_addr = *((BYTE **)ESP_reg(context) - 1);
|
||||
WORD nb_args = *(WORD *)(relay_addr + 1) / sizeof(int);
|
||||
DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5);
|
||||
WORD nb_args = (relay->args & ~0x8000) / sizeof(int);
|
||||
|
||||
/* remove extra stuff from the stack */
|
||||
EIP_reg(context) = stack32_pop(context);
|
||||
|
@ -241,12 +315,14 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
|
|||
|
||||
assert(TRACE_ON(relay));
|
||||
|
||||
entry_point = (BYTE *)BUILTIN32_GetEntryPoint( buffer, relay_addr - 5, &typemask );
|
||||
entry_point = (BYTE *)relay->orig;
|
||||
assert( *entry_point == 0xe8 /* lcall */ );
|
||||
func = *(FARPROC *)(entry_point + 5);
|
||||
|
||||
get_entry_point( buffer, relay );
|
||||
|
||||
DPRINTF( "Call %s(", buffer );
|
||||
RELAY_PrintArgs( args, nb_args, typemask );
|
||||
RELAY_PrintArgs( args, nb_args, relay->argtypes );
|
||||
DPRINTF( ") ret=%08lx fs=%04lx\n", EIP_reg(context), FS_reg(context) );
|
||||
|
||||
DPRINTF(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
|
||||
|
@ -302,5 +378,65 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
|
|||
|
||||
SYSLEVEL_CheckNotLevel( 2 );
|
||||
}
|
||||
#endif /* __i386__ */
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RELAY_SetupDLL
|
||||
*
|
||||
* Setup relay debugging for a built-in dll.
|
||||
*/
|
||||
void RELAY_SetupDLL( const char *module )
|
||||
{
|
||||
IMAGE_DATA_DIRECTORY *dir;
|
||||
IMAGE_EXPORT_DIRECTORY *exports;
|
||||
DEBUG_ENTRY_POINT *debug;
|
||||
DWORD *funcs;
|
||||
int i;
|
||||
const char *name, *dllname;
|
||||
|
||||
dir = &PE_HEADER(module)->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
|
||||
if (!dir->Size) return;
|
||||
exports = (IMAGE_EXPORT_DIRECTORY *)(module + dir->VirtualAddress);
|
||||
debug = (DEBUG_ENTRY_POINT *)((char *)exports + dir->Size);
|
||||
funcs = (DWORD *)(module + exports->AddressOfFunctions);
|
||||
dllname = module + exports->Name;
|
||||
|
||||
for (i = 0; i < exports->NumberOfFunctions; i++, funcs++, debug++)
|
||||
{
|
||||
int on = 1;
|
||||
|
||||
if (!debug->call) continue; /* not a normal function */
|
||||
|
||||
if ((name = find_exported_name( module, exports, i + exports->Base )))
|
||||
{
|
||||
char buffer[200];
|
||||
sprintf( buffer, "%s.%d: %s", dllname, i, name );
|
||||
on = RELAY_ShowDebugmsgRelay(buffer);
|
||||
}
|
||||
|
||||
if (on)
|
||||
{
|
||||
debug->call = 0xe8; /* call relative */
|
||||
if (debug->args & 0x8000) /* register func */
|
||||
debug->callfrom32 = (char *)RELAY_CallFrom32Regs - (char *)&debug->ret;
|
||||
else
|
||||
debug->callfrom32 = (char *)RELAY_CallFrom32 - (char *)&debug->ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug->call = 0xe9; /* jmp relative */
|
||||
debug->callfrom32 = (char *)debug->orig - (char *)&debug->ret;
|
||||
}
|
||||
|
||||
debug->orig = (FARPROC)(module + (DWORD)*funcs);
|
||||
*funcs = (char *)debug - module;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* __i386__ */
|
||||
|
||||
void RELAY_SetupDLL( const char *module )
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* __i386__ */
|
||||
|
|
349
tools/build.c
349
tools/build.c
|
@ -698,7 +698,6 @@ static void ParseTopLevel(void)
|
|||
if (strcmp(token, "name") == 0)
|
||||
{
|
||||
strcpy(DLLName, GetToken());
|
||||
strupper(DLLName);
|
||||
}
|
||||
else if (strcmp(token, "file") == 0)
|
||||
{
|
||||
|
@ -766,9 +765,9 @@ static void ParseTopLevel(void)
|
|||
if (!DLLFileName[0])
|
||||
{
|
||||
if (SpecMode == SPEC_MODE_DLL)
|
||||
sprintf( DLLFileName, "%s.DLL", DLLName );
|
||||
sprintf( DLLFileName, "%s.dll", DLLName );
|
||||
else
|
||||
sprintf( DLLFileName, "%s.EXE", DLLName );
|
||||
sprintf( DLLFileName, "%s.exe", DLLName );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1025,6 +1024,200 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* output_exports
|
||||
*
|
||||
* Output the export table for a Win32 module.
|
||||
*/
|
||||
static void output_exports( FILE *outfile, int nr_exports, int nr_names, int fwd_size )
|
||||
{
|
||||
int i, fwd_pos = 0;
|
||||
|
||||
if (!nr_exports) return;
|
||||
|
||||
fprintf( outfile, "typedef void (*func_ptr)();\n" );
|
||||
fprintf( outfile, "static struct {\n" );
|
||||
fprintf( outfile, " struct {\n" );
|
||||
fprintf( outfile, " unsigned int Characteristics;\n" );
|
||||
fprintf( outfile, " unsigned int TimeDateStamp;\n" );
|
||||
fprintf( outfile, " unsigned short MajorVersion;\n" );
|
||||
fprintf( outfile, " unsigned short MinorVersion;\n" );
|
||||
fprintf( outfile, " const char *Name;\n" );
|
||||
fprintf( outfile, " unsigned int Base;\n" );
|
||||
fprintf( outfile, " unsigned int NumberOfFunctions;\n" );
|
||||
fprintf( outfile, " unsigned int NumberOfNames;\n" );
|
||||
fprintf( outfile, " func_ptr *AddressOfFunctions;\n" );
|
||||
fprintf( outfile, " const char **AddressOfNames;\n" );
|
||||
fprintf( outfile, " unsigned short *AddressOfNameOrdinals;\n" );
|
||||
fprintf( outfile, " func_ptr functions[%d];\n", nr_exports );
|
||||
if (nb_names)
|
||||
{
|
||||
fprintf( outfile, " const char *names[%d];\n", nb_names );
|
||||
fprintf( outfile, " unsigned short ordinals[%d];\n", nb_names );
|
||||
if (nb_names % 2) fprintf( outfile, " unsigned short pad1;\n" );
|
||||
}
|
||||
if (fwd_size)
|
||||
{
|
||||
fprintf( outfile, " char forwards[%d];\n", (fwd_size + 3) & ~3 );
|
||||
}
|
||||
fprintf( outfile, " } exp;\n" );
|
||||
|
||||
#ifdef __i386__
|
||||
fprintf( outfile, " struct {\n" );
|
||||
fprintf( outfile, " unsigned char jmp;\n" );
|
||||
fprintf( outfile, " unsigned char addr[4];\n" );
|
||||
fprintf( outfile, " unsigned char ret;\n" );
|
||||
fprintf( outfile, " unsigned short args;\n" );
|
||||
fprintf( outfile, " func_ptr orig;\n" );
|
||||
fprintf( outfile, " unsigned int argtypes;\n" );
|
||||
fprintf( outfile, " } relay[%d];\n", nr_exports );
|
||||
#endif /* __i386__ */
|
||||
|
||||
fprintf( outfile, "} exports = {\n {\n" );
|
||||
fprintf( outfile, " 0,\n" ); /* Characteristics */
|
||||
fprintf( outfile, " 0,\n" ); /* TimeDateStamp */
|
||||
fprintf( outfile, " 0,\n" ); /* MajorVersion */
|
||||
fprintf( outfile, " 0,\n" ); /* MinorVersion */
|
||||
fprintf( outfile, " dllname,\n" ); /* Name */
|
||||
fprintf( outfile, " %d,\n", Base ); /* Base */
|
||||
fprintf( outfile, " %d,\n", nr_exports ); /* NumberOfFunctions */
|
||||
fprintf( outfile, " %d,\n", nb_names ); /* NumberOfNames */
|
||||
fprintf( outfile, " exports.exp.functions,\n" ); /* AddressOfFunctions */
|
||||
if (nb_names)
|
||||
{
|
||||
fprintf( outfile, " exports.exp.names,\n" ); /* AddressOfNames */
|
||||
fprintf( outfile, " exports.exp.ordinals,\n" ); /* AddressOfNameOrdinals */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( outfile, " 0,\n" ); /* AddressOfNames */
|
||||
fprintf( outfile, " 0,\n" ); /* AddressOfNameOrdinals */
|
||||
}
|
||||
|
||||
/* output the function addresses */
|
||||
|
||||
fprintf( outfile, " {\n " );
|
||||
for (i = Base; i <= Limit; i++)
|
||||
{
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
if (!odp) fprintf( outfile, "0" );
|
||||
else switch(odp->type)
|
||||
{
|
||||
case TYPE_EXTERN:
|
||||
fprintf( outfile, "%s", odp->u.ext.link_name );
|
||||
break;
|
||||
case TYPE_STDCALL:
|
||||
case TYPE_VARARGS:
|
||||
case TYPE_CDECL:
|
||||
fprintf( outfile, "%s", odp->u.func.link_name);
|
||||
break;
|
||||
case TYPE_STUB:
|
||||
fprintf( outfile, "__stub_%d", i );
|
||||
break;
|
||||
case TYPE_REGISTER:
|
||||
fprintf( outfile, "__regs_%d", i );
|
||||
break;
|
||||
case TYPE_FORWARD:
|
||||
fprintf( outfile, "(func_ptr)&exports.exp.forwards[%d] /* %s */",
|
||||
fwd_pos, odp->u.fwd.link_name );
|
||||
fwd_pos += strlen(odp->u.fwd.link_name) + 1;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
if (i < Limit) fprintf( outfile, ",\n " );
|
||||
else fprintf( outfile, "\n },\n" );
|
||||
}
|
||||
|
||||
if (nb_names)
|
||||
{
|
||||
/* output the function names */
|
||||
|
||||
fprintf( outfile, " {\n" );
|
||||
for (i = 0; i < nb_names; i++)
|
||||
{
|
||||
if (i) fprintf( outfile, ",\n" );
|
||||
fprintf( outfile, " \"%s\"", Names[i]->name );
|
||||
}
|
||||
fprintf( outfile, "\n },\n" );
|
||||
|
||||
/* output the function ordinals */
|
||||
|
||||
fprintf( outfile, " {\n " );
|
||||
for (i = 0; i < nb_names; i++)
|
||||
{
|
||||
fprintf( outfile, "%4d", Names[i]->ordinal - Base );
|
||||
if (i < nb_names-1)
|
||||
{
|
||||
fputc( ',', outfile );
|
||||
if ((i % 8) == 7) fprintf( outfile, "\n " );
|
||||
}
|
||||
}
|
||||
fprintf( outfile, "\n },\n" );
|
||||
if (nb_names % 2) fprintf( outfile, " 0,\n" );
|
||||
}
|
||||
|
||||
/* output forwards */
|
||||
|
||||
if (fwd_size)
|
||||
{
|
||||
for (i = Base; i <= Limit; i++)
|
||||
{
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
if (odp && odp->type == TYPE_FORWARD)
|
||||
fprintf( outfile, " \"%s\\0\"\n", odp->u.fwd.link_name );
|
||||
}
|
||||
}
|
||||
|
||||
/* output relays */
|
||||
|
||||
#ifdef __i386__
|
||||
fprintf( outfile, " },\n {\n" );
|
||||
for (i = Base; i <= Limit; i++)
|
||||
{
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
|
||||
if (odp && ((odp->type == TYPE_STDCALL) ||
|
||||
(odp->type == TYPE_CDECL) ||
|
||||
(odp->type == TYPE_REGISTER)))
|
||||
{
|
||||
unsigned int j, mask = 0;
|
||||
for (j = 0; odp->u.func.arg_types[j]; j++)
|
||||
{
|
||||
if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
|
||||
if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
|
||||
}
|
||||
|
||||
switch(odp->type)
|
||||
{
|
||||
case TYPE_STDCALL:
|
||||
fprintf( outfile, " { 0xe9, { 0,0,0,0 }, 0xc2, 0x%04x, %s, 0x%08x }",
|
||||
strlen(odp->u.func.arg_types) * sizeof(int),
|
||||
odp->u.func.link_name, mask );
|
||||
break;
|
||||
case TYPE_CDECL:
|
||||
fprintf( outfile, " { 0xe9, { 0,0,0,0 }, 0xc3, 0x%04x, %s, 0x%08x }",
|
||||
strlen(odp->u.func.arg_types) * sizeof(int),
|
||||
odp->u.func.link_name, mask );
|
||||
break;
|
||||
case TYPE_REGISTER:
|
||||
fprintf( outfile, " { 0xe9, { 0,0,0,0 }, 0xc3, 0x%04x, __regs_%d, 0x%08x }",
|
||||
0x8000 | (strlen(odp->u.func.arg_types) * sizeof(int)), i, mask );
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else fprintf( outfile, " { 0, }" );
|
||||
|
||||
if (i < Limit) fprintf( outfile, ",\n" );
|
||||
}
|
||||
#endif /* __i386__ */
|
||||
|
||||
fprintf( outfile, " }\n};\n" );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* BuildSpec32File
|
||||
*
|
||||
|
@ -1043,7 +1236,15 @@ static int BuildSpec32File( FILE *outfile )
|
|||
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
|
||||
input_file_name );
|
||||
fprintf( outfile, "#include \"builtin32.h\"\n\n" );
|
||||
fprintf( outfile, "static const BUILTIN32_DESCRIPTOR descriptor;\n" );
|
||||
|
||||
/* Reserve some space for the PE header */
|
||||
|
||||
fprintf( outfile, "extern char pe_header[];\n" );
|
||||
fprintf( outfile, "asm(\".section .text\\n\\t\"\n" );
|
||||
fprintf( outfile, " \".align 4096\\n\"\n" );
|
||||
fprintf( outfile, " \"pe_header:\\t.fill 4096,1,0\\n\\t\");\n" );
|
||||
|
||||
fprintf( outfile, "static const char dllname[] = \"%s\";\n", DLLName );
|
||||
|
||||
/* Output the DLL functions prototypes */
|
||||
|
||||
|
@ -1067,8 +1268,15 @@ static int BuildSpec32File( FILE *outfile )
|
|||
have_regs = TRUE;
|
||||
break;
|
||||
case TYPE_STUB:
|
||||
fprintf( outfile, "static void __stub_%d() { BUILTIN32_Unimplemented(&descriptor,%d); }\n",
|
||||
odp->ordinal, odp->ordinal );
|
||||
if (odp->name[0])
|
||||
fprintf( outfile,
|
||||
"static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%s\"); }\n",
|
||||
odp->ordinal, odp->name );
|
||||
else
|
||||
fprintf( outfile,
|
||||
"static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%d\"); }\n",
|
||||
odp->ordinal, odp->ordinal );
|
||||
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"build: function type %d not available for Win32\n",
|
||||
|
@ -1103,117 +1311,9 @@ static int BuildSpec32File( FILE *outfile )
|
|||
fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
|
||||
}
|
||||
|
||||
if (nb_names)
|
||||
{
|
||||
/* Output the DLL names table */
|
||||
/* Output the exports and relay entry points */
|
||||
|
||||
fprintf( outfile, "static const char * const FuncNames[%d] =\n{\n", nb_names );
|
||||
for (i = 0; i < nb_names; i++)
|
||||
{
|
||||
if (i) fprintf( outfile, ",\n" );
|
||||
fprintf( outfile, " \"%s\"", Names[i]->name );
|
||||
}
|
||||
fprintf( outfile, "\n};\n\n" );
|
||||
|
||||
/* Output the DLL ordinals table */
|
||||
|
||||
fprintf( outfile, "static const unsigned short FuncOrdinals[%d] =\n{\n", nb_names );
|
||||
for (i = 0; i < nb_names; i++)
|
||||
{
|
||||
if (i) fprintf( outfile, ",\n" );
|
||||
fprintf( outfile, " %d", Names[i]->ordinal - Base );
|
||||
}
|
||||
fprintf( outfile, "\n};\n\n" );
|
||||
}
|
||||
|
||||
if (nr_exports)
|
||||
{
|
||||
/* Output the DLL functions table */
|
||||
|
||||
fprintf( outfile, "\nstatic const ENTRYPOINT32 Functions[%d] =\n{\n",
|
||||
nr_exports );
|
||||
for (i = Base; i <= Limit; i++)
|
||||
{
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
if (!odp) fprintf( outfile, " 0" );
|
||||
else switch(odp->type)
|
||||
{
|
||||
case TYPE_EXTERN:
|
||||
fprintf( outfile, " %s", odp->u.ext.link_name );
|
||||
break;
|
||||
case TYPE_STDCALL:
|
||||
case TYPE_VARARGS:
|
||||
case TYPE_CDECL:
|
||||
fprintf( outfile, " %s", odp->u.func.link_name);
|
||||
break;
|
||||
case TYPE_STUB:
|
||||
fprintf( outfile, " __stub_%d", i );
|
||||
break;
|
||||
case TYPE_REGISTER:
|
||||
fprintf( outfile, " __regs_%d", i );
|
||||
break;
|
||||
case TYPE_FORWARD:
|
||||
fprintf( outfile, " (ENTRYPOINT32)\"%s\"", odp->u.fwd.link_name );
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (i < Limit) fprintf( outfile, ",\n" );
|
||||
}
|
||||
fprintf( outfile, "\n};\n\n" );
|
||||
|
||||
/* Output the DLL argument types */
|
||||
|
||||
fprintf( outfile, "static const unsigned int ArgTypes[%d] =\n{\n",
|
||||
nr_exports );
|
||||
for (i = Base; i <= Limit; i++)
|
||||
{
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
unsigned int j, mask = 0;
|
||||
if (odp &&
|
||||
((odp->type == TYPE_STDCALL) || (odp->type == TYPE_CDECL) ||
|
||||
(odp->type == TYPE_REGISTER)))
|
||||
for (j = 0; odp->u.func.arg_types[j]; j++)
|
||||
{
|
||||
if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
|
||||
if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
|
||||
}
|
||||
fprintf( outfile, " %d", mask );
|
||||
if (i < Limit) fprintf( outfile, ",\n" );
|
||||
}
|
||||
fprintf( outfile, "\n};\n\n" );
|
||||
|
||||
/* Output the DLL functions arguments */
|
||||
|
||||
fprintf( outfile, "static const unsigned char FuncArgs[%d] =\n{\n",
|
||||
nr_exports );
|
||||
for (i = Base; i <= Limit; i++)
|
||||
{
|
||||
unsigned char args = 0xff;
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
if (odp) switch(odp->type)
|
||||
{
|
||||
case TYPE_STDCALL:
|
||||
args = (unsigned char)strlen(odp->u.func.arg_types);
|
||||
break;
|
||||
case TYPE_CDECL:
|
||||
args = 0x80 | (unsigned char)strlen(odp->u.func.arg_types);
|
||||
break;
|
||||
case TYPE_REGISTER:
|
||||
args = 0x40 | (unsigned char)strlen(odp->u.func.arg_types);
|
||||
break;
|
||||
case TYPE_FORWARD:
|
||||
args = 0xfd;
|
||||
break;
|
||||
default:
|
||||
args = 0xff;
|
||||
break;
|
||||
}
|
||||
fprintf( outfile, " 0x%02x", args );
|
||||
if (i < Limit) fprintf( outfile, ",\n" );
|
||||
}
|
||||
fprintf( outfile, "\n};\n\n" );
|
||||
}
|
||||
output_exports( outfile, nr_exports, nb_names, fwd_size );
|
||||
|
||||
/* Output the DLL imports */
|
||||
|
||||
|
@ -1284,21 +1384,14 @@ static int BuildSpec32File( FILE *outfile )
|
|||
|
||||
/* Output the DLL descriptor */
|
||||
|
||||
if (rsrc_name[0]) fprintf( outfile, "extern const char %s[];\n\n", rsrc_name );
|
||||
if (rsrc_name[0]) fprintf( outfile, "extern char %s[];\n\n", rsrc_name );
|
||||
|
||||
fprintf( outfile, "static const BUILTIN32_DESCRIPTOR descriptor =\n{\n" );
|
||||
fprintf( outfile, " \"%s\",\n", DLLName );
|
||||
fprintf( outfile, " \"%s\",\n", DLLFileName );
|
||||
fprintf( outfile, " %d,\n", nr_exports? Base : 0 );
|
||||
fprintf( outfile, " %d,\n", nr_exports );
|
||||
fprintf( outfile, " %d,\n", nb_names );
|
||||
fprintf( outfile, " %d,\n", nb_imports );
|
||||
fprintf( outfile, " %d,\n", (fwd_size + 3) & ~3 );
|
||||
fprintf( outfile, " %s,\n", nr_exports ? "Functions" : "0" );
|
||||
fprintf( outfile, " %s,\n", nb_names ? "FuncNames" : "0" );
|
||||
fprintf( outfile, " %s,\n", nb_names ? "FuncOrdinals" : "0" );
|
||||
fprintf( outfile, " %s,\n", nr_exports ? "FuncArgs" : "0" );
|
||||
fprintf( outfile, " %s,\n", nr_exports ? "ArgTypes" : "0" );
|
||||
fprintf( outfile, " pe_header,\n" );
|
||||
fprintf( outfile, " %s,\n", nr_exports ? "&exports" : "0" );
|
||||
fprintf( outfile, " %s,\n", nr_exports ? "sizeof(exports.exp)" : "0" );
|
||||
fprintf( outfile, " %s,\n", nb_imports ? "Imports" : "0" );
|
||||
fprintf( outfile, " %s,\n", init_func ? init_func : "0" );
|
||||
fprintf( outfile, " %d,\n", SpecMode == SPEC_MODE_DLL ? IMAGE_FILE_DLL : 0 );
|
||||
|
@ -1369,7 +1462,7 @@ static int BuildSpec16File( FILE *outfile )
|
|||
data = (unsigned char *)xmalloc( 0x10000 );
|
||||
memset( data, 0, 16 );
|
||||
data_offset = 16;
|
||||
|
||||
strupper( DLLName );
|
||||
|
||||
/* Build sorted list of all argument types, without duplicates */
|
||||
|
||||
|
|
Loading…
Reference in New Issue