diff options
-rw-r--r-- | ld/ChangeLog | 30 | ||||
-rw-r--r-- | ld/Makefile.in | 2 | ||||
-rw-r--r-- | ld/aclocal.m4 | 18 | ||||
-rwxr-xr-x | ld/configure | 2 | ||||
-rw-r--r-- | ld/configure.in | 2 | ||||
-rw-r--r-- | ld/deffile.h | 54 | ||||
-rw-r--r-- | ld/emultempl/pe.em | 63 | ||||
-rw-r--r-- | ld/pe-dll.c | 83 | ||||
-rw-r--r-- | ld/sysdep.h | 26 |
9 files changed, 208 insertions, 72 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 74c9200..75d04d9 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,33 @@ +2002-12-13 Ralf Habacker <Ralf.Habacker@freenet.de> + Charles Wilson <cwilson@ece.gatech.edu> + + * configure.in: Add check for realpath function. + * configure: Regenerate. + * config.in: Regenerate. + * aclocal.m4: Regenerate. + * deffile.h: Add .data field to def_file_import + structure. + * pe-dll.c (pe_proces_import_defs): Use .data field of + def_file_import structure to initialize flag_data field of + def_file_export structure. + (pe_implied_import_dll): New variables exp_funcbase and + [data|bss]_[start|end]. Use DLL's internal name to set dll_name, + not filename (which may be a symlink). Scan the sections and + initialize [data|bss]_[start|end]. When scanning the export + table, skip _nm_ symbols, and mark any symbols whose rva indicates + that it is in the .bss or .data sections as data. + * sysdep.h: Include limits.h and sys/param.h, and define + LD_PATHMAX as appropriate. Also define REALPATH as realpath if it + exists, NULL otherwise. + * emultempl/pe.em (gld_${EMULATION_NAME}_after_open): Call + pe_process_import_defs before pe_find_data_imports, so that + auto-import will check the virtual implib as well as "real" + implibs. + (gld_${EMULATION_NAME}_recognized_file): Use REALPATH to follow + symlinks to their target; check that the target's extension is + .dll before calling pe_implied_import_dll(), not the filename + itself (which may be a symlink). + 2002-12-10 Alan Modra <amodra@bigpond.net.au> * emultempl/elf32.em (struct orphan_save): Add os_tail field. diff --git a/ld/Makefile.in b/ld/Makefile.in index 84b3672..8defa7e 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -538,7 +538,7 @@ deffilep.c ldgram.c ldlex.c DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = tar +TAR = gtar GZIP_ENV = --best SOURCES = $(ld_new_SOURCES) $(EXTRA_ld_new_SOURCES) OBJECTS = $(ld_new_OBJECTS) diff --git a/ld/aclocal.m4 b/ld/aclocal.m4 index 6111817..7b50bb9 100644 --- a/ld/aclocal.m4 +++ b/ld/aclocal.m4 @@ -27,6 +27,24 @@ AC_DEFUN([CY_WITH_NLS],) AC_SUBST(INTLLIBS) ]) +#serial 1 +# This test replaces the one in autoconf. +# Currently this macro should have the same name as the autoconf macro +# because gettext's gettext.m4 (distributed in the automake package) +# still uses it. Otherwise, the use in gettext.m4 makes autoheader +# give these diagnostics: +# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX +# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX + +undefine([AC_ISC_POSIX]) + +AC_DEFUN([AC_ISC_POSIX], + [ + dnl This test replaces the obsolescent AC_ISC_POSIX kludge. + AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) + ] +) + # Do all the work for Automake. This macro actually does too much -- # some checks are only needed if your package does certain things. # But this isn't really a big deal. diff --git a/ld/configure b/ld/configure index 2b3f531..baeaf28 100755 --- a/ld/configure +++ b/ld/configure @@ -4551,7 +4551,7 @@ else fi done -for ac_func in sbrk +for ac_func in sbrk realpath do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:4558: checking for $ac_func" >&5 diff --git a/ld/configure.in b/ld/configure.in index b067e96..12efccc 100644 --- a/ld/configure.in +++ b/ld/configure.in @@ -83,7 +83,7 @@ AC_SUBST(HOSTING_LIBS) AC_SUBST(NATIVE_LIB_DIRS) AC_CHECK_HEADERS(string.h strings.h stdlib.h unistd.h) -AC_CHECK_FUNCS(sbrk) +AC_CHECK_FUNCS(sbrk realpath) AC_HEADER_DIRENT BFD_BINARY_FOPEN diff --git a/ld/deffile.h b/ld/deffile.h index efd7834..09f8407 100644 --- a/ld/deffile.h +++ b/ld/deffile.h @@ -1,5 +1,5 @@ /* deffile.h - header for .DEF file parser - Copyright 1998, 1999, 2000 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc. Written by DJ Delorie dj@cygnus.com This file is part of GLD, the Gnu Linker. @@ -52,65 +52,57 @@ typedef struct def_file_import { def_file_module *module; /* always set */ char *name; /* may be NULL; either this or ordinal will be set */ int ordinal; /* may be -1 */ + int data; /* = 1 if data */ } def_file_import; typedef struct def_file { - /* from the NAME or LIBRARY command */ + /* From the NAME or LIBRARY command. */ char *name; int is_dll; /* -1 if NAME/LIBRARY not given */ bfd_vma base_address; /* (bfd_vma)(-1) if unspecified */ - /* from the DESCRIPTION command */ + /* From the DESCRIPTION command. */ char *description; - /* from the STACK/HEAP command, -1 if unspecified */ + /* From the STACK/HEAP command, -1 if unspecified. */ int stack_reserve, stack_commit; int heap_reserve, heap_commit; - /* from the SECTION/SEGMENT commands */ + /* From the SECTION/SEGMENT commands. */ int num_section_defs; def_file_section *section_defs; - /* from the EXPORTS commands */ + /* From the EXPORTS commands. */ int num_exports; def_file_export *exports; - /* used by imports for module names */ + /* Used by imports for module names. */ def_file_module *modules; - /* from the IMPORTS commands */ + /* From the IMPORTS commands. */ int num_imports; def_file_import *imports; - /* from the VERSION command, -1 if not specified */ + /* From the VERSION command, -1 if not specified. */ int version_major, version_minor; } def_file; extern def_file *def_file_empty PARAMS ((void)); -/* add_to may be NULL. If not, this .def is appended to it */ -extern def_file *def_file_parse PARAMS ((const char *_filename, - def_file * _add_to)); - -extern void def_file_free PARAMS ((def_file * _def)); - -extern def_file_export *def_file_add_export PARAMS ((def_file * _def, - const char *_name, - const char *_internal_name, - int _ordinal)); - -extern def_file_import *def_file_add_import PARAMS ((def_file * _def, - const char *_name, - const char *_from, - int _ordinal, - const char *_imported_name)); - -extern void def_file_add_directive PARAMS ((def_file * _def, - const char *param, - int len)); - +/* The second arg may be NULL. If not, this .def is appended to it. */ +extern def_file * def_file_parse + PARAMS ((const char *, def_file *)); +extern void def_file_free + PARAMS ((def_file *)); +extern def_file_export * def_file_add_export + PARAMS ((def_file *, const char *, const char *, int)); +extern def_file_import * def_file_add_import + PARAMS ((def_file *, const char *, const char *, int, const char *)); +extern void def_file_add_directive + PARAMS ((def_file *, const char *, int)); #ifdef DEF_FILE_PRINT -extern void def_file_print PARAMS ((FILE * _file, def_file * _def)); +extern void def_file_print + PARAMS ((FILE *, def_file *)); #endif #endif /* DEFFILE_H */ diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index ca97023..d350ee8 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -384,7 +384,7 @@ set_pe_name (name, val) return; } } - abort(); + abort (); } @@ -507,7 +507,7 @@ set_pe_stack_heap (resname, comname) static int -gld_${EMULATION_NAME}_parse_args(argc, argv) +gld_${EMULATION_NAME}_parse_args (argc, argv) int argc; char **argv; { @@ -633,7 +633,7 @@ gld_${EMULATION_NAME}_parse_args(argc, argv) pe_enable_auto_image_base = 0; break; case OPTION_DLL_SEARCH_PREFIX: - pe_dll_search_prefix = xstrdup( optarg ); + pe_dll_search_prefix = xstrdup (optarg); break; case OPTION_NO_DEFAULT_EXCLUDES: pe_dll_do_default_excludes = 0; @@ -733,16 +733,16 @@ gld_${EMULATION_NAME}_set_symbols () lang_assignment_statement_type *rv; rv = lang_add_assignment (exp_assop ('=', init[j].symbol, exp_intop (val))); - if (init[j].size == sizeof(short)) - *(short *)init[j].ptr = val; - else if (init[j].size == sizeof(int)) - *(int *)init[j].ptr = val; - else if (init[j].size == sizeof(long)) - *(long *)init[j].ptr = val; + if (init[j].size == sizeof (short)) + *(short *) init[j].ptr = val; + else if (init[j].size == sizeof (int)) + *(int *) init[j].ptr = val; + else if (init[j].size == sizeof (long)) + *(long *) init[j].ptr = val; /* This might be a long long or other special type. */ - else if (init[j].size == sizeof(bfd_vma)) - *(bfd_vma *)init[j].ptr = val; - else abort(); + else if (init[j].size == sizeof (bfd_vma)) + *(bfd_vma *) init[j].ptr = val; + else abort (); if (j == IMAGEBASEOFF) image_base_statement = rv; } @@ -843,8 +843,8 @@ pe_fixup_stdcalls () 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")); + einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); + einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); } } } @@ -869,8 +869,8 @@ pe_fixup_stdcalls () 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")); + einfo (_("Use --enable-stdcall-fixup to disable these warnings\n")); + einfo (_("Use --disable-stdcall-fixup to disable these fixups\n")); } } } @@ -890,7 +890,7 @@ make_import_fixup (rel, s) printf ("arelent: %s@%#lx: add=%li\n", sym->name, (long) rel->address, (long) rel->addend); - if (!bfd_get_section_contents(s->owner, s, &addend, rel->address, sizeof(addend))) + 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); @@ -935,8 +935,8 @@ pe_find_data_imports () for (i = 0; i < nsyms; i++) { - if (memcmp(symbols[i]->name, "__head_", - sizeof ("__head_") - 1)) + if (memcmp (symbols[i]->name, "__head_", + sizeof ("__head_") - 1)) continue; if (pe_dll_extra_pe_debug) @@ -1009,9 +1009,10 @@ gld_${EMULATION_NAME}_after_open () if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ pe_fixup_stdcalls (); + pe_process_import_defs (output_bfd, & link_info); + pe_find_data_imports (); - pe_process_import_defs(output_bfd, &link_info); if (link_info.shared) pe_dll_build_sections (output_bfd, &link_info); @@ -1219,7 +1220,7 @@ gld_${EMULATION_NAME}_after_open () } static void -gld_${EMULATION_NAME}_before_allocation() +gld_${EMULATION_NAME}_before_allocation () { #ifdef TARGET_IS_ppcpe /* Here we rummage through the found bfds to collect toc information. */ @@ -1280,7 +1281,7 @@ saw_option (char * option) #endif /* DLL_SUPPORT */ static bfd_boolean -gld_${EMULATION_NAME}_unrecognized_file(entry) +gld_${EMULATION_NAME}_unrecognized_file (entry) lang_input_statement_type *entry ATTRIBUTE_UNUSED; { #ifdef DLL_SUPPORT @@ -1300,7 +1301,7 @@ gld_${EMULATION_NAME}_unrecognized_file(entry) for (i = 0; i < pe_def_file->num_exports; i++) { - len = strlen(pe_def_file->exports[i].internal_name); + len = strlen (pe_def_file->exports[i].internal_name); if (buflen < len + 2) buflen = len + 2; } @@ -1311,7 +1312,7 @@ gld_${EMULATION_NAME}_unrecognized_file(entry) { struct bfd_link_hash_entry *h; - sprintf(buf, "_%s", pe_def_file->exports[i].internal_name); + 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) @@ -1370,7 +1371,7 @@ gld_${EMULATION_NAME}_unrecognized_file(entry) } static bfd_boolean -gld_${EMULATION_NAME}_recognized_file(entry) +gld_${EMULATION_NAME}_recognized_file (entry) lang_input_statement_type *entry ATTRIBUTE_UNUSED; { #ifdef DLL_SUPPORT @@ -1388,10 +1389,16 @@ gld_${EMULATION_NAME}_recognized_file(entry) #endif if (bfd_get_format (entry->the_bfd) == bfd_object) { - const char *ext = entry->filename + strlen (entry->filename) - 4; + char fbuf[LD_PATHMAX]; + const char *ext; + + if (REALPATH (entry->filename, fbuf) == NULL) + strncpy (fbuf, entry->filename, LD_PATHMAX); + + ext = fbuf + strlen (fbuf) - 4; if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0) - return pe_implied_import_dll (entry->filename); + return pe_implied_import_dll (fbuf); } #endif return FALSE; @@ -1903,7 +1910,7 @@ gld_${EMULATION_NAME}_find_potential_libraries (name, entry) } static char * -gld_${EMULATION_NAME}_get_script(isfile) +gld_${EMULATION_NAME}_get_script (isfile) int *isfile; EOF # Scripts compiled in. diff --git a/ld/pe-dll.c b/ld/pe-dll.c index 1c870e2..45f54e4 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -2418,7 +2418,7 @@ pe_process_import_defs (output_bfd, link_info) exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0; exp.flag_private = 0; exp.flag_constant = 0; - exp.flag_data = 0; + exp.flag_data = pe_def_file->imports[i].data; exp.flag_noname = exp.name ? 0 : 1; one = make_one (&exp, output_bfd); add_bfd_to_link (one, one->filename, link_info); @@ -2491,9 +2491,16 @@ pe_implied_import_dll (filename) bfd *dll; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; const char *dll_name; + /* Initialization with start > end guarantees that is_data + will not be set by mistake, and avoids compiler warning. */ + unsigned long data_start = 1; + unsigned long data_end = 0; + unsigned long bss_start = 1; + unsigned long bss_end = 0; /* No, I can't use bfd here. kernel32.dll puts its export table in the middle of the .rdata section. */ @@ -2511,11 +2518,7 @@ pe_implied_import_dll (filename) return FALSE; } - dll_name = filename; - for (i = 0; filename[i]; i++) - if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') - dll_name = filename + i + 1; - + /* Get pe_header, optional header and numbers of export entries. */ pe_header_offset = pe_get32 (dll, 0x3c); opthdr_ofs = pe_header_offset + 4 + 20; num_entries = pe_get32 (dll, opthdr_ofs + 92); @@ -2530,6 +2533,7 @@ pe_implied_import_dll (filename) pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; + /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) { char sname[8]; @@ -2550,6 +2554,40 @@ pe_implied_import_dll (filename) } } + /* Scan sections and store the base and size of the + data and bss segments in data/base_start/end. */ + for (i = 0; i < nsections; i++) + { + unsigned long secptr1 = secptr + 40 * i; + unsigned long vsize = pe_get32 (dll, secptr1 + 8); + unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long flags = pe_get32 (dll, secptr1 + 36); + char sec_name[9]; + + sec_name[8] = '\0'; + bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); + bfd_bread (sec_name, (bfd_size_type) 8, dll); + + if (strcmp(sec_name,".data") == 0) + { + data_start = vaddr; + data_end = vaddr + vsize; + + if (pe_dll_extra_pe_debug) + printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n", + __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags); + } + else if (strcmp (sec_name,".bss") == 0) + { + bss_start = vaddr; + bss_end = vaddr + vsize; + + if (pe_dll_extra_pe_debug) + printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n", + __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags); + } + } + expdata = (unsigned char *) xmalloc (export_size); bfd_seek (dll, (file_ptr) expptr, SEEK_SET); bfd_bread (expdata, (bfd_size_type) export_size, dll); @@ -2562,14 +2600,41 @@ pe_implied_import_dll (filename) name_rvas = pe_as32 (expdata + 32); ordinals = pe_as32 (expdata + 36); ordbase = pe_as32 (expdata + 16); + exp_funcbase = pe_as32 (expdata + 28); + /* Use internal dll name instead of filename + to enable symbolic dll linking. */ + dll_name = pe_as32 (expdata + 12) + erva; + + /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { + /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); def_file_import *imp; - - imp = def_file_add_import (pe_def_file, erva + name_rva, dll_name, - i, 0); + /* Pointer to the function address vector. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + int is_data = 0; + + /* Skip unwanted symbols, which are + exported in buggy auto-import releases. */ + if (strncmp (erva + name_rva, "_nm_", 4) != 0) + { + /* is_data is true if the address is in the data or bss segment. */ + is_data = + (func_rva >= data_start && func_rva < data_end) + || (func_rva >= bss_start && func_rva < bss_end); + + imp = def_file_add_import (pe_def_file, erva + name_rva, + dll_name, i, 0); + /* Mark symbole type. */ + imp->data = is_data; + + if (pe_dll_extra_pe_debug) + printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n", + __FUNCTION__, dll_name, erva + name_rva, + func_rva, is_data ? "(data)" : ""); + } } return TRUE; diff --git a/ld/sysdep.h b/ld/sysdep.h index 24688a6..7151f14 100644 --- a/ld/sysdep.h +++ b/ld/sysdep.h @@ -1,5 +1,5 @@ /* sysdep.h -- handle host dependencies for the GNU linker - Copyright 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + Copyright 1995, 1996, 1997, 1999, 2002 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -48,6 +48,30 @@ extern char *strrchr (); #include <unistd.h> #endif +/* for PATH_MAX */ +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +/* for MAXPATHLEN */ +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef PATH_MAX +# define LD_PATHMAX PATH_MAX +#else +# ifdef MAXPATHLEN +# define LD_PATHMAX MAXPATHLEN +# else +# define LD_PATHMAX 1024 +# endif +#endif + +#ifdef HAVE_REALPATH +# define REALPATH(a,b) realpath (a, b) +#else +# define REALPATH(a,b) NULL +#endif + #ifdef USE_BINARY_FOPEN #include "fopen-bin.h" #else |