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