From fb3643f4833378632c66a745912f0d0f8c9b2cea Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 6 Nov 2002 19:36:20 +0000 Subject: [PATCH] Adds support for fastcall symbols as used on Microsoft Windows platforms (i386) --- binutils/ChangeLog | 20 ++ binutils/deflex.l | 4 +- binutils/dlltool.c | 304 ++++++++++--------- binutils/testsuite/ChangeLog | 7 + binutils/testsuite/binutils-all/dlltool.exp | 47 +++ binutils/testsuite/binutils-all/fastcall.def | 2 + binutils/testsuite/config/default.exp | 12 +- gas/ChangeLog | 5 + gas/config/te-pe.h | 2 +- gas/testsuite/ChangeLog | 6 + gas/testsuite/gas/all/fastcall.s | 1 + gas/testsuite/gas/all/gas.exp | 2 + ld/ChangeLog | 17 ++ ld/deffilep.y | 39 ++- ld/emultempl/pe.em | 429 +++++++++++++-------------- ld/pe-dll.c | 62 ++-- ld/testsuite/ChangeLog | 8 + ld/testsuite/ld-fastcall/export.s | 3 + ld/testsuite/ld-fastcall/fastcall.exp | 50 ++++ ld/testsuite/ld-fastcall/import.s | 4 + 20 files changed, 631 insertions(+), 393 deletions(-) create mode 100644 binutils/testsuite/binutils-all/dlltool.exp create mode 100644 binutils/testsuite/binutils-all/fastcall.def create mode 100644 gas/testsuite/gas/all/fastcall.s create mode 100644 ld/testsuite/ld-fastcall/export.s create mode 100644 ld/testsuite/ld-fastcall/fastcall.exp create mode 100644 ld/testsuite/ld-fastcall/import.s diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 5147d6784..5639e03e0 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,23 @@ +2002-11-07 Danny Smith + + * dlltool.c (add_excludes): Don't prefix excluded fastcall + symbols with underscore. + (xlate): Ignore add_underscore for decorated fastcall symbols. + +2002-11-07 Eric Kohl + + * deflex.l: Accept '@' as first character of an ID. + * dlltool.c (gen_exp_file): Use existing '@' prefix rather than + ASM_PREFIX for fastcall symbols. + (scan_drectve_symbols): Handle fastcall symbols when generating + undecorated aliases for symbols in drectve section. + (scan_filtered_symbols): Likewise, with export-all. + (xlate): Likewise, with --kill-at. + (make_imp_label): New function to handle fastcall symbols + correctly. + (make_one_lib_file): Use make_imp_label instead of make_label + for imp symbols. + 2002-11-06 Svein E. Seldal * MAINTAINERS: Add self as TIC4X maintainer. diff --git a/binutils/deflex.l b/binutils/deflex.l index 8ff72b8ae..d4888bc9b 100644 --- a/binutils/deflex.l +++ b/binutils/deflex.l @@ -1,6 +1,6 @@ %{/* deflex.l - Lexer for .def files */ -/* Copyright 1995, 1997, 1998, 1999 Free Software Foundation, Inc. +/* Copyright 1995, 1997, 1998, 1999, 2002 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -61,7 +61,7 @@ int linenumber; [0-9][x0-9A-Fa-f]* { yylval.number = strtol (yytext,0,0); return NUMBER; } -[A-Za-z$:\-\_?][A-Za-z0-9/$:\-\_@?]* { +(@)?[A-Za-z$:\-\_?][A-Za-z0-9/$:\-\_@?]* { yylval.id = xstrdup (yytext); return ID; } diff --git a/binutils/dlltool.c b/binutils/dlltool.c index 9a1afbc11..6e83cce25 100644 --- a/binutils/dlltool.c +++ b/binutils/dlltool.c @@ -20,8 +20,7 @@ 02111-1307, USA. */ -/* - This program allows you to build the files necessary to create +/* This program allows you to build the files necessary to create DLLs to run on a system which understands PE format image files. (eg, Windows NT) @@ -195,8 +194,7 @@ # Build the dll with file1.o, file2.o and the export table - ld -o thedll.dll thedll.exp file1.o file2.o - */ + ld -o thedll.dll thedll.exp file1.o file2.o */ /* .idata section description @@ -232,8 +230,7 @@ = Array of { short, asciz } entries, one for each imported function. The `short' is the function's ordinal number. - .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc) -*/ + .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc). */ /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ @@ -274,8 +271,8 @@ static char *look_for_prog PARAMS ((const char *, const char *, int)); static char *deduce_name PARAMS ((const char *)); #ifdef DLLTOOL_MCORE_ELF -static void mcore_elf_cache_filename (char *); -static void mcore_elf_gen_out_file (void); +static void mcore_elf_cache_filename PARAMS ((char *)); +static void mcore_elf_gen_out_file PARAMS ((void)); #endif #ifdef HAVE_SYS_WAIT_H @@ -283,10 +280,10 @@ static void mcore_elf_gen_out_file (void); #else /* ! HAVE_SYS_WAIT_H */ #if ! defined (_WIN32) || defined (__CYGWIN32__) #ifndef WIFEXITED -#define WIFEXITED(w) (((w)&0377) == 0) +#define WIFEXITED(w) (((w) & 0377) == 0) #endif #ifndef WIFSIGNALED -#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) +#define WIFSIGNALED(w) (((w) & 0377) != 0177 && ((w) & ~0377) == 0) #endif #ifndef WTERMSIG #define WTERMSIG(w) ((w) & 0177) @@ -327,18 +324,18 @@ static void mcore_elf_gen_out_file (void); typedef struct ifunct { - char *name; /* name of function being imported */ - int ord; /* two-byte ordinal value associated with function */ + char * name; /* Name of function being imported. */ + int ord; /* Two-byte ordinal value associated with function. */ struct ifunct *next; } ifunctype; typedef struct iheadt { - char *dllname; /* name of dll file imported from */ - long nfuncs; /* number of functions in list */ - struct ifunct *funchead; /* first function in list */ - struct ifunct *functail; /* last function in list */ - struct iheadt *next; /* next dll file in list */ + char *dllname; /* Name of dll file imported from. */ + long nfuncs; /* Number of functions in list. */ + struct ifunct *funchead; /* First function in list. */ + struct ifunct *functail; /* Last function in list. */ + struct iheadt *next; /* Next dll file in list. */ } iheadtype; /* Structure containing all import information as defined in .def file @@ -428,7 +425,7 @@ static char * mcore_elf_linker_flags = NULL; #define DRECTVE_SECTION_NAME ".drectve" #endif -#define PATHMAX 250 /* What's the right name for this ? */ +#define PATHMAX 250 /* What's the right name for this ? */ #define TMP_ASM "dc.s" #define TMP_HEAD_S "dh.s" @@ -487,11 +484,11 @@ static const unsigned char mcore_le_jtab[] = 0x00, 0x00, 0x00, 0x00 /*
*/ }; -/* This is the glue sequence for PowerPC PE. There is a */ -/* tocrel16-tocdefn reloc against the first instruction. */ -/* We also need a IMGLUE reloc against the glue function */ -/* to restore the toc saved by the third instruction in */ -/* the glue. */ +/* This is the glue sequence for PowerPC PE. There is a + tocrel16-tocdefn reloc against the first instruction. + We also need a IMGLUE reloc against the glue function + to restore the toc saved by the third instruction in + the glue. */ static const unsigned char ppc_jtab[] = { 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */ @@ -504,8 +501,8 @@ static const unsigned char ppc_jtab[] = }; #ifdef DLLTOOL_PPC -/* the glue instruction, picks up the toc from the stw in */ -/* the above code: "lwz r2,4(r1)" */ +/* The glue instruction, picks up the toc from the stw in + the above code: "lwz r2,4(r1)". */ static bfd_vma ppc_glue_insn = 0x80410004; #endif @@ -526,8 +523,8 @@ struct mac const char *how_bfd_target; enum bfd_architecture how_bfd_arch; const unsigned char *how_jtab; - int how_jtab_size; /* size of the jtab entry */ - int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */ + int how_jtab_size; /* Size of the jtab entry. */ + int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5. */ }; static const struct mac @@ -640,7 +637,7 @@ typedef struct export int noname; int data; int hint; - int forward; /* number of forward label, 0 means no forward */ + int forward; /* Number of forward label, 0 means no forward. */ struct export *next; } export_type; @@ -683,6 +680,7 @@ static const char *xlate PARAMS ((const char *)); static void dump_iat PARAMS ((FILE *, export_type *)); #endif static char *make_label PARAMS ((const char *, const char *)); +static char *make_imp_label PARAMS ((const char *, const char *)); static bfd *make_one_lib_file PARAMS ((export_type *, int)); static bfd *make_head PARAMS ((void)); static bfd *make_tail PARAMS ((void)); @@ -700,7 +698,7 @@ static void inform PARAMS ((const char *, ...)); static void -inform VPARAMS ((const char *message, ...)) +inform VPARAMS ((const char * message, ...)) { VA_OPEN (args, message); VA_FIXEDARG (args, const char *, message); @@ -834,18 +832,18 @@ process_def_file (name) /**********************************************************************/ -/* Communications with the parser */ +/* Communications with the parser. */ -static const char *d_name; /* Arg to NAME or LIBRARY */ -static int d_nfuncs; /* Number of functions exported */ -static int d_named_nfuncs; /* Number of named functions exported */ -static int d_low_ord; /* Lowest ordinal index */ -static int d_high_ord; /* Highest ordinal index */ -static export_type *d_exports; /*list of exported functions */ -static export_type **d_exports_lexically; /* vector of exported functions in alpha order */ -static dlist_type *d_list; /* Descriptions */ -static dlist_type *a_list; /* Stuff to go in directives */ -static int d_nforwards = 0; /* Number of forwarded exports */ +static const char *d_name; /* Arg to NAME or LIBRARY. */ +static int d_nfuncs; /* Number of functions exported. */ +static int d_named_nfuncs; /* Number of named functions exported. */ +static int d_low_ord; /* Lowest ordinal index. */ +static int d_high_ord; /* Highest ordinal index. */ +static export_type *d_exports; /* List of exported functions. */ +static export_type **d_exports_lexically; /* Vector of exported functions in alpha order. */ +static dlist_type *d_list; /* Descriptions. */ +static dlist_type *a_list; /* Stuff to go in directives. */ +static int d_nforwards = 0; /* Number of forwarded exports. */ static int d_is_dll; static int d_is_exe; @@ -900,8 +898,8 @@ def_name (name, base) non_fatal (_("Can't have LIBRARY and NAME")); d_name = name; - /* if --dllname not provided, use the one in the DEF file. - FIXME: Is this appropriate for executables? */ + /* If --dllname not provided, use the one in the DEF file. + FIXME: Is this appropriate for executables? */ if (! dll_name) dll_name = xstrdup (name); d_is_exe = 1; @@ -919,7 +917,7 @@ def_library (name, base) non_fatal (_("Can't have LIBRARY and NAME")); d_name = name; - /* if --dllname not provided, use the one in the DEF file. */ + /* If --dllname not provided, use the one in the DEF file. */ if (! dll_name) dll_name = xstrdup (name); d_is_dll = 1; @@ -1254,7 +1252,8 @@ scan_drectve_symbols (abfd) if (add_stdcall_alias && strchr (c, '@')) { - char *exported_name = xstrdup (c); + int lead_at = (*c == '@') ; + char *exported_name = xstrdup (c + lead_at); char *atsym = strchr (exported_name, '@'); *atsym = '\0'; /* Note: stdcall alias symbols can never be data. */ @@ -1304,7 +1303,8 @@ scan_filtered_symbols (abfd, minisyms, symcount, size) if (add_stdcall_alias && strchr (symbol_name, '@')) { - char *exported_name = xstrdup (symbol_name); + int lead_at = (*symbol_name == '@'); + char *exported_name = xstrdup (symbol_name + lead_at); char *atsym = strchr (exported_name, '@'); *atsym = '\0'; /* Note: stdcall alias symbols can never be data. */ @@ -1332,8 +1332,11 @@ add_excludes (new_excludes) new_exclude = ((struct string_list *) xmalloc (sizeof (struct string_list))); new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2); - /* FIXME: Is it always right to add a leading underscore? */ - sprintf (new_exclude->string, "_%s", exclude_string); + /* Don't add a leading underscore for fastcall symbols. */ + if (*exclude_string == '@') + sprintf (new_exclude->string, "%s", exclude_string); + else + sprintf (new_exclude->string, "_%s", exclude_string); new_exclude->next = excludes; excludes = new_exclude; @@ -1468,7 +1471,7 @@ scan_open_obj_file (abfd) else scan_drectve_symbols (abfd); - /* FIXME: we ought to read in and block out the base relocations */ + /* FIXME: we ought to read in and block out the base relocations. */ /* xgettext:c-format */ inform (_("Done reading %s"), bfd_get_filename (abfd)); @@ -1542,7 +1545,7 @@ dump_def_info (f) } } -/* Generate the .exp file */ +/* Generate the .exp file. */ static int sfunc (a, b) @@ -1561,7 +1564,7 @@ flush_page (f, need, page_addr, on_page) { int i; - /* Flush this page */ + /* Flush this page. */ fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n", ASM_LONG, page_addr, @@ -1825,9 +1828,15 @@ gen_exp_file () } if (exp->forward == 0) - fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE, - ASM_PREFIX, - exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); + { + if (exp->internal_name[0] == '@') + fprintf (f, "\t%s%s%s\t%s %d\n", ASM_RVA_BEFORE, + exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); + else + fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE, + ASM_PREFIX, + exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); + } else fprintf (f, "\t%sf%d%s\t%s %d\n", ASM_RVA_BEFORE, exp->forward, ASM_RVA_AFTER, ASM_C, exp->ordinal); @@ -1927,7 +1936,7 @@ gen_exp_file () } } - /* Dump the reloc section if a base file is provided */ + /* Dump the reloc section if a base file is provided. */ if (base_file) { int addr; @@ -1987,7 +1996,7 @@ gen_exp_file () fclose (f); - /* assemble the file */ + /* Assemble the file. */ assemble_file (TMP_ASM, exp_name); if (dontdeltemps == 0) @@ -2000,9 +2009,12 @@ static const char * xlate (name) const char *name; { - if (add_underscore) + int lead_at = (*name == '@'); + + if (add_underscore && !lead_at) { char *copy = xmalloc (strlen (name) + 2); + copy[0] = '_'; strcpy (copy + 1, name); name = copy; @@ -2011,6 +2023,8 @@ xlate (name) if (killat) { char *p; + + name += lead_at; p = strchr (name, '@'); if (p) *p = 0; @@ -2053,7 +2067,7 @@ typedef struct asymbol *sym; asymbol **sympp; int size; - unsigned char *data; + unsigned char *data; } sinfo; #ifndef DLLTOOL_PPC @@ -2088,8 +2102,8 @@ static sinfo secdata[NSECS] = #else -/* Sections numbered to make the order the same as other PowerPC NT */ -/* compilers. This also keeps funny alignment thingies from happening. */ +/* Sections numbered to make the order the same as other PowerPC NT + compilers. This also keeps funny alignment thingies from happening. */ #define TEXT 0 #define PDATA 1 #define RDATA 2 @@ -2117,9 +2131,8 @@ static sinfo secdata[NSECS] = #endif -/* -This is what we're trying to make. We generate the imp symbols with -both single and double underscores, for compatibility. +/* This is what we're trying to make. We generate the imp symbols with + both single and double underscores, for compatibility. .text .global _GetFileVersionInfoSizeW@8 @@ -2142,7 +2155,7 @@ ID2: .short 2 .asciz "GetFileVersionInfoSizeW" -For the PowerPC, here's the variation on the above scheme: + For the PowerPC, here's the variation on the above scheme: # Rather than a simple "jmp *", the code to get to the dll function # looks like: @@ -2153,8 +2166,7 @@ For the PowerPC, here's the variation on the above scheme: stw r2,4(r1) mtctr r12 lwz r2,4(r11) - bctr -*/ + bctr */ static char * make_label (prefix, name) @@ -2163,12 +2175,39 @@ make_label (prefix, name) { int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name); char *copy = xmalloc (len +1 ); + strcpy (copy, ASM_PREFIX); strcat (copy, prefix); strcat (copy, name); return copy; } +static char * +make_imp_label (prefix, name) + const char *prefix; + const char *name; +{ + int len; + char *copy; + + if (name[0] == '@') + { + len = strlen (prefix) + strlen (name); + copy = xmalloc (len + 1); + strcpy (copy, prefix); + strcat (copy, name); + } + else + { + len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name); + copy = xmalloc (len + 1); + strcpy (copy, prefix); + strcat (copy, ASM_PREFIX); + strcat (copy, name); + } + return copy; +} + static bfd * make_one_lib_file (exp, i) export_type *exp; @@ -2270,7 +2309,7 @@ make_one_lib_file (exp, i) applicable = bfd_applicable_section_flags (abfd); - /* First make symbols for the sections */ + /* First make symbols for the sections. */ for (i = 0; i < NSECS; i++) { sinfo *si = secdata + i; @@ -2299,12 +2338,12 @@ make_one_lib_file (exp, i) if (! exp->data) { exp_label = bfd_make_empty_symbol (abfd); - exp_label->name = make_label ("", exp->name); + exp_label->name = make_imp_label ("", exp->name); /* On PowerPC, the function name points to a descriptor in the rdata section, the first element of which is a pointer to the code (..function_name), and the second - points to the .toc */ + points to the .toc. */ #ifdef DLLTOOL_PPC if (machine == MPPC) exp_label->section = secdata[RDATA].sec; @@ -2328,14 +2367,14 @@ make_one_lib_file (exp, i) if (create_compat_implib) { iname = bfd_make_empty_symbol (abfd); - iname->name = make_label ("__imp_", exp->name); + iname->name = make_imp_label ("___imp", exp->name); iname->section = secdata[IDATA5].sec; iname->flags = BSF_GLOBAL; iname->value = 0; } iname2 = bfd_make_empty_symbol (abfd); - iname2->name = make_label ("_imp__", exp->name); + iname2->name = make_imp_label ("__imp_", exp->name); iname2->section = secdata[IDATA5].sec; iname2->flags = BSF_GLOBAL; iname2->value = 0; @@ -2347,7 +2386,6 @@ make_one_lib_file (exp, i) iname_lab->flags = 0; iname_lab->value = 0; - iname_pp = ptrs + oidx; if (create_compat_implib) ptrs[oidx++] = iname; @@ -2357,7 +2395,7 @@ make_one_lib_file (exp, i) ptrs[oidx++] = iname_lab; #ifdef DLLTOOL_PPC - /* The symbol refering to the code (.text) */ + /* The symbol refering to the code (.text). */ { asymbol *function_name; @@ -2371,9 +2409,9 @@ make_one_lib_file (exp, i) ptrs[oidx++] = function_name; } - /* The .toc symbol */ + /* The .toc symbol. */ { - asymbol *toc_symbol; /* The .toc symbol */ + asymbol *toc_symbol; toc_symbol = bfd_make_empty_symbol (abfd); toc_symbol->name = make_label (".", "toc"); @@ -2432,7 +2470,7 @@ make_one_lib_file (exp, i) case IDATA4: case IDATA5: /* An idata$4 or idata$5 is one word long, and has an - rva to idata$6 */ + rva to idata$6. */ si->data = xmalloc (4); si->size = 4; @@ -2477,7 +2515,7 @@ make_one_lib_file (exp, i) break; case IDATA7: si->size = 4; - si->data =xmalloc(4); + si->data =xmalloc (4); memset (si->data, 0, si->size); rel = xmalloc (sizeof (arelent)); rpp = xmalloc (sizeof (arelent *) * 2); @@ -2493,16 +2531,16 @@ make_one_lib_file (exp, i) #ifdef DLLTOOL_PPC case PDATA: { - /* The .pdata section is 5 words long. */ - /* Think of it as: */ - /* struct */ - /* { */ - /* bfd_vma BeginAddress, [0x00] */ - /* EndAddress, [0x04] */ - /* ExceptionHandler, [0x08] */ - /* HandlerData, [0x0c] */ - /* PrologEndAddress; [0x10] */ - /* }; */ + /* The .pdata section is 5 words long. + Think of it as: + struct + { + bfd_vma BeginAddress, [0x00] + EndAddress, [0x04] + ExceptionHandler, [0x08] + HandlerData, [0x0c] + PrologEndAddress; [0x10] + }; */ /* So this pdata section setups up this as a glue linkage to a dll routine. There are a number of house keeping things @@ -2517,15 +2555,14 @@ make_one_lib_file (exp, i) So we need a total of four relocs for this section. 3. Lastly, the HandlerData field is set to 0x03, to indicate - that this is a glue routine. - */ + that this is a glue routine. */ arelent *imglue, *ba_rel, *ea_rel, *pea_rel; - /* alignment must be set to 2**2 or you get extra stuff */ + /* Alignment must be set to 2**2 or you get extra stuff. */ bfd_set_section_alignment(abfd, sec, 2); si->size = 4 * 5; - si->data =xmalloc(4 * 5); + si->data = xmalloc (si->size); memset (si->data, 0, si->size); rpp = xmalloc (sizeof (arelent *) * 5); rpp[0] = imglue = xmalloc (sizeof (arelent)); @@ -2534,7 +2571,7 @@ make_one_lib_file (exp, i) rpp[3] = pea_rel = xmalloc (sizeof (arelent)); rpp[4] = 0; - /* stick the toc reload instruction in the glue reloc */ + /* Stick the toc reload instruction in the glue reloc. */ bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address); imglue->addend = 0; @@ -2547,17 +2584,17 @@ make_one_lib_file (exp, i) ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); ba_rel->sym_ptr_ptr = fn_pp; - bfd_put_32(abfd, 0x18, si->data + 0x04); + bfd_put_32 (abfd, 0x18, si->data + 0x04); ea_rel->address = 4; ea_rel->addend = 0; ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); ea_rel->sym_ptr_ptr = fn_pp; - /* mark it as glue */ - bfd_put_32(abfd, 0x03, si->data + 0x0c); + /* Mark it as glue. */ + bfd_put_32 (abfd, 0x03, si->data + 0x0c); - /* mark the prolog end address */ - bfd_put_32(abfd, 0x0D, si->data + 0x10); + /* Mark the prolog end address. */ + bfd_put_32 (abfd, 0x0D, si->data + 0x10); pea_rel->address = 0x10; pea_rel->addend = 0; pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); @@ -2572,9 +2609,7 @@ make_one_lib_file (exp, i) descriptor consisting of: 1. The address of the code. 2. The address of the appropriate .toc - We use relocs to build this. - */ - + We use relocs to build this. */ si->size = 8; si->data = xmalloc (8); memset (si->data, 0, si->size); @@ -2605,7 +2640,7 @@ make_one_lib_file (exp, i) { bfd_vma vma = 0; - /* Size up all the sections */ + /* Size up all the sections. */ for (i = 0; i < NSECS; i++) { sinfo *si = secdata + i; @@ -2616,7 +2651,7 @@ make_one_lib_file (exp, i) /* vma += si->size;*/ } } - /* Write them out */ + /* Write them out. */ for (i = 0; i < NSECS; i++) { sinfo *si = secdata + i; @@ -2728,8 +2763,7 @@ make_tail () would be to mark this section as a comdat type 2 section, so only one would appear in the final .exe (if our linker supported comdat, that is) or cause it to be inserted by something else (say - crt0) - */ + crt0). */ fprintf (f, "\t.section .idata$3\n"); fprintf (f, "\t%s\t0\n", ASM_LONG); @@ -2741,7 +2775,7 @@ make_tail () #ifdef DLLTOOL_PPC /* Other PowerPC NT compilers use idata$6 for the dllname, so I - do too. Original, huh? */ + do too. Original, huh? */ fprintf (f, "\t.section .idata$6\n"); #else fprintf (f, "\t.section .idata$7\n"); @@ -2755,7 +2789,7 @@ make_tail () assemble_file (TMP_TAIL_S, TMP_TAIL_O); - return bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET); + return bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET); } static void @@ -2783,7 +2817,6 @@ gen_lib_file () outarch->has_armap = 1; /* Work out a reasonable size of things to put onto one line. */ - ar_head = make_head (); ar_tail = make_tail(); @@ -2797,8 +2830,7 @@ gen_lib_file () head = n; } - /* Now stick them all into the archive */ - + /* Now stick them all into the archive. */ ar_head->next = head; ar_tail->next = ar_head; head = ar_tail; @@ -2816,8 +2848,7 @@ gen_lib_file () head = n; } - /* Delete all the temp files */ - + /* Delete all the temp files. */ if (dontdeltemps == 0) { unlink (TMP_HEAD_O); @@ -2846,7 +2877,7 @@ gen_lib_file () /**********************************************************************/ /* Run through the information gathered from the .o files and the - .def file and work out the best stuff */ + .def file and work out the best stuff. */ static int pfunc (a, b) const void *a; @@ -2857,7 +2888,7 @@ pfunc (a, b) if (ap->ordinal == bp->ordinal) return 0; - /* unset ordinals go to the bottom */ + /* Unset ordinals go to the bottom. */ if (ap->ordinal == -1) return 1; if (bp->ordinal == -1) @@ -2882,6 +2913,7 @@ remove_null_names (ptr) { int src; int dst; + for (dst = src = 0; src < d_nfuncs; src++) { if (ptr[src]) @@ -2925,11 +2957,12 @@ process_duplicates (d_export_vec) { int more = 1; int i; + while (more) { more = 0; - /* Remove duplicates */ + /* Remove duplicates. */ qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc); dtab (d_export_vec); @@ -2954,7 +2987,7 @@ process_duplicates (d_export_vec) fatal (_("Error, duplicate EXPORT with oridinals: %s"), a->name); - /* Merge attributes */ + /* Merge attributes. */ b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal; b->constant |= a->constant; b->noname |= a->noname; @@ -2969,7 +3002,7 @@ process_duplicates (d_export_vec) } - /* Count the names */ + /* Count the names. */ for (i = 0; i < d_nfuncs; i++) { if (!d_export_vec[i]->noname) @@ -2988,22 +3021,20 @@ fill_ordinals (d_export_vec) qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); - /* fill in the unset ordinals with ones from our range */ - + /* Fill in the unset ordinals with ones from our range. */ ptr = (char *) xmalloc (size); memset (ptr, 0, size); - /* Mark in our large vector all the numbers that are taken */ + /* Mark in our large vector all the numbers that are taken. */ for (i = 0; i < d_nfuncs; i++) { if (d_export_vec[i]->ordinal != -1) { ptr[d_export_vec[i]->ordinal] = 1; + if (lowest == -1 || d_export_vec[i]->ordinal < lowest) - { - lowest = d_export_vec[i]->ordinal; - } + lowest = d_export_vec[i]->ordinal; } } @@ -3041,8 +3072,7 @@ fill_ordinals (d_export_vec) free (ptr); - /* And resort */ - + /* And resort. */ qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); /* Work out the lowest and highest ordinal numbers. */ @@ -3069,8 +3099,7 @@ alphafunc (av,bv) static void mangle_defs () { - /* First work out the minimum ordinal chosen */ - + /* First work out the minimum ordinal chosen. */ export_type *exp; int i; @@ -3081,14 +3110,12 @@ mangle_defs () inform (_("Processing definitions")); for (i = 0, exp = d_exports; exp; i++, exp = exp->next) - { - d_export_vec[i] = exp; - } + d_export_vec[i] = exp; process_duplicates (d_export_vec); fill_ordinals (d_export_vec); - /* Put back the list in the new order */ + /* Put back the list in the new order. */ d_exports = 0; for (i = d_nfuncs - 1; i >= 0; i--) { @@ -3096,25 +3123,21 @@ mangle_defs () d_exports = d_export_vec[i]; } - /* Build list in alpha order */ + /* Build list in alpha order. */ d_exports_lexically = (export_type **) xmalloc (sizeof (export_type *) * (d_nfuncs + 1)); for (i = 0, exp = d_exports; exp; i++, exp = exp->next) - { - d_exports_lexically[i] = exp; - } + d_exports_lexically[i] = exp; + d_exports_lexically[i] = 0; qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc); - /* Fill exp entries with their hint values */ - + /* Fill exp entries with their hint values. */ for (i = 0; i < d_nfuncs; i++) - { - if (!d_exports_lexically[i]->noname || show_allnames) - d_exports_lexically[i]->hint = hint++; - } + if (!d_exports_lexically[i]->noname || show_allnames) + d_exports_lexically[i]->hint = hint++; inform (_("Processed definitions")); } @@ -3590,7 +3613,7 @@ mcore_elf_gen_out_file (void) dyn_string_delete (ds); /* Step two. Create a .exp file and a .lib file from the temporary file. - Do this by recursively invoking dlltool....*/ + Do this by recursively invoking dlltool... */ ds = dyn_string_new (100); dyn_string_append (ds, "-S "); @@ -3615,7 +3638,6 @@ mcore_elf_gen_out_file (void) } /* XXX - FIME: ought to check/copy other command line options as well. */ - run (program_name, ds->s); dyn_string_delete (ds); diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog index 7034c1fc9..da464da55 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2002-11-07 Casper S. Hornstrup + + * binutils-all/dlltool.exp: New file for testing dlltool. + * binutils-all/fastcall.def: New file for testing fastcall + exports. + * config/default.exp: Set DLLTOOL variable. + 2002-08-27 Alan Modra * binutils-all/objcopy.exp: Revert last change. diff --git a/binutils/testsuite/binutils-all/dlltool.exp b/binutils/testsuite/binutils-all/dlltool.exp new file mode 100644 index 000000000..77b09eb40 --- /dev/null +++ b/binutils/testsuite/binutils-all/dlltool.exp @@ -0,0 +1,47 @@ +# Copyright 2002 Free Software Foundation, Inc. + +# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +if {![istarget "i*86-*-*"]} { + return +} + +if {![istarget "i*86-*-*pe*"] \ + && ![istarget "i*86-*-cygwin*"] \ + && ![istarget "i*86-*-mingw32*"] } { + set target_xfail "yes" +} else { + set target_xfail "no" +} + +if {![info exists DLLTOOL]} then { + return +} + +if {[which $DLLTOOL] == 0} then { + return +} + +verbose "$DLLTOOL -d $srcdir/$subdir/fastcall.def" 1 +catch "exec $DLLTOOL -d $srcdir/$subdir/fastcall.def" err + +if ![string match "" $err] then { + send_log "$err\n" + verbose "$err" 1 + fail "dlltool (fastcall export)" + continue; +} + +pass "dlltool (fastcall export)" diff --git a/binutils/testsuite/binutils-all/fastcall.def b/binutils/testsuite/binutils-all/fastcall.def new file mode 100644 index 000000000..bef49682c --- /dev/null +++ b/binutils/testsuite/binutils-all/fastcall.def @@ -0,0 +1,2 @@ +EXPORTS +@fastcall@4 diff --git a/binutils/testsuite/config/default.exp b/binutils/testsuite/config/default.exp index 227fd78b5..4aa9ab330 100644 --- a/binutils/testsuite/config/default.exp +++ b/binutils/testsuite/config/default.exp @@ -1,4 +1,4 @@ -# Copyright 1993, 1994, 1995, 1997, 1999, 2001 +# Copyright 1993, 1994, 1995, 1997, 1999, 2001, 2002 # Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify @@ -29,49 +29,45 @@ if ![info exists NM] then { if ![info exists NMFLAGS] then { set NMFLAGS "" } - if ![info exists SIZE] then { set SIZE [findfile $base_dir/size] } if ![info exists SIZEFLAGS] then { set SIZEFLAGS "" } - if ![info exists OBJDUMP] then { set OBJDUMP [findfile $base_dir/objdump] } if ![info exists OBJDUMPFLAGS] then { set OBJDUMPFLAGS "" } - if ![info exists OBJCOPY] then { set OBJCOPY [findfile $base_dir/objcopy] } if ![info exists OBJCOPYFLAGS] then { set OBJCOPYFLAGS "" } - if ![info exists AR] then { set AR [findfile $base_dir/ar] } - if ![info exists STRIP] then { set STRIP [findfile $base_dir/strip-new $base_dir/strip-new [transform strip]] } if ![info exists STRIPFLAGS] then { set STRIPFLAGS "" } - if ![info exists READELF] then { set READELF [findfile $base_dir/readelf] } if ![info exists READELFFLAGS] then { set READELFFLAGS "" } - if ![info exists WINDRES] then { set WINDRES [findfile $base_dir/windres] } +if ![info exists DLLTOOL] then { + set DLLTOOL [findfile $base_dir/dlltool] +} if ![file isdirectory tmpdir] {catch "exec mkdir tmpdir" status} diff --git a/gas/ChangeLog b/gas/ChangeLog index 85da82370..22113aef5 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2002-11-07 Eric Kohl + + * config/te-pe.h (LEX_AT): Accept at-sign (@) as first character + of a label. + 2002-11-05 H.J. Lu * config/tc-mips.c (support_64bit_objects): Check *l before it diff --git a/gas/config/te-pe.h b/gas/config/te-pe.h index 1c1f0b27b..b3e076436 100644 --- a/gas/config/te-pe.h +++ b/gas/config/te-pe.h @@ -1,5 +1,5 @@ #define TE_PE -#define LEX_AT 1 /* can have @'s inside labels */ +#define LEX_AT (LEX_BEGIN_NAME | LEX_NAME) /* Can have @'s inside labels. */ /* The PE format supports long section names. */ #define COFF_LONG_SECTION_NAMES diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 9868851f6..4a6771b27 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2002-11-07 Casper S. Hornstrup + + * gas/all/gas.exp: Run fastcall label handling test. + * gas/all/fastcall.s: New file for testing handling of fastcall + labels. + 2002-11-01 H.J. Lu * gas/i386/i386.exp: Add "sub". diff --git a/gas/testsuite/gas/all/fastcall.s b/gas/testsuite/gas/all/fastcall.s new file mode 100644 index 000000000..de771cd59 --- /dev/null +++ b/gas/testsuite/gas/all/fastcall.s @@ -0,0 +1 @@ +@fastcall_label@0: diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp index a95915148..ef58c7874 100644 --- a/gas/testsuite/gas/all/gas.exp +++ b/gas/testsuite/gas/all/gas.exp @@ -164,3 +164,5 @@ case $target_triplet in { run_dump_test incbin } } + +gas_test "fastcall.s" "" "" "fastcall labels" diff --git a/ld/ChangeLog b/ld/ChangeLog index 5985d59ef..3470f70d2 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,20 @@ +2002-11-07 Danny Smith + + * deffilep.y (def_lex): Handle '@' as first character of an ID. + * pe-dll.c (auto-export): Filter on "_imp_" prefix, not "_imp__". + (make_one): Don't prefix decorated fastcall symbols with '_'. + (pe_process_import_defs): Likewise. + * emultempl/pe.em (pe_fixup_stdcalls): Don't fixup fastcall + symbols to cdecl names or vise-versa. + +2002-10-13 Eric Kohl + + * pe-dll.c (process_def_file): Handle fastcall symbols when + generating undecorated aliases. Don't prefix decorated fastcall + symbols with '_'. + (fill_exported_offsets): Don't prefix decorated fastcall symbols + with '_'. + 2002-10-29 Daniel Jacobowitz * emultempl/aix.em: Use include <> for generated headers. diff --git a/ld/deffilep.y b/ld/deffilep.y index 51d17f8a7..e9a63108e 100644 --- a/ld/deffilep.y +++ b/ld/deffilep.y @@ -1,6 +1,6 @@ %{ /* deffilep.y - parser for .def files */ -/* Copyright 1995, 1997, 1998, 1999, 2000, 2001 +/* Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -966,9 +966,27 @@ def_lex () return NUMBER; } - if (ISALPHA (c) || strchr ("$:-_?", c)) + if (ISALPHA (c) || strchr ("$:-_?@", c)) { bufptr = 0; + q = c; + put_buf (c); + c = def_getc (); + + if (q == '@') + { + if (ISBLANK (c) ) /* '@' followed by whitespace. */ + return (q); + else if (ISDIGIT (c)) /* '@' followed by digit. */ + { + def_ungetc (c); + return (q); + } +#if TRACE + printf ("lex: @ returns itself\n"); +#endif + } + while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@", c))) { put_buf (c); @@ -976,14 +994,17 @@ def_lex () } if (c != EOF) def_ungetc (c); - for (i = 0; tokens[i].name; i++) - if (strcmp (tokens[i].name, buffer) == 0) - { + if (ISALPHA (q)) /* Check for tokens. */ + { + for (i = 0; tokens[i].name; i++) + if (strcmp (tokens[i].name, buffer) == 0) + { #if TRACE - printf ("lex: `%s' is a string token\n", buffer); + printf ("lex: `%s' is a string token\n", buffer); #endif - return tokens[i].token; - } + return tokens[i].token; + } + } #if TRACE printf ("lex: `%s' returns ID\n", buffer); #endif @@ -1008,7 +1029,7 @@ def_lex () return ID; } - if (c == '=' || c == '.' || c == '@' || c == ',') + if (c == '=' || c == '.' || c == ',') { #if TRACE printf ("lex: `%c' returns itself\n", c); diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 474b98454..0eb3eeda5 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -794,69 +794,71 @@ pe_fixup_stdcalls () { static int gave_warning_message = 0; struct bfd_link_hash_entry *undef, *sym; - char *at; + if (pe_dll_extra_pe_debug) - { - printf ("%s\n", __FUNCTION__); - } + printf ("%s\n", __FUNCTION__); for (undef = link_info.hash->undefs; undef; undef=undef->next) if (undef->type == bfd_link_hash_undefined) - { - at = strchr (undef->root.string, '@'); - if (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); - at = strchr (cname, '@'); - *at = 0; - sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); - if (sym && sym->type == bfd_link_hash_defined) - { - undef->type = bfd_link_hash_defined; - undef->u.def.value = sym->u.def.value; - undef->u.def.section = sym->u.def.section; - if (pe_enable_stdcall_fixup == -1) - { - einfo (_("Warning: resolving %s by linking to %s\n"), - undef->root.string, cname); - if (! gave_warning_message) - { - gave_warning_message = 1; - einfo(_("Use --enable-stdcall-fixup to disable these warnings\n")); - einfo(_("Use --disable-stdcall-fixup to disable these fixups\n")); - } - } - } - } - else { - /* The symbol is a cdecl symbol, so we look for stdcall - symbols - which means scanning the whole symbol table */ - pe_undef_found_sym = 0; - bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match, - (PTR) undef->root.string); - sym = pe_undef_found_sym; - if (sym) - { - undef->type = bfd_link_hash_defined; - undef->u.def.value = sym->u.def.value; - undef->u.def.section = sym->u.def.section; - if (pe_enable_stdcall_fixup == -1) - { - einfo (_("Warning: resolving %s by linking to %s\n"), - undef->root.string, sym->root.string); - if (! gave_warning_message) - { - gave_warning_message = 1; - einfo(_("Use --enable-stdcall-fixup to disable these warnings\n")); - einfo(_("Use --disable-stdcall-fixup to disable these fixups\n")); - } - } - } + 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) + { + /* 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 */); + at = strchr (cname, '@'); + *at = 0; + sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); + + if (sym && sym->type == bfd_link_hash_defined) + { + undef->type = bfd_link_hash_defined; + undef->u.def.value = sym->u.def.value; + undef->u.def.section = sym->u.def.section; + if (pe_enable_stdcall_fixup == -1) + { + einfo (_("Warning: resolving %s by linking to %s\n"), + undef->root.string, cname); + if (! gave_warning_message) + { + gave_warning_message = 1; + einfo(_("Use --enable-stdcall-fixup to disable these warnings\n")); + einfo(_("Use --disable-stdcall-fixup to disable these fixups\n")); + } + } + } + } + else + { + /* The symbol is a cdecl symbol, so we look for stdcall + symbols - which means scanning the whole symbol table */ + pe_undef_found_sym = 0; + bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match, + (PTR) undef->root.string); + sym = pe_undef_found_sym; + if (sym) + { + undef->type = bfd_link_hash_defined; + undef->u.def.value = sym->u.def.value; + undef->u.def.section = sym->u.def.section; + if (pe_enable_stdcall_fixup == -1) + { + einfo (_("Warning: resolving %s by linking to %s\n"), + undef->root.string, sym->root.string); + if (! gave_warning_message) + { + gave_warning_message = 1; + einfo(_("Use --enable-stdcall-fixup to disable these warnings\n")); + einfo(_("Use --disable-stdcall-fixup to disable these fixups\n")); + } + } + } + } } - } } static int @@ -865,30 +867,24 @@ make_import_fixup (rel, s) asection *s; { struct symbol_cache_entry *sym = *rel->sym_ptr_ptr; + int addend = 0; if (pe_dll_extra_pe_debug) - { - printf ("arelent: %s@%#lx: add=%li\n", sym->name, - (long) rel->address, (long) rel->addend); - } + printf ("arelent: %s@%#lx: add=%li\n", sym->name, + (long) rel->address, (long) rel->addend); - { - int addend = 0; - if (!bfd_get_section_contents(s->owner, s, &addend, rel->address, sizeof(addend))) - { - einfo (_("%C: Cannot get section contents - auto-import exception\n"), - s->owner, s, rel->address); - } + if (!bfd_get_section_contents(s->owner, s, &addend, rel->address, sizeof(addend))) + einfo (_("%C: Cannot get section contents - auto-import exception\n"), + s->owner, s, rel->address); - if (addend == 0) - pe_create_import_fixup (rel); - else - { - einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"), - s->owner, s, rel->address, sym->name); - einfo ("%X"); - } - } + if (addend == 0) + pe_create_import_fixup (rel); + else + { + einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"), + s->owner, s, rel->address, sym->name); + einfo ("%X"); + } return 1; } @@ -897,59 +893,62 @@ static void pe_find_data_imports () { struct bfd_link_hash_entry *undef, *sym; + for (undef = link_info.hash->undefs; undef; undef=undef->next) { if (undef->type == bfd_link_hash_undefined) { /* C++ symbols are *long* */ char buf[4096]; - if (pe_dll_extra_pe_debug) - { - printf ("%s:%s\n", __FUNCTION__, undef->root.string); - } + + if (pe_dll_extra_pe_debug) + printf ("%s:%s\n", __FUNCTION__, undef->root.string); + sprintf (buf, "__imp_%s", undef->root.string); sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); + if (sym && sym->type == bfd_link_hash_defined) { if (link_info.pei386_auto_import == -1) info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"), - undef->root.string, buf); - { - bfd *b = sym->u.def.section->owner; - asymbol **symbols; - int nsyms, symsize, i; - - symsize = bfd_get_symtab_upper_bound (b); - symbols = (asymbol **) xmalloc (symsize); - nsyms = bfd_canonicalize_symtab (b, symbols); - - for (i = 0; i < nsyms; i++) - { - if (memcmp(symbols[i]->name, "__head_", - sizeof ("__head_") - 1)) - continue; - if (pe_dll_extra_pe_debug) - { - printf ("->%s\n", symbols[i]->name); - } - pe_data_import_dll = (char*) (symbols[i]->name + - sizeof ("__head_") - 1); - break; - } - } - - pe_walk_relocs_of_symbol (&link_info, undef->root.string, - make_import_fixup); - - /* let's differentiate it somehow from defined */ - undef->type = bfd_link_hash_defweak; - /* we replace original name with __imp_ prefixed, this - 1) may trash memory 2) leads to duplicate symbol generation. - Still, IMHO it's better than having name poluted. */ - undef->root.string = sym->root.string; - undef->u.def.value = sym->u.def.value; - undef->u.def.section = sym->u.def.section; + undef->root.string, buf); + + { + bfd *b = sym->u.def.section->owner; + asymbol **symbols; + int nsyms, symsize, i; + + symsize = bfd_get_symtab_upper_bound (b); + symbols = (asymbol **) xmalloc (symsize); + nsyms = bfd_canonicalize_symtab (b, symbols); + + for (i = 0; i < nsyms; i++) + { + if (memcmp(symbols[i]->name, "__head_", + sizeof ("__head_") - 1)) + continue; + + if (pe_dll_extra_pe_debug) + printf ("->%s\n", symbols[i]->name); + + pe_data_import_dll = (char*) (symbols[i]->name + + sizeof ("__head_") - 1); + break; + } + } + + pe_walk_relocs_of_symbol (&link_info, undef->root.string, + make_import_fixup); + + /* Let's differentiate it somehow from defined. */ + undef->type = bfd_link_hash_defweak; + /* We replace original name with __imp_ prefixed, this + 1) may trash memory 2) leads to duplicate symbol generation. + Still, IMHO it's better than having name poluted. */ + undef->root.string = sym->root.string; + undef->u.def.value = sym->u.def.value; + undef->u.def.section = sym->u.def.section; } } } @@ -962,9 +961,8 @@ pr_sym (h, string) PTR string ATTRIBUTE_UNUSED; { if (pe_dll_extra_pe_debug) - { - printf("+%s\n",h->string); - } + printf ("+%s\n",h->string); + return true; } @@ -972,11 +970,11 @@ pr_sym (h, string) static void gld_${EMULATION_NAME}_after_open () { - if (pe_dll_extra_pe_debug) { bfd *a; struct bfd_link_hash_entry *sym; + printf ("%s()\n", __FUNCTION__); for (sym = link_info.hash->undefs; sym; sym=sym->next) @@ -984,9 +982,7 @@ gld_${EMULATION_NAME}_after_open () bfd_hash_traverse (&link_info.hash->table, pr_sym,NULL); for (a = link_info.input_bfds; a; a = a->link_next) - { - printf("*%s\n",a->filename); - } + printf ("*%s\n",a->filename); } /* Pass the wacky PE command line options into the output bfd. @@ -1216,7 +1212,7 @@ static void gld_${EMULATION_NAME}_before_allocation() { #ifdef TARGET_IS_ppcpe - /* Here we rummage through the found bfds to collect toc information */ + /* Here we rummage through the found bfds to collect toc information. */ { LANG_FOR_EACH_INPUT_STATEMENT (is) { @@ -1228,7 +1224,7 @@ gld_${EMULATION_NAME}_before_allocation() } } - /* We have seen it all. Allocate it, and carry on */ + /* We have seen it all. Allocate it, and carry on. */ ppc_allocate_toc_section (&link_info); #endif /* TARGET_IS_ppcpe */ @@ -1238,7 +1234,7 @@ gld_${EMULATION_NAME}_before_allocation() Here we rummage through the found bfds to collect glue information. FIXME: should this be based on a command line - option? krk@cygnus.com */ + option? krk@cygnus.com. */ { LANG_FOR_EACH_INPUT_STATEMENT (is) { @@ -1252,20 +1248,21 @@ gld_${EMULATION_NAME}_before_allocation() } } - /* We have seen it all. Allocate it, and carry on */ + /* We have seen it all. Allocate it, and carry on. */ bfd_arm_pe_allocate_interworking_sections (& link_info); #endif /* TARGET_IS_armpe */ } #ifdef DLL_SUPPORT /* This is called when an input file isn't recognized as a BFD. We - check here for .DEF files and pull them in automatically. */ + check here for .DEF files and pull them in automatically. */ static int -saw_option(char *option) +saw_option (char * option) { int i; - for (i=0; init[i].ptr; i++) + + for (i = 0; init[i].ptr; i++) if (strcmp (init[i].symbol, option) == 0) return init[i].inited; return 0; @@ -1280,81 +1277,86 @@ gld_${EMULATION_NAME}_unrecognized_file(entry) const char *ext = entry->filename + strlen (entry->filename) - 4; if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0) - { - if (pe_def_file == 0) - pe_def_file = def_file_empty (); - def_file_parse (entry->filename, pe_def_file); - if (pe_def_file) { - int i, buflen=0, len; - char *buf; - for (i=0; inum_exports; i++) - { - len = strlen(pe_def_file->exports[i].internal_name); - if (buflen < len+2) - buflen = len+2; - } - buf = (char *) xmalloc (buflen); - for (i=0; inum_exports; i++) + if (pe_def_file == 0) + pe_def_file = def_file_empty (); + + def_file_parse (entry->filename, pe_def_file); + + if (pe_def_file) { - struct bfd_link_hash_entry *h; - sprintf(buf, "_%s", pe_def_file->exports[i].internal_name); + int i, buflen=0, len; + char *buf; - h = bfd_link_hash_lookup (link_info.hash, buf, true, true, true); - if (h == (struct bfd_link_hash_entry *) NULL) - einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); - if (h->type == bfd_link_hash_new) + for (i = 0; i < pe_def_file->num_exports; i++) { - h->type = bfd_link_hash_undefined; - h->u.undef.abfd = NULL; - bfd_link_add_undef (link_info.hash, h); + len = strlen(pe_def_file->exports[i].internal_name); + if (buflen < len + 2) + buflen = len + 2; } - } - free (buf); - /* def_file_print (stdout, pe_def_file); */ - if (pe_def_file->is_dll == 1) - link_info.shared = 1; + buf = (char *) xmalloc (buflen); - if (pe_def_file->base_address != (bfd_vma)(-1)) - { - pe.ImageBase = - pe_data (output_bfd)->pe_opthdr.ImageBase = - init[IMAGEBASEOFF].value = pe_def_file->base_address; - init[IMAGEBASEOFF].inited = 1; - if (image_base_statement) - image_base_statement->exp = - exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase)); - } + for (i = 0; i < pe_def_file->num_exports; i++) + { + struct bfd_link_hash_entry *h; + + sprintf(buf, "_%s", pe_def_file->exports[i].internal_name); + + h = bfd_link_hash_lookup (link_info.hash, buf, true, true, true); + if (h == (struct bfd_link_hash_entry *) NULL) + einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); + if (h->type == bfd_link_hash_new) + { + h->type = bfd_link_hash_undefined; + h->u.undef.abfd = NULL; + bfd_link_add_undef (link_info.hash, h); + } + } + free (buf); + + /* def_file_print (stdout, pe_def_file); */ + if (pe_def_file->is_dll == 1) + link_info.shared = 1; + + if (pe_def_file->base_address != (bfd_vma)(-1)) + { + pe.ImageBase = + pe_data (output_bfd)->pe_opthdr.ImageBase = + init[IMAGEBASEOFF].value = pe_def_file->base_address; + init[IMAGEBASEOFF].inited = 1; + if (image_base_statement) + image_base_statement->exp = + exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase)); + } #if 0 - /* Not sure if these *should* be set */ - if (pe_def_file->version_major != -1) - { - pe.MajorImageVersion = pe_def_file->version_major; - pe.MinorImageVersion = pe_def_file->version_minor; - } + /* Not sure if these *should* be set */ + if (pe_def_file->version_major != -1) + { + pe.MajorImageVersion = pe_def_file->version_major; + pe.MinorImageVersion = pe_def_file->version_minor; + } #endif - if (pe_def_file->stack_reserve != -1 - && ! saw_option ("__size_of_stack_reserve__")) - { - pe.SizeOfStackReserve = pe_def_file->stack_reserve; - if (pe_def_file->stack_commit != -1) - pe.SizeOfStackCommit = pe_def_file->stack_commit; - } - if (pe_def_file->heap_reserve != -1 - && ! saw_option ("__size_of_heap_reserve__")) - { - pe.SizeOfHeapReserve = pe_def_file->heap_reserve; - if (pe_def_file->heap_commit != -1) - pe.SizeOfHeapCommit = pe_def_file->heap_commit; - } - return true; + if (pe_def_file->stack_reserve != -1 + && ! saw_option ("__size_of_stack_reserve__")) + { + pe.SizeOfStackReserve = pe_def_file->stack_reserve; + if (pe_def_file->stack_commit != -1) + pe.SizeOfStackCommit = pe_def_file->stack_commit; + } + if (pe_def_file->heap_reserve != -1 + && ! saw_option ("__size_of_heap_reserve__")) + { + pe.SizeOfHeapReserve = pe_def_file->heap_reserve; + if (pe_def_file->heap_commit != -1) + pe.SizeOfHeapCommit = pe_def_file->heap_commit; + } + return true; + } } - } #endif return false; - } static boolean @@ -1377,6 +1379,7 @@ gld_${EMULATION_NAME}_recognized_file(entry) if (bfd_get_format (entry->the_bfd) == bfd_object) { const char *ext = entry->filename + strlen (entry->filename) - 4; + if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0) return pe_implied_import_dll (entry->filename); } @@ -1447,9 +1450,10 @@ gld_${EMULATION_NAME}_finish () pe_dll_generate_def_file (pe_out_def_filename); #endif /* DLL_SUPPORT */ - /* I don't know where .idata gets set as code, but it shouldn't be */ + /* I don't know where .idata gets set as code, but it shouldn't be. */ { asection *asec = bfd_get_section_by_name (output_bfd, ".idata"); + if (asec) { asec->flags &= ~SEC_CODE; @@ -1505,7 +1509,6 @@ struct orphan_save lang_statement_union_type **stmt; }; -/*ARGSUSED*/ static boolean gld_${EMULATION_NAME}_place_orphan (file, s) lang_input_statement_type *file; @@ -1521,7 +1524,6 @@ gld_${EMULATION_NAME}_place_orphan (file, s) secname = bfd_get_section_name (s->owner, s); /* Look through the script to see where to place this section. */ - hold_section_name = xstrdup (secname); if (!link_info.relocateable) { @@ -1655,8 +1657,8 @@ gld_${EMULATION_NAME}_place_orphan (file, s) { char *symname; - /* lang_leave_ouput_section_statement resets stat_ptr. Put - stat_ptr back where we want it. */ + /* lang_leave_ouput_section_statement resets stat_ptr. + Put stat_ptr back where we want it. */ if (place != NULL) stat_ptr = &add; @@ -1752,7 +1754,6 @@ gld_${EMULATION_NAME}_place_orphan (file, s) /* The section name has a '$'. Sort it with the other '$' sections. */ - found_dollar = false; for ( ; *pl != NULL; pl = &(*pl)->header.next) { @@ -1813,26 +1814,24 @@ gld_${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) #endif + 1); - /* Try "libfoo.dll.a" first (preferred explicit import library for dll's */ + /* Try "libfoo.dll.a" first (preferred explicit import library for dll's. */ sprintf (string, "%s/lib%s.dll.a", search->name, filename); if (! ldfile_try_open_bfd (string, entry)) { - /* Try "foo.dll.a" next (alternate explicit import library for dll's */ + /* Try "foo.dll.a" next (alternate explicit import library for dll's. */ sprintf (string, "%s/%s.dll.a", search->name, filename); if (! ldfile_try_open_bfd (string, entry)) { -/* - Try libfoo.a next. Normally, this would be interpreted as a static - library, but it *could* be an import library. For backwards compatibility, - libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search, - or sometimes errors occur when building legacy packages. - - Putting libfoo.a here means that in a failure case (i.e. the library - -lfoo is not found) we will search for libfoo.a twice before - giving up -- once here, and once when searching for a "static" lib. - for a "static" lib. -*/ + /* Try libfoo.a next. Normally, this would be interpreted as a static + library, but it *could* be an import library. For backwards compatibility, + libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search, + or sometimes errors occur when building legacy packages. + + Putting libfoo.a here means that in a failure case (i.e. the library + -lfoo is not found) we will search for libfoo.a twice before + giving up -- once here, and once when searching for a "static" lib. + for a "static" lib. */ /* Try "libfoo.a" (import lib, or static lib, but must take precedence over dll's) */ sprintf (string, "%s/lib%s.a", search->name, filename); @@ -1859,14 +1858,14 @@ gld_${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) } } } - else /* pe_dll_search_prefix not specified */ + else /* pe_dll_search_prefix not specified. */ #endif { - /* Try "libfoo.dll" (preferred dll name) */ + /* Try "libfoo.dll" (preferred dll name). */ sprintf (string, "%s/lib%s.dll", search->name, filename); if (! ldfile_try_open_bfd (string, entry)) { - /* Finally, try "foo.dll" (alternate dll name) */ + /* Finally, try "foo.dll" (alternate dll name). */ sprintf (string, "%s/%s.dll", search->name, filename); if (! ldfile_try_open_bfd (string, entry)) { diff --git a/ld/pe-dll.c b/ld/pe-dll.c index e59c32d09..a85bf9403 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -618,7 +618,8 @@ process_def_file (abfd, info) /* This will preserve internal_name, which may have been pointing to the same memory as name, or might not have. */ - char *tmp = xstrdup (pe_def_file->exports[i].name); + int lead_at = (*pe_def_file->exports[i].name =='@'); + char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at); *(strchr (tmp, '@')) = 0; pe_def_file->exports[i].name = tmp; @@ -632,7 +633,8 @@ process_def_file (abfd, info) { if (strchr (pe_def_file->exports[i].name, '@')) { - char *tmp = xstrdup (pe_def_file->exports[i].name); + int lead_at = (*pe_def_file->exports[i].name == '@' ) ; + char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at); *(strchr (tmp, '@')) = 0; if (auto_export (NULL, pe_def_file, tmp)) @@ -701,7 +703,8 @@ process_def_file (abfd, info) { char *name = (char *) xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); - if (pe_details->underscored) + if (pe_details->underscored + && (*pe_def_file->exports[i].internal_name != '@')) { *name = '_'; strcpy (name + 1, pe_def_file->exports[i].internal_name); @@ -915,7 +918,8 @@ fill_exported_offsets (abfd, info) { char *name = (char *) xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); - if (pe_details->underscored) + if (pe_details->underscored + && (*pe_def_file->exports[i].internal_name != '@')) { *name = '_'; strcpy (name + 1, pe_def_file->exports[i].internal_name); @@ -1811,15 +1815,27 @@ make_one (exp, parent) id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2); - if (! exp->flag_data) - quick_symbol (abfd, U (""), exp->internal_name, "", tx, BSF_GLOBAL, 0); - quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, BSF_GLOBAL, 0); - quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5, BSF_GLOBAL, 0); - /* Symbol to reference ord/name of imported - data symbol, used to implement auto-import. */ - if (exp->flag_data) - quick_symbol (abfd, U("_nm__"), exp->internal_name, "", id6, - BSF_GLOBAL,0); + + if (*exp->internal_name == '@') + { + if (! exp->flag_data) + quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0); + quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, BSF_GLOBAL, 0); + quick_symbol (abfd, U ("_imp_"), exp->internal_name, "", id5, BSF_GLOBAL, 0); + /* Fastcall applies only to functions, + so no need for auto-import symbol. */ + } + else + { + if (! exp->flag_data) + quick_symbol (abfd, U (""), exp->internal_name, "", tx, BSF_GLOBAL, 0); + quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, BSF_GLOBAL, 0); + quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5, BSF_GLOBAL, 0); + /* Symbol to reference ord/name of imported + data symbol, used to implement auto-import. */ + if (exp->flag_data) + quick_symbol (abfd, U("_nm__"), exp->internal_name, "", id6, BSF_GLOBAL,0); + } if (pe_dll_compat_implib) quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", id5, BSF_GLOBAL, 0); @@ -2231,20 +2247,32 @@ pe_process_import_defs (output_bfd, link_info) { def_file_export exp; struct bfd_link_hash_entry *blhe; - + int lead_at = (*pe_def_file->imports[i].internal_name == '@'); /* See if we need this import. */ char *name = (char *) xmalloc (strlen (pe_def_file->imports[i].internal_name) + 2 + 6); - sprintf (name, "%s%s", U (""), pe_def_file->imports[i].internal_name); + + if (lead_at) + sprintf (name, "%s%s", "", pe_def_file->imports[i].internal_name); + else + sprintf (name, "%s%s",U (""), pe_def_file->imports[i].internal_name); + blhe = bfd_link_hash_lookup (link_info->hash, name, false, false, false); + if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)) { - sprintf (name, "%s%s", U ("_imp__"), - pe_def_file->imports[i].internal_name); + if (lead_at) + sprintf (name, "%s%s", U ("_imp_"), + pe_def_file->imports[i].internal_name); + else + sprintf (name, "%s%s", U ("_imp__"), + pe_def_file->imports[i].internal_name); + blhe = bfd_link_hash_lookup (link_info->hash, name, false, false, false); } free (name); + if (blhe && blhe->type == bfd_link_hash_undefined) { bfd *one; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index b10913bed..744f7fcf3 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2002-11-07 Casper S. Hornstrup + + * ld-fastcall: New directory for testing fastcall support. + * ld-fastcall/export.s: New file for testing fastcall symbol + handling. + * ld-fastcall/import.s: Likewise. + * ld-fastcall/fastcall.exp: Likewise. + 2002-11-03 Kaz Kojima * ld-sh/rd-sh.exp: Add -isa=SHcompact to ASFLAGS for SH-5. diff --git a/ld/testsuite/ld-fastcall/export.s b/ld/testsuite/ld-fastcall/export.s new file mode 100644 index 000000000..d8df66ddf --- /dev/null +++ b/ld/testsuite/ld-fastcall/export.s @@ -0,0 +1,3 @@ + .text +.globl @extern_fastcall_function@0 +@extern_fastcall_function@0: diff --git a/ld/testsuite/ld-fastcall/fastcall.exp b/ld/testsuite/ld-fastcall/fastcall.exp new file mode 100644 index 000000000..896adb91e --- /dev/null +++ b/ld/testsuite/ld-fastcall/fastcall.exp @@ -0,0 +1,50 @@ +# Test that the linker can handle fastcall symbols correctly. +# Copyright 2002 Free Software Foundation, Inc. +# +# This file 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +set testname "ld (fastcall symbols)" + +if {![istarget "i*86-*-*"]} { + return +} + +if {![istarget "i*86-*-*pe*"] \ + && ![istarget "i*86-*-cygwin*"] \ + && ![istarget "i*86-*-mingw32*"] } { + set target_xfail "yes" +} else { + set target_xfail "no" +} + +set ldflags "" + +if ![ld_assemble $as $srcdir/$subdir/export.s tmpdir/export.o] { + verbose "Unable to assemble test file!" 1 + unresolved $testname + return +} + +if ![ld_assemble $as $srcdir/$subdir/import.s tmpdir/import.o] { + verbose "Unable to assemble test file!" 1 + unresolved $testname + return +} + +if ![ld_simple_link $ld tmpdir/extern.x "$ldflags tmpdir/export.o tmpdir/import.o"] { + fail $testname +} else { + pass $testname +} diff --git a/ld/testsuite/ld-fastcall/import.s b/ld/testsuite/ld-fastcall/import.s new file mode 100644 index 000000000..e33918b48 --- /dev/null +++ b/ld/testsuite/ld-fastcall/import.s @@ -0,0 +1,4 @@ + .text +.globl _start +_start: + call @extern_fastcall_function@0 -- 2.11.4.GIT