Mail Archives: cygwin-developers/2001/06/10/21:24:53
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" <cgf AT redhat DOT com>
To: <cygwin-developers AT cygwin DOT com>
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<string> When linking =
dynamically to a dll witout an\n"));=0A=
fprintf (file, _(" importlib, =
use <string><basename>.dll \n"));=0A=
fprintf (file, _(" in =
preference to lib<basename>.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 <sym>, if __imp_<sym> 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_<sym> 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_<symbol>)=0A=
+ pointing to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) 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--
- Raw text -