Index: configure.in =================================================================== RCS file: /cvs/src/src/ld/configure.in,v retrieving revision 1.20 diff -u -3 -p -B -u -b -B -p -r1.20 configure.in --- configure.in 12 Nov 2002 10:08:23 -0000 1.20 +++ configure.in 13 Dec 2002 08:33:14 -0000 @@ -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 Index: deffile.h =================================================================== RCS file: /cvs/src/src/ld/deffile.h,v retrieving revision 1.5 diff -u -3 -p -B -u -b -B -p -r1.5 deffile.h --- deffile.h 13 Mar 2001 06:14:27 -0000 1.5 +++ deffile.h 13 Dec 2002 08:33:14 -0000 @@ -52,6 +52,7 @@ 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 { Index: pe-dll.c =================================================================== RCS file: /cvs/src/src/ld/pe-dll.c,v retrieving revision 1.49 diff -u -3 -p -B -u -b -B -p -r1.49 pe-dll.c --- pe-dll.c 30 Nov 2002 08:39:45 -0000 1.49 +++ pe-dll.c 13 Dec 2002 08:33:17 -0000 @@ -2418,7 +2418,7 @@ pe_process_import_defs (output_bfd, link 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); @@ -2490,11 +2490,18 @@ 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 export_rva, export_size, nsections, secptr, expptr,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. */ dll = bfd_openr (filename, pe_details->target_name); @@ -2511,11 +2518,8 @@ 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 +2534,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 +2555,43 @@ 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,16 +2604,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; - + /* 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; } Index: sysdep.h =================================================================== RCS file: /cvs/src/src/ld/sysdep.h,v retrieving revision 1.2 diff -u -3 -p -B -u -b -B -p -r1.2 sysdep.h --- sysdep.h 13 Mar 2001 06:14:27 -0000 1.2 +++ sysdep.h 13 Dec 2002 08:33:17 -0000 @@ -48,6 +48,30 @@ extern char *strrchr (); #include #endif +/* for PATH_MAX */ +#ifdef HAVE_LIMITS_H +#include +#endif +/* for MAXPATHLEN */ +#ifdef HAVE_SYS_PARAM_H +#include +#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 Index: emultempl/pe.em =================================================================== RCS file: /cvs/src/src/ld/emultempl/pe.em,v retrieving revision 1.70 diff -u -3 -p -B -u -b -B -p -r1.70 pe.em --- emultempl/pe.em 30 Nov 2002 08:39:46 -0000 1.70 +++ emultempl/pe.em 13 Dec 2002 08:33:21 -0000 @@ -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); @@ -1388,10 +1389,13 @@ gld_${EMULATION_NAME}_recognized_file(en #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;