This is slightly different from dlltool but I think it should be compatible. The transition is done by first replacing dlltool with its bugs, and fixing them in separate changes.
I based the ARM / AARCH64 implementation on the existing code around, but I have no idea if it is correct, and dlltool also doesn't include any delay load implementation for ARM.
From: Rémi Bernon rbernon@codeweavers.com
And rename it to get_abi_name. --- tools/winebuild/build.h | 2 +- tools/winebuild/import.c | 4 ++-- tools/winebuild/spec16.c | 2 +- tools/winebuild/spec32.c | 10 +++++----- tools/winebuild/utils.c | 24 ++++++++++++------------ 5 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 9918c2341f4..79a22315b0d 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -273,7 +273,7 @@ extern DLLSPEC *alloc_dll_spec(void); extern void free_dll_spec( DLLSPEC *spec ); extern char *make_c_identifier( const char *str ); extern const char *get_stub_name( const ORDDEF *odp, const DLLSPEC *spec ); -extern const char *get_link_name( const ORDDEF *odp ); +extern const char *get_abi_name( const ORDDEF *odp, const char *name ); extern int sort_func_list( ORDDEF **list, int count, int (*compare)(const void *, const void *) ); extern unsigned int get_alignment(unsigned int align); extern unsigned int get_page_size(void); diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index b1c14db9cab..3f3775dc3bd 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -627,7 +627,7 @@ static char *create_undef_symbols_file( DLLSPEC *spec ) if (odp->type == TYPE_STUB || odp->type == TYPE_ABS || odp->type == TYPE_VARIABLE) continue; if (odp->flags & FLAG_FORWARD) continue; if (odp->flags & FLAG_SYSCALL) continue; - output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name( get_link_name( odp ))); + output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name( get_abi_name( odp, odp->link_name ))); } for (j = 0; j < extra_ld_symbols.count; j++) output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(extra_ld_symbols.str[j]) ); @@ -1393,7 +1393,7 @@ void output_syscalls( DLLSPEC *spec ) for (i = 0; i < count; i++) { ORDDEF *odp = syscalls[i]; - const char *name = get_link_name(odp); + const char *name = get_abi_name(odp, odp->link_name); unsigned int id = (spec->syscall_table << 12) + i;
output( "\t.align %d\n", get_alignment(16) ); diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c index 8d4f96ea323..ea5fb44986c 100644 --- a/tools/winebuild/spec16.c +++ b/tools/winebuild/spec16.c @@ -738,7 +738,7 @@ static void output_module16( DLLSPEC *spec ) output( ".L__wine_%s_%u:\n", spec->c_name, i ); output( "\tpushw %%bp\n" ); output( "\tpushl $%s\n", - asm_name( odp->type == TYPE_STUB ? get_stub_name( odp, spec ) : get_link_name( odp ))); + asm_name( odp->type == TYPE_STUB ? get_stub_name( odp, spec ) : get_abi_name( odp, odp->link_name ))); output( "\tcallw .L__wine_spec_callfrom16_%s\n", get_callfrom16_name( odp ) ); } output( ".L__wine_spec_code_segment_end:\n" ); diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index c09e58084cc..c445a2440d2 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -470,7 +470,7 @@ void output_exports( DLLSPEC *spec ) } else { - output( "\t%s %s\n", func_ptr, asm_name( get_link_name( odp ))); + output( "\t%s %s\n", func_ptr, asm_name( get_abi_name( odp, odp->link_name ))); } break; case TYPE_STUB: @@ -592,14 +592,14 @@ void output_exports( DLLSPEC *spec ) if (UsePIC) { output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") ); - output( "1:\tjmp *__imp_%s-1b(%%eax)\n", asm_name( get_link_name( odp ))); + output( "1:\tjmp *__imp_%s-1b(%%eax)\n", asm_name( get_abi_name( odp, odp->link_name ))); needs_get_pc_thunk = 1; } - else output( "\tjmp *__imp_%s\n", asm_name( get_link_name( odp ))); + else output( "\tjmp *__imp_%s\n", asm_name( get_abi_name( odp, odp->link_name ))); break; case CPU_x86_64: output( "\t.byte 0x48,0x8d,0xa4,0x24,0x00,0x00,0x00,0x00\n" ); /* hotpatch prolog */ - output( "\tjmp *__imp_%s(%%rip)\n", asm_name( get_link_name( odp ))); + output( "\tjmp *__imp_%s(%%rip)\n", asm_name( get_abi_name( odp, odp->link_name ))); break; default: assert(0); @@ -1325,7 +1325,7 @@ void output_def_file( DLLSPEC *spec, int import_only ) if (odp->flags & FLAG_FORWARD) output( "=%s", odp->link_name ); else if (strcmp(name, odp->link_name)) /* try to reduce output */ - output( "=%s", get_link_name( odp )); + output( "=%s", get_abi_name( odp, odp->link_name )); break; } case TYPE_STUB: diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index 4f1bdf7cd2d..eb75aaed50b 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -728,28 +728,28 @@ const char *get_stub_name( const ORDDEF *odp, const DLLSPEC *spec ) }
/* return the stdcall-decorated name for an entry point */ -const char *get_link_name( const ORDDEF *odp ) +const char *get_abi_name( const ORDDEF *odp, const char *name ) { static char *buffer; char *ret;
- if (target.cpu != CPU_i386) return odp->link_name; + if (target.cpu != CPU_i386) return name;
switch (odp->type) { case TYPE_STDCALL: if (is_pe()) { - if (odp->flags & FLAG_THISCALL) return odp->link_name; - if (odp->flags & FLAG_FASTCALL) ret = strmake( "@%s@%u", odp->link_name, get_args_size( odp )); - else if (!kill_at) ret = strmake( "%s@%u", odp->link_name, get_args_size( odp )); - else return odp->link_name; + if (odp->flags & FLAG_THISCALL) return name; + if (odp->flags & FLAG_FASTCALL) ret = strmake( "@%s@%u", name, get_args_size( odp )); + else if (!kill_at) ret = strmake( "%s@%u", name, get_args_size( odp )); + else return name; } else { - if (odp->flags & FLAG_THISCALL) ret = strmake( "__thiscall_%s", odp->link_name ); - else if (odp->flags & FLAG_FASTCALL) ret = strmake( "__fastcall_%s", odp->link_name ); - else return odp->link_name; + if (odp->flags & FLAG_THISCALL) ret = strmake( "__thiscall_%s", name ); + else if (odp->flags & FLAG_FASTCALL) ret = strmake( "__fastcall_%s", name ); + else return name; } break;
@@ -758,13 +758,13 @@ const char *get_link_name( const ORDDEF *odp ) { int args = get_args_size( odp ); if (odp->flags & FLAG_REGISTER) args += get_ptr_size(); /* context argument */ - ret = strmake( "%s@%u", odp->link_name, args ); + ret = strmake( "%s@%u", name, args ); } - else return odp->link_name; + else return name; break;
default: - return odp->link_name; + return name; }
free( buffer );
From: Rémi Bernon rbernon@codeweavers.com
--- tools/winebuild/utils.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index eb75aaed50b..f5928965c36 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -1016,8 +1016,7 @@ const char *asm_globl( const char *func ) break; case PLATFORM_MINGW: case PLATFORM_WINDOWS: - buffer = strmake( "\t.globl %s%s\n%s%s:", target.cpu == CPU_i386 ? "_" : "", func, - target.cpu == CPU_i386 ? "_" : "", func ); + buffer = strmake( "\t.globl %s\n%s:", asm_name( func ), asm_name( func ) ); break; default: buffer = strmake( "\t.globl %s\n\t.hidden %s\n%s:", func, func, func );
From: Rémi Bernon rbernon@codeweavers.com
--- tools/winebuild/import.c | 301 +++++++++++++++++++++++++++++++++++---- 1 file changed, 277 insertions(+), 24 deletions(-)
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 3f3775dc3bd..d4338cc3939 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1584,45 +1584,298 @@ static void build_library( const char *output_name, struct strarray files, int c /* create a Windows-style import library */ static void build_windows_import_lib( const char *lib_name, DLLSPEC *spec ) { - struct strarray args; - char *def_file; + char *dll_name = encode_dll_name( spec->file_name ), *delay_load, *import_desc, *import_name; + struct strarray objs = empty_strarray; + int i, total, by_name; + const char *name;
- def_file = open_temp_output_file( ".def" ); - output_def_file( spec, 1 ); - fclose( output_file ); + /* make sure assemble_files doesn't strip suffixes */ + for (i = 0; i < strlen( dll_name ); ++i) if (dll_name[i] == '.') dll_name[i] = '_';
- args = find_tool( "dlltool", NULL ); - strarray_add( &args, "-k" ); - strarray_add( &args, strendswith( lib_name, ".delay.a" ) ? "-y" : "-l" ); - strarray_add( &args, lib_name ); - strarray_add( &args, "-d" ); - strarray_add( &args, def_file ); + delay_load = strmake( "__wine_delay_load_%s", dll_name ); + import_desc = strmake( "__wine_import_%s_desc", dll_name ); + import_name = strmake( "__wine_import_%s_name", dll_name );
- switch (target.cpu) + new_output_as_file(); + + if (strendswith( lib_name, ".delay.a" )) { + output( "\t.text\n" ); + output( "\n\t.align %d\n", get_alignment( get_ptr_size() )); + output( "%s\n", asm_globl( delay_load ) ); + + output_cfi( ".cfi_startproc" ); + switch (target.cpu) + { case CPU_i386: - strarray_add( &args, "-m" ); - strarray_add( &args, "i386" ); - strarray_add( &args, "--as-flags=--32" ); + output( "\tpushl %%ecx\n" ); + output_cfi( ".cfi_adjust_cfa_offset 4" ); + output( "\tpushl %%edx\n" ); + output_cfi( ".cfi_adjust_cfa_offset 4" ); + output( "\tpushl %%eax\n" ); + output_cfi( ".cfi_adjust_cfa_offset 4" ); + output( "\tpushl $.L__wine_delay_import_desc\n" ); + output( "\tcall ___delayLoadHelper2@8\n" ); + output_cfi( ".cfi_adjust_cfa_offset -4" ); + output( "\tpopl %%edx\n" ); + output_cfi( ".cfi_adjust_cfa_offset -4" ); + output( "\tpopl %%ecx\n" ); + output_cfi( ".cfi_adjust_cfa_offset -4" ); + output( "\tjmp *%%eax\n" ); break; case CPU_x86_64: - strarray_add( &args, "-m" ); - strarray_add( &args, "i386:x86-64" ); - strarray_add( &args, "--as-flags=--64" ); + output_cfi( ".seh_proc %s", asm_name( delay_load ) ); + output( "\tsub $0x48, %%rsp\n" ); + output_cfi( ".cfi_adjust_cfa_offset 0x48" ); + output_cfi( ".seh_stackalloc 0x48" ); + output_cfi( ".seh_endprologue" ); + output( "\tmov %%rcx, 0x40(%%rsp)\n" ); + output( "\tmov %%rdx, 0x38(%%rsp)\n" ); + output( "\tmov %%r8, 0x30(%%rsp)\n" ); + output( "\tmov %%r9, 0x28(%%rsp)\n" ); + output( "\tmov %%rax, %%rdx\n" ); + output( "\tlea .L__wine_delay_import_desc(%%rip), %%rcx\n" ); + output( "\tcall __delayLoadHelper2\n" ); + output( "\tmov 0x28(%%rsp), %%r9\n" ); + output( "\tmov 0x30(%%rsp), %%r8\n" ); + output( "\tmov 0x38(%%rsp), %%rdx\n" ); + output( "\tmov 0x40(%%rsp), %%rcx\n" ); + output( "\tadd $0x48, %%rsp\n" ); + output_cfi( ".cfi_adjust_cfa_offset -0x48" ); + output( "\tjmp *%%rax\n" ); + output_cfi( ".seh_endproc" ); break; case CPU_ARM: - strarray_add( &args, "-m" ); - strarray_add( &args, "arm" ); + output( "\tpush {r0-r3, FP, LR}\n" ); + output( "\tmov r1, IP\n" ); + output( "\tldr r0, 1f\n" ); + output( "\tldr r0, [r0]\n" ); + output( "\tbl __delayLoadHelper2\n" ); + output( "\tmov IP, r0\n" ); + output( "\tpop {r0-r3, FP, LR}\n" ); + output( "\tbx IP\n" ); + output( "1:\t.long .L__wine_delay_import_desc\n" ); break; case CPU_ARM64: - strarray_add( &args, "-m" ); - strarray_add( &args, "arm64" ); + output( "\tstp x29, x30, [sp, #-80]!\n" ); + output( "\tmov x29, sp\n" ); + output( "\tstp x0, x1, [sp, #16]\n" ); + output( "\tstp x2, x3, [sp, #32]\n" ); + output( "\tstp x4, x5, [sp, #48]\n" ); + output( "\tstp x6, x7, [sp, #64]\n" ); + output( "\tmov x1, x16\n" ); + output( "\tadrp x0, .L__wine_delay_import_desc\n" ); + output( "\tadd x0, x0, #.L__wine_delay_import_desc\n" ); + output( "\tbl __delayLoadHelper2\n" ); + output( "\tmov x16, x0\n" ); + output( "\tldp x0, x1, [sp, #16]\n" ); + output( "\tldp x2, x3, [sp, #32]\n" ); + output( "\tldp x4, x5, [sp, #48]\n" ); + output( "\tldp x6, x7, [sp, #64]\n" ); + output( "\tldp x29, x30, [sp], #80\n" ); + output( "\tbr x16\n" ); break; + } + output_cfi( ".cfi_endproc" ); + output_function_size( delay_load ); + output_gnu_stack_note(); + + output( "\n\t.section ".text$2"\n" ); + output( ".L__wine_delay_import_desc:\n" ); + output( "\t.long 1\n" ); /* DllAttributes */ + output_rva( "%s\n", asm_name( import_name ) ); /* DllNameRVA */ + output_rva( ".L__wine_delay_import_handle\n" ); /* ModuleHandleRVA */ + output_rva( ".L__wine_delay_import_IAT\n" ); /* ImportAddressTableRVA */ + output_rva( ".L__wine_delay_import_INT\n" ); /* ImportNameTableRVA */ + output( "\t.long 0\n"); /* BoundImportAddressTableRVA */ + output( "\t.long 0\n"); /* UnloadInformationTableRVA */ + output( "\t.long 0\n"); /* TimeDateStamp */ + + output( "\t.data\n" ); + output( ".L__wine_delay_import_handle:\n" ); + output( "\t%s 0\n", get_asm_ptr_keyword() ); + } + + output( "\n\t.section ".idata$2","2"\n" ); + output( "%s\n", asm_globl( import_desc ) ); + output_rva( ".L__wine_import_names" ); /* OriginalFirstThunk */ + output( "\t.long 0\n" ); /* TimeDateStamp */ + output( "\t.long 0\n" ); /* ForwarderChain */ + output_rva( "%s", asm_name( import_name ) ); /* Name */ + output_rva( ".L__wine_import_addrs" ); /* FirstThunk */ + + output( "\n\t.section ".idata$4","2"\n" ); + output( ".L__wine_import_names:\n" ); /* OriginalFirstThunk head */ + if (strendswith( lib_name, ".delay.a" )) + { + output( "\t%s 0\n", get_asm_ptr_keyword() ); /* OriginalFirstThunk tail */ + output( ".L__wine_delay_import_INT:\n" ); + } + + output( "\n\t.section ".idata$5","2"\n" ); + output( ".L__wine_import_addrs:\n" ); /* FirstThunk head */ + if (strendswith( lib_name, ".delay.a" )) + { + output( "\t%s 0\n", get_asm_ptr_keyword() ); /* FirstThunk tail */ + output( ".L__wine_delay_import_IAT:\n" ); + } + + /* _head suffix to keep this object sections first */ + assemble_files( strmake( "%s_head", dll_name ) ); + strarray_addall( &objs, as_files ); + as_files = empty_strarray; + + + new_output_as_file(); + + output( "\n\t.section ".idata$7","2"\n" ); + output( "%s\n", asm_globl( import_name ) ); + output( "\t%s "%s"\n", get_asm_string_keyword(), spec->file_name ); + output( "\n\t.section ".idata$4","2"\n" ); + output( "\t%s 0\n", get_asm_ptr_keyword() ); /* OriginalFirstThunk tail */ + output( "\n\t.section ".idata$5","2"\n" ); + output( "\t%s 0\n", get_asm_ptr_keyword() ); /* FirstThunk tail */ + + /* _tail suffix to keep this object sections last */ + assemble_files( strmake( "%s_tail", dll_name ) ); + strarray_addall( &objs, as_files ); + as_files = empty_strarray; + + + for (i = total = 0; i < spec->nb_entry_points; i++) + { + const ORDDEF *odp = &spec->entry_points[i]; + const char *abi_name; + char *imp_name; + + if (odp->name) name = odp->name; + else if (odp->export_name) name = odp->export_name; + else continue; + + if (odp->flags & FLAG_PRIVATE) continue; + total++; + + /* C++ mangled names cannot be imported */ + if (strpbrk( name, "?@" )) continue; + + switch(odp->type) + { + case TYPE_VARARGS: + case TYPE_CDECL: + case TYPE_STDCALL: + by_name = odp->name && !(odp->flags & FLAG_ORDINAL); + abi_name = get_abi_name( odp, name ); + imp_name = strmake( "%s_imp_%s", target.cpu != CPU_i386 ? "_" : "", + asm_name( abi_name ) ); + + new_output_as_file(); + + output( "\n\t.text\n" ); + output( "\n\t.align %d\n", get_alignment( get_ptr_size() )); + output( "%s\n", asm_globl( abi_name ) ); + + switch (target.cpu) + { + case CPU_i386: + output( "\tjmp *%s\n", asm_name( imp_name ) ); + if (strendswith( lib_name, ".delay.a" )) + { + output( "\t.L__wine_delay_import:\n" ); + output( "\tmov $%s,%%eax\n", asm_name( imp_name ) ); + output( "\tjmp %s\n", asm_name( delay_load ) ); + } + break; + case CPU_x86_64: + output( "\tjmp *%s(%%rip)\n", asm_name( imp_name ) ); + if (strendswith( lib_name, ".delay.a" )) + { + output( "\t.L__wine_delay_import:\n" ); + output( "\tlea %s(%%rip),%%rax\n", asm_name( imp_name ) ); + output( "\tjmp %s\n", asm_name( delay_load ) ); + } + break; + case CPU_ARM: + output( "\tldr IP, 1f\n"); + output( "\tldr PC, [IP]\n"); + if (strendswith( lib_name, ".delay.a" )) + { + output( "\t.L__wine_delay_import:\n" ); + output( "\tldr IP, 1f\n"); + output( "\tldr IP, [IP]\n"); + output( "\tb %s\n", asm_name( delay_load ) ); + } + output( "1:\t.long %s\n", asm_name( imp_name ) ); + break; + case CPU_ARM64: + output( "\tadrp x16, %s\n", arm64_page( asm_name( imp_name ) ) ); + output( "\tadd x16, x16, #%s\n", arm64_pageoff( asm_name( imp_name ) ) ); + output( "\tbr x16\n" ); + if (strendswith( lib_name, ".delay.a" )) + { + output( "\t.L__wine_delay_import:\n" ); + output( "\tadrp x16, %s\n", arm64_page( asm_name( imp_name ) ) ); + output( "\tadd x16, x16, #%s\n", arm64_pageoff( asm_name( imp_name ) ) ); + output( "\tb %s\n", asm_name( delay_load ) ); + } + break; + } + + /* reference head object to always pull its sections */ + output( "\n\t.section ".idata$7","2"\n" ); + output_rva( "%s", asm_name( import_desc ) ); + + output( "\n\t.section ".idata$4","2"\n" ); + if (by_name) + { + output_rva( ".L__wine_import_name" ); + if (get_ptr_size() == 8) output( "\t.long 0\n" ); + } + else + { + if (get_ptr_size() == 4) output( "\t.long 0x8000%04x\n", odp->ordinal ); + else output( "\t.quad 0x800000000000%04x\n", odp->ordinal ); + } + + output( "\n\t.section ".idata$5","2"\n" ); + output( "%s\n", asm_globl( imp_name ) ); + if (strendswith( lib_name, ".delay.a" )) + output( "\t%s .L__wine_delay_import\n", get_asm_ptr_keyword() ); + else if (by_name) + { + output_rva( ".L__wine_import_name" ); + if (get_ptr_size() == 8) output( "\t.long 0\n" ); + } + else + { + if (get_ptr_size() == 4) output( "\t.long 0x8000%04x\n", odp->ordinal ); + else output( "\t.quad 0x800000000000%04x\n", odp->ordinal ); + } + + if (by_name) + { + output( "\n\t.section ".idata$6","1"\n" ); + output( "\t.L__wine_import_name:\n" ); + output( "\t.short %d\n", odp->ordinal ); + output( "\t%s "%s"\n", get_asm_string_keyword(), name ); + } + + free( imp_name ); + break; + default: break; + } }
- spawn( args ); + /* _syms suffix to keep these objects sections in between _head and _tail */ + assemble_files( strmake( "%s_syms", dll_name ) ); + strarray_addall( &objs, as_files ); + as_files = objs; + + free( delay_load ); + free( import_desc ); + free( import_name ); + free( dll_name ); }
/* create a Unix-style import library */ @@ -1687,7 +1940,7 @@ void output_static_lib( DLLSPEC *spec, struct strarray files ) if (is_pe()) { if (spec) build_windows_import_lib( output_file_name, spec ); - if (files.count || !spec) build_library( output_file_name, files, !spec ); + build_library( output_file_name, files, 1 ); } else {
From: Rémi Bernon rbernon@codeweavers.com
This fixes incorrect hint values generated by dlltool: instead of the index in the name table, it used the ordinal value, which almost always ends up in a hint lookup failure and a fallback to binary search. --- tools/winebuild/import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index d4338cc3939..14ee27c2f18 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1855,7 +1855,7 @@ static void build_windows_import_lib( const char *lib_name, DLLSPEC *spec ) { output( "\n\t.section ".idata$6","1"\n" ); output( "\t.L__wine_import_name:\n" ); - output( "\t.short %d\n", odp->ordinal ); + output( "\t.short %d\n", odp->hint ); output( "\t%s "%s"\n", get_asm_string_keyword(), name ); }
From: Rémi Bernon rbernon@codeweavers.com
This fixes incorrect .text section flags for any module using delay imports. The use of a custom .text$2 section as dlltool is doing causes the section to be flagged as DATA, and ends up with the .text section being writable, which triggers the anti tamper used in Forza Horizon. --- tools/winebuild/import.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 14ee27c2f18..273f5848ad4 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1680,7 +1680,7 @@ static void build_windows_import_lib( const char *lib_name, DLLSPEC *spec ) output_function_size( delay_load ); output_gnu_stack_note();
- output( "\n\t.section ".text$2"\n" ); + output( "\t.data\n" ); output( ".L__wine_delay_import_desc:\n" ); output( "\t.long 1\n" ); /* DllAttributes */ output_rva( "%s\n", asm_name( import_name ) ); /* DllNameRVA */ @@ -1691,7 +1691,6 @@ static void build_windows_import_lib( const char *lib_name, DLLSPEC *spec ) output( "\t.long 0\n"); /* UnloadInformationTableRVA */ output( "\t.long 0\n"); /* TimeDateStamp */
- output( "\t.data\n" ); output( ".L__wine_delay_import_handle:\n" ); output( "\t%s 0\n", get_asm_ptr_keyword() ); }
It breaks the llvm-mingw build:
``` tools/winebuild/winebuild -b x86_64-w64-mingw32 -w --implib -o dlls/ucrtbase/libucrtbase.cross.a --export \ ../wine/dlls/ucrtbase/ucrtbase.spec dlls/ucrtbase/crt_gccmain.cross.o \ dlls/ucrtbase/crt_main.cross.o dlls/ucrtbase/crt_winmain.cross.o dlls/ucrtbase/crt_wmain.cross.o \ dlls/ucrtbase/crt_wwinmain.cross.o dlls/ucrtbase/mathf.cross.o dlls/ucrtbase/printf.cross.o \ dlls/ucrtbase/sincos.cross.o ld.lld: error: undefined symbol: __wine_import_ucrtbase_name
referenced by /tmp/libucrtbase-8744d1.o:(__wine_import_ucrtbase_desc)
ld.lld: error: undefined symbol: WinMain
referenced by ../crt/crt0_c.c:18 libmingw32.a(lib64_libmingw32_a-crt0_c.o):(main)
clang-13: error: linker command failed with exit code 1 (use -v to see invocation) winebuild: /home/julliard/llvm-mingw/bin/x86_64-w64-mingw32-as failed with status 1 make: *** [Makefile:149778: dlls/ucrtbase/libucrtbase.cross.a] Error 1 ```
On Wed Oct 12 07:58:15 2022 +0000, Alexandre Julliard wrote:
It breaks the llvm-mingw build:
tools/winebuild/winebuild -b x86_64-w64-mingw32 -w --implib -o dlls/ucrtbase/libucrtbase.cross.a --export \ ../wine/dlls/ucrtbase/ucrtbase.spec dlls/ucrtbase/crt_gccmain.cross.o \ dlls/ucrtbase/crt_main.cross.o dlls/ucrtbase/crt_winmain.cross.o dlls/ucrtbase/crt_wmain.cross.o \ dlls/ucrtbase/crt_wwinmain.cross.o dlls/ucrtbase/mathf.cross.o dlls/ucrtbase/printf.cross.o \ dlls/ucrtbase/sincos.cross.o ld.lld: error: undefined symbol: __wine_import_ucrtbase_name >>> referenced by /tmp/libucrtbase-8744d1.o:(__wine_import_ucrtbase_desc) ld.lld: error: undefined symbol: WinMain >>> referenced by ../crt/crt0_c.c:18 >>> libmingw32.a(lib64_libmingw32_a-crt0_c.o):(main) clang-13: error: linker command failed with exit code 1 (use -v to see invocation) winebuild: /home/julliard/llvm-mingw/bin/x86_64-w64-mingw32-as failed with status 1 make: *** [Makefile:149778: dlls/ucrtbase/libucrtbase.cross.a] Error 1
Indeed, and there's several issues at play. Looks like LLVM dlltool is doing MSVC-like import libs, I'm not sure how well we can do that with assembly files or if it's required.