Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin-developers AT sources DOT redhat DOT com Message-ID: <02f501c0f215$669a30f0$0200a8c0@lifelesswks> From: "Robert Collins" To: References: <001f01c0f0e6$72b8ec80$0200a8c0 AT lifelesswks> <20010610004015 DOT D29231 AT redhat DOT com> <23114413578 DOT 20010610185633 AT logos-m DOT ru> <20010610120846 DOT B5292 AT redhat DOT com> <027801c0f210$d1e7c5c0$0200a8c0 AT lifelesswks> <20010610211823 DOT A9379 AT redhat DOT com> Subject: Re: dll base address - patch with description attached Date: Mon, 11 Jun 2001 11:25:28 +1000 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_02F2_01C0F269.37B6AB20" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.50.4133.2400 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400 X-OriginalArrivalTime: 11 Jun 2001 01:15:23.0301 (UTC) FILETIME=[FD387550:01C0F213] This is a multi-part message in MIME format. ------=_NextPart_000_02F2_01C0F269.37B6AB20 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit ----- Original Message ----- From: "Christopher Faylor" To: Sent: Monday, June 11, 2001 11:18 AM Subject: Re: dll base address > If someone has a patch that applies cleanly to the current CVS sources > and a writeup of how auto-import works, I'd like to revisit it again. > I'm not binutils maintainer, however. I've attached a diff file for the patch. I don't know if it applies cleanly... It does have a description by Paul of what the auto-import does. Rob ------=_NextPart_000_02F2_01C0F269.37B6AB20 Content-Type: application/octet-stream; name="ld-2.11-auto-import-20010504.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="ld-2.11-auto-import-20010504.diff" diff -uwr org/bfd/cofflink.c src/bfd/cofflink.c=0A= --- org/bfd/cofflink.c Fri Apr 27 12:57:43 2001=0A= +++ src/bfd/cofflink.c Fri Apr 27 13:51:28 2001=0A= @@ -27,6 +27,9 @@=0A= #include "coff/internal.h"=0A= #include "libcoff.h"=0A= =0A= +/* Setting this to 0 disables PE autoimport support */=0A= +int pe_dll_auto_import=3D1;=0A= +=0A= static boolean coff_link_add_object_symbols=0A= PARAMS ((bfd *, struct bfd_link_info *));=0A= static boolean coff_link_check_archive_element=0A= @@ -276,6 +279,14 @@=0A= return false;=0A= h =3D bfd_link_hash_lookup (info->hash, name, false, false, true);=0A= =0A= + /*PS*/=0A= + if (!h && pe_dll_auto_import)=0A= + {=0A= + if (!strncmp(name,"__imp_",6))=0A= + {=0A= + h =3D bfd_link_hash_lookup (info->hash, name+6, false, = false, true);=0A= + }=0A= + }=0A= /* We are only interested in symbols that are currently=0A= undefined. If a symbol is currently known to be common,=0A= COFF linkers do not bring in an object file which defines=0A= diff -uwr org/bfd/linker.c src/bfd/linker.c=0A= --- org/bfd/linker.c Fri Apr 27 12:58:12 2001=0A= +++ src/bfd/linker.c Fri Apr 27 13:54:54 2001=0A= @@ -1003,10 +1003,22 @@=0A= arh =3D archive_hash_lookup (&arsym_hash, h->root.string, false, = false);=0A= if (arh =3D=3D (struct archive_hash_entry *) NULL)=0A= {=0A= + /* If we haven't found very symbol, let's look for its=0A= + import thunk */=0A= + extern int pe_dll_auto_import;=0A= +=0A= + if (pe_dll_auto_import)=0A= + {=0A= + char *buf=3Dalloca(strlen(h->root.string)+10);=0A= + sprintf(buf,"__imp_%s",h->root.string);=0A= + arh =3D archive_hash_lookup (&arsym_hash, buf, false, = false);=0A= + }=0A= + if (arh =3D=3D (struct archive_hash_entry *) NULL)=0A= + {=0A= pundef =3D &(*pundef)->next;=0A= continue;=0A= }=0A= -=0A= + }=0A= /* Look at all the objects which define this symbol. */=0A= for (l =3D arh->defs; l !=3D (struct archive_list *) NULL; l =3D = l->next)=0A= {=0A= diff -uwr org/ld/emultempl/pe.em src/ld/emultempl/pe.em=0A= --- org/ld/emultempl/pe.em Tue Dec 26 20:55:30 2000=0A= +++ src/ld/emultempl/pe.em Fri Apr 27 14:10:11 2001=0A= @@ -118,7 +118,7 @@=0A= static int pe_enable_stdcall_fixup =3D -1; /* 0=3Ddisable 1=3Denable */=0A= static char *pe_out_def_filename =3D NULL;=0A= static char *pe_implib_filename =3D NULL;=0A= -static int pe_enable_auto_image_base =3D 0;=0A= +static int pe_enable_auto_image_base =3D 1;=0A= static char *pe_dll_search_prefix =3D NULL;=0A= #endif=0A= =0A= @@ -130,6 +130,7 @@=0A= output_filename =3D "${EXECUTABLE_NAME:-a.exe}";=0A= ldfile_output_architecture =3D bfd_arch_${ARCH};=0A= #ifdef DLL_SUPPORT=0A= + config.dynamic_link =3D true;=0A= config.has_shared =3D 1;=0A= =0A= #if (PE_DEF_SUBSYSTEM =3D=3D 9) || (PE_DEF_SUBSYSTEM =3D=3D 2)=0A= @@ -175,6 +176,8 @@=0A= #define OPTION_DISABLE_AUTO_IMAGE_BASE (OPTION_ENABLE_AUTO_IMAGE_BASE + = 1)=0A= #define OPTION_DLL_SEARCH_PREFIX (OPTION_DISABLE_AUTO_IMAGE_BASE + 1)=0A= #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_DLL_SEARCH_PREFIX + 1)=0A= +#define OPTION_DLL_DISABLE_AUTO_IMPORT (OPTION_NO_DEFAULT_EXCLUDES + 1)=0A= +#define OPTION_DLL_ENABLE_GORY_DEBUG (OPTION_DLL_DISABLE_AUTO_IMPORT + = 1)=0A= =0A= static struct option longopts[] =3D {=0A= /* PE options */=0A= @@ -212,6 +215,8 @@=0A= {"disable-auto-image-base", no_argument, NULL, = OPTION_DISABLE_AUTO_IMAGE_BASE},=0A= {"dll-search-prefix", required_argument, NULL, = OPTION_DLL_SEARCH_PREFIX},=0A= {"no-default-excludes", no_argument, NULL, = OPTION_NO_DEFAULT_EXCLUDES},=0A= + {"disable-auto-import", no_argument, NULL, = OPTION_DLL_DISABLE_AUTO_IMPORT},=0A= + {"enable-gory-debug", no_argument, NULL, = OPTION_DLL_ENABLE_GORY_DEBUG},=0A= #endif=0A= {NULL, no_argument, NULL, 0}=0A= };=0A= @@ -297,6 +302,8 @@=0A= fprintf (file, _(" --dll-search-prefix=3D When linking = dynamically to a dll witout an\n"));=0A= fprintf (file, _(" importlib, = use .dll \n"));=0A= fprintf (file, _(" in = preference to lib.dll \n"));=0A= + fprintf (file, _(" --disable-auto-import Do not do = sophistcated linking of _sym to \n"));=0A= + fprintf (file, _(" __imp_sym = for DATA references\n"));=0A= #endif=0A= }=0A= =0A= @@ -567,6 +574,12 @@=0A= case OPTION_NO_DEFAULT_EXCLUDES:=0A= pe_dll_do_default_excludes =3D 0;=0A= break;=0A= + case OPTION_DLL_DISABLE_AUTO_IMPORT:=0A= + pe_dll_auto_import =3D 0;=0A= + break;=0A= + case OPTION_DLL_ENABLE_GORY_DEBUG:=0A= + pe_dll_gory_debug =3D 1;=0A= + break;=0A= #endif=0A= }=0A= return 1;=0A= @@ -717,6 +730,8 @@=0A= static int gave_warning_message =3D 0;=0A= struct bfd_link_hash_entry *undef, *sym;=0A= char *at;=0A= + if (pe_dll_gory_debug) printf(__FUNCTION__"\n");=0A= +=0A= for (undef =3D link_info.hash->undefs; undef; undef=3Dundef->next)=0A= if (undef->type =3D=3D bfd_link_hash_undefined)=0A= {=0A= @@ -775,11 +790,101 @@=0A= }=0A= }=0A= }=0A= +=0A= +static int=0A= +make_import_fixup (rel)=0A= + arelent *rel;=0A= +{=0A= + struct symbol_cache_entry *sym =3D *rel->sym_ptr_ptr;=0A= +// bfd *b;=0A= +=0A= + if (pe_dll_gory_debug) printf("arelent: %s@%#x: = add=3D%li\n",sym->name,(int)rel->address,rel->addend);=0A= + pe_create_import_fixup(rel);=0A= + return 1;=0A= +}=0A= +=0A= +char *data_import_dll;=0A= +=0A= +static void=0A= +pe_find_data_imports ()=0A= +{=0A= + struct bfd_link_hash_entry *undef, *sym;=0A= + for (undef =3D link_info.hash->undefs; undef; undef=3Dundef->next)=0A= + if (undef->type =3D=3D bfd_link_hash_undefined)=0A= + {=0A= + /* C++ symbols are *long* */=0A= + char buf[4096];=0A= +if (pe_dll_gory_debug) printf(__FUNCTION__":%s\n",undef->root.string);=0A= + sprintf(buf,"__imp_%s",undef->root.string);=0A= +=0A= + sym =3D bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);=0A= + if (sym && sym->type =3D=3D bfd_link_hash_defined)=0A= + {=0A= + einfo (_("Warning: resolving %s by linking to %s = (auto-import)\n"),=0A= + undef->root.string, buf);=0A= +=0A= + {=0A= + bfd *b=3Dsym->u.def.section->owner;=0A= + asymbol **symbols;=0A= + int nsyms, symsize, i;=0A= + =0A= + symsize =3D bfd_get_symtab_upper_bound (b);=0A= + symbols =3D (asymbol **) xmalloc (symsize);=0A= + nsyms =3D bfd_canonicalize_symtab (b, symbols);=0A= +=0A= + for (i =3D 0; i < nsyms; i++)=0A= + {=0A= + if = (memcmp(symbols[i]->name,"__head_",sizeof("__head_")-1))=0A= + continue;=0A= +if (pe_dll_gory_debug) printf("->%s\n",symbols[i]->name);=0A= + = data_import_dll=3D(char*)(symbols[i]->name+sizeof("__head_")-1);=0A= + break;=0A= + }=0A= + }=0A= +=0A= +=0A= + pe_walk_relocs_of_symbol(&link_info, undef->root.string, = make_import_fixup);=0A= +=0A= + /* let's differentiate it somehow from defined */=0A= + undef->type =3D bfd_link_hash_defweak;=0A= + /* we replace original name with __imp_ prefixed, this=0A= + 1) may trash memory 2) leads to duplicate symbol generation.=0A= + Still, IMHO it's better than having name poluted. */=0A= + undef->root.string =3D sym->root.string;=0A= + undef->u.def.value =3D sym->u.def.value;=0A= + undef->u.def.section =3D sym->u.def.section;=0A= + }=0A= + }=0A= +}=0A= #endif /* DLL_SUPPORT */=0A= =0A= +static boolean=0A= +pr_sym (h, string)=0A= + struct bfd_hash_entry *h;=0A= + PTR string;=0A= +{=0A= +if (pe_dll_gory_debug) printf("+%s\n",h->string);=0A= + return true;=0A= +}=0A= +=0A= +=0A= static void=0A= gld_${EMULATION_NAME}_after_open ()=0A= {=0A= +=0A= +if (pe_dll_gory_debug) =0A= +{=0A= + bfd *a;=0A= + struct bfd_link_hash_entry *sym;=0A= + printf(__FUNCTION__"()\n");=0A= +=0A= + for (sym =3D link_info.hash->undefs; sym; sym=3Dsym->next)=0A= + printf("-%s\n",sym->root.string);=0A= + bfd_hash_traverse(&link_info.hash->table,pr_sym,NULL);=0A= +=0A= + for (a=3Dlink_info.input_bfds; a; a=3Da->link_next)=0A= + printf("*%s\n",a->filename);=0A= +}=0A= /* Pass the wacky PE command line options into the output bfd.=0A= FIXME: This should be done via a function, rather than by=0A= including an internal BFD header. */=0A= @@ -794,6 +899,8 @@=0A= if (pe_enable_stdcall_fixup) /* -1=3Dwarn or 1=3Ddisable */=0A= pe_fixup_stdcalls ();=0A= =0A= + pe_find_data_imports (output_bfd, &link_info);=0A= +=0A= pe_process_import_defs(output_bfd, &link_info);=0A= if (link_info.shared)=0A= pe_dll_build_sections (output_bfd, &link_info);=0A= @@ -1235,6 +1342,16 @@=0A= if (pe_out_def_filename)=0A= pe_dll_generate_def_file (pe_out_def_filename);=0A= #endif /* DLL_SUPPORT */=0A= +=0A= +/* I don't know which bugger sets .idata as code */=0A= + {=0A= + asection *asec =3D bfd_get_section_by_name (output_bfd, ".idata");=0A= + if (asec)=0A= + {=0A= + asec->flags &=3D ~SEC_CODE;=0A= + asec->flags |=3D SEC_DATA;=0A= + }=0A= + }=0A= }=0A= =0A= diff -uwr org/ld/ldlang.c src/ld/ldlang.c=0A= --- org/ld/ldlang.c Thu Jan 25 02:31:42 2001=0A= +++ src/ld/ldlang.c Fri Apr 27 17:12:35 2001=0A= @@ -1432,6 +1432,10 @@=0A= bfd_error_type err;=0A= lang_statement_list_type *hold;=0A= =0A= + /* See if the emulation has some special knowledge. */=0A= + if (ldemul_unrecognized_file (entry))=0A= + return;=0A= +=0A= err =3D bfd_get_error ();=0A= if (err =3D=3D bfd_error_file_ambiguously_recognized)=0A= {=0A= @@ -1450,11 +1454,6 @@=0A= bfd_close (entry->the_bfd);=0A= entry->the_bfd =3D NULL;=0A= =0A= - /* See if the emulation has some special knowledge. */=0A= -=0A= - if (ldemul_unrecognized_file (entry))=0A= - return;=0A= -=0A= /* Try to interpret the file as a linker script. */=0A= =0A= ldfile_open_command_file (entry->filename);=0A= diff -uwr org/ld/pe-dll.c src/ld/pe-dll.c=0A= --- org/ld/pe-dll.c Tue Oct 10 03:28:01 2000=0A= +++ src/ld/pe-dll.c Fri Apr 27 17:25:45 2001=0A= @@ -54,6 +54,84 @@=0A= =0A= = ************************************************************************/=0A= =0A= +/***********************************************************************= *=0A= +=0A= + Auto-import feature by Paul Sokolovsky=0A= +=0A= + Quick facts:=0A= +=0A= + 1. With this feature on, DLL clients can import variables from DLL=0A= + without any concern from their side (for example, without any source=0A= + code modifications).=0A= +=0A= + 2. This is done completely in bounds of the PE specification (to be = fair,=0A= + there's a place where it pokes nose out of, but in practise it works).=0A= + So, resulting module can be used with any other PE compiler/linker.=0A= +=0A= + 3. Auto-import is fully compatible with standard import method and they=0A= + can be mixed together.=0A= +=0A= + 4. Overheads: space: 8 bytes per imported symbol, plus 20 for each=0A= + reference to it; load time: negligible; virtual/physical memory: = should be=0A= + less than effect of DLL relocation, and I sincerely hope it doesn't = affect=0A= + DLL sharability (too much).=0A= +=0A= + Idea=0A= +=0A= + The obvious and only way to get rid of dllimport insanity is to make = client=0A= + access variable directly in the DLL, bypassing extra dereference. I.e.,=0A= + whenever client contains someting like=0A= +=0A= + mov dll_var,%eax,=0A= +=0A= + address of dll_var in the command should be relocated to point into = loaded=0A= + DLL. The aim is to make OS loader do so, and than make ld help with = that.=0A= + Import section of PE made following way: there's a vector of structures=0A= + each describing imports from particular DLL. Each such structure points=0A= + to two other parellel vectors: one holding imported names, and one = which=0A= + will hold address of corresponding imported name. So, the solution is=0A= + de-vectorize these structures, making import locations be sparse and=0A= + pointing directly into code. Before continuing, it is worth a note = that,=0A= + while authors strives to make PE act ELF-like, there're some other = people=0A= + make ELF act PE-like: elfvector, ;-) .=0A= +=0A= + Implementation=0A= +=0A= + For each reference of data symbol to be imported from DLL (to set of = which=0A= + belong symbols with name , if __imp_ is found in implib), the=0A= + import fixup entry is generated. That entry is of type=0A= + IMAGE_IMPORT_DESCRIPTOR and stored in .idata$3 subsection. Each=0A= + fixup entry contains pointer to symbol's address within .text section=0A= + (marked with __fuN_ symbol, where N is integer), pointer to DLL = name=0A= + (so, DLL name is referenced by multiple entries), and pointer to symbol=0A= + name thunk. Symbol name thunk is singleton vector (__nm_th_)=0A= + pointing to IMAGE_IMPORT_BY_NAME structure (__nm_) directly=0A= + containing imported name. Here comes that "om the edge" problem = mentioned=0A= + above: PE specification rambles that name vector (OriginalFirstThunk)=0A= + should run in parallel with addresses vector (FirstThunk), i.e. that = they=0A= + should have same number of elements and terminated with zero. We = violate=0A= + this, since FirstThunk points directly into machine code. But in = practise,=0A= + OS loader implemented the sane way: it goes thru OriginalFirstThunk and=0A= + puts addresses to FirstThunk, not something else. It once again should = be=0A= + noted that dll and symbol name structures are reused across fixup = entries=0A= + and should be there anyway to support standard import stuff, so = sustained=0A= + overhead is 20 bytes per reference. Other question is whether having = several=0A= + IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible. Answer is yes, = it is=0A= + done even by native compiler/linker (libth32's functions are in fact = reside=0A= + in windows9x kernel32.dll, so if you use it, you have two=0A= + IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other question is = whether=0A= + referencing the same PE structures several times is valid. The answer = is why=0A= + not, prohibitting that (detecting violation) would require more work on=0A= + behalf of loader than not doing it.=0A= +=0A= +=0A= + See also: ld/emultempl/pe.em=0A= +=0A= + = ************************************************************************/=0A= +=0A= +void=0A= +add_bfd_to_link (bfd *abfd, CONST char *name, struct bfd_link_info = *link_info);=0A= +=0A= /* for emultempl/pe.em */=0A= =0A= def_file *pe_def_file =3D 0;=0A= @@ -63,6 +141,7 @@=0A= int pe_dll_stdcall_aliases =3D 0;=0A= int pe_dll_warn_dup_exports =3D 0;=0A= int pe_dll_compat_implib =3D 0;=0A= +int pe_dll_gory_debug =3D 0;=0A= =0A= = /************************************************************************=0A= =0A= @@ -231,24 +310,79 @@=0A= free (local_copy);=0A= }=0A= =0A= +/*=0A= + abfd is a bfd containing n (or NULL)=0A= + It can be used for contextual checks.=0A= +*/=0A= static int=0A= -auto_export (d, n)=0A= +auto_export (abfd, d, n)=0A= + bfd *abfd;=0A= def_file *d;=0A= const char *n;=0A= {=0A= int i;=0A= struct exclude_list_struct *ex;=0A= +=0A= + /* we should not re-export imported stuff */=0A= + if (strncmp (n, "_imp__",6) =3D=3D 0)=0A= + return 0;=0A= +=0A= for (i =3D 0; i < d->num_exports; i++)=0A= if (strcmp (d->exports[i].name, n) =3D=3D 0)=0A= return 0;=0A= if (pe_dll_do_default_excludes)=0A= {=0A= +if (pe_dll_gory_debug) printf("considering exporting: %s "=0A= + "abfd=3D%x, abfd->my_arc=3D%x\n",n,abfd,abfd->my_archive);=0A= + /* First of all, make context checks:=0A= + Don't export anything from libgcc */=0A= +=0A= + if (abfd=0A= + && abfd->my_archive)=0A= + {=0A= + /* Do not specify suffix explicitly, to allow for dllized = versions */=0A= + if (strstr(abfd->my_archive->filename,"libgcc.")) return 0;=0A= + if (strstr(abfd->my_archive->filename,"libstdc++.")) return 0;=0A= + if (strstr(abfd->my_archive->filename,"libmingw32.")) return = 0;=0A= + }=0A= +=0A= + {=0A= + /* skip .*crt\d\.o */=0A= + char *p;=0A= + if (abfd=0A= + && (p=3Dstrstr(abfd->filename,"crt"))=0A= + && (isdigit(p[3]) && p[4]=3D=3D'.' && p[5]=3D=3D'o' && = p[6]=3D=3D0)) return 0;=0A= + }=0A= +=0A= +#if 0=0A= + /* Don't export any 'reserved' symbols */=0A= + if (*n && *n=3D=3D'_' && n[1]=3D=3D'_') return 0;=0A= +#endif=0A= +=0A= if (strcmp (n, "DllMain AT 12") =3D=3D 0)=0A= return 0;=0A= if (strcmp (n, "DllEntryPoint AT 0") =3D=3D 0)=0A= return 0;=0A= + if (strcmp (n, "DllMainCRTStartup AT 12") =3D=3D 0)=0A= + return 0;=0A= if (strcmp (n, "impure_ptr") =3D=3D 0)=0A= return 0;=0A= +=0A= + if (strncmp (n, "__rtti_", 7) =3D=3D 0)=0A= + return 0;=0A= + if (strncmp (n, "__builtin_", 10) =3D=3D 0)=0A= + return 0;=0A= +=0A= + /* Don't export symbols for specifying DLL's internal layout */=0A= +=0A= + if (strncmp (n, "_head_", 6) =3D=3D 0)=0A= + return 0;=0A= +=0A= + {=0A= + int len =3D strlen(n);=0A= + if (len>6 && strncmp (n + len - 6, "_iname", 7) =3D=3D 0)=0A= + return 0;=0A= + }=0A= }=0A= for (ex =3D excludes; ex; ex =3D ex->next)=0A= if (strcmp (n, ex->string) =3D=3D 0)=0A= @@ -302,14 +436,29 @@=0A= for (j =3D 0; j < nsyms; j++)=0A= {=0A= /* We should export symbols which are either global or not=0A= - anything at all. (.bss data is the latter) */=0A= - if ((symbols[j]->flags & BSF_GLOBAL)=0A= - || (symbols[j]->flags =3D=3D BSF_NO_FLAGS))=0A= + anything at all. (.bss data is the latter)=0A= + We should not export undefined symbols=0A= + */=0A= + if (symbols[j]->section!=3D&bfd_und_section=0A= + && ((symbols[j]->flags & BSF_GLOBAL)=0A= + || (symbols[j]->flags =3D=3D BFD_FORT_COMM_DEFAULT_VALUE)))=0A= {=0A= const char *sn =3D symbols[j]->name;=0A= +=0A= + /* we should not re-export imported stuff */=0A= + {=0A= + char *name =3D (char *) xmalloc (strlen (sn) + 2 + = 6);=0A= + sprintf (name, "%s%s", U("_imp_"), sn);=0A= + blhe =3D bfd_link_hash_lookup (info->hash, name,=0A= + false, false, false);=0A= + free (name);=0A= +=0A= + if (blhe && blhe->type =3D=3D = bfd_link_hash_defined) continue;=0A= + }=0A= +=0A= if (*sn =3D=3D '_')=0A= sn++;=0A= - if (auto_export (pe_def_file, sn))=0A= + if (auto_export (b, pe_def_file, sn))=0A= {=0A= def_file_export *p;=0A= p=3Ddef_file_add_export (pe_def_file, sn, 0, -1);=0A= @@ -350,7 +499,7 @@=0A= {=0A= char *tmp =3D xstrdup (pe_def_file->exports[i].name);=0A= *(strchr (tmp, '@')) =3D 0;=0A= - if (auto_export (pe_def_file, tmp))=0A= + if (auto_export (NULL, pe_def_file, tmp))=0A= def_file_add_export (pe_def_file, tmp,=0A= pe_def_file->exports[i].internal_name, -1);=0A= else=0A= @@ -731,6 +880,52 @@=0A= }=0A= }=0A= =0A= +=0A= +static struct sec *current_sec;=0A= +=0A= +void=0A= +pe_walk_relocs_of_symbol (info, name, cb)=0A= + struct bfd_link_info *info;=0A= + CONST char *name;=0A= + int (*cb)(arelent*);=0A= +{=0A= + bfd *b;=0A= + struct sec *s;=0A= +=0A= + for (b =3D info->input_bfds; b; b =3D b->link_next)=0A= + {=0A= + arelent **relocs;=0A= + int relsize, nrelocs, i;=0A= +=0A= + for (s =3D b->sections; s; s =3D s->next)=0A= + {=0A= + asymbol **symbols;=0A= + int nsyms, symsize;=0A= +=0A= + current_sec=3Ds;=0A= +=0A= + symsize =3D bfd_get_symtab_upper_bound (b);=0A= + symbols =3D (asymbol **) xmalloc (symsize);=0A= + nsyms =3D bfd_canonicalize_symtab (b, symbols);=0A= +=0A= + relsize =3D bfd_get_reloc_upper_bound (b, s);=0A= + relocs =3D (arelent **) xmalloc ((size_t) relsize);=0A= + nrelocs =3D bfd_canonicalize_reloc (b, s, relocs, symbols);=0A= +=0A= + for (i =3D 0; i < nrelocs; i++)=0A= + {=0A= + struct symbol_cache_entry *sym =3D = *relocs[i]->sym_ptr_ptr;=0A= + if (!strcmp(name,sym->name)) cb(relocs[i]);=0A= + }=0A= + free (relocs);=0A= + /* Warning: the allocated symbols are remembered in BFD and reused=0A= + later, so don't free them! */=0A= + /* free (symbols); */=0A= + }=0A= + }=0A= +=0A= +}=0A= +=0A= = /************************************************************************=0A= =0A= Gather all the relocations and build the .reloc section=0A= @@ -801,6 +996,10 @@=0A= =0A= for (i =3D 0; i < nrelocs; i++)=0A= {=0A= +if (pe_dll_gory_debug) {=0A= +struct symbol_cache_entry *sym =3D *relocs[i]->sym_ptr_ptr;=0A= +printf("rel: %s\n",sym->name);=0A= +}=0A= if (!relocs[i]->howto->pc_relative=0A= && relocs[i]->howto->type !=3D pe_details->imagebase_reloc)=0A= {=0A= @@ -902,6 +902,13 @@=0A= asymbol **symbols;=0A= int nsyms, symsize;=0A= =0A= + int flags =3D bfd_get_section_flags (b, s);=0A= +=0A= + /* Skip discarded linkonce sections */=0A= + if (flags & SEC_LINK_ONCE=0A= + && s->output_section =3D=3D bfd_abs_section_ptr)=0A= + continue;=0A= +=0A= current_sec=3Ds;=0A= =0A= symsize =3D bfd_get_symtab_upper_bound (b);=0A= @@ -1039,7 +1238,7 @@=0A= =0A= if (pe_def_file->num_exports > 0)=0A= {=0A= - fprintf (out, "\nEXPORTS\n\n");=0A= + fprintf (out, "EXPORTS\n");=0A= for (i =3D 0; i < pe_def_file->num_exports; i++)=0A= {=0A= def_file_export *e =3D pe_def_file->exports + i;=0A= @@ -1445,7 +1644,7 @@=0A= bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);=0A= =0A= symptr =3D 0;=0A= - symtab =3D (asymbol **) xmalloc (10 * sizeof (asymbol *));=0A= + symtab =3D (asymbol **) xmalloc (11 * sizeof (asymbol *));=0A= tx =3D quick_section (abfd, ".text", SEC_CODE|SEC_HAS_CONTENTS, = 2);=0A= id7 =3D quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);=0A= id5 =3D quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);=0A= @@ -1455,6 +1654,9 @@=0A= quick_symbol (abfd, U (""), exp->internal_name, "", tx, BSF_GLOBAL, = 0);=0A= quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, = BSF_GLOBAL, 0);=0A= quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5, = BSF_GLOBAL, 0);=0A= + /* symbol to reference ord/name of imported symbol, used to implement=0A= + auto-import */=0A= + quick_symbol (abfd, U("_nm__"), exp->internal_name, "", id6, = BSF_GLOBAL, 0);=0A= if (pe_dll_compat_implib)=0A= quick_symbol (abfd, U ("__imp_"), exp->internal_name, "",=0A= id5, BSF_GLOBAL, 0);=0A= @@ -1553,6 +1755,175 @@=0A= return abfd;=0A= }=0A= =0A= +static bfd *=0A= +make_singleton_name_thunk (import, parent)=0A= + char *import;=0A= + bfd *parent;=0A= +{=0A= + /* name thunks go to idata$4 */=0A= +=0A= + asection *id4;=0A= + unsigned char *d4;=0A= + char *oname;=0A= + bfd *abfd;=0A= +=0A= + oname =3D (char *) xmalloc (20);=0A= + sprintf (oname, "nmth%06d.o", tmp_seq);=0A= + tmp_seq++;=0A= +=0A= + abfd =3D bfd_create (oname, parent);=0A= + bfd_find_target (pe_details->object_target, abfd);=0A= + bfd_make_writable (abfd);=0A= +=0A= + bfd_set_format (abfd, bfd_object);=0A= + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);=0A= +=0A= + symptr =3D 0;=0A= + symtab =3D (asymbol **) xmalloc (3 * sizeof (asymbol *));=0A= + id4 =3D quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);=0A= + quick_symbol (abfd, U("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);=0A= + quick_symbol (abfd, U("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);=0A= +=0A= + bfd_set_section_size (abfd, id4, 8);=0A= + d4 =3D (unsigned char *) xmalloc (4);=0A= + id4->contents =3D d4;=0A= + memset (d4, 0, 8);=0A= + quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);=0A= + save_relocs (id4);=0A= +=0A= + bfd_set_symtab (abfd, symtab, symptr);=0A= +=0A= + bfd_set_section_contents (abfd, id4, d4, 0, 8);=0A= +=0A= + bfd_make_readable (abfd);=0A= + return abfd;=0A= +}=0A= +=0A= +char *=0A= +make_import_fixup_mark (rel)=0A= + arelent *rel;=0A= +{=0A= + /* we convert reloc to symbol, for later reference */=0A= + static int counter;=0A= + static char fixup_name[300];=0A= +=0A= + struct symbol_cache_entry *sym =3D *rel->sym_ptr_ptr;=0A= +=0A= + bfd *abfd=3Dbfd_asymbol_bfd(sym);=0A= + struct coff_link_hash_entry *myh=3DNULL;=0A= +=0A= + sprintf(fixup_name,"__fu%d_%s",counter++,sym->name);=0A= + bfd_coff_link_add_one_symbol(&link_info,=0A= + abfd,=0A= + fixup_name,=0A= + BSF_GLOBAL,=0A= + current_sec, //sym->section,=0A= + rel->address,=0A= + NULL,=0A= + true,=0A= + false,=0A= + (struct bfd_link_hash_entry **) = &myh);=0A= +=0A= +/*printf("type:%d\n",myh->type);=0A= +printf("%s\n",myh->root.u.def.section->name);=0A= +*/=0A= + return fixup_name;=0A= +}=0A= +=0A= +=0A= +/*=0A= + * .section .idata$3=0A= + * .rva __nm_thnk_SYM (singleton thunk with name of func)=0A= + * .long 0=0A= + * .long 0=0A= + * .rva __my_dll_iname (name of dll)=0A= + * .rva __fuNN_SYM (pointer to reference (address) in text)=0A= + *=0A= + */=0A= +=0A= +static bfd *=0A= +make_import_fixup_entry (name,fixup_name,dll_symname,parent)=0A= + char *name;=0A= + char *fixup_name;=0A= + char *dll_symname;=0A= + bfd *parent;=0A= +{=0A= + asection *id3;=0A= + unsigned char *d3;=0A= + char *oname;=0A= + bfd *abfd;=0A= +=0A= + oname =3D (char *) xmalloc (20);=0A= + sprintf (oname, "fu%06d.o", tmp_seq);=0A= + tmp_seq++;=0A= +=0A= + abfd =3D bfd_create (oname, parent);=0A= + bfd_find_target (pe_details->object_target, abfd);=0A= + bfd_make_writable (abfd);=0A= +=0A= + bfd_set_format (abfd, bfd_object);=0A= + bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);=0A= +=0A= + symptr =3D 0;=0A= + symtab =3D (asymbol **) xmalloc (6 * sizeof (asymbol *));=0A= + id3 =3D quick_section (abfd, ".idata$3", SEC_HAS_CONTENTS, 2);=0A= +// quick_symbol (abfd, U("_head_"), dll_symname, "", id2, BSF_GLOBAL, = 0);=0A= +=0A= + quick_symbol (abfd, U("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0);=0A= + quick_symbol (abfd, U(""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, = 0);=0A= + quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);=0A= +=0A= + bfd_set_section_size (abfd, id3, 20);=0A= + d3 =3D (unsigned char *) xmalloc (20);=0A= + id3->contents =3D d3;=0A= + memset (d3, 0, 20);=0A= +=0A= + quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);=0A= + quick_reloc (abfd, 12, BFD_RELOC_RVA, 2);=0A= + quick_reloc (abfd, 16, BFD_RELOC_RVA, 3);=0A= + save_relocs (id3);=0A= +=0A= + bfd_set_symtab (abfd, symtab, symptr);=0A= +=0A= + bfd_set_section_contents (abfd, id3, d3, 0, 20);=0A= +=0A= + bfd_make_readable (abfd);=0A= + return abfd;=0A= +}=0A= +=0A= +void=0A= +pe_create_import_fixup (rel)=0A= + arelent *rel;=0A= +{=0A= + char buf[300];=0A= + struct symbol_cache_entry *sym =3D *rel->sym_ptr_ptr;=0A= + struct bfd_link_hash_entry *name_thunk_sym;=0A= + CONST char *name =3D sym->name;=0A= + char *fixup_name =3D make_import_fixup_mark(rel);=0A= +=0A= + sprintf(buf,U("_nm_thnk_%s"),name);=0A= +=0A= + name_thunk_sym =3D=0A= + bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);=0A= +=0A= + if (!name_thunk_sym || name_thunk_sym->type !=3D = bfd_link_hash_defined)=0A= + {=0A= + bfd *b=3Dmake_singleton_name_thunk (name, output_bfd);=0A= + add_bfd_to_link (b, b->filename, &link_info);=0A= +=0A= + /* If we ever use autoimport, we have to cast text section writable = */=0A= + config.text_read_only=3Dfalse;=0A= + }=0A= +=0A= + {=0A= + extern char *data_import_dll;=0A= + bfd *b=3Dmake_import_fixup_entry = (name,fixup_name,data_import_dll,output_bfd);=0A= + add_bfd_to_link (b, b->filename, &link_info);=0A= + }=0A= +=0A= +}=0A= +=0A= +=0A= void=0A= pe_dll_generate_implib (def, impfilename)=0A= def_file *def;=0A= @@ -1628,10 +1999,10 @@=0A= }=0A= }=0A= =0A= -static void=0A= +void=0A= add_bfd_to_link (abfd, name, link_info)=0A= bfd *abfd;=0A= - char *name;=0A= + CONST char *name;=0A= struct bfd_link_info *link_info;=0A= {=0A= lang_input_statement_type *fake_file;=0A= diff -uwr org/ld/pe-dll.h src/ld/pe-dll.h=0A= --- org/ld/pe-dll.h Tue Jan 4 23:44:03 2000=0A= +++ src/ld/pe-dll.h Fri Apr 27 17:25:53 2001=0A= @@ -33,6 +33,10 @@=0A= extern int pe_dll_stdcall_aliases;=0A= extern int pe_dll_warn_dup_exports;=0A= extern int pe_dll_compat_implib;=0A= +/* This resides in bfd */=0A= +//_BFD_IMPORT =0A= +extern int pe_dll_auto_import;=0A= +extern int pe_dll_gory_debug;=0A= =0A= extern void pe_dll_id_target PARAMS ((const char *));=0A= extern void pe_dll_add_excludes PARAMS ((const char *));=0A= @@ -45,4 +49,9 @@=0A= extern void pe_dll_fill_sections PARAMS ((bfd *, struct bfd_link_info = *));=0A= extern void pe_exe_fill_sections PARAMS ((bfd *, struct bfd_link_info = *));=0A= =0A= +extern void pe_walk_relocs_of_symbol PARAMS ((struct bfd_link_info = *info,=0A= + CONST char *name,=0A= + int (*cb)(arelent*)));=0A= +=0A= +extern void pe_create_import_fixup PARAMS ((arelent *rel));=0A= #endif /* PE_DLL_H */=0A= ------=_NextPart_000_02F2_01C0F269.37B6AB20--