2009-11-15 Kai Tietz <kai.tietz@onevision.com>
* pe-dll.c (pe_undef_alias_cdecl_match): New function. (pe_find_cdecl_alias_match): New function. (pe_process_import_defs): Add matching for import symbols declared as cdecl for fastcall/stdcall. * emultempl/pe.em (pe_undef_cdecl_match): Treat fastcall symbols, too. (pe_fixup_stdcalls): Likewise. (gld_XXX_after_open): Redo scanning for imported fastcall/stdcall symbols as cdecl one. * emultempl/pep.em (pep_undef_cdecl_match): Treat fastcall symbols, too. (pep_fixup_stdcalls): Likewise. (gld_XXX_after_open): Redo scanning for imported fastcall/stdcall symbols as cdecl one. 2009-11-15 Kai Tietz <kai.tietz@onevision.com> * ld-pe/direct2_client.c: New file. * ld-pe/direct2_dll.c: Likewise. * ld-pe/direct2_dll.def: Likewise. * ld-pe/pe-run2.exp: Likewise.
This commit is contained in:
parent
213fc0adc4
commit
8a9eab9b5e
17
ld/ChangeLog
17
ld/ChangeLog
|
@ -1,3 +1,20 @@
|
|||
2009-11-15 Kai Tietz <kai.tietz@onevision.com>
|
||||
|
||||
* pe-dll.c (pe_undef_alias_cdecl_match): New function.
|
||||
(pe_find_cdecl_alias_match): New function.
|
||||
(pe_process_import_defs): Add matching for import symbols
|
||||
declared as cdecl for fastcall/stdcall.
|
||||
* emultempl/pe.em (pe_undef_cdecl_match): Treat fastcall
|
||||
symbols, too.
|
||||
(pe_fixup_stdcalls): Likewise.
|
||||
(gld_XXX_after_open): Redo scanning for imported
|
||||
fastcall/stdcall symbols as cdecl one.
|
||||
* emultempl/pep.em (pep_undef_cdecl_match): Treat fastcall
|
||||
symbols, too.
|
||||
(pep_fixup_stdcalls): Likewise.
|
||||
(gld_XXX_after_open): Redo scanning for imported
|
||||
fastcall/stdcall symbols as cdecl one.
|
||||
|
||||
2009-11-11 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* po/id.po: Updated Indonesian translation.
|
||||
|
|
|
@ -942,10 +942,13 @@ pe_undef_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_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 @@ pe_fixup_stdcalls (void)
|
|||
{
|
||||
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,11 @@ gld_${EMULATION_NAME}_after_open (void)
|
|||
|
||||
pe_find_data_imports ();
|
||||
|
||||
/* As possibly new symbols are added by imports, we rerun
|
||||
stdcall/fastcall fixup here. */
|
||||
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) \
|
||||
|
|
|
@ -871,10 +871,13 @@ pep_undef_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_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 +900,19 @@ pep_fixup_stdcalls (void)
|
|||
{
|
||||
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 +1186,11 @@ gld_${EMULATION_NAME}_after_open (void)
|
|||
|
||||
pep_find_data_imports ();
|
||||
|
||||
/* As possibly new symbols are added by imports, we rerun
|
||||
stdcall/fastcall fixup here. */
|
||||
if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */
|
||||
pep_fixup_stdcalls ();
|
||||
|
||||
#ifndef TARGET_IS_i386pep
|
||||
if (link_info.shared)
|
||||
#else
|
||||
|
|
42
ld/pe-dll.c
42
ld/pe-dll.c
|
@ -2761,6 +2761,37 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info)
|
||||
{
|
||||
|
@ -2808,6 +2839,9 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
|
|||
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 +2870,14 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
|
|||
else
|
||||
include_jmp_stub = TRUE;
|
||||
|
||||
if (is_cdecl && !blhe)
|
||||
{
|
||||
sprintf (name, "%s%s",U (""),
|
||||
pe_def_file->imports[i].internal_name);
|
||||
blhe = pe_find_cdecl_alias_match (name);
|
||||
include_jmp_stub = TRUE;
|
||||
}
|
||||
|
||||
free (name);
|
||||
|
||||
if (blhe && blhe->type == bfd_link_hash_undefined)
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2009-11-15 Kai Tietz <kai.tietz@onevision.com>
|
||||
|
||||
* ld-pe/direct2_client.c: New file.
|
||||
* ld-pe/direct2_dll.c: Likewise.
|
||||
* ld-pe/direct2_dll.def: Likewise.
|
||||
* ld-pe/pe-run2.exp: Likewise.
|
||||
|
||||
2009-11-13 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* ld-x86-64/tlsbin.dd: Updated for prefix processing.
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
extern void abort (void);
|
||||
|
||||
void
|
||||
__cdecl
|
||||
lib2foocdecl(int junk1, int* junk2);
|
||||
|
||||
void
|
||||
__stdcall
|
||||
lib2foostdcall(int junk1, int* junk2);
|
||||
|
||||
void
|
||||
__fastcall
|
||||
lib2foofastcall(int junk1, int* junk2);
|
||||
|
||||
void
|
||||
__cdecl
|
||||
lib1foocdecl(int junk1, int* junk2)
|
||||
{
|
||||
lib2foocdecl(junk1, junk2);
|
||||
}
|
||||
|
||||
void
|
||||
__stdcall
|
||||
lib1foostdcall(int junk1, int* junk2)
|
||||
{
|
||||
lib2foostdcall(junk1, junk2);
|
||||
}
|
||||
|
||||
void
|
||||
__fastcall
|
||||
lib1foofastcall(int junk1, int* junk2)
|
||||
{
|
||||
lib2foofastcall(junk1, junk2);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int junk[3];
|
||||
lib1foofastcall (1, &junk[0]);
|
||||
lib1foostdcall (2, &junk[1]);
|
||||
lib1foocdecl (3, &junk[2]);
|
||||
if (junk[1] != 2 || junk[0] != 1 || junk[2] != 3)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
void
|
||||
__cdecl
|
||||
lib2foocdecl(int junk1, int* junk2)
|
||||
{
|
||||
*junk2 = junk1;
|
||||
}
|
||||
|
||||
void
|
||||
__stdcall
|
||||
lib2foostdcall(int junk1, int* junk2)
|
||||
{
|
||||
*junk2 = junk1;
|
||||
}
|
||||
|
||||
void
|
||||
__fastcall
|
||||
lib2foofastcall(int junk1, int* junk2)
|
||||
{
|
||||
*junk2 = junk1;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
LIBRARY "direct2_dll.dll"
|
||||
|
||||
EXPORTS
|
||||
lib2foocdecl
|
||||
lib2foostdcall
|
||||
lib2foofastcall
|
|
@ -0,0 +1,151 @@
|
|||
# Expect script for complex PE tests that require a C compiler and the ability
|
||||
# to run target executables natively, in addition to the just-built binutils.
|
||||
# Copyright 2006, 2007, 2009
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of the GNU Binutils.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
# Based on the script pe-run.exp written by Pedro Alves.
|
||||
# Written by Kai Tietz <kai.tietz@onevision.com>
|
||||
#
|
||||
|
||||
# Note:
|
||||
#
|
||||
# This test checks the "direct linking to a dll" functionality with stdcall
|
||||
# and fastcall fixup.
|
||||
#
|
||||
# The test has 7 stages:
|
||||
#
|
||||
# 1. compile and link a test dll with ".dll" extension.
|
||||
#
|
||||
# 2. compile and link a test dll with ".sl" (i.e. != ".dll") extension.
|
||||
#
|
||||
# 3. compile and link a client application linking directly to the ".dll" dll built in 1.
|
||||
# This should produce no errors.
|
||||
#
|
||||
# 4. compile and link a client application linking directly to the ".sl" dll built in 2.
|
||||
# This should produce no errors.
|
||||
#
|
||||
# 5. compile and link a client application linking directly to a symlink into
|
||||
# the ".dll" dll built in 1.
|
||||
# This should produce no errors.
|
||||
#
|
||||
# 6. compile and link a client application linking directly to a symlink into
|
||||
# the ".sl" dll built in 1.
|
||||
# This should produce no errors.
|
||||
#
|
||||
# 7. run the produced executables
|
||||
|
||||
# This test can only be run on PE/COFF platforms.
|
||||
if {![is_pecoff_format]} {
|
||||
return
|
||||
}
|
||||
|
||||
# No compiler, no test.
|
||||
if { [which $CC] == 0 } {
|
||||
untested "Direct linking to dll fastcall/stdcall test"
|
||||
return
|
||||
}
|
||||
|
||||
set tmpdir tmpdir
|
||||
|
||||
proc test_direct2_link_dll {} {
|
||||
global CC
|
||||
global CFLAGS
|
||||
global srcdir
|
||||
global subdir
|
||||
global tmpdir
|
||||
|
||||
# Compile the dll.
|
||||
if ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/direct2_dll.c $tmpdir/direct2_dll.o ] {
|
||||
fail "compiling shared lib fastcall/stdcall"
|
||||
} elseif ![ld_simple_link "$CC -shared -Wl,--enable-stdcall-fixup -Wl,--kill-at " $tmpdir/direct2_dll.dll "$tmpdir/direct2_dll.o" ] {
|
||||
fail "linking shared lib (.dll) fastcall/stdcall"
|
||||
} elseif ![ld_simple_link "$CC -shared -Wl,--enable-stdcall-fixup -Wl,--kill-at " $tmpdir/direct2_dll.sl "$tmpdir/direct2_dll.o" ] {
|
||||
fail "linking shared lib (.sl) fastcall/stdcall"
|
||||
} else {
|
||||
# Compile and link the client program.
|
||||
if ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/direct2_client.c $tmpdir/direct2_client.o ] {
|
||||
fail "compiling client fastcall/stdcall"
|
||||
} else {
|
||||
# Check linking directly to direct2_dll.dll.
|
||||
set msg "linking client (.dll) fastcall/stdcall"
|
||||
if [ld_simple_link "$CC -Wl,--enable-stdcall-fixup --enable-auto-import" $tmpdir/direct2_client_dll.exe \
|
||||
"$tmpdir/direct2_client.o $tmpdir/direct2_dll.dll" ] {
|
||||
pass $msg
|
||||
} else {
|
||||
fail $msg
|
||||
}
|
||||
|
||||
# Check linking directly to direct2_dll.sl.
|
||||
set msg "linking client (.sl) fastcall/stdcall"
|
||||
if [ld_simple_link "$CC -Wl,--enable-stdcall-fixup -Wl,--enable-auto-import" $tmpdir/direct2_client_sl.exe \
|
||||
"$tmpdir/direct2_client.o $tmpdir/direct2_dll.sl" ] {
|
||||
pass $msg
|
||||
} else {
|
||||
fail $msg
|
||||
}
|
||||
|
||||
# Check dll direct linking through symlink to .dll.
|
||||
# Create symbolic link.
|
||||
catch "exec ln -fs direct2_dll.dll $tmpdir/libdirect2_dll.dll.a" ln_catch
|
||||
set msg "linking client (symlink -> .dll) fastcall/stdcall"
|
||||
if [ld_simple_link "$CC -Wl,--enable-stdcall-fixup -Wl,--enable-auto-import" $tmpdir/direct2_client_symlink_dll.exe \
|
||||
"$tmpdir/direct2_client.o $tmpdir/libdirect2_dll.dll.a" ] {
|
||||
pass $msg
|
||||
} else {
|
||||
fail $msg
|
||||
}
|
||||
|
||||
# Check dll direct linking through symlink to .sl.
|
||||
# Create symbolic link.
|
||||
catch "exec ln -fs direct2_dll.sl $tmpdir/libdirect2_sl.dll.a" ln_catch
|
||||
set msg "linking client (symlink -> .sl) fastcall/stdcall"
|
||||
if [ld_simple_link "$CC -Wl,--enable-stdcall-fixup -Wl,--enable-auto-import" $tmpdir/direct2_client_symlink_sl.exe \
|
||||
"$tmpdir/direct2_client.o $tmpdir/libdirect2_sl.dll.a" ] {
|
||||
pass $msg
|
||||
} else {
|
||||
fail $msg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc directdll_execute {exe msg} {
|
||||
set expected ""
|
||||
catch "exec $exe" prog_output
|
||||
if [string match $expected $prog_output] then {
|
||||
pass $msg
|
||||
} else {
|
||||
verbose $prog_output
|
||||
fail $msg
|
||||
}
|
||||
}
|
||||
|
||||
test_direct2_link_dll
|
||||
|
||||
# This is as far as we can go with a cross-compiler
|
||||
if ![isnative] then {
|
||||
verbose "Not running natively, so cannot execute binaries"
|
||||
return
|
||||
}
|
||||
|
||||
directdll_execute "$tmpdir/direct2_client_dll.exe" "running direct linked dll (.dll) fastcall/stdcall"
|
||||
directdll_execute "$tmpdir/direct2_client_sl.exe" "running direct linked dll (.sl) fastcall/stdcall"
|
||||
directdll_execute "$tmpdir/direct2_client_symlink_sl.exe" "running direct linked dll (symlink -> .sl) fastcall/stdcall"
|
||||
directdll_execute "$tmpdir/direct2_client_symlink_dll.exe" "running direct linked dll (symlink -> .dll) fastcall/stdcall"
|
Loading…
Reference in New Issue