From 3513a176fd325492e5b5e498e4eebf3f820f8cc6 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 30 Aug 2021 11:46:51 +0200 Subject: [PATCH] winebuild: Add an option to set the syscall table id. Signed-off-by: Alexandre Julliard --- tools/winebuild/build.h | 1 + tools/winebuild/import.c | 12 +++++++----- tools/winebuild/main.c | 15 +++++++++++++++ tools/winebuild/utils.c | 1 + tools/winebuild/winebuild.man.in | 5 +++++ 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 1918932ad1f..52472958d31 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -136,6 +136,7 @@ typedef struct int subsystem; /* subsystem id */ int subsystem_major; /* subsystem version major number */ int subsystem_minor; /* subsystem version minor number */ + int syscall_table; /* syscall table id */ int unicode_app; /* default to unicode entry point */ ORDDEF *entry_points; /* dll entry points */ ORDDEF **names; /* array of entry point names (points into entry_points) */ diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 6a158578143..84738fc9135 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1458,6 +1458,8 @@ void output_syscalls( DLLSPEC *spec ) { ORDDEF *odp = syscalls[i]; const char *name = get_link_name(odp); + unsigned int id = (spec->syscall_table << 12) + i; + output( "\t.align %d\n", get_alignment(16) ); output( "\t%s\n", func_declaration(name) ); output( "%s\n", asm_globl(name) ); @@ -1469,12 +1471,12 @@ void output_syscalls( DLLSPEC *spec ) { output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") ); output( "1:\tmovl %s-1b(%%eax),%%edx\n", asm_name("__wine_syscall_dispatcher") ); - output( "\tmovl $%u,%%eax\n", i ); + output( "\tmovl $%u,%%eax\n", id ); needs_get_pc_thunk = 1; } else { - output( "\tmovl $%u,%%eax\n", i ); + output( "\tmovl $%u,%%eax\n", id ); output( "\tmovl $%s,%%edx\n", asm_name("__wine_syscall") ); } output( "\tcall *%%edx\n" ); @@ -1488,7 +1490,7 @@ void output_syscalls( DLLSPEC *spec ) * validate that instruction, we can just put a jmp there instead. */ output( "\t.byte 0x4c,0x8b,0xd1\n" ); /* movq %rcx,%r10 */ output( "\t.byte 0xb8\n" ); /* movl $i,%eax */ - output( "\t.long %u\n", i ); + output( "\t.long %u\n", id ); output( "\t.byte 0xf6,0x04,0x25,0x08,0x03,0xfe,0x7f,0x01\n" ); /* testb $1,0x7ffe0308 */ output( "\t.byte 0x75,0x03\n" ); /* jne 1f */ output( "\t.byte 0x0f,0x05\n" ); /* syscall */ @@ -1509,14 +1511,14 @@ void output_syscalls( DLLSPEC *spec ) break; case CPU_ARM: output( "\tpush {r0-r3}\n" ); - output( "\tmovw ip, #%u\n", i ); + output( "\tmovw ip, #%u\n", id ); output( "\tmov r3, lr\n" ); output( "\tbl %s\n", asm_name("__wine_syscall") ); output( "\tadd sp, #16\n" ); output( "\tbx lr\n" ); break; case CPU_ARM64: - output( "\tmov x8, #%u\n", i ); + output( "\tmov x8, #%u\n", id ); output( "\tmov x9, x30\n" ); output( "\tbl %s\n", asm_name("__wine_syscall" )); output( "\tret\n" ); diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index 8c0e77030b6..84923249c66 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -202,6 +202,15 @@ static void set_subsystem( const char *subsystem, DLLSPEC *spec ) free( str ); } +/* set the syscall table id */ +static void set_syscall_table( const char *id, DLLSPEC *spec ) +{ + int val = atoi( id ); + + if (val < 0 || val > 3) fatal_error( "Invalid syscall table id '%s', must be 0-3\n", id ); + spec->syscall_table = val; +} + /* set the target CPU and platform */ static void set_target( const char *target ) { @@ -303,6 +312,7 @@ static const char usage_str[] = " --safeseh Mark object files as SEH compatible\n" " --save-temps Do not delete the generated intermediate files\n" " --subsystem=SUBSYS Set the subsystem (one of native, windows, console, wince)\n" +" --syscall-table=ID Set the syscall table id (between 0 and 3)\n" " -u, --undefined=SYMBOL Add an undefined reference to SYMBOL when linking\n" " -v, --verbose Display the programs invoked\n" " --version Print the version and exit\n" @@ -340,6 +350,7 @@ enum long_options_values LONG_OPT_SAVE_TEMPS, LONG_OPT_STATICLIB, LONG_OPT_SUBSYSTEM, + LONG_OPT_SYSCALL_TABLE, LONG_OPT_VERSION }; @@ -367,6 +378,7 @@ static const struct option long_options[] = { "safeseh", 0, 0, LONG_OPT_SAFE_SEH }, { "save-temps", 0, 0, LONG_OPT_SAVE_TEMPS }, { "subsystem", 1, 0, LONG_OPT_SUBSYSTEM }, + { "syscall-table", 1, 0, LONG_OPT_SYSCALL_TABLE }, { "version", 0, 0, LONG_OPT_VERSION }, /* aliases for short options */ { "target", 1, 0, 'b' }, @@ -595,6 +607,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) case LONG_OPT_SUBSYSTEM: set_subsystem( optarg, spec ); break; + case LONG_OPT_SYSCALL_TABLE: + set_syscall_table( optarg, spec ); + break; case LONG_OPT_VERSION: printf( "winebuild version " PACKAGE_VERSION "\n" ); exit(0); diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index 441e84aa092..709ffb9e28d 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -911,6 +911,7 @@ DLLSPEC *alloc_dll_spec(void) spec->subsystem = 0; spec->subsystem_major = 4; spec->subsystem_minor = 0; + spec->syscall_table = 0; if (get_ptr_size() > 4) spec->characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; else diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in index d55c00b2d24..d9a05fc99d9 100644 --- a/tools/winebuild/winebuild.man.in +++ b/tools/winebuild/winebuild.man.in @@ -255,6 +255,11 @@ argument array to use Unicode strings. A graphical executable has a Optionally a major and minor subsystem version can also be specified; the default subsystem version is 4.0. .TP +.BI --syscall-table= id +Set the system call table id, between 0 and 3. The default is 0, the +ntdll syscall table. Only useful in modules that define syscall entry +points. +.TP .BI \-u,\ --undefined= symbol Add \fIsymbol\fR to the list of undefined symbols when invoking the linker. This makes it possible to force a specific module of a static