pe-dll.c revision 104834
160484Sobrien/* Routines to help build PEI-format DLLs (Win32 etc) 2104834Sobrien Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 360484Sobrien Written by DJ Delorie <dj@cygnus.com> 460484Sobrien 560484Sobrien This file is part of GLD, the Gnu Linker. 660484Sobrien 760484Sobrien GLD is free software; you can redistribute it and/or modify 860484Sobrien it under the terms of the GNU General Public License as published by 960484Sobrien the Free Software Foundation; either version 2, or (at your option) 1060484Sobrien any later version. 1160484Sobrien 1260484Sobrien GLD is distributed in the hope that it will be useful, 1360484Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1460484Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1560484Sobrien GNU General Public License for more details. 1660484Sobrien 1760484Sobrien You should have received a copy of the GNU General Public License 1860484Sobrien along with GLD; see the file COPYING. If not, write to the Free 1960484Sobrien Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2060484Sobrien 02111-1307, USA. */ 2160484Sobrien 2260484Sobrien#include "bfd.h" 2360484Sobrien#include "sysdep.h" 2460484Sobrien#include "bfdlink.h" 2560484Sobrien#include "libiberty.h" 2689857Sobrien#include "safe-ctype.h" 2760484Sobrien 2860484Sobrien#include <time.h> 2960484Sobrien 3060484Sobrien#include "ld.h" 3160484Sobrien#include "ldexp.h" 3260484Sobrien#include "ldlang.h" 3360484Sobrien#include "ldwrite.h" 3460484Sobrien#include "ldmisc.h" 3560484Sobrien#include "ldgram.h" 3660484Sobrien#include "ldmain.h" 3777298Sobrien#include "ldfile.h" 3860484Sobrien#include "ldemul.h" 3960484Sobrien#include "coff/internal.h" 4060484Sobrien#include "../bfd/libcoff.h" 4160484Sobrien#include "deffile.h" 4260484Sobrien#include "pe-dll.h" 4360484Sobrien 4489857Sobrien/* This file turns a regular Windows PE image into a DLL. Because of 4589857Sobrien the complexity of this operation, it has been broken down into a 4689857Sobrien number of separate modules which are all called by the main function 4789857Sobrien at the end of this file. This function is not re-entrant and is 4889857Sobrien normally only called once, so static variables are used to reduce 4989857Sobrien the number of parameters and return values required. 50104834Sobrien 5189857Sobrien See also: ld/emultempl/pe.em. */ 5260484Sobrien 5389857Sobrien/* Auto-import feature by Paul Sokolovsky 5460484Sobrien 5589857Sobrien Quick facts: 5660484Sobrien 5789857Sobrien 1. With this feature on, DLL clients can import variables from DLL 5889857Sobrien without any concern from their side (for example, without any source 5989857Sobrien code modifications). 6060484Sobrien 6189857Sobrien 2. This is done completely in bounds of the PE specification (to be fair, 6289857Sobrien there's a place where it pokes nose out of, but in practise it works). 6389857Sobrien So, resulting module can be used with any other PE compiler/linker. 6460484Sobrien 6589857Sobrien 3. Auto-import is fully compatible with standard import method and they 6689857Sobrien can be mixed together. 6789857Sobrien 6889857Sobrien 4. Overheads: space: 8 bytes per imported symbol, plus 20 for each 6989857Sobrien reference to it; load time: negligible; virtual/physical memory: should be 7089857Sobrien less than effect of DLL relocation, and I sincerely hope it doesn't affect 7189857Sobrien DLL sharability (too much). 7289857Sobrien 7389857Sobrien Idea 7489857Sobrien 7589857Sobrien The obvious and only way to get rid of dllimport insanity is to make client 7689857Sobrien access variable directly in the DLL, bypassing extra dereference. I.e., 7789857Sobrien whenever client contains someting like 7889857Sobrien 7989857Sobrien mov dll_var,%eax, 8089857Sobrien 8189857Sobrien address of dll_var in the command should be relocated to point into loaded 8289857Sobrien DLL. The aim is to make OS loader do so, and than make ld help with that. 8389857Sobrien Import section of PE made following way: there's a vector of structures 8489857Sobrien each describing imports from particular DLL. Each such structure points 8589857Sobrien to two other parellel vectors: one holding imported names, and one which 8689857Sobrien will hold address of corresponding imported name. So, the solution is 8789857Sobrien de-vectorize these structures, making import locations be sparse and 8889857Sobrien pointing directly into code. Before continuing, it is worth a note that, 8989857Sobrien while authors strives to make PE act ELF-like, there're some other people 9089857Sobrien make ELF act PE-like: elfvector, ;-) . 9189857Sobrien 9289857Sobrien Implementation 9389857Sobrien 9489857Sobrien For each reference of data symbol to be imported from DLL (to set of which 9589857Sobrien belong symbols with name <sym>, if __imp_<sym> is found in implib), the 9689857Sobrien import fixup entry is generated. That entry is of type 9789857Sobrien IMAGE_IMPORT_DESCRIPTOR and stored in .idata$3 subsection. Each 9889857Sobrien fixup entry contains pointer to symbol's address within .text section 9989857Sobrien (marked with __fuN_<sym> symbol, where N is integer), pointer to DLL name 10089857Sobrien (so, DLL name is referenced by multiple entries), and pointer to symbol 10189857Sobrien name thunk. Symbol name thunk is singleton vector (__nm_th_<symbol>) 10289857Sobrien pointing to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) directly 10389857Sobrien containing imported name. Here comes that "om the edge" problem mentioned 10489857Sobrien above: PE specification rambles that name vector (OriginalFirstThunk) 10589857Sobrien should run in parallel with addresses vector (FirstThunk), i.e. that they 10689857Sobrien should have same number of elements and terminated with zero. We violate 10789857Sobrien this, since FirstThunk points directly into machine code. But in practise, 10889857Sobrien OS loader implemented the sane way: it goes thru OriginalFirstThunk and 10989857Sobrien puts addresses to FirstThunk, not something else. It once again should be 11089857Sobrien noted that dll and symbol name structures are reused across fixup entries 11189857Sobrien and should be there anyway to support standard import stuff, so sustained 11289857Sobrien overhead is 20 bytes per reference. Other question is whether having several 11389857Sobrien IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible. Answer is yes, it is 11489857Sobrien done even by native compiler/linker (libth32's functions are in fact reside 11589857Sobrien in windows9x kernel32.dll, so if you use it, you have two 11689857Sobrien IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other question is whether 11789857Sobrien referencing the same PE structures several times is valid. The answer is why 11889857Sobrien not, prohibitting that (detecting violation) would require more work on 11989857Sobrien behalf of loader than not doing it. 12089857Sobrien 12189857Sobrien See also: ld/emultempl/pe.em. */ 12289857Sobrien 12389857Sobrienstatic void 12489857Sobrienadd_bfd_to_link PARAMS ((bfd *, const char *, struct bfd_link_info *)); 12589857Sobrien 12689857Sobrien/* For emultempl/pe.em. */ 12789857Sobrien 12889857Sobriendef_file * pe_def_file = 0; 12960484Sobrienint pe_dll_export_everything = 0; 13060484Sobrienint pe_dll_do_default_excludes = 1; 13160484Sobrienint pe_dll_kill_ats = 0; 13260484Sobrienint pe_dll_stdcall_aliases = 0; 13360484Sobrienint pe_dll_warn_dup_exports = 0; 13460484Sobrienint pe_dll_compat_implib = 0; 13589857Sobrienint pe_dll_extra_pe_debug = 0; 13660484Sobrien 13789857Sobrien/* Static variables and types. */ 13860484Sobrien 13960484Sobrienstatic bfd_vma image_base; 14060484Sobrienstatic bfd *filler_bfd; 14160484Sobrienstatic struct sec *edata_s, *reloc_s; 14260484Sobrienstatic unsigned char *edata_d, *reloc_d; 14360484Sobrienstatic size_t edata_sz, reloc_sz; 14460484Sobrien 14589857Sobrientypedef struct 14689857Sobrien { 14789857Sobrien char *target_name; 14889857Sobrien char *object_target; 14989857Sobrien unsigned int imagebase_reloc; 15089857Sobrien int pe_arch; 15189857Sobrien int bfd_arch; 15289857Sobrien int underscored; 15389857Sobrien } 15489857Sobrienpe_details_type; 15560484Sobrien 15689857Sobrientypedef struct 15789857Sobrien { 15889857Sobrien char *name; 15989857Sobrien int len; 16089857Sobrien } 16189857Sobrienautofilter_entry_type; 16289857Sobrien 16360484Sobrien#define PE_ARCH_i386 1 16460484Sobrien#define PE_ARCH_sh 2 16560484Sobrien#define PE_ARCH_mips 3 16660484Sobrien#define PE_ARCH_arm 4 16789857Sobrien#define PE_ARCH_arm_epoc 5 16860484Sobrien 16989857Sobrienstatic pe_details_type pe_detail_list[] = 17089857Sobrien{ 17160484Sobrien { 17260484Sobrien "pei-i386", 17360484Sobrien "pe-i386", 17460484Sobrien 7 /* R_IMAGEBASE */, 17560484Sobrien PE_ARCH_i386, 17660484Sobrien bfd_arch_i386, 17760484Sobrien 1 17860484Sobrien }, 17960484Sobrien { 18060484Sobrien "pei-shl", 18160484Sobrien "pe-shl", 18260484Sobrien 16 /* R_SH_IMAGEBASE */, 18360484Sobrien PE_ARCH_sh, 18460484Sobrien bfd_arch_sh, 18560484Sobrien 1 18660484Sobrien }, 18760484Sobrien { 18860484Sobrien "pei-mips", 18960484Sobrien "pe-mips", 19060484Sobrien 34 /* MIPS_R_RVA */, 19160484Sobrien PE_ARCH_mips, 19260484Sobrien bfd_arch_mips, 19360484Sobrien 0 19460484Sobrien }, 19560484Sobrien { 19660484Sobrien "pei-arm-little", 19760484Sobrien "pe-arm-little", 19860484Sobrien 11 /* ARM_RVA32 */, 19960484Sobrien PE_ARCH_arm, 20060484Sobrien bfd_arch_arm, 20160484Sobrien 0 20260484Sobrien }, 20389857Sobrien { 20489857Sobrien "epoc-pei-arm-little", 20589857Sobrien "epoc-pe-arm-little", 20689857Sobrien 11 /* ARM_RVA32 */, 20789857Sobrien PE_ARCH_arm_epoc, 20889857Sobrien bfd_arch_arm, 20989857Sobrien 0 21089857Sobrien }, 21160484Sobrien { NULL, NULL, 0, 0, 0, 0 } 21260484Sobrien}; 21360484Sobrien 21460484Sobrienstatic pe_details_type *pe_details; 21560484Sobrien 21689857Sobrienstatic autofilter_entry_type autofilter_symbollist[] = 21789857Sobrien{ 21889857Sobrien { "DllMain@12", 10 }, 21989857Sobrien { "DllEntryPoint@0", 15 }, 22089857Sobrien { "DllMainCRTStartup@12", 20 }, 22189857Sobrien { "_cygwin_dll_entry@12", 20 }, 22289857Sobrien { "_cygwin_crt0_common@8", 21 }, 22389857Sobrien { "_cygwin_noncygwin_dll_entry@12", 30 }, 22489857Sobrien { "impure_ptr", 10 }, 22589857Sobrien { NULL, 0 } 22689857Sobrien}; 22789857Sobrien 22889857Sobrien/* Do not specify library suffix explicitly, to allow for dllized versions. */ 22989857Sobrienstatic autofilter_entry_type autofilter_liblist[] = 23089857Sobrien{ 23189857Sobrien { "libgcc.", 7 }, 23289857Sobrien { "libstdc++.", 10 }, 23389857Sobrien { "libmingw32.", 11 }, 234104834Sobrien { "libg2c.", 7 }, 235104834Sobrien { "libsupc++.", 10 }, 236104834Sobrien { "libobjc.", 8 }, 23789857Sobrien { NULL, 0 } 23889857Sobrien}; 23989857Sobrien 24089857Sobrienstatic autofilter_entry_type autofilter_objlist[] = 24189857Sobrien{ 24289857Sobrien { "crt0.o", 6 }, 24389857Sobrien { "crt1.o", 6 }, 24489857Sobrien { "crt2.o", 6 }, 24589857Sobrien { "dllcrt1.o", 9 }, 24689857Sobrien { "dllcrt2.o", 9 }, 24789857Sobrien { "gcrt0.o", 7 }, 24889857Sobrien { "gcrt1.o", 7 }, 249104834Sobrien { "gcrt2.o", 7 }, 250104834Sobrien { "crtbegin.o", 10 }, 251104834Sobrien { "crtend.o", 8 }, 25289857Sobrien { NULL, 0 } 25389857Sobrien}; 25489857Sobrien 25589857Sobrienstatic autofilter_entry_type autofilter_symbolprefixlist[] = 25689857Sobrien{ 25789857Sobrien /* { "__imp_", 6 }, */ 25889857Sobrien /* Do __imp_ explicitly to save time. */ 25989857Sobrien { "__rtti_", 7 }, 26089857Sobrien { "__builtin_", 10 }, 26189857Sobrien /* Don't export symbols specifying internal DLL layout. */ 26289857Sobrien { "_head_", 6 }, 26389857Sobrien { "_fmode", 6 }, 26489857Sobrien { "_impure_ptr", 11 }, 26589857Sobrien { "cygwin_attach_dll", 17 }, 26689857Sobrien { "cygwin_premain0", 15 }, 26789857Sobrien { "cygwin_premain1", 15 }, 26889857Sobrien { "cygwin_premain2", 15 }, 26989857Sobrien { "cygwin_premain3", 15 }, 27089857Sobrien { "environ", 7 }, 27189857Sobrien { NULL, 0 } 27289857Sobrien}; 27389857Sobrien 27489857Sobrienstatic autofilter_entry_type autofilter_symbolsuffixlist[] = 27589857Sobrien{ 27689857Sobrien { "_iname", 6 }, 27789857Sobrien { NULL, 0 } 27889857Sobrien}; 27989857Sobrien 28060484Sobrien#define U(str) (pe_details->underscored ? "_" str : str) 28160484Sobrien 28289857Sobrienstatic int reloc_sort PARAMS ((const void *, const void *)); 28389857Sobrienstatic int pe_export_sort PARAMS ((const void *, const void *)); 28489857Sobrienstatic int auto_export PARAMS ((bfd *, def_file *, const char *)); 28589857Sobrienstatic void process_def_file PARAMS ((bfd *, struct bfd_link_info *)); 28689857Sobrienstatic void build_filler_bfd PARAMS ((int)); 28789857Sobrienstatic void generate_edata PARAMS ((bfd *, struct bfd_link_info *)); 28889857Sobrienstatic void fill_exported_offsets PARAMS ((bfd *, struct bfd_link_info *)); 28989857Sobrienstatic void fill_edata PARAMS ((bfd *, struct bfd_link_info *)); 29089857Sobrienstatic void generate_reloc PARAMS ((bfd *, struct bfd_link_info *)); 29189857Sobrienstatic void quoteput PARAMS ((char *, FILE *, int)); 29289857Sobrienstatic asection *quick_section PARAMS ((bfd *, const char *, int, int)); 29389857Sobrienstatic void quick_symbol 29489857Sobrien PARAMS ((bfd *, const char *, const char *, const char *, 29589857Sobrien asection *, int, int)); 29689857Sobrienstatic void quick_reloc PARAMS ((bfd *, int, int, int)); 29789857Sobrienstatic bfd *make_head PARAMS ((bfd *)); 29889857Sobrienstatic bfd *make_tail PARAMS ((bfd *)); 29989857Sobrienstatic bfd *make_one PARAMS ((def_file_export *, bfd *)); 30089857Sobrienstatic bfd *make_singleton_name_thunk PARAMS ((const char *, bfd *)); 30189857Sobrienstatic char *make_import_fixup_mark PARAMS ((arelent *)); 30289857Sobrienstatic bfd *make_import_fixup_entry 30389857Sobrien PARAMS ((const char *, const char *, const char *, bfd *)); 30489857Sobrienstatic unsigned int pe_get16 PARAMS ((bfd *, int)); 30589857Sobrienstatic unsigned int pe_get32 PARAMS ((bfd *, int)); 30689857Sobrienstatic unsigned int pe_as32 PARAMS ((void *)); 30789857Sobrien 30860484Sobrienvoid 30960484Sobrienpe_dll_id_target (target) 31060484Sobrien const char *target; 31160484Sobrien{ 31260484Sobrien int i; 31389857Sobrien 31477298Sobrien for (i = 0; pe_detail_list[i].target_name; i++) 31577298Sobrien if (strcmp (pe_detail_list[i].target_name, target) == 0 31677298Sobrien || strcmp (pe_detail_list[i].object_target, target) == 0) 31760484Sobrien { 31877298Sobrien pe_details = pe_detail_list + i; 31960484Sobrien return; 32060484Sobrien } 32160484Sobrien einfo (_("%XUnsupported PEI architecture: %s\n"), target); 32260484Sobrien exit (1); 32360484Sobrien} 32460484Sobrien 325104834Sobrien/* Helper functions for qsort. Relocs must be sorted so that we can write 32689857Sobrien them out by pages. */ 32760484Sobrien 32889857Sobrientypedef struct 32989857Sobrien { 33089857Sobrien bfd_vma vma; 33189857Sobrien char type; 33289857Sobrien short extra; 33389857Sobrien } 33489857Sobrienreloc_data_type; 33560484Sobrien 33660484Sobrienstatic int 33760484Sobrienreloc_sort (va, vb) 33860484Sobrien const void *va, *vb; 33960484Sobrien{ 34060484Sobrien bfd_vma a = ((reloc_data_type *) va)->vma; 34160484Sobrien bfd_vma b = ((reloc_data_type *) vb)->vma; 34289857Sobrien 34360484Sobrien return (a > b) ? 1 : ((a < b) ? -1 : 0); 34460484Sobrien} 34560484Sobrien 34660484Sobrienstatic int 34760484Sobrienpe_export_sort (va, vb) 34860484Sobrien const void *va, *vb; 34960484Sobrien{ 35060484Sobrien def_file_export *a = (def_file_export *) va; 35160484Sobrien def_file_export *b = (def_file_export *) vb; 35289857Sobrien 35360484Sobrien return strcmp (a->name, b->name); 35460484Sobrien} 35560484Sobrien 35689857Sobrien/* Read and process the .DEF file. */ 35760484Sobrien 35860484Sobrien/* These correspond to the entries in pe_def_file->exports[]. I use 35960484Sobrien exported_symbol_sections[i] to tag whether or not the symbol was 36077298Sobrien defined, since we can't export symbols we don't have. */ 36160484Sobrien 36260484Sobrienstatic bfd_vma *exported_symbol_offsets; 36360484Sobrienstatic struct sec **exported_symbol_sections; 36460484Sobrienstatic int export_table_size; 36560484Sobrienstatic int count_exported; 36660484Sobrienstatic int count_exported_byname; 36760484Sobrienstatic int count_with_ordinals; 36860484Sobrienstatic const char *dll_name; 36960484Sobrienstatic int min_ordinal, max_ordinal; 37060484Sobrienstatic int *exported_symbols; 37160484Sobrien 37289857Sobrientypedef struct exclude_list_struct 37389857Sobrien { 37489857Sobrien char *string; 37589857Sobrien struct exclude_list_struct *next; 376104834Sobrien int type; 37789857Sobrien } 37889857Sobrienexclude_list_struct; 37977298Sobrien 38060484Sobrienstatic struct exclude_list_struct *excludes = 0; 38160484Sobrien 38260484Sobrienvoid 383104834Sobrienpe_dll_add_excludes (new_excludes, type) 38460484Sobrien const char *new_excludes; 385104834Sobrien const int type; 38660484Sobrien{ 38760484Sobrien char *local_copy; 38860484Sobrien char *exclude_string; 38960484Sobrien 39060484Sobrien local_copy = xstrdup (new_excludes); 39160484Sobrien 39260484Sobrien exclude_string = strtok (local_copy, ",:"); 39360484Sobrien for (; exclude_string; exclude_string = strtok (NULL, ",:")) 39460484Sobrien { 39560484Sobrien struct exclude_list_struct *new_exclude; 39660484Sobrien 39760484Sobrien new_exclude = ((struct exclude_list_struct *) 39860484Sobrien xmalloc (sizeof (struct exclude_list_struct))); 39960484Sobrien new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 1); 40060484Sobrien strcpy (new_exclude->string, exclude_string); 401104834Sobrien new_exclude->type = type; 40260484Sobrien new_exclude->next = excludes; 40360484Sobrien excludes = new_exclude; 40460484Sobrien } 40560484Sobrien 40660484Sobrien free (local_copy); 40760484Sobrien} 40860484Sobrien 409104834Sobrien 41089857Sobrien/* abfd is a bfd containing n (or NULL) 41189857Sobrien It can be used for contextual checks. */ 41289857Sobrien 41360484Sobrienstatic int 41489857Sobrienauto_export (abfd, d, n) 41589857Sobrien bfd *abfd; 41660484Sobrien def_file *d; 41760484Sobrien const char *n; 41860484Sobrien{ 41960484Sobrien int i; 42060484Sobrien struct exclude_list_struct *ex; 42189857Sobrien autofilter_entry_type *afptr; 422104834Sobrien const char * libname = 0; 423104834Sobrien if (abfd && abfd->my_archive) 424104834Sobrien libname = lbasename (abfd->my_archive->filename); 42589857Sobrien 42689857Sobrien /* We should not re-export imported stuff. */ 42789857Sobrien if (strncmp (n, "_imp__", 6) == 0) 42889857Sobrien return 0; 42989857Sobrien 43060484Sobrien for (i = 0; i < d->num_exports; i++) 43160484Sobrien if (strcmp (d->exports[i].name, n) == 0) 43260484Sobrien return 0; 43389857Sobrien 43460484Sobrien if (pe_dll_do_default_excludes) 43560484Sobrien { 43689857Sobrien const char * p; 43789857Sobrien int len; 43889857Sobrien 43989857Sobrien if (pe_dll_extra_pe_debug) 44089857Sobrien printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n", 44189857Sobrien n, abfd, abfd->my_archive); 44289857Sobrien 44389857Sobrien /* First of all, make context checks: 444104834Sobrien Don't export anything from standard libs. */ 445104834Sobrien if (libname) 44689857Sobrien { 44789857Sobrien afptr = autofilter_liblist; 44889857Sobrien 44989857Sobrien while (afptr->name) 45089857Sobrien { 451104834Sobrien if (strncmp (libname, afptr->name, afptr->len) == 0 ) 45289857Sobrien return 0; 45389857Sobrien afptr++; 45489857Sobrien } 45589857Sobrien } 45689857Sobrien 45789857Sobrien /* Next, exclude symbols from certain startup objects. */ 45889857Sobrien 45989857Sobrien if (abfd && (p = lbasename (abfd->filename))) 46089857Sobrien { 461104834Sobrien afptr = autofilter_objlist; 462104834Sobrien while (afptr->name) 46389857Sobrien { 464104834Sobrien if (strcmp (p, afptr->name) == 0) 465104834Sobrien return 0; 46689857Sobrien afptr++; 46789857Sobrien } 46889857Sobrien } 46989857Sobrien 47089857Sobrien /* Don't try to blindly exclude all symbols 47189857Sobrien that begin with '__'; this was tried and 47289857Sobrien it is too restrictive. */ 47389857Sobrien 47489857Sobrien /* Then, exclude specific symbols. */ 47589857Sobrien afptr = autofilter_symbollist; 47689857Sobrien while (afptr->name) 47789857Sobrien { 47889857Sobrien if (strcmp (n, afptr->name) == 0) 47989857Sobrien return 0; 48089857Sobrien 481104834Sobrien afptr++; 48289857Sobrien } 48389857Sobrien 48489857Sobrien /* Next, exclude symbols starting with ... */ 48589857Sobrien afptr = autofilter_symbolprefixlist; 48689857Sobrien while (afptr->name) 48789857Sobrien { 48889857Sobrien if (strncmp (n, afptr->name, afptr->len) == 0) 48989857Sobrien return 0; 49089857Sobrien 491104834Sobrien afptr++; 49289857Sobrien } 49389857Sobrien 49489857Sobrien /* Finally, exclude symbols ending with ... */ 49589857Sobrien len = strlen (n); 49689857Sobrien afptr = autofilter_symbolsuffixlist; 49789857Sobrien while (afptr->name) 49889857Sobrien { 499104834Sobrien if ((len >= afptr->len) 50089857Sobrien /* Add 1 to insure match with trailing '\0'. */ 501104834Sobrien && strncmp (n + len - afptr->len, afptr->name, 502104834Sobrien afptr->len + 1) == 0) 50389857Sobrien return 0; 50489857Sobrien 505104834Sobrien afptr++; 50689857Sobrien } 50760484Sobrien } 50889857Sobrien 50960484Sobrien for (ex = excludes; ex; ex = ex->next) 510104834Sobrien { 511104834Sobrien if (ex->type == 1) /* exclude-libs */ 512104834Sobrien { 513104834Sobrien if (libname 514104834Sobrien && ((strcmp (libname, ex->string) == 0) 515104834Sobrien || (strcasecmp ("ALL", ex->string) == 0))) 516104834Sobrien return 0; 517104834Sobrien } 518104834Sobrien else if (strcmp (n, ex->string) == 0) 519104834Sobrien return 0; 520104834Sobrien } 52189857Sobrien 52260484Sobrien return 1; 52360484Sobrien} 52460484Sobrien 52560484Sobrienstatic void 52660484Sobrienprocess_def_file (abfd, info) 52760484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 52860484Sobrien struct bfd_link_info *info; 52960484Sobrien{ 53060484Sobrien int i, j; 53160484Sobrien struct bfd_link_hash_entry *blhe; 53260484Sobrien bfd *b; 53360484Sobrien struct sec *s; 53477298Sobrien def_file_export *e = 0; 53560484Sobrien 53660484Sobrien if (!pe_def_file) 53760484Sobrien pe_def_file = def_file_empty (); 53860484Sobrien 53960484Sobrien /* First, run around to all the objects looking for the .drectve 54077298Sobrien sections, and push those into the def file too. */ 54160484Sobrien for (b = info->input_bfds; b; b = b->link_next) 54260484Sobrien { 54360484Sobrien s = bfd_get_section_by_name (b, ".drectve"); 54460484Sobrien if (s) 54560484Sobrien { 54660484Sobrien int size = bfd_get_section_size_before_reloc (s); 54760484Sobrien char *buf = xmalloc (size); 54889857Sobrien 54960484Sobrien bfd_get_section_contents (b, s, buf, 0, size); 55060484Sobrien def_file_add_directive (pe_def_file, buf, size); 55160484Sobrien free (buf); 55260484Sobrien } 55360484Sobrien } 55460484Sobrien 55577298Sobrien /* Now, maybe export everything else the default way. */ 55660484Sobrien if (pe_dll_export_everything || pe_def_file->num_exports == 0) 55760484Sobrien { 55860484Sobrien for (b = info->input_bfds; b; b = b->link_next) 55960484Sobrien { 56060484Sobrien asymbol **symbols; 56160484Sobrien int nsyms, symsize; 56260484Sobrien 56360484Sobrien symsize = bfd_get_symtab_upper_bound (b); 56460484Sobrien symbols = (asymbol **) xmalloc (symsize); 56560484Sobrien nsyms = bfd_canonicalize_symtab (b, symbols); 56660484Sobrien 56760484Sobrien for (j = 0; j < nsyms; j++) 56860484Sobrien { 56977298Sobrien /* We should export symbols which are either global or not 57089857Sobrien anything at all. (.bss data is the latter) 57189857Sobrien We should not export undefined symbols. */ 57289857Sobrien if (symbols[j]->section != &bfd_und_section 57389857Sobrien && ((symbols[j]->flags & BSF_GLOBAL) 57489857Sobrien || (symbols[j]->flags == BFD_FORT_COMM_DEFAULT_VALUE))) 57560484Sobrien { 57660484Sobrien const char *sn = symbols[j]->name; 57789857Sobrien 57889857Sobrien /* We should not re-export imported stuff. */ 57989857Sobrien { 58089857Sobrien char *name = (char *) xmalloc (strlen (sn) + 2 + 6); 58189857Sobrien sprintf (name, "%s%s", U("_imp_"), sn); 58289857Sobrien 58389857Sobrien blhe = bfd_link_hash_lookup (info->hash, name, 584104834Sobrien false, false, false); 58589857Sobrien free (name); 58689857Sobrien 587104834Sobrien if (blhe && blhe->type == bfd_link_hash_defined) 58889857Sobrien continue; 58989857Sobrien } 59089857Sobrien 59160484Sobrien if (*sn == '_') 59260484Sobrien sn++; 59389857Sobrien 59489857Sobrien if (auto_export (b, pe_def_file, sn)) 59589857Sobrien { 59689857Sobrien def_file_export *p; 59789857Sobrien p=def_file_add_export (pe_def_file, sn, 0, -1); 59889857Sobrien /* Fill data flag properly, from dlltool.c. */ 59989857Sobrien p->flag_data = !(symbols[j]->flags & BSF_FUNCTION); 60089857Sobrien } 60160484Sobrien } 60260484Sobrien } 60360484Sobrien } 60460484Sobrien } 60560484Sobrien 60660484Sobrien#undef NE 60760484Sobrien#define NE pe_def_file->num_exports 60860484Sobrien 60977298Sobrien /* Canonicalize the export list. */ 61060484Sobrien if (pe_dll_kill_ats) 61160484Sobrien { 61260484Sobrien for (i = 0; i < NE; i++) 61360484Sobrien { 61460484Sobrien if (strchr (pe_def_file->exports[i].name, '@')) 61560484Sobrien { 61677298Sobrien /* This will preserve internal_name, which may have been 61777298Sobrien pointing to the same memory as name, or might not 61877298Sobrien have. */ 61960484Sobrien char *tmp = xstrdup (pe_def_file->exports[i].name); 62089857Sobrien 62160484Sobrien *(strchr (tmp, '@')) = 0; 62260484Sobrien pe_def_file->exports[i].name = tmp; 62360484Sobrien } 62460484Sobrien } 62560484Sobrien } 62660484Sobrien 62760484Sobrien if (pe_dll_stdcall_aliases) 62860484Sobrien { 62960484Sobrien for (i = 0; i < NE; i++) 63060484Sobrien { 63160484Sobrien if (strchr (pe_def_file->exports[i].name, '@')) 63260484Sobrien { 63360484Sobrien char *tmp = xstrdup (pe_def_file->exports[i].name); 63489857Sobrien 63560484Sobrien *(strchr (tmp, '@')) = 0; 63689857Sobrien if (auto_export (NULL, pe_def_file, tmp)) 63760484Sobrien def_file_add_export (pe_def_file, tmp, 63889857Sobrien pe_def_file->exports[i].internal_name, 63989857Sobrien -1); 64060484Sobrien else 64160484Sobrien free (tmp); 64260484Sobrien } 64360484Sobrien } 64460484Sobrien } 64560484Sobrien 64677298Sobrien /* Convenience, but watch out for it changing. */ 64777298Sobrien e = pe_def_file->exports; 64860484Sobrien 64960484Sobrien exported_symbol_offsets = (bfd_vma *) xmalloc (NE * sizeof (bfd_vma)); 65060484Sobrien exported_symbol_sections = (struct sec **) xmalloc (NE * sizeof (struct sec *)); 65160484Sobrien 65260484Sobrien memset (exported_symbol_sections, 0, NE * sizeof (struct sec *)); 65360484Sobrien max_ordinal = 0; 65460484Sobrien min_ordinal = 65536; 65560484Sobrien count_exported = 0; 65660484Sobrien count_exported_byname = 0; 65760484Sobrien count_with_ordinals = 0; 65860484Sobrien 65960484Sobrien qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]), pe_export_sort); 66060484Sobrien for (i = 0, j = 0; i < NE; i++) 66160484Sobrien { 66260484Sobrien if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0) 66360484Sobrien { 66460484Sobrien /* This is a duplicate. */ 66560484Sobrien if (e[j - 1].ordinal != -1 66660484Sobrien && e[i].ordinal != -1 66760484Sobrien && e[j - 1].ordinal != e[i].ordinal) 66860484Sobrien { 66960484Sobrien if (pe_dll_warn_dup_exports) 67060484Sobrien /* xgettext:c-format */ 67177298Sobrien einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"), 67260484Sobrien e[j - 1].name, e[j - 1].ordinal, e[i].ordinal); 67360484Sobrien } 67460484Sobrien else 67560484Sobrien { 67660484Sobrien if (pe_dll_warn_dup_exports) 67760484Sobrien /* xgettext:c-format */ 67860484Sobrien einfo (_("Warning, duplicate EXPORT: %s\n"), 67960484Sobrien e[j - 1].name); 68060484Sobrien } 68189857Sobrien 68277298Sobrien if (e[i].ordinal != -1) 68360484Sobrien e[j - 1].ordinal = e[i].ordinal; 68460484Sobrien e[j - 1].flag_private |= e[i].flag_private; 68560484Sobrien e[j - 1].flag_constant |= e[i].flag_constant; 68660484Sobrien e[j - 1].flag_noname |= e[i].flag_noname; 68760484Sobrien e[j - 1].flag_data |= e[i].flag_data; 68860484Sobrien } 68960484Sobrien else 69060484Sobrien { 69160484Sobrien if (i != j) 69260484Sobrien e[j] = e[i]; 69360484Sobrien j++; 69460484Sobrien } 69560484Sobrien } 69660484Sobrien pe_def_file->num_exports = j; /* == NE */ 69760484Sobrien 69860484Sobrien for (i = 0; i < NE; i++) 69960484Sobrien { 70060484Sobrien char *name = (char *) xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); 70189857Sobrien 70260484Sobrien if (pe_details->underscored) 70360484Sobrien { 70460484Sobrien *name = '_'; 70560484Sobrien strcpy (name + 1, pe_def_file->exports[i].internal_name); 70660484Sobrien } 70760484Sobrien else 70860484Sobrien strcpy (name, pe_def_file->exports[i].internal_name); 70960484Sobrien 71060484Sobrien blhe = bfd_link_hash_lookup (info->hash, 71160484Sobrien name, 71260484Sobrien false, false, true); 71360484Sobrien 71460484Sobrien if (blhe 71577298Sobrien && (blhe->type == bfd_link_hash_defined 71660484Sobrien || (blhe->type == bfd_link_hash_common))) 71760484Sobrien { 71860484Sobrien count_exported++; 71960484Sobrien if (!pe_def_file->exports[i].flag_noname) 72060484Sobrien count_exported_byname++; 72160484Sobrien 72260484Sobrien /* Only fill in the sections. The actual offsets are computed 72360484Sobrien in fill_exported_offsets() after common symbols are laid 72460484Sobrien out. */ 72577298Sobrien if (blhe->type == bfd_link_hash_defined) 72660484Sobrien exported_symbol_sections[i] = blhe->u.def.section; 72760484Sobrien else 72860484Sobrien exported_symbol_sections[i] = blhe->u.c.p->section; 72977298Sobrien 73060484Sobrien if (pe_def_file->exports[i].ordinal != -1) 73160484Sobrien { 73260484Sobrien if (max_ordinal < pe_def_file->exports[i].ordinal) 73360484Sobrien max_ordinal = pe_def_file->exports[i].ordinal; 73460484Sobrien if (min_ordinal > pe_def_file->exports[i].ordinal) 73560484Sobrien min_ordinal = pe_def_file->exports[i].ordinal; 73660484Sobrien count_with_ordinals++; 73760484Sobrien } 73860484Sobrien } 73960484Sobrien else if (blhe && blhe->type == bfd_link_hash_undefined) 74060484Sobrien { 74160484Sobrien /* xgettext:c-format */ 74260484Sobrien einfo (_("%XCannot export %s: symbol not defined\n"), 74360484Sobrien pe_def_file->exports[i].internal_name); 74460484Sobrien } 74560484Sobrien else if (blhe) 74660484Sobrien { 74760484Sobrien /* xgettext:c-format */ 74860484Sobrien einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"), 74960484Sobrien pe_def_file->exports[i].internal_name, 75060484Sobrien blhe->type, bfd_link_hash_defined); 75160484Sobrien } 75260484Sobrien else 75360484Sobrien { 75460484Sobrien /* xgettext:c-format */ 75560484Sobrien einfo (_("%XCannot export %s: symbol not found\n"), 75660484Sobrien pe_def_file->exports[i].internal_name); 75760484Sobrien } 75860484Sobrien free (name); 75960484Sobrien } 76060484Sobrien} 76160484Sobrien 76289857Sobrien/* Build the bfd that will contain .edata and .reloc sections. */ 76360484Sobrien 76460484Sobrienstatic void 76560484Sobrienbuild_filler_bfd (include_edata) 76660484Sobrien int include_edata; 76760484Sobrien{ 76860484Sobrien lang_input_statement_type *filler_file; 76960484Sobrien filler_file = lang_add_input_file ("dll stuff", 77060484Sobrien lang_input_file_is_fake_enum, 77160484Sobrien NULL); 77260484Sobrien filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", output_bfd); 77360484Sobrien if (filler_bfd == NULL 77460484Sobrien || !bfd_set_arch_mach (filler_bfd, 77560484Sobrien bfd_get_arch (output_bfd), 77660484Sobrien bfd_get_mach (output_bfd))) 77760484Sobrien { 77860484Sobrien einfo ("%X%P: can not create BFD %E\n"); 77960484Sobrien return; 78060484Sobrien } 78160484Sobrien 78260484Sobrien if (include_edata) 78360484Sobrien { 78460484Sobrien edata_s = bfd_make_section_old_way (filler_bfd, ".edata"); 78560484Sobrien if (edata_s == NULL 78660484Sobrien || !bfd_set_section_flags (filler_bfd, edata_s, 78760484Sobrien (SEC_HAS_CONTENTS 78860484Sobrien | SEC_ALLOC 78960484Sobrien | SEC_LOAD 79060484Sobrien | SEC_KEEP 79160484Sobrien | SEC_IN_MEMORY))) 79260484Sobrien { 79360484Sobrien einfo ("%X%P: can not create .edata section: %E\n"); 79460484Sobrien return; 79560484Sobrien } 79660484Sobrien bfd_set_section_size (filler_bfd, edata_s, edata_sz); 79760484Sobrien } 79860484Sobrien 79960484Sobrien reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc"); 80060484Sobrien if (reloc_s == NULL 80160484Sobrien || !bfd_set_section_flags (filler_bfd, reloc_s, 80260484Sobrien (SEC_HAS_CONTENTS 80360484Sobrien | SEC_ALLOC 80460484Sobrien | SEC_LOAD 80560484Sobrien | SEC_KEEP 80660484Sobrien | SEC_IN_MEMORY))) 80760484Sobrien { 80860484Sobrien einfo ("%X%P: can not create .reloc section: %E\n"); 80960484Sobrien return; 81060484Sobrien } 81189857Sobrien 81260484Sobrien bfd_set_section_size (filler_bfd, reloc_s, 0); 81360484Sobrien 81460484Sobrien ldlang_add_file (filler_file); 81560484Sobrien} 81660484Sobrien 81789857Sobrien/* Gather all the exported symbols and build the .edata section. */ 81860484Sobrien 81960484Sobrienstatic void 82060484Sobriengenerate_edata (abfd, info) 82160484Sobrien bfd *abfd; 82260484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 82360484Sobrien{ 82460484Sobrien int i, next_ordinal; 82560484Sobrien int name_table_size = 0; 82660484Sobrien const char *dlnp; 82760484Sobrien 82860484Sobrien /* First, we need to know how many exported symbols there are, 82977298Sobrien and what the range of ordinals is. */ 83060484Sobrien if (pe_def_file->name) 83189857Sobrien dll_name = pe_def_file->name; 83260484Sobrien else 83360484Sobrien { 83460484Sobrien dll_name = abfd->filename; 83589857Sobrien 83660484Sobrien for (dlnp = dll_name; *dlnp; dlnp++) 83789857Sobrien if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':') 83889857Sobrien dll_name = dlnp + 1; 83960484Sobrien } 84060484Sobrien 84160484Sobrien if (count_with_ordinals && max_ordinal > count_exported) 84260484Sobrien { 84360484Sobrien if (min_ordinal > max_ordinal - count_exported + 1) 84460484Sobrien min_ordinal = max_ordinal - count_exported + 1; 84560484Sobrien } 84660484Sobrien else 84760484Sobrien { 84860484Sobrien min_ordinal = 1; 84960484Sobrien max_ordinal = count_exported; 85060484Sobrien } 85189857Sobrien 85260484Sobrien export_table_size = max_ordinal - min_ordinal + 1; 85360484Sobrien exported_symbols = (int *) xmalloc (export_table_size * sizeof (int)); 85460484Sobrien for (i = 0; i < export_table_size; i++) 85560484Sobrien exported_symbols[i] = -1; 85660484Sobrien 85777298Sobrien /* Now we need to assign ordinals to those that don't have them. */ 85860484Sobrien for (i = 0; i < NE; i++) 85960484Sobrien { 86060484Sobrien if (exported_symbol_sections[i]) 86160484Sobrien { 86260484Sobrien if (pe_def_file->exports[i].ordinal != -1) 86360484Sobrien { 86460484Sobrien int ei = pe_def_file->exports[i].ordinal - min_ordinal; 86560484Sobrien int pi = exported_symbols[ei]; 86689857Sobrien 86760484Sobrien if (pi != -1) 86860484Sobrien { 86960484Sobrien /* xgettext:c-format */ 87077298Sobrien einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"), 87160484Sobrien pe_def_file->exports[i].ordinal, 87260484Sobrien pe_def_file->exports[i].name, 87360484Sobrien pe_def_file->exports[pi].name); 87460484Sobrien } 87560484Sobrien exported_symbols[ei] = i; 87660484Sobrien } 87760484Sobrien name_table_size += strlen (pe_def_file->exports[i].name) + 1; 87860484Sobrien } 87960484Sobrien } 88060484Sobrien 88160484Sobrien next_ordinal = min_ordinal; 88260484Sobrien for (i = 0; i < NE; i++) 88360484Sobrien if (exported_symbol_sections[i]) 88460484Sobrien if (pe_def_file->exports[i].ordinal == -1) 88560484Sobrien { 88660484Sobrien while (exported_symbols[next_ordinal - min_ordinal] != -1) 887104834Sobrien next_ordinal++; 88889857Sobrien 88960484Sobrien exported_symbols[next_ordinal - min_ordinal] = i; 89060484Sobrien pe_def_file->exports[i].ordinal = next_ordinal; 89160484Sobrien } 89260484Sobrien 89377298Sobrien /* OK, now we can allocate some memory. */ 89489857Sobrien edata_sz = (40 /* directory */ 89589857Sobrien + 4 * export_table_size /* addresses */ 89660484Sobrien + 4 * count_exported_byname /* name ptrs */ 89760484Sobrien + 2 * count_exported_byname /* ordinals */ 89860484Sobrien + name_table_size + strlen (dll_name) + 1); 89960484Sobrien} 90060484Sobrien 90160484Sobrien/* Fill the exported symbol offsets. The preliminary work has already 90260484Sobrien been done in process_def_file(). */ 90360484Sobrien 90460484Sobrienstatic void 90560484Sobrienfill_exported_offsets (abfd, info) 90660484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 90760484Sobrien struct bfd_link_info *info; 90860484Sobrien{ 90960484Sobrien int i; 91060484Sobrien struct bfd_link_hash_entry *blhe; 91177298Sobrien 91260484Sobrien for (i = 0; i < pe_def_file->num_exports; i++) 91360484Sobrien { 91460484Sobrien char *name = (char *) xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); 91589857Sobrien 91660484Sobrien if (pe_details->underscored) 91760484Sobrien { 91860484Sobrien *name = '_'; 91960484Sobrien strcpy (name + 1, pe_def_file->exports[i].internal_name); 92060484Sobrien } 92160484Sobrien else 92260484Sobrien strcpy (name, pe_def_file->exports[i].internal_name); 92360484Sobrien 92460484Sobrien blhe = bfd_link_hash_lookup (info->hash, 92560484Sobrien name, 92660484Sobrien false, false, true); 92760484Sobrien 92860484Sobrien if (blhe && (blhe->type == bfd_link_hash_defined)) 92989857Sobrien exported_symbol_offsets[i] = blhe->u.def.value; 93089857Sobrien 93160484Sobrien free (name); 93260484Sobrien } 93360484Sobrien} 93460484Sobrien 93560484Sobrienstatic void 93660484Sobrienfill_edata (abfd, info) 93760484Sobrien bfd *abfd; 93860484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 93960484Sobrien{ 94060484Sobrien int i, hint; 94160484Sobrien unsigned char *edirectory; 94260484Sobrien unsigned long *eaddresses; 94360484Sobrien unsigned long *enameptrs; 94460484Sobrien unsigned short *eordinals; 94560484Sobrien unsigned char *enamestr; 94660484Sobrien time_t now; 94760484Sobrien 94860484Sobrien time (&now); 94960484Sobrien 95060484Sobrien edata_d = (unsigned char *) xmalloc (edata_sz); 95160484Sobrien 95277298Sobrien /* Note use of array pointer math here. */ 95360484Sobrien edirectory = edata_d; 95460484Sobrien eaddresses = (unsigned long *) (edata_d + 40); 95560484Sobrien enameptrs = eaddresses + export_table_size; 95660484Sobrien eordinals = (unsigned short *) (enameptrs + count_exported_byname); 95760484Sobrien enamestr = (char *) (eordinals + count_exported_byname); 95860484Sobrien 95960484Sobrien#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) + edata_s->output_section->vma - image_base) 96060484Sobrien 96177298Sobrien memset (edata_d, 0, edata_sz); 96260484Sobrien bfd_put_32 (abfd, now, edata_d + 4); 96360484Sobrien if (pe_def_file->version_major != -1) 96460484Sobrien { 96560484Sobrien bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8); 96660484Sobrien bfd_put_16 (abfd, pe_def_file->version_minor, edata_d + 10); 96760484Sobrien } 96889857Sobrien 96960484Sobrien bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12); 97060484Sobrien strcpy (enamestr, dll_name); 97160484Sobrien enamestr += strlen (enamestr) + 1; 97260484Sobrien bfd_put_32 (abfd, min_ordinal, edata_d + 16); 97360484Sobrien bfd_put_32 (abfd, export_table_size, edata_d + 20); 97460484Sobrien bfd_put_32 (abfd, count_exported_byname, edata_d + 24); 97560484Sobrien bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28); 97660484Sobrien bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32); 97760484Sobrien bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36); 97860484Sobrien 97960484Sobrien fill_exported_offsets (abfd, info); 98060484Sobrien 98177298Sobrien /* Ok, now for the filling in part. */ 98260484Sobrien hint = 0; 98360484Sobrien for (i = 0; i < export_table_size; i++) 98460484Sobrien { 98560484Sobrien int s = exported_symbols[i]; 98689857Sobrien 98760484Sobrien if (s != -1) 98860484Sobrien { 98960484Sobrien struct sec *ssec = exported_symbol_sections[s]; 99060484Sobrien unsigned long srva = (exported_symbol_offsets[s] 99160484Sobrien + ssec->output_section->vma 99260484Sobrien + ssec->output_offset); 99377298Sobrien int ord = pe_def_file->exports[s].ordinal; 99460484Sobrien 99577298Sobrien bfd_put_32 (abfd, srva - image_base, 99677298Sobrien (void *) (eaddresses + ord - min_ordinal)); 99789857Sobrien 99860484Sobrien if (!pe_def_file->exports[s].flag_noname) 99960484Sobrien { 100060484Sobrien char *ename = pe_def_file->exports[s].name; 100160484Sobrien bfd_put_32 (abfd, ERVA (enamestr), (void *) enameptrs); 100277298Sobrien enameptrs++; 100360484Sobrien strcpy (enamestr, ename); 100460484Sobrien enamestr += strlen (enamestr) + 1; 100577298Sobrien bfd_put_16 (abfd, ord - min_ordinal, (void *) eordinals); 100677298Sobrien eordinals++; 100760484Sobrien pe_def_file->exports[s].hint = hint++; 100860484Sobrien } 100960484Sobrien } 101060484Sobrien } 101160484Sobrien} 101260484Sobrien 101360484Sobrien 101489857Sobrienstatic struct sec *current_sec; 101560484Sobrien 101689857Sobrienvoid 101789857Sobrienpe_walk_relocs_of_symbol (info, name, cb) 101889857Sobrien struct bfd_link_info *info; 101989857Sobrien const char *name; 102089857Sobrien int (*cb) (arelent *, asection *); 102189857Sobrien{ 102289857Sobrien bfd *b; 102389857Sobrien asection *s; 102460484Sobrien 102589857Sobrien for (b = info->input_bfds; b; b = b->link_next) 102689857Sobrien { 102789857Sobrien asymbol **symbols; 102889857Sobrien int nsyms, symsize; 102989857Sobrien 103089857Sobrien symsize = bfd_get_symtab_upper_bound (b); 103189857Sobrien symbols = (asymbol **) xmalloc (symsize); 103289857Sobrien nsyms = bfd_canonicalize_symtab (b, symbols); 103389857Sobrien 103489857Sobrien for (s = b->sections; s; s = s->next) 103589857Sobrien { 103689857Sobrien arelent **relocs; 103789857Sobrien int relsize, nrelocs, i; 103889857Sobrien int flags = bfd_get_section_flags (b, s); 103989857Sobrien 104089857Sobrien /* Skip discarded linkonce sections. */ 104189857Sobrien if (flags & SEC_LINK_ONCE 104289857Sobrien && s->output_section == bfd_abs_section_ptr) 104389857Sobrien continue; 104489857Sobrien 104589857Sobrien current_sec = s; 104689857Sobrien 104789857Sobrien relsize = bfd_get_reloc_upper_bound (b, s); 104889857Sobrien relocs = (arelent **) xmalloc ((size_t) relsize); 104989857Sobrien nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols); 105089857Sobrien 105189857Sobrien for (i = 0; i < nrelocs; i++) 105289857Sobrien { 105389857Sobrien struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr; 105489857Sobrien 105589857Sobrien if (!strcmp (name, sym->name)) 105689857Sobrien cb (relocs[i], s); 105789857Sobrien } 105889857Sobrien 105989857Sobrien free (relocs); 106089857Sobrien 106189857Sobrien /* Warning: the allocated symbols are remembered in BFD and reused 106289857Sobrien later, so don't free them! */ 106389857Sobrien /* free (symbols); */ 106489857Sobrien } 106589857Sobrien } 106689857Sobrien} 106789857Sobrien 106889857Sobrien/* Gather all the relocations and build the .reloc section. */ 106989857Sobrien 107060484Sobrienstatic void 107160484Sobriengenerate_reloc (abfd, info) 107260484Sobrien bfd *abfd; 107360484Sobrien struct bfd_link_info *info; 107460484Sobrien{ 107560484Sobrien 107677298Sobrien /* For .reloc stuff. */ 107760484Sobrien reloc_data_type *reloc_data; 107860484Sobrien int total_relocs = 0; 107960484Sobrien int i; 108060484Sobrien unsigned long sec_page = (unsigned long) (-1); 108160484Sobrien unsigned long page_ptr, page_count; 108260484Sobrien int bi; 108360484Sobrien bfd *b; 108460484Sobrien struct sec *s; 108560484Sobrien 108660484Sobrien total_relocs = 0; 108760484Sobrien for (b = info->input_bfds; b; b = b->link_next) 108860484Sobrien for (s = b->sections; s; s = s->next) 108960484Sobrien total_relocs += s->reloc_count; 109060484Sobrien 109189857Sobrien reloc_data = 109289857Sobrien (reloc_data_type *) xmalloc (total_relocs * sizeof (reloc_data_type)); 109360484Sobrien 109460484Sobrien total_relocs = 0; 109560484Sobrien bi = 0; 109660484Sobrien for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next) 109760484Sobrien { 109860484Sobrien arelent **relocs; 109960484Sobrien int relsize, nrelocs, i; 110060484Sobrien 110160484Sobrien for (s = b->sections; s; s = s->next) 110260484Sobrien { 110360484Sobrien unsigned long sec_vma = s->output_section->vma + s->output_offset; 110460484Sobrien asymbol **symbols; 110560484Sobrien int nsyms, symsize; 110660484Sobrien 110777298Sobrien /* If it's not loaded, we don't need to relocate it this way. */ 110860484Sobrien if (!(s->output_section->flags & SEC_LOAD)) 110960484Sobrien continue; 111060484Sobrien 111160484Sobrien /* I don't know why there would be a reloc for these, but I've 111277298Sobrien seen it happen - DJ */ 111360484Sobrien if (s->output_section == &bfd_abs_section) 111460484Sobrien continue; 111560484Sobrien 111660484Sobrien if (s->output_section->vma == 0) 111760484Sobrien { 111877298Sobrien /* Huh? Shouldn't happen, but punt if it does. */ 111960484Sobrien einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n", 112060484Sobrien s->output_section->name, s->output_section->index, 112160484Sobrien s->output_section->flags); 112260484Sobrien continue; 112360484Sobrien } 112460484Sobrien 112560484Sobrien symsize = bfd_get_symtab_upper_bound (b); 112660484Sobrien symbols = (asymbol **) xmalloc (symsize); 112760484Sobrien nsyms = bfd_canonicalize_symtab (b, symbols); 112860484Sobrien 112960484Sobrien relsize = bfd_get_reloc_upper_bound (b, s); 113060484Sobrien relocs = (arelent **) xmalloc ((size_t) relsize); 113160484Sobrien nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols); 113260484Sobrien 113360484Sobrien for (i = 0; i < nrelocs; i++) 113460484Sobrien { 113589857Sobrien if (pe_dll_extra_pe_debug) 1136104834Sobrien { 113789857Sobrien struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr; 1138104834Sobrien printf ("rel: %s\n", sym->name); 113989857Sobrien } 114060484Sobrien if (!relocs[i]->howto->pc_relative 114160484Sobrien && relocs[i]->howto->type != pe_details->imagebase_reloc) 114260484Sobrien { 114360484Sobrien bfd_vma sym_vma; 114460484Sobrien struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr; 114589857Sobrien 114660484Sobrien sym_vma = (relocs[i]->addend 114760484Sobrien + sym->value 114860484Sobrien + sym->section->vma 114960484Sobrien + sym->section->output_offset 115060484Sobrien + sym->section->output_section->vma); 115160484Sobrien reloc_data[total_relocs].vma = sec_vma + relocs[i]->address; 115277298Sobrien 115360484Sobrien#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift) 115477298Sobrien 115560484Sobrien switch BITS_AND_SHIFT (relocs[i]->howto->bitsize, 115660484Sobrien relocs[i]->howto->rightshift) 115760484Sobrien { 115860484Sobrien case BITS_AND_SHIFT (32, 0): 115960484Sobrien reloc_data[total_relocs].type = 3; 116060484Sobrien total_relocs++; 116160484Sobrien break; 116260484Sobrien case BITS_AND_SHIFT (16, 0): 116360484Sobrien reloc_data[total_relocs].type = 2; 116460484Sobrien total_relocs++; 116560484Sobrien break; 116660484Sobrien case BITS_AND_SHIFT (16, 16): 116760484Sobrien reloc_data[total_relocs].type = 4; 116877298Sobrien /* FIXME: we can't know the symbol's right value 116977298Sobrien yet, but we probably can safely assume that 117077298Sobrien CE will relocate us in 64k blocks, so leaving 117177298Sobrien it zero is safe. */ 117260484Sobrien reloc_data[total_relocs].extra = 0; 117360484Sobrien total_relocs++; 117460484Sobrien break; 117560484Sobrien case BITS_AND_SHIFT (26, 2): 117660484Sobrien reloc_data[total_relocs].type = 5; 117760484Sobrien total_relocs++; 117860484Sobrien break; 117960484Sobrien default: 118060484Sobrien /* xgettext:c-format */ 118160484Sobrien einfo (_("%XError: %d-bit reloc in dll\n"), 118260484Sobrien relocs[i]->howto->bitsize); 118360484Sobrien break; 118460484Sobrien } 118560484Sobrien } 118660484Sobrien } 118760484Sobrien free (relocs); 118877298Sobrien /* Warning: the allocated symbols are remembered in BFD and 118977298Sobrien reused later, so don't free them! */ 119077298Sobrien#if 0 119177298Sobrien free (symbol); 119277298Sobrien#endif 119360484Sobrien } 119460484Sobrien } 119560484Sobrien 119660484Sobrien /* At this point, we have total_relocs relocation addresses in 119760484Sobrien reloc_addresses, which are all suitable for the .reloc section. 119877298Sobrien We must now create the new sections. */ 119960484Sobrien qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort); 120060484Sobrien 120160484Sobrien for (i = 0; i < total_relocs; i++) 120260484Sobrien { 120360484Sobrien unsigned long this_page = (reloc_data[i].vma >> 12); 120477298Sobrien 120560484Sobrien if (this_page != sec_page) 120660484Sobrien { 120789857Sobrien reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */ 120860484Sobrien reloc_sz += 8; 120960484Sobrien sec_page = this_page; 121060484Sobrien } 121177298Sobrien 121260484Sobrien reloc_sz += 2; 121377298Sobrien 121460484Sobrien if (reloc_data[i].type == 4) 121560484Sobrien reloc_sz += 2; 121660484Sobrien } 1217104834Sobrien 121889857Sobrien reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */ 121960484Sobrien reloc_d = (unsigned char *) xmalloc (reloc_sz); 122060484Sobrien sec_page = (unsigned long) (-1); 122160484Sobrien reloc_sz = 0; 122260484Sobrien page_ptr = (unsigned long) (-1); 122360484Sobrien page_count = 0; 122489857Sobrien 122560484Sobrien for (i = 0; i < total_relocs; i++) 122660484Sobrien { 122760484Sobrien unsigned long rva = reloc_data[i].vma - image_base; 122860484Sobrien unsigned long this_page = (rva & ~0xfff); 122989857Sobrien 123060484Sobrien if (this_page != sec_page) 123160484Sobrien { 123260484Sobrien while (reloc_sz & 3) 123360484Sobrien reloc_d[reloc_sz++] = 0; 123489857Sobrien 123560484Sobrien if (page_ptr != (unsigned long) (-1)) 123660484Sobrien bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4); 123789857Sobrien 123860484Sobrien bfd_put_32 (abfd, this_page, reloc_d + reloc_sz); 123960484Sobrien page_ptr = reloc_sz; 124060484Sobrien reloc_sz += 8; 124160484Sobrien sec_page = this_page; 124260484Sobrien page_count = 0; 124360484Sobrien } 124489857Sobrien 124577298Sobrien bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12), 124660484Sobrien reloc_d + reloc_sz); 124760484Sobrien reloc_sz += 2; 124889857Sobrien 124960484Sobrien if (reloc_data[i].type == 4) 125060484Sobrien { 125160484Sobrien bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz); 125260484Sobrien reloc_sz += 2; 125360484Sobrien } 125489857Sobrien 125560484Sobrien page_count++; 125660484Sobrien } 125789857Sobrien 125860484Sobrien while (reloc_sz & 3) 125960484Sobrien reloc_d[reloc_sz++] = 0; 126089857Sobrien 126160484Sobrien if (page_ptr != (unsigned long) (-1)) 126260484Sobrien bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4); 126389857Sobrien 126460484Sobrien while (reloc_sz < reloc_s->_raw_size) 126560484Sobrien reloc_d[reloc_sz++] = 0; 126660484Sobrien} 126760484Sobrien 126889857Sobrien/* Given the exiting def_file structure, print out a .DEF file that 126989857Sobrien corresponds to it. */ 127060484Sobrien 127160484Sobrienstatic void 127260484Sobrienquoteput (s, f, needs_quotes) 127360484Sobrien char *s; 127477298Sobrien FILE *f; 127560484Sobrien int needs_quotes; 127660484Sobrien{ 127760484Sobrien char *cp; 127889857Sobrien 127960484Sobrien for (cp = s; *cp; cp++) 128060484Sobrien if (*cp == '\'' 128160484Sobrien || *cp == '"' 128260484Sobrien || *cp == '\\' 128389857Sobrien || ISSPACE (*cp) 128460484Sobrien || *cp == ',' 128560484Sobrien || *cp == ';') 128660484Sobrien needs_quotes = 1; 128789857Sobrien 128860484Sobrien if (needs_quotes) 128960484Sobrien { 129060484Sobrien putc ('"', f); 129189857Sobrien 129260484Sobrien while (*s) 129360484Sobrien { 129460484Sobrien if (*s == '"' || *s == '\\') 129560484Sobrien putc ('\\', f); 129689857Sobrien 129760484Sobrien putc (*s, f); 129860484Sobrien s++; 129960484Sobrien } 130089857Sobrien 130160484Sobrien putc ('"', f); 130260484Sobrien } 130360484Sobrien else 130460484Sobrien fputs (s, f); 130560484Sobrien} 130660484Sobrien 130760484Sobrienvoid 130860484Sobrienpe_dll_generate_def_file (pe_out_def_filename) 130960484Sobrien const char *pe_out_def_filename; 131060484Sobrien{ 131160484Sobrien int i; 131260484Sobrien FILE *out = fopen (pe_out_def_filename, "w"); 131389857Sobrien 131460484Sobrien if (out == NULL) 131589857Sobrien /* xgettext:c-format */ 131689857Sobrien einfo (_("%s: Can't open output def file %s\n"), 131789857Sobrien program_name, pe_out_def_filename); 131860484Sobrien 131960484Sobrien if (pe_def_file) 132060484Sobrien { 132160484Sobrien if (pe_def_file->name) 132260484Sobrien { 132360484Sobrien if (pe_def_file->is_dll) 132460484Sobrien fprintf (out, "LIBRARY "); 132560484Sobrien else 132660484Sobrien fprintf (out, "NAME "); 132789857Sobrien 132860484Sobrien quoteput (pe_def_file->name, out, 1); 132989857Sobrien 133060484Sobrien if (pe_data (output_bfd)->pe_opthdr.ImageBase) 133160484Sobrien fprintf (out, " BASE=0x%lx", 133260484Sobrien (unsigned long) pe_data (output_bfd)->pe_opthdr.ImageBase); 133360484Sobrien fprintf (out, "\n"); 133460484Sobrien } 133560484Sobrien 133660484Sobrien if (pe_def_file->description) 133760484Sobrien { 133860484Sobrien fprintf (out, "DESCRIPTION "); 133960484Sobrien quoteput (pe_def_file->description, out, 1); 134060484Sobrien fprintf (out, "\n"); 134160484Sobrien } 134260484Sobrien 134360484Sobrien if (pe_def_file->version_minor != -1) 134460484Sobrien fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major, 134560484Sobrien pe_def_file->version_minor); 134660484Sobrien else if (pe_def_file->version_major != -1) 134760484Sobrien fprintf (out, "VERSION %d\n", pe_def_file->version_major); 134860484Sobrien 134960484Sobrien if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1) 135060484Sobrien fprintf (out, "\n"); 135160484Sobrien 135260484Sobrien if (pe_def_file->stack_commit != -1) 135360484Sobrien fprintf (out, "STACKSIZE 0x%x,0x%x\n", 135460484Sobrien pe_def_file->stack_reserve, pe_def_file->stack_commit); 135560484Sobrien else if (pe_def_file->stack_reserve != -1) 135660484Sobrien fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve); 135789857Sobrien 135860484Sobrien if (pe_def_file->heap_commit != -1) 135960484Sobrien fprintf (out, "HEAPSIZE 0x%x,0x%x\n", 136060484Sobrien pe_def_file->heap_reserve, pe_def_file->heap_commit); 136160484Sobrien else if (pe_def_file->heap_reserve != -1) 136260484Sobrien fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve); 136360484Sobrien 136460484Sobrien if (pe_def_file->num_section_defs > 0) 136560484Sobrien { 136660484Sobrien fprintf (out, "\nSECTIONS\n\n"); 136789857Sobrien 136860484Sobrien for (i = 0; i < pe_def_file->num_section_defs; i++) 136960484Sobrien { 137060484Sobrien fprintf (out, " "); 137160484Sobrien quoteput (pe_def_file->section_defs[i].name, out, 0); 137289857Sobrien 137360484Sobrien if (pe_def_file->section_defs[i].class) 137460484Sobrien { 137560484Sobrien fprintf (out, " CLASS "); 137660484Sobrien quoteput (pe_def_file->section_defs[i].class, out, 0); 137760484Sobrien } 137889857Sobrien 137960484Sobrien if (pe_def_file->section_defs[i].flag_read) 138060484Sobrien fprintf (out, " READ"); 138189857Sobrien 138260484Sobrien if (pe_def_file->section_defs[i].flag_write) 138360484Sobrien fprintf (out, " WRITE"); 138489857Sobrien 138560484Sobrien if (pe_def_file->section_defs[i].flag_execute) 138660484Sobrien fprintf (out, " EXECUTE"); 138789857Sobrien 138860484Sobrien if (pe_def_file->section_defs[i].flag_shared) 138960484Sobrien fprintf (out, " SHARED"); 139089857Sobrien 139160484Sobrien fprintf (out, "\n"); 139260484Sobrien } 139360484Sobrien } 139460484Sobrien 139560484Sobrien if (pe_def_file->num_exports > 0) 139660484Sobrien { 139789857Sobrien fprintf (out, "EXPORTS\n"); 139889857Sobrien 139960484Sobrien for (i = 0; i < pe_def_file->num_exports; i++) 140060484Sobrien { 140160484Sobrien def_file_export *e = pe_def_file->exports + i; 140260484Sobrien fprintf (out, " "); 140360484Sobrien quoteput (e->name, out, 0); 140489857Sobrien 140560484Sobrien if (e->internal_name && strcmp (e->internal_name, e->name)) 140660484Sobrien { 140760484Sobrien fprintf (out, " = "); 140860484Sobrien quoteput (e->internal_name, out, 0); 140960484Sobrien } 141089857Sobrien 141160484Sobrien if (e->ordinal != -1) 141260484Sobrien fprintf (out, " @%d", e->ordinal); 141389857Sobrien 141460484Sobrien if (e->flag_private) 141560484Sobrien fprintf (out, " PRIVATE"); 141689857Sobrien 141760484Sobrien if (e->flag_constant) 141860484Sobrien fprintf (out, " CONSTANT"); 141989857Sobrien 142060484Sobrien if (e->flag_noname) 142160484Sobrien fprintf (out, " NONAME"); 142289857Sobrien 142360484Sobrien if (e->flag_data) 142460484Sobrien fprintf (out, " DATA"); 142560484Sobrien 142660484Sobrien fprintf (out, "\n"); 142760484Sobrien } 142860484Sobrien } 142960484Sobrien 143060484Sobrien if (pe_def_file->num_imports > 0) 143160484Sobrien { 143260484Sobrien fprintf (out, "\nIMPORTS\n\n"); 143389857Sobrien 143460484Sobrien for (i = 0; i < pe_def_file->num_imports; i++) 143560484Sobrien { 143660484Sobrien def_file_import *im = pe_def_file->imports + i; 143760484Sobrien fprintf (out, " "); 143889857Sobrien 143960484Sobrien if (im->internal_name 144060484Sobrien && (!im->name || strcmp (im->internal_name, im->name))) 144160484Sobrien { 144260484Sobrien quoteput (im->internal_name, out, 0); 144360484Sobrien fprintf (out, " = "); 144460484Sobrien } 144589857Sobrien 144660484Sobrien quoteput (im->module->name, out, 0); 144760484Sobrien fprintf (out, "."); 144889857Sobrien 144960484Sobrien if (im->name) 145060484Sobrien quoteput (im->name, out, 0); 145160484Sobrien else 145260484Sobrien fprintf (out, "%d", im->ordinal); 145389857Sobrien 145460484Sobrien fprintf (out, "\n"); 145560484Sobrien } 145660484Sobrien } 145760484Sobrien } 145860484Sobrien else 145960484Sobrien fprintf (out, _("; no contents available\n")); 146060484Sobrien 146160484Sobrien if (fclose (out) == EOF) 146289857Sobrien /* xgettext:c-format */ 146389857Sobrien einfo (_("%P: Error closing file `%s'\n"), pe_out_def_filename); 146460484Sobrien} 146560484Sobrien 146689857Sobrien/* Generate the import library. */ 146760484Sobrien 146860484Sobrienstatic asymbol **symtab; 146960484Sobrienstatic int symptr; 147060484Sobrienstatic int tmp_seq; 147160484Sobrienstatic const char *dll_filename; 147260484Sobrienstatic char *dll_symname; 147360484Sobrien 147460484Sobrien#define UNDSEC (asection *) &bfd_und_section 147560484Sobrien 147660484Sobrienstatic asection * 147777298Sobrienquick_section (abfd, name, flags, align) 147860484Sobrien bfd *abfd; 147960484Sobrien const char *name; 148060484Sobrien int flags; 148160484Sobrien int align; 148260484Sobrien{ 148360484Sobrien asection *sec; 148460484Sobrien asymbol *sym; 148560484Sobrien 148660484Sobrien sec = bfd_make_section_old_way (abfd, name); 148777298Sobrien bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP); 148860484Sobrien bfd_set_section_alignment (abfd, sec, align); 148977298Sobrien /* Remember to undo this before trying to link internally! */ 149060484Sobrien sec->output_section = sec; 149160484Sobrien 149260484Sobrien sym = bfd_make_empty_symbol (abfd); 149360484Sobrien symtab[symptr++] = sym; 149460484Sobrien sym->name = sec->name; 149560484Sobrien sym->section = sec; 149660484Sobrien sym->flags = BSF_LOCAL; 149760484Sobrien sym->value = 0; 149860484Sobrien 149960484Sobrien return sec; 150060484Sobrien} 150160484Sobrien 150260484Sobrienstatic void 150360484Sobrienquick_symbol (abfd, n1, n2, n3, sec, flags, addr) 150460484Sobrien bfd *abfd; 150589857Sobrien const char *n1; 150689857Sobrien const char *n2; 150789857Sobrien const char *n3; 150860484Sobrien asection *sec; 150960484Sobrien int flags; 151060484Sobrien int addr; 151160484Sobrien{ 151260484Sobrien asymbol *sym; 151360484Sobrien char *name = (char *) xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1); 151489857Sobrien 151560484Sobrien strcpy (name, n1); 151660484Sobrien strcat (name, n2); 151760484Sobrien strcat (name, n3); 151860484Sobrien sym = bfd_make_empty_symbol (abfd); 151960484Sobrien sym->name = name; 152060484Sobrien sym->section = sec; 152160484Sobrien sym->flags = flags; 152260484Sobrien sym->value = addr; 152360484Sobrien symtab[symptr++] = sym; 152460484Sobrien} 152560484Sobrien 152660484Sobrienstatic arelent *reltab = 0; 152760484Sobrienstatic int relcount = 0, relsize = 0; 152860484Sobrien 152960484Sobrienstatic void 153060484Sobrienquick_reloc (abfd, address, which_howto, symidx) 153160484Sobrien bfd *abfd; 153260484Sobrien int address; 153360484Sobrien int which_howto; 153460484Sobrien int symidx; 153560484Sobrien{ 153677298Sobrien if (relcount >= (relsize - 1)) 153760484Sobrien { 153860484Sobrien relsize += 10; 153960484Sobrien if (reltab) 154060484Sobrien reltab = (arelent *) xrealloc (reltab, relsize * sizeof (arelent)); 154160484Sobrien else 154260484Sobrien reltab = (arelent *) xmalloc (relsize * sizeof (arelent)); 154360484Sobrien } 154460484Sobrien reltab[relcount].address = address; 154560484Sobrien reltab[relcount].addend = 0; 154660484Sobrien reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto); 154760484Sobrien reltab[relcount].sym_ptr_ptr = symtab + symidx; 154860484Sobrien relcount++; 154960484Sobrien} 155060484Sobrien 155160484Sobrienstatic void 155260484Sobriensave_relocs (asection *sec) 155360484Sobrien{ 155460484Sobrien int i; 155589857Sobrien 155660484Sobrien sec->relocation = reltab; 155760484Sobrien sec->reloc_count = relcount; 155877298Sobrien sec->orelocation = (arelent **) xmalloc ((relcount + 1) * sizeof (arelent *)); 155977298Sobrien for (i = 0; i < relcount; i++) 156060484Sobrien sec->orelocation[i] = sec->relocation + i; 156160484Sobrien sec->orelocation[relcount] = 0; 156260484Sobrien sec->flags |= SEC_RELOC; 156360484Sobrien reltab = 0; 156460484Sobrien relcount = relsize = 0; 156560484Sobrien} 156660484Sobrien 156789857Sobrien/* .section .idata$2 156889857Sobrien .global __head_my_dll 156989857Sobrien __head_my_dll: 157089857Sobrien .rva hname 157189857Sobrien .long 0 157289857Sobrien .long 0 157389857Sobrien .rva __my_dll_iname 157489857Sobrien .rva fthunk 1575104834Sobrien 157689857Sobrien .section .idata$5 157789857Sobrien .long 0 157889857Sobrien fthunk: 1579104834Sobrien 158089857Sobrien .section .idata$4 158189857Sobrien .long 0 158289857Sobrien hname: */ 158360484Sobrien 158460484Sobrienstatic bfd * 158560484Sobrienmake_head (parent) 158660484Sobrien bfd *parent; 158760484Sobrien{ 158860484Sobrien asection *id2, *id5, *id4; 158960484Sobrien unsigned char *d2, *d5, *d4; 159060484Sobrien char *oname; 159160484Sobrien bfd *abfd; 159260484Sobrien 159360484Sobrien oname = (char *) xmalloc (20); 159460484Sobrien sprintf (oname, "d%06d.o", tmp_seq); 159560484Sobrien tmp_seq++; 159660484Sobrien 159760484Sobrien abfd = bfd_create (oname, parent); 159860484Sobrien bfd_find_target (pe_details->object_target, abfd); 159960484Sobrien bfd_make_writable (abfd); 160060484Sobrien 160160484Sobrien bfd_set_format (abfd, bfd_object); 160260484Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 160360484Sobrien 160460484Sobrien symptr = 0; 160560484Sobrien symtab = (asymbol **) xmalloc (6 * sizeof (asymbol *)); 160660484Sobrien id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2); 160760484Sobrien id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); 160860484Sobrien id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); 160977298Sobrien quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0); 161077298Sobrien quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0); 161160484Sobrien 161260484Sobrien /* OK, pay attention here. I got confused myself looking back at 161360484Sobrien it. We create a four-byte section to mark the beginning of the 161460484Sobrien list, and we include an offset of 4 in the section, so that the 161560484Sobrien pointer to the list points to the *end* of this section, which is 161677298Sobrien the start of the list of sections from other objects. */ 161760484Sobrien 161860484Sobrien bfd_set_section_size (abfd, id2, 20); 161960484Sobrien d2 = (unsigned char *) xmalloc (20); 162060484Sobrien id2->contents = d2; 162160484Sobrien memset (d2, 0, 20); 162289857Sobrien d2[0] = d2[16] = 4; /* Reloc addend. */ 162360484Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); 162460484Sobrien quick_reloc (abfd, 12, BFD_RELOC_RVA, 4); 162560484Sobrien quick_reloc (abfd, 16, BFD_RELOC_RVA, 1); 162660484Sobrien save_relocs (id2); 162760484Sobrien 162860484Sobrien bfd_set_section_size (abfd, id5, 4); 162960484Sobrien d5 = (unsigned char *) xmalloc (4); 163060484Sobrien id5->contents = d5; 163160484Sobrien memset (d5, 0, 4); 163260484Sobrien 163360484Sobrien bfd_set_section_size (abfd, id4, 4); 163460484Sobrien d4 = (unsigned char *) xmalloc (4); 163560484Sobrien id4->contents = d4; 163660484Sobrien memset (d4, 0, 4); 163760484Sobrien 163860484Sobrien bfd_set_symtab (abfd, symtab, symptr); 163960484Sobrien 164060484Sobrien bfd_set_section_contents (abfd, id2, d2, 0, 20); 164160484Sobrien bfd_set_section_contents (abfd, id5, d5, 0, 4); 164260484Sobrien bfd_set_section_contents (abfd, id4, d4, 0, 4); 164377298Sobrien 164460484Sobrien bfd_make_readable (abfd); 164560484Sobrien return abfd; 164660484Sobrien} 164760484Sobrien 164889857Sobrien/* .section .idata$4 164989857Sobrien .long 0 165089857Sobrien .section .idata$5 165189857Sobrien .long 0 165289857Sobrien .section idata$7 165389857Sobrien .global __my_dll_iname 165489857Sobrien __my_dll_iname: 165589857Sobrien .asciz "my.dll" */ 165660484Sobrien 165760484Sobrienstatic bfd * 165860484Sobrienmake_tail (parent) 165960484Sobrien bfd *parent; 166060484Sobrien{ 166160484Sobrien asection *id4, *id5, *id7; 166260484Sobrien unsigned char *d4, *d5, *d7; 166360484Sobrien int len; 166460484Sobrien char *oname; 166560484Sobrien bfd *abfd; 166660484Sobrien 166760484Sobrien oname = (char *) xmalloc (20); 166860484Sobrien sprintf (oname, "d%06d.o", tmp_seq); 166960484Sobrien tmp_seq++; 167060484Sobrien 167160484Sobrien abfd = bfd_create (oname, parent); 167260484Sobrien bfd_find_target (pe_details->object_target, abfd); 167360484Sobrien bfd_make_writable (abfd); 167460484Sobrien 167560484Sobrien bfd_set_format (abfd, bfd_object); 167660484Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 167760484Sobrien 167860484Sobrien symptr = 0; 167960484Sobrien symtab = (asymbol **) xmalloc (5 * sizeof (asymbol *)); 168060484Sobrien id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); 168160484Sobrien id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); 168260484Sobrien id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2); 168377298Sobrien quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0); 168460484Sobrien 168560484Sobrien bfd_set_section_size (abfd, id4, 4); 168660484Sobrien d4 = (unsigned char *) xmalloc (4); 168760484Sobrien id4->contents = d4; 168860484Sobrien memset (d4, 0, 4); 168960484Sobrien 169060484Sobrien bfd_set_section_size (abfd, id5, 4); 169160484Sobrien d5 = (unsigned char *) xmalloc (4); 169260484Sobrien id5->contents = d5; 169360484Sobrien memset (d5, 0, 4); 169460484Sobrien 169577298Sobrien len = strlen (dll_filename) + 1; 169660484Sobrien if (len & 1) 169777298Sobrien len++; 169860484Sobrien bfd_set_section_size (abfd, id7, len); 169960484Sobrien d7 = (unsigned char *) xmalloc (len); 170060484Sobrien id7->contents = d7; 170160484Sobrien strcpy (d7, dll_filename); 170260484Sobrien 170360484Sobrien bfd_set_symtab (abfd, symtab, symptr); 170460484Sobrien 170560484Sobrien bfd_set_section_contents (abfd, id4, d4, 0, 4); 170660484Sobrien bfd_set_section_contents (abfd, id5, d5, 0, 4); 170760484Sobrien bfd_set_section_contents (abfd, id7, d7, 0, len); 170860484Sobrien 170960484Sobrien bfd_make_readable (abfd); 171060484Sobrien return abfd; 171160484Sobrien} 171260484Sobrien 171389857Sobrien/* .text 171489857Sobrien .global _function 171589857Sobrien .global ___imp_function 171689857Sobrien .global __imp__function 171789857Sobrien _function: 171889857Sobrien jmp *__imp__function: 1719104834Sobrien 172089857Sobrien .section idata$7 172189857Sobrien .long __head_my_dll 1722104834Sobrien 172389857Sobrien .section .idata$5 172489857Sobrien ___imp_function: 172589857Sobrien __imp__function: 172689857Sobrien iat? 172789857Sobrien .section .idata$4 172889857Sobrien iat? 172989857Sobrien .section .idata$6 173089857Sobrien ID<ordinal>: 173189857Sobrien .short <hint> 173289857Sobrien .asciz "function" xlate? (add underscore, kill at) */ 173360484Sobrien 173489857Sobrienstatic unsigned char jmp_ix86_bytes[] = 173589857Sobrien{ 173660484Sobrien 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 173760484Sobrien}; 173860484Sobrien 173989857Sobrien/* _function: 174089857Sobrien mov.l ip+8,r0 174189857Sobrien mov.l @r0,r0 174289857Sobrien jmp @r0 174389857Sobrien nop 174489857Sobrien .dw __imp_function */ 174560484Sobrien 174689857Sobrienstatic unsigned char jmp_sh_bytes[] = 174789857Sobrien{ 174860484Sobrien 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 174960484Sobrien}; 175060484Sobrien 175189857Sobrien/* _function: 175289857Sobrien lui $t0,<high:__imp_function> 175389857Sobrien lw $t0,<low:__imp_function> 175489857Sobrien jr $t0 175589857Sobrien nop */ 175660484Sobrien 175789857Sobrienstatic unsigned char jmp_mips_bytes[] = 175889857Sobrien{ 175960484Sobrien 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d, 176060484Sobrien 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 176160484Sobrien}; 176260484Sobrien 176360484Sobrienstatic bfd * 176460484Sobrienmake_one (exp, parent) 176560484Sobrien def_file_export *exp; 176660484Sobrien bfd *parent; 176760484Sobrien{ 176860484Sobrien asection *tx, *id7, *id5, *id4, *id6; 176977298Sobrien unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL; 177060484Sobrien int len; 177160484Sobrien char *oname; 177260484Sobrien bfd *abfd; 177360484Sobrien unsigned char *jmp_bytes = NULL; 177460484Sobrien int jmp_byte_count = 0; 177560484Sobrien 177660484Sobrien switch (pe_details->pe_arch) 177760484Sobrien { 177860484Sobrien case PE_ARCH_i386: 177960484Sobrien jmp_bytes = jmp_ix86_bytes; 178060484Sobrien jmp_byte_count = sizeof (jmp_ix86_bytes); 178160484Sobrien break; 178260484Sobrien case PE_ARCH_sh: 178360484Sobrien jmp_bytes = jmp_sh_bytes; 178460484Sobrien jmp_byte_count = sizeof (jmp_sh_bytes); 178560484Sobrien break; 178660484Sobrien case PE_ARCH_mips: 178760484Sobrien jmp_bytes = jmp_mips_bytes; 178860484Sobrien jmp_byte_count = sizeof (jmp_mips_bytes); 178960484Sobrien break; 179089857Sobrien default: 179189857Sobrien abort (); 179260484Sobrien } 179360484Sobrien 179460484Sobrien oname = (char *) xmalloc (20); 179560484Sobrien sprintf (oname, "d%06d.o", tmp_seq); 179660484Sobrien tmp_seq++; 179760484Sobrien 179860484Sobrien abfd = bfd_create (oname, parent); 179960484Sobrien bfd_find_target (pe_details->object_target, abfd); 180060484Sobrien bfd_make_writable (abfd); 180160484Sobrien 180260484Sobrien bfd_set_format (abfd, bfd_object); 180360484Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 180460484Sobrien 180560484Sobrien symptr = 0; 180689857Sobrien symtab = (asymbol **) xmalloc (11 * sizeof (asymbol *)); 180760484Sobrien tx = quick_section (abfd, ".text", SEC_CODE|SEC_HAS_CONTENTS, 2); 180860484Sobrien id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2); 180960484Sobrien id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); 181060484Sobrien id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); 181160484Sobrien id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2); 181260484Sobrien if (! exp->flag_data) 181377298Sobrien quick_symbol (abfd, U (""), exp->internal_name, "", tx, BSF_GLOBAL, 0); 181477298Sobrien quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, BSF_GLOBAL, 0); 181577298Sobrien quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5, BSF_GLOBAL, 0); 181689857Sobrien /* Symbol to reference ord/name of imported 181789857Sobrien symbol, used to implement auto-import. */ 181889857Sobrien quick_symbol (abfd, U("_nm__"), exp->internal_name, "", id6, BSF_GLOBAL, 0); 181960484Sobrien if (pe_dll_compat_implib) 182077298Sobrien quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", 182177298Sobrien id5, BSF_GLOBAL, 0); 182260484Sobrien 182377298Sobrien if (! exp->flag_data) 182489857Sobrien { 182589857Sobrien bfd_set_section_size (abfd, tx, jmp_byte_count); 182689857Sobrien td = (unsigned char *) xmalloc (jmp_byte_count); 182789857Sobrien tx->contents = td; 182889857Sobrien memcpy (td, jmp_bytes, jmp_byte_count); 182960484Sobrien 183089857Sobrien switch (pe_details->pe_arch) 183189857Sobrien { 183289857Sobrien case PE_ARCH_i386: 183389857Sobrien quick_reloc (abfd, 2, BFD_RELOC_32, 2); 183489857Sobrien break; 183589857Sobrien case PE_ARCH_sh: 183689857Sobrien quick_reloc (abfd, 8, BFD_RELOC_32, 2); 183789857Sobrien break; 183889857Sobrien case PE_ARCH_mips: 183989857Sobrien quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2); 184089857Sobrien quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */ 184189857Sobrien quick_reloc (abfd, 4, BFD_RELOC_LO16, 2); 184289857Sobrien break; 184389857Sobrien default: 184489857Sobrien abort (); 184589857Sobrien } 184689857Sobrien save_relocs (tx); 184789857Sobrien } 184889857Sobrien 184960484Sobrien bfd_set_section_size (abfd, id7, 4); 185060484Sobrien d7 = (unsigned char *) xmalloc (4); 185160484Sobrien id7->contents = d7; 185260484Sobrien memset (d7, 0, 4); 185360484Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 6); 185460484Sobrien save_relocs (id7); 185560484Sobrien 185660484Sobrien bfd_set_section_size (abfd, id5, 4); 185760484Sobrien d5 = (unsigned char *) xmalloc (4); 185860484Sobrien id5->contents = d5; 185960484Sobrien memset (d5, 0, 4); 186089857Sobrien 186160484Sobrien if (exp->flag_noname) 186260484Sobrien { 186360484Sobrien d5[0] = exp->ordinal; 186460484Sobrien d5[1] = exp->ordinal >> 8; 186560484Sobrien d5[3] = 0x80; 186660484Sobrien } 186760484Sobrien else 186860484Sobrien { 186960484Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); 187060484Sobrien save_relocs (id5); 187160484Sobrien } 187260484Sobrien 187360484Sobrien bfd_set_section_size (abfd, id4, 4); 187460484Sobrien d4 = (unsigned char *) xmalloc (4); 187560484Sobrien id4->contents = d4; 187660484Sobrien memset (d4, 0, 4); 187789857Sobrien 187860484Sobrien if (exp->flag_noname) 187960484Sobrien { 188077298Sobrien d4[0] = exp->ordinal; 188177298Sobrien d4[1] = exp->ordinal >> 8; 188277298Sobrien d4[3] = 0x80; 188360484Sobrien } 188460484Sobrien else 188560484Sobrien { 188660484Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); 188760484Sobrien save_relocs (id4); 188860484Sobrien } 188960484Sobrien 189060484Sobrien if (exp->flag_noname) 189160484Sobrien { 189260484Sobrien len = 0; 189360484Sobrien bfd_set_section_size (abfd, id6, 0); 189460484Sobrien } 189560484Sobrien else 189660484Sobrien { 189760484Sobrien len = strlen (exp->name) + 3; 189860484Sobrien if (len & 1) 189960484Sobrien len++; 190060484Sobrien bfd_set_section_size (abfd, id6, len); 190160484Sobrien d6 = (unsigned char *) xmalloc (len); 190260484Sobrien id6->contents = d6; 190360484Sobrien memset (d6, 0, len); 190460484Sobrien d6[0] = exp->hint & 0xff; 190560484Sobrien d6[1] = exp->hint >> 8; 190677298Sobrien strcpy (d6 + 2, exp->name); 190760484Sobrien } 190860484Sobrien 190960484Sobrien bfd_set_symtab (abfd, symtab, symptr); 191060484Sobrien 191160484Sobrien bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count); 191260484Sobrien bfd_set_section_contents (abfd, id7, d7, 0, 4); 191360484Sobrien bfd_set_section_contents (abfd, id5, d5, 0, 4); 191460484Sobrien bfd_set_section_contents (abfd, id4, d4, 0, 4); 191560484Sobrien if (!exp->flag_noname) 191660484Sobrien bfd_set_section_contents (abfd, id6, d6, 0, len); 191760484Sobrien 191860484Sobrien bfd_make_readable (abfd); 191960484Sobrien return abfd; 192060484Sobrien} 192160484Sobrien 192289857Sobrienstatic bfd * 192389857Sobrienmake_singleton_name_thunk (import, parent) 192489857Sobrien const char *import; 192589857Sobrien bfd *parent; 192689857Sobrien{ 192789857Sobrien /* Name thunks go to idata$4. */ 192889857Sobrien asection *id4; 192989857Sobrien unsigned char *d4; 193089857Sobrien char *oname; 193189857Sobrien bfd *abfd; 193289857Sobrien 193389857Sobrien oname = (char *) xmalloc (20); 193489857Sobrien sprintf (oname, "nmth%06d.o", tmp_seq); 193589857Sobrien tmp_seq++; 193689857Sobrien 193789857Sobrien abfd = bfd_create (oname, parent); 193889857Sobrien bfd_find_target (pe_details->object_target, abfd); 193989857Sobrien bfd_make_writable (abfd); 194089857Sobrien 194189857Sobrien bfd_set_format (abfd, bfd_object); 194289857Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 194389857Sobrien 194489857Sobrien symptr = 0; 194589857Sobrien symtab = (asymbol **) xmalloc (3 * sizeof (asymbol *)); 194689857Sobrien id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); 194789857Sobrien quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0); 194889857Sobrien quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0); 194989857Sobrien 195089857Sobrien bfd_set_section_size (abfd, id4, 8); 195189857Sobrien d4 = (unsigned char *) xmalloc (4); 195289857Sobrien id4->contents = d4; 195389857Sobrien memset (d4, 0, 8); 195489857Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); 195589857Sobrien save_relocs (id4); 195689857Sobrien 195789857Sobrien bfd_set_symtab (abfd, symtab, symptr); 195889857Sobrien 195989857Sobrien bfd_set_section_contents (abfd, id4, d4, 0, 8); 196089857Sobrien 196189857Sobrien bfd_make_readable (abfd); 196289857Sobrien return abfd; 196389857Sobrien} 196489857Sobrien 196589857Sobrienstatic char * 196689857Sobrienmake_import_fixup_mark (rel) 196789857Sobrien arelent *rel; 196889857Sobrien{ 196989857Sobrien /* We convert reloc to symbol, for later reference. */ 197089857Sobrien static int counter; 197189857Sobrien static char *fixup_name = NULL; 197289857Sobrien static size_t buffer_len = 0; 1973104834Sobrien 197489857Sobrien struct symbol_cache_entry *sym = *rel->sym_ptr_ptr; 1975104834Sobrien 197689857Sobrien bfd *abfd = bfd_asymbol_bfd (sym); 197789857Sobrien struct coff_link_hash_entry *myh = NULL; 197889857Sobrien 197989857Sobrien if (!fixup_name) 198089857Sobrien { 198189857Sobrien fixup_name = (char *) xmalloc (384); 198289857Sobrien buffer_len = 384; 198389857Sobrien } 198489857Sobrien 198589857Sobrien if (strlen (sym->name) + 25 > buffer_len) 1986104834Sobrien /* Assume 25 chars for "__fu" + counter + "_". If counter is 198789857Sobrien bigger than 20 digits long, we've got worse problems than 198889857Sobrien overflowing this buffer... */ 198989857Sobrien { 199089857Sobrien free (fixup_name); 199189857Sobrien /* New buffer size is length of symbol, plus 25, but then 199289857Sobrien rounded up to the nearest multiple of 128. */ 199389857Sobrien buffer_len = ((strlen (sym->name) + 25) + 127) & ~127; 199489857Sobrien fixup_name = (char *) xmalloc (buffer_len); 199589857Sobrien } 1996104834Sobrien 199789857Sobrien sprintf (fixup_name, "__fu%d_%s", counter++, sym->name); 199889857Sobrien 1999104834Sobrien bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL, 200089857Sobrien current_sec, /* sym->section, */ 200189857Sobrien rel->address, NULL, true, false, 200289857Sobrien (struct bfd_link_hash_entry **) &myh); 200389857Sobrien 200489857Sobrien#if 0 2005104834Sobrien printf ("type:%d\n", myh->type); 2006104834Sobrien printf ("%s\n", myh->root.u.def.section->name); 200789857Sobrien#endif 200889857Sobrien return fixup_name; 200989857Sobrien} 201089857Sobrien 201189857Sobrien/* .section .idata$3 201289857Sobrien .rva __nm_thnk_SYM (singleton thunk with name of func) 201389857Sobrien .long 0 201489857Sobrien .long 0 201589857Sobrien .rva __my_dll_iname (name of dll) 201689857Sobrien .rva __fuNN_SYM (pointer to reference (address) in text) */ 201789857Sobrien 201889857Sobrienstatic bfd * 2019104834Sobrienmake_import_fixup_entry (name, fixup_name, dll_symname, parent) 202089857Sobrien const char *name; 202189857Sobrien const char *fixup_name; 202289857Sobrien const char *dll_symname; 202389857Sobrien bfd *parent; 202489857Sobrien{ 202589857Sobrien asection *id3; 202689857Sobrien unsigned char *d3; 202789857Sobrien char *oname; 202889857Sobrien bfd *abfd; 202989857Sobrien 203089857Sobrien oname = (char *) xmalloc (20); 203189857Sobrien sprintf (oname, "fu%06d.o", tmp_seq); 203289857Sobrien tmp_seq++; 203389857Sobrien 203489857Sobrien abfd = bfd_create (oname, parent); 203589857Sobrien bfd_find_target (pe_details->object_target, abfd); 203689857Sobrien bfd_make_writable (abfd); 203789857Sobrien 203889857Sobrien bfd_set_format (abfd, bfd_object); 203989857Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 204089857Sobrien 204189857Sobrien symptr = 0; 204289857Sobrien symtab = (asymbol **) xmalloc (6 * sizeof (asymbol *)); 204389857Sobrien id3 = quick_section (abfd, ".idata$3", SEC_HAS_CONTENTS, 2); 204489857Sobrien 2045104834Sobrien#if 0 2046104834Sobrien quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0); 204789857Sobrien#endif 204889857Sobrien quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0); 204989857Sobrien quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0); 205089857Sobrien quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0); 205189857Sobrien 205289857Sobrien bfd_set_section_size (abfd, id3, 20); 205389857Sobrien d3 = (unsigned char *) xmalloc (20); 205489857Sobrien id3->contents = d3; 205589857Sobrien memset (d3, 0, 20); 205689857Sobrien 205789857Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 1); 205889857Sobrien quick_reloc (abfd, 12, BFD_RELOC_RVA, 2); 205989857Sobrien quick_reloc (abfd, 16, BFD_RELOC_RVA, 3); 206089857Sobrien save_relocs (id3); 206189857Sobrien 206289857Sobrien bfd_set_symtab (abfd, symtab, symptr); 206389857Sobrien 206489857Sobrien bfd_set_section_contents (abfd, id3, d3, 0, 20); 206589857Sobrien 206689857Sobrien bfd_make_readable (abfd); 206789857Sobrien return abfd; 206889857Sobrien} 206989857Sobrien 207060484Sobrienvoid 207189857Sobrienpe_create_import_fixup (rel) 207289857Sobrien arelent *rel; 207389857Sobrien{ 207489857Sobrien char buf[300]; 207589857Sobrien struct symbol_cache_entry *sym = *rel->sym_ptr_ptr; 207689857Sobrien struct bfd_link_hash_entry *name_thunk_sym; 207789857Sobrien const char *name = sym->name; 207889857Sobrien char *fixup_name = make_import_fixup_mark (rel); 207989857Sobrien 208089857Sobrien sprintf (buf, U ("_nm_thnk_%s"), name); 208189857Sobrien 208289857Sobrien name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); 208389857Sobrien 208489857Sobrien if (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined) 208589857Sobrien { 208689857Sobrien bfd *b = make_singleton_name_thunk (name, output_bfd); 208789857Sobrien add_bfd_to_link (b, b->filename, &link_info); 208889857Sobrien 208989857Sobrien /* If we ever use autoimport, we have to cast text section writable. */ 209089857Sobrien config.text_read_only = false; 209189857Sobrien } 209289857Sobrien 209389857Sobrien { 209489857Sobrien extern char * pe_data_import_dll; 209589857Sobrien char * dll_symname = pe_data_import_dll ? pe_data_import_dll : "unknown"; 209689857Sobrien 209789857Sobrien bfd *b = make_import_fixup_entry (name, fixup_name, dll_symname, 209889857Sobrien output_bfd); 209989857Sobrien add_bfd_to_link (b, b->filename, &link_info); 210089857Sobrien } 210189857Sobrien} 210289857Sobrien 210389857Sobrien 210489857Sobrienvoid 210560484Sobrienpe_dll_generate_implib (def, impfilename) 210660484Sobrien def_file *def; 210760484Sobrien const char *impfilename; 210860484Sobrien{ 210960484Sobrien int i; 211060484Sobrien bfd *ar_head; 211160484Sobrien bfd *ar_tail; 211260484Sobrien bfd *outarch; 211360484Sobrien bfd *head = 0; 211460484Sobrien 211560484Sobrien dll_filename = (def->name) ? def->name : dll_name; 211660484Sobrien dll_symname = xstrdup (dll_filename); 211777298Sobrien for (i = 0; dll_symname[i]; i++) 211889857Sobrien if (!ISALNUM (dll_symname[i])) 211960484Sobrien dll_symname[i] = '_'; 212060484Sobrien 212160484Sobrien unlink (impfilename); 212260484Sobrien 212360484Sobrien outarch = bfd_openw (impfilename, 0); 212460484Sobrien 212560484Sobrien if (!outarch) 212660484Sobrien { 212760484Sobrien /* xgettext:c-format */ 212860484Sobrien einfo (_("%XCan't open .lib file: %s\n"), impfilename); 212960484Sobrien return; 213060484Sobrien } 213160484Sobrien 213260484Sobrien /* xgettext:c-format */ 213360484Sobrien einfo (_("Creating library file: %s\n"), impfilename); 213477298Sobrien 213560484Sobrien bfd_set_format (outarch, bfd_archive); 213660484Sobrien outarch->has_armap = 1; 213760484Sobrien 213877298Sobrien /* Work out a reasonable size of things to put onto one line. */ 213960484Sobrien ar_head = make_head (outarch); 214060484Sobrien 214177298Sobrien for (i = 0; i < def->num_exports; i++) 214260484Sobrien { 214377298Sobrien /* The import library doesn't know about the internal name. */ 214460484Sobrien char *internal = def->exports[i].internal_name; 214560484Sobrien bfd *n; 214689857Sobrien 214760484Sobrien def->exports[i].internal_name = def->exports[i].name; 214877298Sobrien n = make_one (def->exports + i, outarch); 214960484Sobrien n->next = head; 215060484Sobrien head = n; 215160484Sobrien def->exports[i].internal_name = internal; 215260484Sobrien } 215360484Sobrien 215460484Sobrien ar_tail = make_tail (outarch); 215560484Sobrien 215660484Sobrien if (ar_head == NULL || ar_tail == NULL) 215760484Sobrien return; 215860484Sobrien 215977298Sobrien /* Now stick them all into the archive. */ 216060484Sobrien ar_head->next = head; 216160484Sobrien ar_tail->next = ar_head; 216260484Sobrien head = ar_tail; 216360484Sobrien 216460484Sobrien if (! bfd_set_archive_head (outarch, head)) 216560484Sobrien einfo ("%Xbfd_set_archive_head: %s\n", bfd_errmsg (bfd_get_error ())); 216677298Sobrien 216760484Sobrien if (! bfd_close (outarch)) 216860484Sobrien einfo ("%Xbfd_close %s: %s\n", impfilename, bfd_errmsg (bfd_get_error ())); 216960484Sobrien 217060484Sobrien while (head != NULL) 217160484Sobrien { 217260484Sobrien bfd *n = head->next; 217360484Sobrien bfd_close (head); 217460484Sobrien head = n; 217560484Sobrien } 217660484Sobrien} 217760484Sobrien 217860484Sobrienstatic void 217960484Sobrienadd_bfd_to_link (abfd, name, link_info) 218060484Sobrien bfd *abfd; 218189857Sobrien const char *name; 218260484Sobrien struct bfd_link_info *link_info; 218360484Sobrien{ 218460484Sobrien lang_input_statement_type *fake_file; 218589857Sobrien 218660484Sobrien fake_file = lang_add_input_file (name, 218760484Sobrien lang_input_file_is_fake_enum, 218860484Sobrien NULL); 218960484Sobrien fake_file->the_bfd = abfd; 219060484Sobrien ldlang_add_file (fake_file); 219189857Sobrien 219260484Sobrien if (!bfd_link_add_symbols (abfd, link_info)) 219360484Sobrien einfo ("%Xaddsym %s: %s\n", name, bfd_errmsg (bfd_get_error ())); 219460484Sobrien} 219560484Sobrien 219660484Sobrienvoid 219760484Sobrienpe_process_import_defs (output_bfd, link_info) 219860484Sobrien bfd *output_bfd; 219960484Sobrien struct bfd_link_info *link_info; 220060484Sobrien{ 220160484Sobrien def_file_module *module; 220289857Sobrien 220377298Sobrien pe_dll_id_target (bfd_get_target (output_bfd)); 220460484Sobrien 220560484Sobrien if (!pe_def_file) 220660484Sobrien return; 220760484Sobrien 220860484Sobrien for (module = pe_def_file->modules; module; module = module->next) 220960484Sobrien { 221060484Sobrien int i, do_this_dll; 221160484Sobrien 221260484Sobrien dll_filename = module->name; 221360484Sobrien dll_symname = xstrdup (module->name); 221477298Sobrien for (i = 0; dll_symname[i]; i++) 221589857Sobrien if (!ISALNUM (dll_symname[i])) 221660484Sobrien dll_symname[i] = '_'; 221760484Sobrien 221860484Sobrien do_this_dll = 0; 221960484Sobrien 222077298Sobrien for (i = 0; i < pe_def_file->num_imports; i++) 222160484Sobrien if (pe_def_file->imports[i].module == module) 222260484Sobrien { 222360484Sobrien def_file_export exp; 222460484Sobrien struct bfd_link_hash_entry *blhe; 222560484Sobrien 222677298Sobrien /* See if we need this import. */ 222777298Sobrien char *name = (char *) xmalloc (strlen (pe_def_file->imports[i].internal_name) + 2 + 6); 222877298Sobrien sprintf (name, "%s%s", U (""), pe_def_file->imports[i].internal_name); 222960484Sobrien blhe = bfd_link_hash_lookup (link_info->hash, name, 223060484Sobrien false, false, false); 223177298Sobrien if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)) 223277298Sobrien { 223377298Sobrien sprintf (name, "%s%s", U ("_imp__"), 223477298Sobrien pe_def_file->imports[i].internal_name); 223577298Sobrien blhe = bfd_link_hash_lookup (link_info->hash, name, 223677298Sobrien false, false, false); 223777298Sobrien } 223860484Sobrien free (name); 223960484Sobrien if (blhe && blhe->type == bfd_link_hash_undefined) 224060484Sobrien { 224160484Sobrien bfd *one; 224277298Sobrien /* We do. */ 224360484Sobrien if (!do_this_dll) 224460484Sobrien { 224560484Sobrien bfd *ar_head = make_head (output_bfd); 224660484Sobrien add_bfd_to_link (ar_head, ar_head->filename, link_info); 224760484Sobrien do_this_dll = 1; 224860484Sobrien } 224960484Sobrien exp.internal_name = pe_def_file->imports[i].internal_name; 225060484Sobrien exp.name = pe_def_file->imports[i].name; 225160484Sobrien exp.ordinal = pe_def_file->imports[i].ordinal; 225260484Sobrien exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0; 225360484Sobrien exp.flag_private = 0; 225460484Sobrien exp.flag_constant = 0; 225560484Sobrien exp.flag_data = 0; 225660484Sobrien exp.flag_noname = exp.name ? 0 : 1; 225760484Sobrien one = make_one (&exp, output_bfd); 225860484Sobrien add_bfd_to_link (one, one->filename, link_info); 225960484Sobrien } 226060484Sobrien } 226160484Sobrien if (do_this_dll) 226260484Sobrien { 226360484Sobrien bfd *ar_tail = make_tail (output_bfd); 226460484Sobrien add_bfd_to_link (ar_tail, ar_tail->filename, link_info); 226560484Sobrien } 226660484Sobrien 226760484Sobrien free (dll_symname); 226860484Sobrien } 226960484Sobrien} 227060484Sobrien 227189857Sobrien/* We were handed a *.DLL file. Parse it and turn it into a set of 227289857Sobrien IMPORTS directives in the def file. Return true if the file was 227389857Sobrien handled, false if not. */ 227460484Sobrien 227560484Sobrienstatic unsigned int 227660484Sobrienpe_get16 (abfd, where) 227760484Sobrien bfd *abfd; 227860484Sobrien int where; 227960484Sobrien{ 228060484Sobrien unsigned char b[2]; 228189857Sobrien 228289857Sobrien bfd_seek (abfd, (file_ptr) where, SEEK_SET); 228389857Sobrien bfd_bread (b, (bfd_size_type) 2, abfd); 228477298Sobrien return b[0] + (b[1] << 8); 228560484Sobrien} 228660484Sobrien 228760484Sobrienstatic unsigned int 228860484Sobrienpe_get32 (abfd, where) 228960484Sobrien bfd *abfd; 229060484Sobrien int where; 229160484Sobrien{ 229260484Sobrien unsigned char b[4]; 229389857Sobrien 229489857Sobrien bfd_seek (abfd, (file_ptr) where, SEEK_SET); 229589857Sobrien bfd_bread (b, (bfd_size_type) 4, abfd); 229677298Sobrien return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); 229760484Sobrien} 229860484Sobrien 229960484Sobrien#if 0 /* This is not currently used. */ 230060484Sobrien 230160484Sobrienstatic unsigned int 230260484Sobrienpe_as16 (ptr) 230360484Sobrien void *ptr; 230460484Sobrien{ 230560484Sobrien unsigned char *b = ptr; 230689857Sobrien 230777298Sobrien return b[0] + (b[1] << 8); 230860484Sobrien} 230960484Sobrien 231060484Sobrien#endif 231160484Sobrien 231260484Sobrienstatic unsigned int 231360484Sobrienpe_as32 (ptr) 231460484Sobrien void *ptr; 231560484Sobrien{ 231660484Sobrien unsigned char *b = ptr; 231789857Sobrien 231877298Sobrien return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); 231960484Sobrien} 232060484Sobrien 232160484Sobrienboolean 232260484Sobrienpe_implied_import_dll (filename) 232360484Sobrien const char *filename; 232460484Sobrien{ 232560484Sobrien bfd *dll; 232660484Sobrien unsigned long pe_header_offset, opthdr_ofs, num_entries, i; 232760484Sobrien unsigned long export_rva, export_size, nsections, secptr, expptr; 232860484Sobrien unsigned char *expdata, *erva; 232960484Sobrien unsigned long name_rvas, ordinals, nexp, ordbase; 233060484Sobrien const char *dll_name; 233160484Sobrien 233260484Sobrien /* No, I can't use bfd here. kernel32.dll puts its export table in 233377298Sobrien the middle of the .rdata section. */ 233460484Sobrien dll = bfd_openr (filename, pe_details->target_name); 233560484Sobrien if (!dll) 233660484Sobrien { 233760484Sobrien einfo ("%Xopen %s: %s\n", filename, bfd_errmsg (bfd_get_error ())); 233860484Sobrien return false; 233960484Sobrien } 234089857Sobrien 234177298Sobrien /* PEI dlls seem to be bfd_objects. */ 234260484Sobrien if (!bfd_check_format (dll, bfd_object)) 234360484Sobrien { 234460484Sobrien einfo ("%X%s: this doesn't appear to be a DLL\n", filename); 234560484Sobrien return false; 234660484Sobrien } 234760484Sobrien 234860484Sobrien dll_name = filename; 234977298Sobrien for (i = 0; filename[i]; i++) 235060484Sobrien if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') 235160484Sobrien dll_name = filename + i + 1; 235260484Sobrien 235360484Sobrien pe_header_offset = pe_get32 (dll, 0x3c); 235460484Sobrien opthdr_ofs = pe_header_offset + 4 + 20; 235560484Sobrien num_entries = pe_get32 (dll, opthdr_ofs + 92); 235689857Sobrien 235789857Sobrien if (num_entries < 1) /* No exports. */ 235860484Sobrien return false; 235989857Sobrien 236060484Sobrien export_rva = pe_get32 (dll, opthdr_ofs + 96); 236160484Sobrien export_size = pe_get32 (dll, opthdr_ofs + 100); 236260484Sobrien nsections = pe_get16 (dll, pe_header_offset + 4 + 2); 236360484Sobrien secptr = (pe_header_offset + 4 + 20 + 236460484Sobrien pe_get16 (dll, pe_header_offset + 4 + 16)); 236560484Sobrien expptr = 0; 236689857Sobrien 236777298Sobrien for (i = 0; i < nsections; i++) 236860484Sobrien { 236960484Sobrien char sname[8]; 237060484Sobrien unsigned long secptr1 = secptr + 40 * i; 237160484Sobrien unsigned long vaddr = pe_get32 (dll, secptr1 + 12); 237260484Sobrien unsigned long vsize = pe_get32 (dll, secptr1 + 16); 237360484Sobrien unsigned long fptr = pe_get32 (dll, secptr1 + 20); 237489857Sobrien 237589857Sobrien bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); 237689857Sobrien bfd_bread (sname, (bfd_size_type) 8, dll); 237789857Sobrien 237877298Sobrien if (vaddr <= export_rva && vaddr + vsize > export_rva) 237960484Sobrien { 238060484Sobrien expptr = fptr + (export_rva - vaddr); 238160484Sobrien if (export_rva + export_size > vaddr + vsize) 238260484Sobrien export_size = vsize - (export_rva - vaddr); 238360484Sobrien break; 238460484Sobrien } 238560484Sobrien } 238660484Sobrien 238760484Sobrien expdata = (unsigned char *) xmalloc (export_size); 238889857Sobrien bfd_seek (dll, (file_ptr) expptr, SEEK_SET); 238989857Sobrien bfd_bread (expdata, (bfd_size_type) export_size, dll); 239060484Sobrien erva = expdata - export_rva; 239160484Sobrien 239260484Sobrien if (pe_def_file == 0) 239377298Sobrien pe_def_file = def_file_empty (); 239460484Sobrien 239577298Sobrien nexp = pe_as32 (expdata + 24); 239677298Sobrien name_rvas = pe_as32 (expdata + 32); 239777298Sobrien ordinals = pe_as32 (expdata + 36); 239877298Sobrien ordbase = pe_as32 (expdata + 16); 239989857Sobrien 240077298Sobrien for (i = 0; i < nexp; i++) 240160484Sobrien { 240277298Sobrien unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); 240360484Sobrien def_file_import *imp; 240489857Sobrien 240577298Sobrien imp = def_file_add_import (pe_def_file, erva + name_rva, dll_name, 240660484Sobrien i, 0); 240760484Sobrien } 240860484Sobrien 240960484Sobrien return true; 241060484Sobrien} 241160484Sobrien 241289857Sobrien/* These are the main functions, called from the emulation. The first 241389857Sobrien is called after the bfds are read, so we can guess at how much space 241489857Sobrien we need. The second is called after everything is placed, so we 241589857Sobrien can put the right values in place. */ 241660484Sobrien 241760484Sobrienvoid 241860484Sobrienpe_dll_build_sections (abfd, info) 241960484Sobrien bfd *abfd; 242060484Sobrien struct bfd_link_info *info; 242160484Sobrien{ 242260484Sobrien pe_dll_id_target (bfd_get_target (abfd)); 242360484Sobrien process_def_file (abfd, info); 242460484Sobrien 242560484Sobrien generate_edata (abfd, info); 242660484Sobrien build_filler_bfd (1); 242760484Sobrien} 242860484Sobrien 242960484Sobrienvoid 243060484Sobrienpe_exe_build_sections (abfd, info) 243160484Sobrien bfd *abfd; 243260484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 243360484Sobrien{ 243460484Sobrien pe_dll_id_target (bfd_get_target (abfd)); 243560484Sobrien build_filler_bfd (0); 243660484Sobrien} 243760484Sobrien 243860484Sobrienvoid 243960484Sobrienpe_dll_fill_sections (abfd, info) 244060484Sobrien bfd *abfd; 244160484Sobrien struct bfd_link_info *info; 244260484Sobrien{ 244360484Sobrien pe_dll_id_target (bfd_get_target (abfd)); 244460484Sobrien image_base = pe_data (abfd)->pe_opthdr.ImageBase; 244560484Sobrien 244660484Sobrien generate_reloc (abfd, info); 244760484Sobrien if (reloc_sz > 0) 244860484Sobrien { 244960484Sobrien bfd_set_section_size (filler_bfd, reloc_s, reloc_sz); 245060484Sobrien 245160484Sobrien /* Resize the sections. */ 245260484Sobrien lang_size_sections (stat_ptr->head, abs_output_section, 245389857Sobrien &stat_ptr->head, 0, (bfd_vma) 0, NULL); 245460484Sobrien 245560484Sobrien /* Redo special stuff. */ 245660484Sobrien ldemul_after_allocation (); 245760484Sobrien 245860484Sobrien /* Do the assignments again. */ 245960484Sobrien lang_do_assignments (stat_ptr->head, 246060484Sobrien abs_output_section, 2461104834Sobrien (fill_type *) 0, (bfd_vma) 0); 246260484Sobrien } 246360484Sobrien 246460484Sobrien fill_edata (abfd, info); 246560484Sobrien 246660484Sobrien pe_data (abfd)->dll = 1; 246760484Sobrien 246860484Sobrien edata_s->contents = edata_d; 246960484Sobrien reloc_s->contents = reloc_d; 247060484Sobrien} 247160484Sobrien 247260484Sobrienvoid 247360484Sobrienpe_exe_fill_sections (abfd, info) 247460484Sobrien bfd *abfd; 247560484Sobrien struct bfd_link_info *info; 247660484Sobrien{ 247760484Sobrien pe_dll_id_target (bfd_get_target (abfd)); 247860484Sobrien image_base = pe_data (abfd)->pe_opthdr.ImageBase; 247960484Sobrien 248060484Sobrien generate_reloc (abfd, info); 248160484Sobrien if (reloc_sz > 0) 248260484Sobrien { 248360484Sobrien bfd_set_section_size (filler_bfd, reloc_s, reloc_sz); 248460484Sobrien 248560484Sobrien /* Resize the sections. */ 248660484Sobrien lang_size_sections (stat_ptr->head, abs_output_section, 248789857Sobrien &stat_ptr->head, 0, (bfd_vma) 0, NULL); 248860484Sobrien 248960484Sobrien /* Redo special stuff. */ 249060484Sobrien ldemul_after_allocation (); 249160484Sobrien 249260484Sobrien /* Do the assignments again. */ 249360484Sobrien lang_do_assignments (stat_ptr->head, 249460484Sobrien abs_output_section, 2495104834Sobrien (fill_type *) 0, (bfd_vma) 0); 249660484Sobrien } 249760484Sobrien reloc_s->contents = reloc_d; 249860484Sobrien} 2499