#include <stdio.h>
#include <string.h>
#include <stdarg.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "winglue.h"
+#include "wine/exception.h"
#include "build.h"
struct import
{
- DLLSPEC *spec; /* description of the imported dll */
+ DLLSPEC *spec; /* description of the imported dll */
+ char *full_name; /* full name of the input file */
+ dev_t dev; /* device/inode of the input file */
+ ino_t ino;
int delay; /* delay or not dll loading ? */
ORDDEF **exports; /* functions exported from this dll */
int nb_exports; /* number of exported functions */
static int nb_delayed = 0; /* number of delayed dlls */
static int total_imports = 0; /* total number of imported functions */
static int total_delayed = 0; /* total number of imported functions in delayed DLLs */
+static char **delayed_imports; /* names of delayed import dlls */
+static int nb_delayed_imports; /* size of the delayed_imports array */
/* list of symbols that are ignored by default */
static const char * const default_ignored_symbols[] =
free( imp->exports );
free( imp->imports );
free_dll_spec( imp->spec );
+ free( imp->full_name );
free( imp );
}
if (ld_tmp_file) unlink( ld_tmp_file );
}
+/* check whether a given dll is imported in delayed mode */
+static int is_delayed_import( const char *name )
+{
+ int i;
+
+ for (i = 0; i < nb_delayed_imports; i++)
+ {
+ if (!strcmp( delayed_imports[i], name )) return 1;
+ }
+ return 0;
+}
+
/* check whether a given dll has already been imported */
-static int is_already_imported( const char *name )
+static struct import *is_already_imported( const char *name )
{
int i;
for (i = 0; i < nb_imports; i++)
{
- if (!strcmp( dll_imports[i]->spec->file_name, name )) return 1;
+ if (!strcmp( dll_imports[i]->spec->file_name, name )) return dll_imports[i];
}
- return 0;
+ return NULL;
}
/* open the .so library for a given dll in a specified path */
return NULL;
}
-/* open the .so library for a given dll */
-static char *open_library( const char *name )
+/* find the .def import library for a given dll */
+static char *find_library( const char *name )
{
char *fullname;
int i;
}
/* read in the list of exported symbols of an import library */
-static int read_import_lib( const char *name, struct import *imp )
+static int read_import_lib( struct import *imp )
{
FILE *f;
- char *fullname;
int i, ret;
+ struct stat stat;
+ struct import *prev_imp;
DLLSPEC *spec = imp->spec;
- imp->exports = NULL;
- imp->nb_exports = 0;
-
- fullname = open_library( name );
- f = open_input_file( NULL, fullname );
- free( fullname );
-
+ f = open_input_file( NULL, imp->full_name );
+ fstat( fileno(f), &stat );
+ imp->dev = stat.st_dev;
+ imp->ino = stat.st_ino;
ret = parse_def_file( f, spec );
close_input_file( f );
if (!ret) return 0;
- if (is_already_imported( spec->file_name )) return 0;
+
+ /* check if we already imported that library from a different file */
+ if ((prev_imp = is_already_imported( spec->file_name )))
+ {
+ if (prev_imp->dev != imp->dev || prev_imp->ino != imp->ino)
+ fatal_error( "%s and %s have the same export name '%s'\n",
+ prev_imp->full_name, imp->full_name, spec->file_name );
+ return 0; /* the same file was already loaded, ignore this one */
+ }
+
+ if (is_delayed_import( spec->file_name ))
+ {
+ imp->delay = 1;
+ nb_delayed++;
+ }
imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
return 1;
}
-/* add a dll to the list of imports */
-void add_import_dll( const char *name, int delay )
+/* build the dll exported name from the import lib name or path */
+static char *get_dll_name( const char *name, const char *filename )
{
- struct import *imp;
- char *fullname;
-
- fullname = xmalloc( strlen(name) + 5 );
- strcpy( fullname, name );
- if (!strchr( fullname, '.' )) strcat( fullname, ".dll" );
+ char *ret;
- /* check if we already imported it */
- if (is_already_imported( fullname ))
+ if (filename)
+ {
+ const char *basename = strrchr( filename, '/' );
+ if (!basename) basename = filename;
+ else basename++;
+ if (!strncmp( basename, "lib", 3 )) basename += 3;
+ ret = xmalloc( strlen(basename) + 5 );
+ strcpy( ret, basename );
+ if (strendswith( ret, ".def" )) ret[strlen(ret)-4] = 0;
+ }
+ else
{
- free( fullname );
- return;
+ ret = xmalloc( strlen(name) + 5 );
+ strcpy( ret, name );
}
+ if (!strchr( ret, '.' )) strcat( ret, ".dll" );
+ return ret;
+}
+
+/* add a dll to the list of imports */
+void add_import_dll( const char *name, const char *filename )
+{
+ struct import *imp = xmalloc( sizeof(*imp) );
- imp = xmalloc( sizeof(*imp) );
imp->spec = alloc_dll_spec();
- imp->spec->file_name = fullname;
- imp->delay = delay;
+ imp->spec->file_name = get_dll_name( name, filename );
+ imp->delay = 0;
imp->imports = NULL;
imp->nb_imports = 0;
- if (delay) nb_delayed++;
+ imp->exports = NULL;
+ imp->nb_exports = 0;
+
+ if (filename) imp->full_name = xstrdup( filename );
+ else imp->full_name = find_library( name );
- if (read_import_lib( name, imp ))
+ if (read_import_lib( imp ))
{
dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
dll_imports[nb_imports++] = imp;
}
}
+/* add a library to the list of delayed imports */
+void add_delayed_import( const char *name )
+{
+ struct import *imp;
+ char *fullname = get_dll_name( name, NULL );
+
+ delayed_imports = xrealloc( delayed_imports, (nb_delayed_imports+1) * sizeof(*delayed_imports) );
+ delayed_imports[nb_delayed_imports++] = fullname;
+ if ((imp = is_already_imported( fullname )) && !imp->delay)
+ {
+ imp->delay = 1;
+ nb_delayed++;
+ }
+}
+
/* remove an imported dll, based on its index in the dll_imports array */
static void remove_import_dll( int index )
{
static void add_extra_undef_symbols( const DLLSPEC *spec )
{
const char *extras[10];
- int i, count = 0, nb_stubs = 0, nb_regs = 0;
+ int i, count = 0, nb_stubs = 0;
int kernel_imports = 0, ntdll_imports = 0;
sort_symbols( undef_symbols, nb_undef_symbols );
{
ORDDEF *odp = &spec->entry_points[i];
if (odp->type == TYPE_STUB) nb_stubs++;
- if (odp->flags & FLAG_REGISTER) nb_regs++;
}
/* add symbols that will be contained in the spec file itself */
if (nb_delayed)
{
kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec );
+ kernel_imports += add_extra_symbol( extras, &count, "FreeLibrary", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec );
+ kernel_imports += add_extra_symbol( extras, &count, "RaiseException", spec );
}
- if (nb_regs)
- ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs", spec );
- if (nb_delayed || nb_stubs)
+ if (nb_stubs)
ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
/* make sure we import the dlls that contain these functions */
- if (kernel_imports) add_import_dll( "kernel32", 0 );
- if (ntdll_imports) add_import_dll( "ntdll", 0 );
+ if (kernel_imports) add_import_dll( "kernel32", NULL );
+ if (ntdll_imports) add_import_dll( "ntdll", NULL );
if (count)
{
if (!nb_delayed) goto done;
+ fprintf( outfile, "static void *__wine_delay_imp_hmod[%d];\n", nb_delayed );
for (i = 0; i < nb_imports; i++)
{
if (!dll_imports[i]->delay) continue;
- fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
for (j = 0; j < dll_imports[i]->nb_imports; j++)
{
ORDDEF *odp = dll_imports[i]->imports[j];
for (i = j = 0; i < nb_imports; i++)
{
if (!dll_imports[i]->delay) continue;
- fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
+ fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_hmod[%d], &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
dll_imports[i]->spec->file_name, i, j, j );
j += dll_imports[i]->nb_imports;
}
}
fprintf( outfile, " }\n};\n\n" );
- /* check if there's some stub defined. if so, exception struct
- * is already defined, so don't emit it twice
- */
- for (i = 0; i < spec->nb_entry_points; i++) if (spec->entry_points[i].type == TYPE_STUB) break;
-
- if (i == spec->nb_entry_points) {
- fprintf( outfile, "struct exc_record {\n" );
- fprintf( outfile, " unsigned int code, flags;\n" );
- fprintf( outfile, " void *rec, *addr;\n" );
- fprintf( outfile, " unsigned int params;\n" );
- fprintf( outfile, " const void *info[15];\n" );
- fprintf( outfile, "};\n\n" );
- fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n" );
- }
-
+ fprintf( outfile, "extern void __stdcall RaiseException(unsigned int, unsigned int, unsigned int, const void *args[]);\n" );
fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
fprintf( outfile, "\n" );
fprintf( outfile, " /* patch IAT with final value */\n" );
fprintf( outfile, " return *pIAT = fn;\n" );
fprintf( outfile, " else {\n");
- fprintf( outfile, " struct exc_record rec;\n" );
- fprintf( outfile, " rec.code = 0x80000100;\n" );
- fprintf( outfile, " rec.flags = 1;\n" );
- fprintf( outfile, " rec.rec = 0;\n" );
- fprintf( outfile, " rec.params = 2;\n" );
- fprintf( outfile, " rec.info[0] = imd->szName;\n" );
- fprintf( outfile, " rec.info[1] = *pINT;\n" );
- fprintf( outfile, "#ifdef __GNUC__\n" );
- fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
- fprintf( outfile, "#else\n" );
- fprintf( outfile, " rec.addr = 0;\n" );
- fprintf( outfile, "#endif\n" );
- fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n" );
- fprintf( outfile, " return 0; /* shouldn't go here */\n" );
+ fprintf( outfile, " const void *args[2];\n" );
+ fprintf( outfile, " args[0] = imd->szName;\n" );
+ fprintf( outfile, " args[1] = *pINT;\n" );
+ fprintf( outfile, " RaiseException( 0x%08x, %d, 2, args );\n",
+ EXCEPTION_WINE_STUB, EXCEPTION_NONCONTINUABLE );
+ fprintf( outfile, " return 0;\n" );
fprintf( outfile, " }\n}\n\n" );
fprintf( outfile, "#ifndef __GNUC__\n" );
/* output the import and delayed import tables of a Win32 module
* returns number of DLLs exported in 'immediate' mode
*/
-int output_imports( FILE *outfile, DLLSPEC *spec )
+int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed )
{
- output_delayed_imports( outfile, spec );
- return output_immediate_imports( outfile );
+ *nb_delayed = output_delayed_imports( outfile, spec );
+ return output_immediate_imports( outfile );
}
#include <ctype.h>
#include "wine/exception.h"
-#include "stackframe.h"
-#include "builtin16.h"
-#include "module.h"
+#include "wine/winbase16.h"
#include "build.h"
/*******************************************************************
- * StoreVariableCode
- *
- * Store a list of ints into a byte array.
- */
-static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp )
-{
- int i;
-
- switch(size)
- {
- case 1:
- for (i = 0; i < odp->u.var.n_values; i++)
- buffer[i] = odp->u.var.values[i];
- break;
- case 2:
- for (i = 0; i < odp->u.var.n_values; i++)
- ((unsigned short *)buffer)[i] = odp->u.var.values[i];
- break;
- case 4:
- for (i = 0; i < odp->u.var.n_values; i++)
- ((unsigned int *)buffer)[i] = odp->u.var.values[i];
- break;
- }
- return odp->u.var.n_values * size;
-}
-
-
-/*******************************************************************
- * BuildModule16
- *
- * Build the in-memory representation of a 16-bit NE module, and dump it
- * as a byte stream into the assembly code.
+ * output_entry_table
*/
-static int BuildModule16( FILE *outfile, int max_code_offset,
- int max_data_offset, DLLSPEC *spec )
+static int output_entry_table( unsigned char **ret_buff, DLLSPEC *spec )
{
- int i;
- char *buffer;
- NE_MODULE *pModule;
- SEGTABLEENTRY *pSegment;
- OFSTRUCT *pFileInfo;
- BYTE *pstr;
- ET_BUNDLE *bundle = 0;
- ET_ENTRY entry;
-
- /* Module layout:
- * NE_MODULE Module
- * OFSTRUCT File information
- * SEGTABLEENTRY Segment 1 (code)
- * SEGTABLEENTRY Segment 2 (data)
- * WORD[2] Resource table (empty)
- * BYTE[2] Imported names (empty)
- * BYTE[n] Resident names table
- * BYTE[n] Entry table
- */
-
- buffer = xmalloc( 0x10000 );
- memset( buffer, 0, 0x10000 );
-
- pModule = (NE_MODULE *)buffer;
- pModule->magic = IMAGE_OS2_SIGNATURE;
- pModule->count = 1;
- pModule->next = 0;
- pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE;
- pModule->dgroup = 2;
- pModule->heap_size = spec->heap_size;
- pModule->stack_size = 0;
- pModule->ip = 0;
- pModule->cs = 0;
- pModule->sp = 0;
- pModule->ss = 0;
- pModule->seg_count = 2;
- pModule->modref_count = 0;
- pModule->nrname_size = 0;
- pModule->modref_table = 0;
- pModule->nrname_fpos = 0;
- pModule->moveable_entries = 0;
- pModule->alignment = 0;
- pModule->truetype = 0;
- pModule->os_flags = NE_OSFLAGS_WINDOWS;
- pModule->misc_flags = 0;
- pModule->dlls_to_init = 0;
- pModule->nrname_handle = 0;
- pModule->min_swap_area = 0;
- pModule->expected_version = 0;
- pModule->module32 = 0;
- pModule->self = 0;
- pModule->self_loading_sel = 0;
-
- /* File information */
-
- pFileInfo = (OFSTRUCT *)(pModule + 1);
- pModule->fileinfo = (int)pFileInfo - (int)pModule;
- memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
- pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
- + strlen(spec->file_name);
- strcpy( pFileInfo->szPathName, spec->file_name );
- pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
-
- /* Segment table */
-
- pstr = (char *)(((long)pstr + 3) & ~3);
- pSegment = (SEGTABLEENTRY *)pstr;
- pModule->seg_table = (int)pSegment - (int)pModule;
- pSegment->filepos = 0;
- pSegment->size = max_code_offset;
- pSegment->flags = 0;
- pSegment->minsize = max_code_offset;
- pSegment->hSeg = 0;
- pSegment++;
-
- pModule->dgroup_entry = (int)pSegment - (int)pModule;
- pSegment->filepos = 0;
- pSegment->size = max_data_offset;
- pSegment->flags = NE_SEGFLAGS_DATA;
- pSegment->minsize = max_data_offset;
- pSegment->hSeg = 0;
- pSegment++;
-
- /* Resource table */
-
- pstr = (char *)pSegment;
- pstr = (char *)(((long)pstr + 3) & ~3);
- pModule->res_table = (int)pstr - (int)pModule;
- pstr += output_res16_directory( pstr, spec );
-
- /* Imported names table */
-
- pstr = (char *)(((long)pstr + 3) & ~3);
- pModule->import_table = (int)pstr - (int)pModule;
- *pstr++ = 0;
- *pstr++ = 0;
-
- /* Resident names table */
-
- pstr = (char *)(((long)pstr + 3) & ~3);
- pModule->name_table = (int)pstr - (int)pModule;
- /* First entry is module name */
- *pstr = strlen( spec->dll_name );
- strcpy( pstr + 1, spec->dll_name );
- strupper( pstr + 1 );
- pstr += *pstr + 1;
- *pstr++ = 0;
- *pstr++ = 0;
- /* Store all ordinals */
- for (i = 1; i <= spec->limit; i++)
- {
- ORDDEF *odp = spec->ordinals[i];
- WORD ord = i;
- if (!odp || !odp->name[0]) continue;
- *pstr = strlen( odp->name );
- strcpy( pstr + 1, odp->name );
- strupper( pstr + 1 );
- pstr += *pstr + 1;
- memcpy( pstr, &ord, sizeof(WORD) );
- pstr += sizeof(WORD);
- }
- *pstr++ = 0;
+ int i, prev = 0, prev_sel = -1;
+ unsigned char *pstr, *buffer;
+ unsigned char *bundle = NULL;
- /* Entry table */
+ buffer = xmalloc( spec->limit * 5 ); /* we use at most 5 bytes per entry-point */
+ pstr = buffer;
- pstr = (char *)(((long)pstr + 3) & ~3);
- pModule->entry_table = (int)pstr - (int)pModule;
for (i = 1; i <= spec->limit; i++)
{
int selector = 0;
+ WORD offset;
ORDDEF *odp = spec->ordinals[i];
if (!odp) continue;
- switch (odp->type)
- {
+ switch (odp->type)
+ {
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_VARARGS:
case TYPE_STUB:
selector = 1; /* Code selector */
break;
-
case TYPE_VARIABLE:
selector = 2; /* Data selector */
break;
-
case TYPE_ABS:
selector = 0xfe; /* Constant selector */
break;
-
default:
- selector = 0; /* Invalid selector */
- break;
+ continue;
}
- if ( !selector )
- continue;
-
- if ( bundle && bundle->last+1 == i )
- bundle->last++;
- else
+ if (!bundle || prev + 1 != i || prev_sel != selector || *bundle == 255)
{
- pstr = (char *)(((long)pstr + 1) & ~1);
- if ( bundle )
- bundle->next = (char *)pstr - (char *)pModule;
-
- bundle = (ET_BUNDLE *)pstr;
- bundle->first = i-1;
- bundle->last = i;
- bundle->next = 0;
- pstr += sizeof(ET_BUNDLE);
- }
+ /* need to start a new bundle */
- /* FIXME: is this really correct ?? */
- entry.type = 0xff; /* movable */
- entry.flags = 3; /* exported & public data */
- entry.segnum = selector;
- entry.offs = odp->offset;
- memcpy( pstr, &entry, sizeof(ET_ENTRY) );
- pstr += sizeof(ET_ENTRY);
+ if (prev + 1 != i)
+ {
+ int skip = i - (prev + 1);
+ while (skip > 255)
+ {
+ *pstr++ = 255;
+ *pstr++ = 0;
+ skip -= 255;
+ }
+ *pstr++ = skip;
+ *pstr++ = 0;
+ }
+
+ bundle = pstr;
+ *pstr++ = 0;
+ *pstr++ = selector;
+ prev_sel = selector;
+ }
+ /* output the entry */
+ *pstr++ = 3; /* flags: exported & public data */
+ offset = odp->offset;
+ memcpy( pstr, &offset, sizeof(WORD) );
+ pstr += sizeof(WORD);
+ (*bundle)++; /* increment bundle entry count */
+ prev = i;
}
*pstr++ = 0;
+ if ((pstr - buffer) & 1) *pstr++ = 0;
+ *ret_buff = xrealloc( buffer, pstr - buffer );
+ return pstr - buffer;
+}
- /* Dump the module content */
- pstr = (char *)(((long)pstr + 3) & ~3);
- dump_bytes( outfile, (char *)pModule, (int)pstr - (int)pModule, "Module", 0 );
- return (int)pstr - (int)pModule;
+/*******************************************************************
+ * output_bytes
+ */
+static void output_bytes( FILE *outfile, const void *buffer, unsigned int size )
+{
+ unsigned int i;
+ const unsigned char *ptr = buffer;
+
+ fprintf( outfile, " {" );
+ for (i = 0; i < size; i++)
+ {
+ if (!(i & 7)) fprintf( outfile, "\n " );
+ fprintf( outfile, " 0x%02x", *ptr++ );
+ if (i < size - 1) fprintf( outfile, "," );
+ }
+ fprintf( outfile, "\n },\n" );
}
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
fprintf( outfile, "#endif\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
- fprintf( outfile, " struct exc_record {\n" );
- fprintf( outfile, " unsigned int code, flags;\n" );
- fprintf( outfile, " void *rec, *addr;\n" );
- fprintf( outfile, " unsigned int params;\n" );
- fprintf( outfile, " const void *info[15];\n" );
- fprintf( outfile, " } rec;\n\n" );
- fprintf( outfile, " extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" );
- fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB );
- fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
- fprintf( outfile, " rec.rec = 0;\n" );
- fprintf( outfile, " rec.params = 2;\n" );
- fprintf( outfile, " rec.info[0] = \"%s\";\n", spec->file_name );
- fprintf( outfile, " rec.info[1] = func;\n" );
- fprintf( outfile, "#ifdef __GNUC__\n" );
- fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
- fprintf( outfile, "#else\n" );
- fprintf( outfile, " rec.addr = 0;\n" );
- fprintf( outfile, "#endif\n" );
- fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" );
+ fprintf( outfile, " extern void __stdcall RaiseException( unsigned int, unsigned int, unsigned int, const void ** );\n" );
+ fprintf( outfile, " const void *args[2];\n" );
+ fprintf( outfile, " args[0] = \"%s\";\n", spec->file_name );
+ fprintf( outfile, " args[1] = func;\n" );
+ fprintf( outfile, " for (;;) RaiseException( 0x%08x, %d, 2, args );\n}\n\n",
+ EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
break;
}
for (i = 0; i <= spec->limit; i++)
{
ORDDEF **type, **typelist;
int i, nFuncs, nTypes;
- int code_offset, data_offset, module_size, res_size;
- unsigned char *data;
+ unsigned char *resdir_buffer, *resdata_buffer, *et_buffer, *data_buffer;
+ unsigned char string[256];
+ unsigned int ne_offset, segtable_offset, impnames_offset;
+ unsigned int entrypoint_size, callfrom_size;
+ unsigned int code_size, code_offset;
+ unsigned int data_size, data_offset;
+ unsigned int resnames_size, resnames_offset;
+ unsigned int resdir_size, resdir_offset;
+ unsigned int resdata_size, resdata_offset, resdata_align;
+ unsigned int et_size, et_offset;
+
char constructor[100], destructor[100];
#ifdef __i386__
unsigned short code_selector = get_cs();
fprintf( outfile, "extern void __wine_call_from_16_regs();\n" );
fprintf( outfile, "extern void __wine_call_from_16_thunk();\n" );
- data = (unsigned char *)xmalloc( 0x10000 );
- memset( data, 0, 16 );
- data_offset = 16;
+ data_buffer = xmalloc( 0x10000 );
+ memset( data_buffer, 0, 16 );
+ data_size = 16;
if (!spec->dll_name) /* set default name from file name */
{
}
#endif
- /* Output the DLL functions prototypes */
+ /* compute code and data sizes, set offsets, and output prototypes */
+
+#ifdef __i386__
+ entrypoint_size = 2 + 5 + 4; /* pushw bp + pushl target + call */
+ callfrom_size = 5 + 7 + 4 + 8; /* pushl relay + lcall cs:glue + lret n + args */
+#else
+ entrypoint_size = 4 + 4; /* target + call */
+ callfrom_size = 4 + 8; /* lret n + args */
+#endif
+ code_size = nTypes * callfrom_size;
for (i = 0; i <= spec->limit; i++)
{
ORDDEF *odp = spec->ordinals[i];
if (!odp) continue;
- switch(odp->type)
+ switch (odp->type)
{
+ case TYPE_ABS:
+ odp->offset = LOWORD(odp->u.abs.value);
+ break;
+ case TYPE_VARIABLE:
+ odp->offset = data_size;
+ memcpy( data_buffer + data_size, odp->u.var.values, odp->u.var.n_values * sizeof(int) );
+ data_size += odp->u.var.n_values * sizeof(int);
+ break;
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_VARARGS:
fprintf( outfile, "extern void %s();\n", odp->link_name );
+ /* fall through */
+ case TYPE_STUB:
+ odp->offset = code_size;
+ code_size += entrypoint_size;
break;
default:
+ assert(0);
break;
}
}
+ data_buffer = xrealloc( data_buffer, data_size ); /* free unneeded data */
- /* Output code segment */
+ /* Output the module structure */
+
+ /* DOS header */
fprintf( outfile, "\n#include \"pshpack1.h\"\n" );
- fprintf( outfile, "\nstatic struct code_segment\n{\n" );
+ fprintf( outfile, "static const struct module_data\n{\n" );
+ fprintf( outfile, " struct\n {\n" );
+ fprintf( outfile, " unsigned short e_magic;\n" );
+ fprintf( outfile, " unsigned short e_cblp;\n" );
+ fprintf( outfile, " unsigned short e_cp;\n" );
+ fprintf( outfile, " unsigned short e_crlc;\n" );
+ fprintf( outfile, " unsigned short e_cparhdr;\n" );
+ fprintf( outfile, " unsigned short e_minalloc;\n" );
+ fprintf( outfile, " unsigned short e_maxalloc;\n" );
+ fprintf( outfile, " unsigned short e_ss;\n" );
+ fprintf( outfile, " unsigned short e_sp;\n" );
+ fprintf( outfile, " unsigned short e_csum;\n" );
+ fprintf( outfile, " unsigned short e_ip;\n" );
+ fprintf( outfile, " unsigned short e_cs;\n" );
+ fprintf( outfile, " unsigned short e_lfarlc;\n" );
+ fprintf( outfile, " unsigned short e_ovno;\n" );
+ fprintf( outfile, " unsigned short e_res[4];\n" );
+ fprintf( outfile, " unsigned short e_oemid;\n" );
+ fprintf( outfile, " unsigned short e_oeminfo;\n" );
+ fprintf( outfile, " unsigned short e_res2[10];\n" );
+ fprintf( outfile, " unsigned int e_lfanew;\n" );
+ fprintf( outfile, " } dos_header;\n" );
+
+ /* NE header */
+
+ ne_offset = 64;
+ fprintf( outfile, " struct\n {\n" );
+ fprintf( outfile, " unsigned short ne_magic;\n" );
+ fprintf( outfile, " unsigned char ne_ver;\n" );
+ fprintf( outfile, " unsigned char ne_rev;\n" );
+ fprintf( outfile, " unsigned short ne_enttab;\n" );
+ fprintf( outfile, " unsigned short ne_cbenttab;\n" );
+ fprintf( outfile, " int ne_crc;\n" );
+ fprintf( outfile, " unsigned short ne_flags;\n" );
+ fprintf( outfile, " unsigned short ne_autodata;\n" );
+ fprintf( outfile, " unsigned short ne_heap;\n" );
+ fprintf( outfile, " unsigned short ne_stack;\n" );
+ fprintf( outfile, " unsigned int ne_csip;\n" );
+ fprintf( outfile, " unsigned int ne_sssp;\n" );
+ fprintf( outfile, " unsigned short ne_cseg;\n" );
+ fprintf( outfile, " unsigned short ne_cmod;\n" );
+ fprintf( outfile, " unsigned short ne_cbnrestab;\n" );
+ fprintf( outfile, " unsigned short ne_segtab;\n" );
+ fprintf( outfile, " unsigned short ne_rsrctab;\n" );
+ fprintf( outfile, " unsigned short ne_restab;\n" );
+ fprintf( outfile, " unsigned short ne_modtab;\n" );
+ fprintf( outfile, " unsigned short ne_imptab;\n" );
+ fprintf( outfile, " unsigned int ne_nrestab;\n" );
+ fprintf( outfile, " unsigned short ne_cmovent;\n" );
+ fprintf( outfile, " unsigned short ne_align;\n" );
+ fprintf( outfile, " unsigned short ne_cres;\n" );
+ fprintf( outfile, " unsigned char ne_exetyp;\n" );
+ fprintf( outfile, " unsigned char ne_flagsothers;\n" );
+ fprintf( outfile, " unsigned short ne_pretthunks;\n" );
+ fprintf( outfile, " unsigned short ne_psegrefbytes;\n" );
+ fprintf( outfile, " unsigned short ne_swaparea;\n" );
+ fprintf( outfile, " unsigned short ne_expver;\n" );
+ fprintf( outfile, " } os2_header;\n" );
+
+ /* segment table */
+
+ segtable_offset = 64;
+ fprintf( outfile, " struct\n {\n" );
+ fprintf( outfile, " unsigned short filepos;\n" );
+ fprintf( outfile, " unsigned short size;\n" );
+ fprintf( outfile, " unsigned short flags;\n" );
+ fprintf( outfile, " unsigned short minsize;\n" );
+ fprintf( outfile, " } segtable[2];\n" );
+
+ /* resource directory */
+
+ resdir_offset = segtable_offset + 2 * 8;
+ resdir_size = get_res16_directory_size( spec );
+ fprintf( outfile, " unsigned char resdir[%d];\n", resdir_size );
+
+ /* resident names table */
+
+ resnames_offset = resdir_offset + resdir_size;
+ fprintf( outfile, " struct\n {\n" );
+ fprintf( outfile, " struct { unsigned char len; char name[%d]; unsigned short ord; } name_0;\n",
+ strlen( spec->dll_name ) );
+ resnames_size = 3 + strlen( spec->dll_name );
+ for (i = 1; i <= spec->limit; i++)
+ {
+ ORDDEF *odp = spec->ordinals[i];
+ if (!odp || !odp->name[0]) continue;
+ fprintf( outfile, " struct { unsigned char len; char name[%d]; unsigned short ord; } name_%d;\n",
+ strlen(odp->name), i );
+ resnames_size += 3 + strlen( odp->name );
+ }
+ fprintf( outfile, " unsigned char name_last[%d];\n", 2 - (resnames_size & 1) );
+ resnames_size = (resnames_size + 2) & ~1;
+ fprintf( outfile, " } resnames;\n" );
+
+ /* imported names table */
+
+ impnames_offset = resnames_offset + resnames_size;
+ fprintf( outfile, " unsigned char impnames[2];\n" );
+
+ /* entry table */
+
+ et_offset = impnames_offset + 2;
+ et_size = output_entry_table( &et_buffer, spec );
+ fprintf( outfile, " unsigned char entry_table[%d];\n", et_size );
+
+ /* code segment */
+
+ code_offset = et_offset + et_size;
fprintf( outfile, " struct {\n" );
#ifdef __i386__
fprintf( outfile, " unsigned char pushl;\n" ); /* pushl $relay */
fprintf( outfile, " unsigned short call;\n" ); /* call CALLFROM16 */
fprintf( outfile, " short callfrom16;\n" );
fprintf( outfile, " } entry[%d];\n", nFuncs );
- fprintf( outfile, "} code_segment =\n{\n {\n" );
- code_offset = 0;
+ /* data segment */
+
+ data_offset = code_offset + code_size;
+ fprintf( outfile, " unsigned char data_segment[%d];\n", data_size );
+ if (data_offset + data_size >= 0x10000)
+ fatal_error( "Not supported yet: 16-bit module data larger than 64K\n" );
+
+ /* resource data */
+
+ resdata_offset = ne_offset + data_offset + data_size;
+ for (resdata_align = 0; resdata_align < 16; resdata_align++)
+ {
+ unsigned int size = get_res16_data_size( spec, resdata_offset, resdata_align );
+ if ((resdata_offset + size) >> resdata_align <= 0xffff) break;
+ }
+ output_res16_directory( &resdir_buffer, spec, resdata_offset, resdata_align );
+ resdata_size = output_res16_data( &resdata_buffer, spec, resdata_offset, resdata_align );
+ if (resdata_size) fprintf( outfile, " unsigned char resources[%d];\n", resdata_size );
+
+ /* Output the module data */
+
+ /* DOS header */
+
+ fprintf( outfile, "} module =\n{\n {\n" );
+ fprintf( outfile, " 0x%04x,\n", IMAGE_DOS_SIGNATURE ); /* e_magic */
+ fprintf( outfile, " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n" );
+ fprintf( outfile, " { 0, 0, 0, 0, }, 0, 0,\n" );
+ fprintf( outfile, " { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n" );
+ fprintf( outfile, " sizeof(module.dos_header)\n" ); /* e_lfanew */
+
+ /* NE header */
+ fprintf( outfile, " },\n {\n" );
+ fprintf( outfile, " 0x%04x,\n", IMAGE_OS2_SIGNATURE ); /* ne_magic */
+ fprintf( outfile, " 0, 0,\n" );
+ fprintf( outfile, " %d,\n", et_offset ); /* ne_enttab */
+ fprintf( outfile, " sizeof(module.entry_table),\n" ); /* ne_cbenttab */
+ fprintf( outfile, " 0,\n" ); /* ne_crc */
+ fprintf( outfile, " 0x%04x,\n", /* ne_flags */
+ NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE );
+ fprintf( outfile, " 2,\n" ); /* ne_autodata */
+ fprintf( outfile, " %d,\n", spec->heap_size ); /* ne_heap */
+ fprintf( outfile, " 0, 0, 0,\n" );
+ fprintf( outfile, " 2,\n" ); /* ne_cseg */
+ fprintf( outfile, " 0,\n" ); /* ne_cmod */
+ fprintf( outfile, " 0,\n" ); /* ne_cbnrestab */
+ fprintf( outfile, " %d,\n", segtable_offset ); /* ne_segtab */
+ fprintf( outfile, " %d,\n", resdir_offset ); /* ne_rsrctab */
+ fprintf( outfile, " %d,\n", resnames_offset ); /* ne_restab */
+ fprintf( outfile, " %d,\n", impnames_offset ); /* ne_modtab */
+ fprintf( outfile, " %d,\n", impnames_offset ); /* ne_imptab */
+ fprintf( outfile, " 0,\n" ); /* ne_nrestab */
+ fprintf( outfile, " 0,\n" ); /* ne_cmovent */
+ fprintf( outfile, " 0,\n" ); /* ne_align */
+ fprintf( outfile, " 0,\n" ); /* ne_cres */
+ fprintf( outfile, " 0x%04x,\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */
+ fprintf( outfile, " 0x%04x,\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */
+ fprintf( outfile, " 0,\n" ); /* ne_pretthunks */
+ fprintf( outfile, " 0,\n" ); /* ne_psegrefbytes */
+ fprintf( outfile, " 0,\n" ); /* ne_swaparea */
+ fprintf( outfile, " 0\n" ); /* ne_expver */
+ fprintf( outfile, " },\n" );
+
+ /* segment table */
+
+ fprintf( outfile, " {\n" );
+ fprintf( outfile, " { %d, %d, 0x%04x, %d },\n",
+ ne_offset + code_offset, code_size, NE_SEGFLAGS_32BIT, code_size );
+ fprintf( outfile, " { %d, %d, 0x%04x, %d },\n",
+ ne_offset + data_offset, data_size, NE_SEGFLAGS_DATA, data_size );
+ fprintf( outfile, " },\n" );
+
+ /* resource directory */
+
+ output_bytes( outfile, resdir_buffer, resdir_size );
+ free( resdir_buffer );
+
+ /* resident names table */
+
+ fprintf( outfile, " {\n" );
+ strcpy( string, spec->dll_name );
+ fprintf( outfile, " { %d, \"%s\", 0 },\n", strlen(string), strupper(string) );
+ for (i = 1; i <= spec->limit; i++)
+ {
+ ORDDEF *odp = spec->ordinals[i];
+ if (!odp || !odp->name[0]) continue;
+ strcpy( string, odp->name );
+ fprintf( outfile, " { %d, \"%s\", %d },\n", strlen(string), strupper(string), i );
+ }
+ fprintf( outfile, " { 0 }\n },\n" );
+
+ /* imported names table */
+
+ fprintf( outfile, " { 0, 0 },\n" );
+
+ /* entry table */
+
+ output_bytes( outfile, et_buffer, et_size );
+ free( et_buffer );
+
+ /* code segment */
+
+ fprintf( outfile, " {\n" );
for ( i = 0; i < nTypes; i++ )
{
char profile[101], *arg;
fprintf( outfile, " { 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n",
arg_types[0], arg_types[1] );
#endif
- code_offset += sizeof(CALLFROM16);
}
fprintf( outfile, " },\n {\n" );
if (!odp) continue;
switch (odp->type)
{
- case TYPE_ABS:
- odp->offset = LOWORD(odp->u.abs.value);
- break;
-
- case TYPE_VARIABLE:
- odp->offset = data_offset;
- data_offset += StoreVariableCode( data + data_offset, 4, odp);
- break;
-
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_VARARGS:
assert( type );
fprintf( outfile, " /* %s.%d */ ", spec->dll_name, i );
+ fprintf( outfile,
#ifdef __i386__
- fprintf( outfile, "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n",
+ "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n",
#else
- fprintf( outfile, "{ %s, 0xe866, %d, /* %s */ },\n",
+ "{ %s, 0xe866, %d, /* %s */ },\n",
#endif
odp->link_name,
- (type-typelist)*sizeof(CALLFROM16) -
- (code_offset + sizeof(ENTRYPOINT16)),
+ (type - typelist) * callfrom_size - (odp->offset + entrypoint_size),
get_function_name( odp ) );
-
- odp->offset = code_offset;
- code_offset += sizeof(ENTRYPOINT16);
break;
-
- default:
- fprintf(stderr,"build: function type %d not available for Win16\n",
- odp->type);
- exit(1);
+ default:
+ break;
}
}
+ fprintf( outfile, " },\n" );
- fprintf( outfile, " }\n};\n" );
-
- /* Output data segment */
- dump_bytes( outfile, data, data_offset, "Data_Segment", 0 );
+ /* data_segment */
- /* Build the module */
+ output_bytes( outfile, data_buffer, data_size );
+ free( data_buffer );
- module_size = BuildModule16( outfile, code_offset, data_offset, spec );
- res_size = output_res16_data( outfile, spec );
+ /* resource data */
- /* Output the DLL descriptor */
-
- fprintf( outfile, "#include \"poppack.h\"\n\n" );
+ if (resdata_size)
+ {
+ output_bytes( outfile, resdata_buffer, resdata_size );
+ free( resdata_buffer );
+ }
- fprintf( outfile, "static const struct dll_descriptor\n{\n" );
- fprintf( outfile, " unsigned char *module_start;\n" );
- fprintf( outfile, " int module_size;\n" );
- fprintf( outfile, " struct code_segment *code_start;\n" );
- fprintf( outfile, " unsigned char *data_start;\n" );
- fprintf( outfile, " const char *owner;\n" );
- fprintf( outfile, " const unsigned char *rsrc;\n" );
- fprintf( outfile, "} descriptor =\n{\n" );
- fprintf( outfile, " Module,\n" );
- fprintf( outfile, " sizeof(Module),\n" );
- fprintf( outfile, " &code_segment,\n" );
- fprintf( outfile, " Data_Segment,\n" );
- fprintf( outfile, " \"%s\",\n", spec->owner_name );
- fprintf( outfile, " %s\n", res_size ? "resource_data" : "0" );
fprintf( outfile, "};\n" );
+ fprintf( outfile, "#include \"poppack.h\"\n\n" );
/* Output the DLL constructor */
fprintf( outfile,
"void %s(void)\n"
"{\n"
- " extern void __wine_register_dll_16( const struct dll_descriptor *descr );\n"
- " __wine_register_dll_16( &descriptor );\n"
- "}\n", constructor );
+ " extern void __wine_dll_register_16( const struct module_data *, const char * );\n"
+ " __wine_dll_register_16( &module, \"%s\" );\n"
+ "}\n", constructor, spec->file_name );
fprintf( outfile,
"void %s(void)\n"
"{\n"
- " extern void __wine_unregister_dll_16( const struct dll_descriptor *descr );\n"
- " __wine_unregister_dll_16( &descriptor );\n"
+ " extern void __wine_dll_unregister_16( const struct module_data * );\n"
+ " __wine_dll_unregister_16( &module );\n"
"}\n", destructor );
}