Index: src/ld/emultempl/pe.em =================================================================== --- src.orig/ld/emultempl/pe.em 2009-11-13 10:34:26.167485000 +0100 +++ src/ld/emultempl/pe.em 2009-11-13 10:46:35.056485400 +0100 @@ -942,10 +942,13 @@ { int sl; char *string = inf; + const char *hs = h->root.string; sl = strlen (string); if (h->type == bfd_link_hash_defined - && strncmp (h->root.string, string, sl) == 0 + && ((*hs == '@' && *string == '_' + && strncmp (hs + 1, string + 1, sl - 1) == 0) + || strncmp (hs, string, sl) == 0) && h->root.string[sl] == '@') { pe_undef_found_sym = h; @@ -968,15 +971,20 @@ { char* at = strchr (undef->root.string, '@'); int lead_at = (*undef->root.string == '@'); - /* For now, don't try to fixup fastcall symbols. */ + if (lead_at) + at = strchr (undef->root.string + 1, '@'); - if (at && !lead_at) + if (at || lead_at) { /* The symbol is a stdcall symbol, so let's look for a cdecl symbol with the same name and resolve to that. */ - char *cname = xstrdup (undef->root.string /* + lead_at */); + char *cname = xstrdup (undef->root.string); + + if (lead_at) + *cname = '_'; at = strchr (cname, '@'); - *at = 0; + if (at) + *at = 0; sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); if (sym && sym->type == bfd_link_hash_defined) @@ -1212,6 +1220,9 @@ pe_find_data_imports (); + if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ + pe_fixup_stdcalls (); + #if defined (TARGET_IS_i386pe) \ || defined (TARGET_IS_armpe) \ || defined (TARGET_IS_arm_epoc_pe) \ Index: src/ld/emultempl/pep.em =================================================================== --- src.orig/ld/emultempl/pep.em 2009-11-13 10:34:26.170485000 +0100 +++ src/ld/emultempl/pep.em 2009-11-13 10:57:29.401485400 +0100 @@ -874,7 +874,9 @@ sl = strlen (string); if (h->type == bfd_link_hash_defined - && strncmp (h->root.string, string, sl) == 0 + && ((*hs == '@' && *string == '_' + && strncmp (hs + 1, string + 1, sl - 1) == 0) + || strncmp (hs, string, sl) == 0) && h->root.string[sl] == '@') { pep_undef_found_sym = h; @@ -897,15 +899,19 @@ { char* at = strchr (undef->root.string, '@'); int lead_at = (*undef->root.string == '@'); - /* For now, don't try to fixup fastcall symbols. */ - - if (at && !lead_at) + if (lead_at) + at = strchr (undef->root.string + 1, '@'); + if (at || lead_at) { /* The symbol is a stdcall symbol, so let's look for a cdecl symbol with the same name and resolve to that. */ - char *cname = xstrdup (undef->root.string /* + lead_at */); + char *cname = xstrdup (undef->root.string); + + if (lead_at) + *cname = '_'; at = strchr (cname, '@'); - *at = 0; + if (at) + *at = 0; sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); if (sym && sym->type == bfd_link_hash_defined) @@ -1179,6 +1185,9 @@ pep_find_data_imports (); + if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */ + pep_fixup_stdcalls (); + #ifndef TARGET_IS_i386pep if (link_info.shared) #else Index: src/ld/pe-dll.c =================================================================== --- src.orig/ld/pe-dll.c 2009-11-13 10:34:26.192485000 +0100 +++ src/ld/pe-dll.c 2009-11-13 11:01:49.880485400 +0100 @@ -2761,6 +2761,39 @@ } } +#ifdef DLL_SUPPORT +static struct bfd_link_hash_entry *found_sym; + +static bfd_boolean +pe_undef_alias_cdecl_match (struct bfd_link_hash_entry *h, void *inf) +{ + int sl; + char *string = inf; + const char *hs = h->root.string; + + sl = strlen (string); + if (h->type == bfd_link_hash_undefined + && ((*hs == '@' && *string == '_' + && strncmp (hs + 1, string + 1, sl - 1) == 0) + || strncmp (hs, string, sl) == 0) + && h->root.string[sl] == '@') + { + found_sym = h; + return FALSE; + } + return TRUE; +} + +static struct bfd_link_hash_entry * +pe_find_cdecl_alias_match (char *name) +{ + found_sym = 0; + bfd_link_hash_traverse (link_info.hash, pe_undef_alias_cdecl_match, + (char *) name); + return found_sym; +} +#endif + static void add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info) { @@ -2808,6 +2841,9 @@ size_t len = strlen (pe_def_file->imports[i].internal_name); char *name = xmalloc (len + 2 + 6); bfd_boolean include_jmp_stub = FALSE; + bfd_boolean is_cdecl = FALSE; + if (!lead_at && strchr (pe_def_file->imports[i].internal_name, '@') == NULL) + is_cdecl = TRUE; if (lead_at) sprintf (name, "%s", @@ -2836,6 +2872,16 @@ else include_jmp_stub = TRUE; + if (is_cdecl && !blhe) + { + sprintf (name, "%s%s",U (""), + pe_def_file->imports[i].internal_name); +#ifdef DLL_SUPPORT + blhe = pe_find_cdecl_alias_match (name); + include_jmp_stub = TRUE; +#endif + } + free (name); if (blhe && blhe->type == bfd_link_hash_undefined)