pe-dll.c revision 89857
160484Sobrien/* Routines to help build PEI-format DLLs (Win32 etc) 289857Sobrien Copyright 1998, 1999, 2000, 2001 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. 5089857Sobrien 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 }, 23489857Sobrien { NULL, 0 } 23589857Sobrien}; 23689857Sobrien 23789857Sobrienstatic autofilter_entry_type autofilter_objlist[] = 23889857Sobrien{ 23989857Sobrien { "crt0.o", 6 }, 24089857Sobrien { "crt1.o", 6 }, 24189857Sobrien { "crt2.o", 6 }, 24289857Sobrien { "dllcrt1.o", 9 }, 24389857Sobrien { "dllcrt2.o", 9 }, 24489857Sobrien { "gcrt0.o", 7 }, 24589857Sobrien { "gcrt1.o", 7 }, 24689857Sobrien { "gcrt2.o", 7 }, 24789857Sobrien { NULL, 0 } 24889857Sobrien}; 24989857Sobrien 25089857Sobrienstatic autofilter_entry_type autofilter_symbolprefixlist[] = 25189857Sobrien{ 25289857Sobrien /* { "__imp_", 6 }, */ 25389857Sobrien /* Do __imp_ explicitly to save time. */ 25489857Sobrien { "__rtti_", 7 }, 25589857Sobrien { "__builtin_", 10 }, 25689857Sobrien /* Don't export symbols specifying internal DLL layout. */ 25789857Sobrien { "_head_", 6 }, 25889857Sobrien { "_fmode", 6 }, 25989857Sobrien { "_impure_ptr", 11 }, 26089857Sobrien { "cygwin_attach_dll", 17 }, 26189857Sobrien { "cygwin_premain0", 15 }, 26289857Sobrien { "cygwin_premain1", 15 }, 26389857Sobrien { "cygwin_premain2", 15 }, 26489857Sobrien { "cygwin_premain3", 15 }, 26589857Sobrien { "environ", 7 }, 26689857Sobrien { NULL, 0 } 26789857Sobrien}; 26889857Sobrien 26989857Sobrienstatic autofilter_entry_type autofilter_symbolsuffixlist[] = 27089857Sobrien{ 27189857Sobrien { "_iname", 6 }, 27289857Sobrien { NULL, 0 } 27389857Sobrien}; 27489857Sobrien 27560484Sobrien#define U(str) (pe_details->underscored ? "_" str : str) 27660484Sobrien 27789857Sobrienstatic int reloc_sort PARAMS ((const void *, const void *)); 27889857Sobrienstatic int pe_export_sort PARAMS ((const void *, const void *)); 27989857Sobrienstatic int auto_export PARAMS ((bfd *, def_file *, const char *)); 28089857Sobrienstatic void process_def_file PARAMS ((bfd *, struct bfd_link_info *)); 28189857Sobrienstatic void build_filler_bfd PARAMS ((int)); 28289857Sobrienstatic void generate_edata PARAMS ((bfd *, struct bfd_link_info *)); 28389857Sobrienstatic void fill_exported_offsets PARAMS ((bfd *, struct bfd_link_info *)); 28489857Sobrienstatic void fill_edata PARAMS ((bfd *, struct bfd_link_info *)); 28589857Sobrienstatic void generate_reloc PARAMS ((bfd *, struct bfd_link_info *)); 28689857Sobrienstatic void quoteput PARAMS ((char *, FILE *, int)); 28789857Sobrienstatic asection *quick_section PARAMS ((bfd *, const char *, int, int)); 28889857Sobrienstatic void quick_symbol 28989857Sobrien PARAMS ((bfd *, const char *, const char *, const char *, 29089857Sobrien asection *, int, int)); 29189857Sobrienstatic void quick_reloc PARAMS ((bfd *, int, int, int)); 29289857Sobrienstatic bfd *make_head PARAMS ((bfd *)); 29389857Sobrienstatic bfd *make_tail PARAMS ((bfd *)); 29489857Sobrienstatic bfd *make_one PARAMS ((def_file_export *, bfd *)); 29589857Sobrienstatic bfd *make_singleton_name_thunk PARAMS ((const char *, bfd *)); 29689857Sobrienstatic char *make_import_fixup_mark PARAMS ((arelent *)); 29789857Sobrienstatic bfd *make_import_fixup_entry 29889857Sobrien PARAMS ((const char *, const char *, const char *, bfd *)); 29989857Sobrienstatic unsigned int pe_get16 PARAMS ((bfd *, int)); 30089857Sobrienstatic unsigned int pe_get32 PARAMS ((bfd *, int)); 30189857Sobrienstatic unsigned int pe_as32 PARAMS ((void *)); 30289857Sobrien 30360484Sobrienvoid 30460484Sobrienpe_dll_id_target (target) 30560484Sobrien const char *target; 30660484Sobrien{ 30760484Sobrien int i; 30889857Sobrien 30977298Sobrien for (i = 0; pe_detail_list[i].target_name; i++) 31077298Sobrien if (strcmp (pe_detail_list[i].target_name, target) == 0 31177298Sobrien || strcmp (pe_detail_list[i].object_target, target) == 0) 31260484Sobrien { 31377298Sobrien pe_details = pe_detail_list + i; 31460484Sobrien return; 31560484Sobrien } 31660484Sobrien einfo (_("%XUnsupported PEI architecture: %s\n"), target); 31760484Sobrien exit (1); 31860484Sobrien} 31960484Sobrien 32089857Sobrien/* Helper functions for qsort. Relocs must be sorted so that we can write 32189857Sobrien them out by pages. */ 32260484Sobrien 32389857Sobrientypedef struct 32489857Sobrien { 32589857Sobrien bfd_vma vma; 32689857Sobrien char type; 32789857Sobrien short extra; 32889857Sobrien } 32989857Sobrienreloc_data_type; 33060484Sobrien 33160484Sobrienstatic int 33260484Sobrienreloc_sort (va, vb) 33360484Sobrien const void *va, *vb; 33460484Sobrien{ 33560484Sobrien bfd_vma a = ((reloc_data_type *) va)->vma; 33660484Sobrien bfd_vma b = ((reloc_data_type *) vb)->vma; 33789857Sobrien 33860484Sobrien return (a > b) ? 1 : ((a < b) ? -1 : 0); 33960484Sobrien} 34060484Sobrien 34160484Sobrienstatic int 34260484Sobrienpe_export_sort (va, vb) 34360484Sobrien const void *va, *vb; 34460484Sobrien{ 34560484Sobrien def_file_export *a = (def_file_export *) va; 34660484Sobrien def_file_export *b = (def_file_export *) vb; 34789857Sobrien 34860484Sobrien return strcmp (a->name, b->name); 34960484Sobrien} 35060484Sobrien 35189857Sobrien/* Read and process the .DEF file. */ 35260484Sobrien 35360484Sobrien/* These correspond to the entries in pe_def_file->exports[]. I use 35460484Sobrien exported_symbol_sections[i] to tag whether or not the symbol was 35577298Sobrien defined, since we can't export symbols we don't have. */ 35660484Sobrien 35760484Sobrienstatic bfd_vma *exported_symbol_offsets; 35860484Sobrienstatic struct sec **exported_symbol_sections; 35960484Sobrienstatic int export_table_size; 36060484Sobrienstatic int count_exported; 36160484Sobrienstatic int count_exported_byname; 36260484Sobrienstatic int count_with_ordinals; 36360484Sobrienstatic const char *dll_name; 36460484Sobrienstatic int min_ordinal, max_ordinal; 36560484Sobrienstatic int *exported_symbols; 36660484Sobrien 36789857Sobrientypedef struct exclude_list_struct 36889857Sobrien { 36989857Sobrien char *string; 37089857Sobrien struct exclude_list_struct *next; 37189857Sobrien } 37289857Sobrienexclude_list_struct; 37377298Sobrien 37460484Sobrienstatic struct exclude_list_struct *excludes = 0; 37560484Sobrien 37660484Sobrienvoid 37760484Sobrienpe_dll_add_excludes (new_excludes) 37860484Sobrien const char *new_excludes; 37960484Sobrien{ 38060484Sobrien char *local_copy; 38160484Sobrien char *exclude_string; 38260484Sobrien 38360484Sobrien local_copy = xstrdup (new_excludes); 38460484Sobrien 38560484Sobrien exclude_string = strtok (local_copy, ",:"); 38660484Sobrien for (; exclude_string; exclude_string = strtok (NULL, ",:")) 38760484Sobrien { 38860484Sobrien struct exclude_list_struct *new_exclude; 38960484Sobrien 39060484Sobrien new_exclude = ((struct exclude_list_struct *) 39160484Sobrien xmalloc (sizeof (struct exclude_list_struct))); 39260484Sobrien new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 1); 39360484Sobrien strcpy (new_exclude->string, exclude_string); 39460484Sobrien new_exclude->next = excludes; 39560484Sobrien excludes = new_exclude; 39660484Sobrien } 39760484Sobrien 39860484Sobrien free (local_copy); 39960484Sobrien} 40060484Sobrien 40189857Sobrien/* abfd is a bfd containing n (or NULL) 40289857Sobrien It can be used for contextual checks. */ 40389857Sobrien 40460484Sobrienstatic int 40589857Sobrienauto_export (abfd, d, n) 40689857Sobrien bfd *abfd; 40760484Sobrien def_file *d; 40860484Sobrien const char *n; 40960484Sobrien{ 41060484Sobrien int i; 41160484Sobrien struct exclude_list_struct *ex; 41289857Sobrien autofilter_entry_type *afptr; 41389857Sobrien 41489857Sobrien /* We should not re-export imported stuff. */ 41589857Sobrien if (strncmp (n, "_imp__", 6) == 0) 41689857Sobrien return 0; 41789857Sobrien 41860484Sobrien for (i = 0; i < d->num_exports; i++) 41960484Sobrien if (strcmp (d->exports[i].name, n) == 0) 42060484Sobrien return 0; 42189857Sobrien 42260484Sobrien if (pe_dll_do_default_excludes) 42360484Sobrien { 42489857Sobrien const char * p; 42589857Sobrien int len; 42689857Sobrien 42789857Sobrien if (pe_dll_extra_pe_debug) 42889857Sobrien printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n", 42989857Sobrien n, abfd, abfd->my_archive); 43089857Sobrien 43189857Sobrien /* First of all, make context checks: 43289857Sobrien Don't export anything from libgcc. */ 43389857Sobrien if (abfd && abfd->my_archive) 43489857Sobrien { 43589857Sobrien afptr = autofilter_liblist; 43689857Sobrien 43789857Sobrien while (afptr->name) 43889857Sobrien { 43989857Sobrien if (strstr (abfd->my_archive->filename, afptr->name)) 44089857Sobrien return 0; 44189857Sobrien afptr++; 44289857Sobrien } 44389857Sobrien } 44489857Sobrien 44589857Sobrien /* Next, exclude symbols from certain startup objects. */ 44689857Sobrien 44789857Sobrien if (abfd && (p = lbasename (abfd->filename))) 44889857Sobrien { 44989857Sobrien afptr = autofilter_objlist; 45089857Sobrien while (afptr->name) 45189857Sobrien { 45289857Sobrien if ( strcmp (p, afptr->name) == 0 ) 45389857Sobrien return 0; 45489857Sobrien afptr++; 45589857Sobrien } 45689857Sobrien } 45789857Sobrien 45889857Sobrien /* Don't try to blindly exclude all symbols 45989857Sobrien that begin with '__'; this was tried and 46089857Sobrien it is too restrictive. */ 46189857Sobrien 46289857Sobrien /* Then, exclude specific symbols. */ 46389857Sobrien afptr = autofilter_symbollist; 46489857Sobrien while (afptr->name) 46589857Sobrien { 46689857Sobrien if (strcmp (n, afptr->name) == 0) 46789857Sobrien return 0; 46889857Sobrien 46989857Sobrien afptr ++; 47089857Sobrien } 47189857Sobrien 47289857Sobrien /* Next, exclude symbols starting with ... */ 47389857Sobrien afptr = autofilter_symbolprefixlist; 47489857Sobrien while (afptr->name) 47589857Sobrien { 47689857Sobrien if (strncmp (n, afptr->name, afptr->len) == 0) 47789857Sobrien return 0; 47889857Sobrien 47989857Sobrien afptr ++; 48089857Sobrien } 48189857Sobrien 48289857Sobrien /* Finally, exclude symbols ending with ... */ 48389857Sobrien len = strlen (n); 48489857Sobrien afptr = autofilter_symbolsuffixlist; 48589857Sobrien while (afptr->name) 48689857Sobrien { 48789857Sobrien if ((len >= afptr->len) && 48889857Sobrien /* Add 1 to insure match with trailing '\0'. */ 48989857Sobrien strncmp (n + len - afptr->len, afptr->name, 49089857Sobrien afptr->len + 1) == 0) 49189857Sobrien return 0; 49289857Sobrien 49389857Sobrien afptr ++; 49489857Sobrien } 49560484Sobrien } 49689857Sobrien 49760484Sobrien for (ex = excludes; ex; ex = ex->next) 49860484Sobrien if (strcmp (n, ex->string) == 0) 49960484Sobrien return 0; 50089857Sobrien 50160484Sobrien return 1; 50260484Sobrien} 50360484Sobrien 50460484Sobrienstatic void 50560484Sobrienprocess_def_file (abfd, info) 50660484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 50760484Sobrien struct bfd_link_info *info; 50860484Sobrien{ 50960484Sobrien int i, j; 51060484Sobrien struct bfd_link_hash_entry *blhe; 51160484Sobrien bfd *b; 51260484Sobrien struct sec *s; 51377298Sobrien def_file_export *e = 0; 51460484Sobrien 51560484Sobrien if (!pe_def_file) 51660484Sobrien pe_def_file = def_file_empty (); 51760484Sobrien 51860484Sobrien /* First, run around to all the objects looking for the .drectve 51977298Sobrien sections, and push those into the def file too. */ 52060484Sobrien for (b = info->input_bfds; b; b = b->link_next) 52160484Sobrien { 52260484Sobrien s = bfd_get_section_by_name (b, ".drectve"); 52360484Sobrien if (s) 52460484Sobrien { 52560484Sobrien int size = bfd_get_section_size_before_reloc (s); 52660484Sobrien char *buf = xmalloc (size); 52789857Sobrien 52860484Sobrien bfd_get_section_contents (b, s, buf, 0, size); 52960484Sobrien def_file_add_directive (pe_def_file, buf, size); 53060484Sobrien free (buf); 53160484Sobrien } 53260484Sobrien } 53360484Sobrien 53477298Sobrien /* Now, maybe export everything else the default way. */ 53560484Sobrien if (pe_dll_export_everything || pe_def_file->num_exports == 0) 53660484Sobrien { 53760484Sobrien for (b = info->input_bfds; b; b = b->link_next) 53860484Sobrien { 53960484Sobrien asymbol **symbols; 54060484Sobrien int nsyms, symsize; 54160484Sobrien 54260484Sobrien symsize = bfd_get_symtab_upper_bound (b); 54360484Sobrien symbols = (asymbol **) xmalloc (symsize); 54460484Sobrien nsyms = bfd_canonicalize_symtab (b, symbols); 54560484Sobrien 54660484Sobrien for (j = 0; j < nsyms; j++) 54760484Sobrien { 54877298Sobrien /* We should export symbols which are either global or not 54989857Sobrien anything at all. (.bss data is the latter) 55089857Sobrien We should not export undefined symbols. */ 55189857Sobrien if (symbols[j]->section != &bfd_und_section 55289857Sobrien && ((symbols[j]->flags & BSF_GLOBAL) 55389857Sobrien || (symbols[j]->flags == BFD_FORT_COMM_DEFAULT_VALUE))) 55460484Sobrien { 55560484Sobrien const char *sn = symbols[j]->name; 55689857Sobrien 55789857Sobrien /* We should not re-export imported stuff. */ 55889857Sobrien { 55989857Sobrien char *name = (char *) xmalloc (strlen (sn) + 2 + 6); 56089857Sobrien sprintf (name, "%s%s", U("_imp_"), sn); 56189857Sobrien 56289857Sobrien blhe = bfd_link_hash_lookup (info->hash, name, 56389857Sobrien false, false, false); 56489857Sobrien free (name); 56589857Sobrien 56689857Sobrien if (blhe && blhe->type == bfd_link_hash_defined) 56789857Sobrien continue; 56889857Sobrien } 56989857Sobrien 57060484Sobrien if (*sn == '_') 57160484Sobrien sn++; 57289857Sobrien 57389857Sobrien if (auto_export (b, pe_def_file, sn)) 57489857Sobrien { 57589857Sobrien def_file_export *p; 57689857Sobrien p=def_file_add_export (pe_def_file, sn, 0, -1); 57789857Sobrien /* Fill data flag properly, from dlltool.c. */ 57889857Sobrien p->flag_data = !(symbols[j]->flags & BSF_FUNCTION); 57989857Sobrien } 58060484Sobrien } 58160484Sobrien } 58260484Sobrien } 58360484Sobrien } 58460484Sobrien 58560484Sobrien#undef NE 58660484Sobrien#define NE pe_def_file->num_exports 58760484Sobrien 58877298Sobrien /* Canonicalize the export list. */ 58960484Sobrien if (pe_dll_kill_ats) 59060484Sobrien { 59160484Sobrien for (i = 0; i < NE; i++) 59260484Sobrien { 59360484Sobrien if (strchr (pe_def_file->exports[i].name, '@')) 59460484Sobrien { 59577298Sobrien /* This will preserve internal_name, which may have been 59677298Sobrien pointing to the same memory as name, or might not 59777298Sobrien have. */ 59860484Sobrien char *tmp = xstrdup (pe_def_file->exports[i].name); 59989857Sobrien 60060484Sobrien *(strchr (tmp, '@')) = 0; 60160484Sobrien pe_def_file->exports[i].name = tmp; 60260484Sobrien } 60360484Sobrien } 60460484Sobrien } 60560484Sobrien 60660484Sobrien if (pe_dll_stdcall_aliases) 60760484Sobrien { 60860484Sobrien for (i = 0; i < NE; i++) 60960484Sobrien { 61060484Sobrien if (strchr (pe_def_file->exports[i].name, '@')) 61160484Sobrien { 61260484Sobrien char *tmp = xstrdup (pe_def_file->exports[i].name); 61389857Sobrien 61460484Sobrien *(strchr (tmp, '@')) = 0; 61589857Sobrien if (auto_export (NULL, pe_def_file, tmp)) 61660484Sobrien def_file_add_export (pe_def_file, tmp, 61789857Sobrien pe_def_file->exports[i].internal_name, 61889857Sobrien -1); 61960484Sobrien else 62060484Sobrien free (tmp); 62160484Sobrien } 62260484Sobrien } 62360484Sobrien } 62460484Sobrien 62577298Sobrien /* Convenience, but watch out for it changing. */ 62677298Sobrien e = pe_def_file->exports; 62760484Sobrien 62860484Sobrien exported_symbol_offsets = (bfd_vma *) xmalloc (NE * sizeof (bfd_vma)); 62960484Sobrien exported_symbol_sections = (struct sec **) xmalloc (NE * sizeof (struct sec *)); 63060484Sobrien 63160484Sobrien memset (exported_symbol_sections, 0, NE * sizeof (struct sec *)); 63260484Sobrien max_ordinal = 0; 63360484Sobrien min_ordinal = 65536; 63460484Sobrien count_exported = 0; 63560484Sobrien count_exported_byname = 0; 63660484Sobrien count_with_ordinals = 0; 63760484Sobrien 63860484Sobrien qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]), pe_export_sort); 63960484Sobrien for (i = 0, j = 0; i < NE; i++) 64060484Sobrien { 64160484Sobrien if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0) 64260484Sobrien { 64360484Sobrien /* This is a duplicate. */ 64460484Sobrien if (e[j - 1].ordinal != -1 64560484Sobrien && e[i].ordinal != -1 64660484Sobrien && e[j - 1].ordinal != e[i].ordinal) 64760484Sobrien { 64860484Sobrien if (pe_dll_warn_dup_exports) 64960484Sobrien /* xgettext:c-format */ 65077298Sobrien einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"), 65160484Sobrien e[j - 1].name, e[j - 1].ordinal, e[i].ordinal); 65260484Sobrien } 65360484Sobrien else 65460484Sobrien { 65560484Sobrien if (pe_dll_warn_dup_exports) 65660484Sobrien /* xgettext:c-format */ 65760484Sobrien einfo (_("Warning, duplicate EXPORT: %s\n"), 65860484Sobrien e[j - 1].name); 65960484Sobrien } 66089857Sobrien 66177298Sobrien if (e[i].ordinal != -1) 66260484Sobrien e[j - 1].ordinal = e[i].ordinal; 66360484Sobrien e[j - 1].flag_private |= e[i].flag_private; 66460484Sobrien e[j - 1].flag_constant |= e[i].flag_constant; 66560484Sobrien e[j - 1].flag_noname |= e[i].flag_noname; 66660484Sobrien e[j - 1].flag_data |= e[i].flag_data; 66760484Sobrien } 66860484Sobrien else 66960484Sobrien { 67060484Sobrien if (i != j) 67160484Sobrien e[j] = e[i]; 67260484Sobrien j++; 67360484Sobrien } 67460484Sobrien } 67560484Sobrien pe_def_file->num_exports = j; /* == NE */ 67660484Sobrien 67760484Sobrien for (i = 0; i < NE; i++) 67860484Sobrien { 67960484Sobrien char *name = (char *) xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); 68089857Sobrien 68160484Sobrien if (pe_details->underscored) 68260484Sobrien { 68360484Sobrien *name = '_'; 68460484Sobrien strcpy (name + 1, pe_def_file->exports[i].internal_name); 68560484Sobrien } 68660484Sobrien else 68760484Sobrien strcpy (name, pe_def_file->exports[i].internal_name); 68860484Sobrien 68960484Sobrien blhe = bfd_link_hash_lookup (info->hash, 69060484Sobrien name, 69160484Sobrien false, false, true); 69260484Sobrien 69360484Sobrien if (blhe 69477298Sobrien && (blhe->type == bfd_link_hash_defined 69560484Sobrien || (blhe->type == bfd_link_hash_common))) 69660484Sobrien { 69760484Sobrien count_exported++; 69860484Sobrien if (!pe_def_file->exports[i].flag_noname) 69960484Sobrien count_exported_byname++; 70060484Sobrien 70160484Sobrien /* Only fill in the sections. The actual offsets are computed 70260484Sobrien in fill_exported_offsets() after common symbols are laid 70360484Sobrien out. */ 70477298Sobrien if (blhe->type == bfd_link_hash_defined) 70560484Sobrien exported_symbol_sections[i] = blhe->u.def.section; 70660484Sobrien else 70760484Sobrien exported_symbol_sections[i] = blhe->u.c.p->section; 70877298Sobrien 70960484Sobrien if (pe_def_file->exports[i].ordinal != -1) 71060484Sobrien { 71160484Sobrien if (max_ordinal < pe_def_file->exports[i].ordinal) 71260484Sobrien max_ordinal = pe_def_file->exports[i].ordinal; 71360484Sobrien if (min_ordinal > pe_def_file->exports[i].ordinal) 71460484Sobrien min_ordinal = pe_def_file->exports[i].ordinal; 71560484Sobrien count_with_ordinals++; 71660484Sobrien } 71760484Sobrien } 71860484Sobrien else if (blhe && blhe->type == bfd_link_hash_undefined) 71960484Sobrien { 72060484Sobrien /* xgettext:c-format */ 72160484Sobrien einfo (_("%XCannot export %s: symbol not defined\n"), 72260484Sobrien pe_def_file->exports[i].internal_name); 72360484Sobrien } 72460484Sobrien else if (blhe) 72560484Sobrien { 72660484Sobrien /* xgettext:c-format */ 72760484Sobrien einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"), 72860484Sobrien pe_def_file->exports[i].internal_name, 72960484Sobrien blhe->type, bfd_link_hash_defined); 73060484Sobrien } 73160484Sobrien else 73260484Sobrien { 73360484Sobrien /* xgettext:c-format */ 73460484Sobrien einfo (_("%XCannot export %s: symbol not found\n"), 73560484Sobrien pe_def_file->exports[i].internal_name); 73660484Sobrien } 73760484Sobrien free (name); 73860484Sobrien } 73960484Sobrien} 74060484Sobrien 74189857Sobrien/* Build the bfd that will contain .edata and .reloc sections. */ 74260484Sobrien 74360484Sobrienstatic void 74460484Sobrienbuild_filler_bfd (include_edata) 74560484Sobrien int include_edata; 74660484Sobrien{ 74760484Sobrien lang_input_statement_type *filler_file; 74860484Sobrien filler_file = lang_add_input_file ("dll stuff", 74960484Sobrien lang_input_file_is_fake_enum, 75060484Sobrien NULL); 75160484Sobrien filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", output_bfd); 75260484Sobrien if (filler_bfd == NULL 75360484Sobrien || !bfd_set_arch_mach (filler_bfd, 75460484Sobrien bfd_get_arch (output_bfd), 75560484Sobrien bfd_get_mach (output_bfd))) 75660484Sobrien { 75760484Sobrien einfo ("%X%P: can not create BFD %E\n"); 75860484Sobrien return; 75960484Sobrien } 76060484Sobrien 76160484Sobrien if (include_edata) 76260484Sobrien { 76360484Sobrien edata_s = bfd_make_section_old_way (filler_bfd, ".edata"); 76460484Sobrien if (edata_s == NULL 76560484Sobrien || !bfd_set_section_flags (filler_bfd, edata_s, 76660484Sobrien (SEC_HAS_CONTENTS 76760484Sobrien | SEC_ALLOC 76860484Sobrien | SEC_LOAD 76960484Sobrien | SEC_KEEP 77060484Sobrien | SEC_IN_MEMORY))) 77160484Sobrien { 77260484Sobrien einfo ("%X%P: can not create .edata section: %E\n"); 77360484Sobrien return; 77460484Sobrien } 77560484Sobrien bfd_set_section_size (filler_bfd, edata_s, edata_sz); 77660484Sobrien } 77760484Sobrien 77860484Sobrien reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc"); 77960484Sobrien if (reloc_s == NULL 78060484Sobrien || !bfd_set_section_flags (filler_bfd, reloc_s, 78160484Sobrien (SEC_HAS_CONTENTS 78260484Sobrien | SEC_ALLOC 78360484Sobrien | SEC_LOAD 78460484Sobrien | SEC_KEEP 78560484Sobrien | SEC_IN_MEMORY))) 78660484Sobrien { 78760484Sobrien einfo ("%X%P: can not create .reloc section: %E\n"); 78860484Sobrien return; 78960484Sobrien } 79089857Sobrien 79160484Sobrien bfd_set_section_size (filler_bfd, reloc_s, 0); 79260484Sobrien 79360484Sobrien ldlang_add_file (filler_file); 79460484Sobrien} 79560484Sobrien 79689857Sobrien/* Gather all the exported symbols and build the .edata section. */ 79760484Sobrien 79860484Sobrienstatic void 79960484Sobriengenerate_edata (abfd, info) 80060484Sobrien bfd *abfd; 80160484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 80260484Sobrien{ 80360484Sobrien int i, next_ordinal; 80460484Sobrien int name_table_size = 0; 80560484Sobrien const char *dlnp; 80660484Sobrien 80760484Sobrien /* First, we need to know how many exported symbols there are, 80877298Sobrien and what the range of ordinals is. */ 80960484Sobrien if (pe_def_file->name) 81089857Sobrien dll_name = pe_def_file->name; 81160484Sobrien else 81260484Sobrien { 81360484Sobrien dll_name = abfd->filename; 81489857Sobrien 81560484Sobrien for (dlnp = dll_name; *dlnp; dlnp++) 81689857Sobrien if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':') 81789857Sobrien dll_name = dlnp + 1; 81860484Sobrien } 81960484Sobrien 82060484Sobrien if (count_with_ordinals && max_ordinal > count_exported) 82160484Sobrien { 82260484Sobrien if (min_ordinal > max_ordinal - count_exported + 1) 82360484Sobrien min_ordinal = max_ordinal - count_exported + 1; 82460484Sobrien } 82560484Sobrien else 82660484Sobrien { 82760484Sobrien min_ordinal = 1; 82860484Sobrien max_ordinal = count_exported; 82960484Sobrien } 83089857Sobrien 83160484Sobrien export_table_size = max_ordinal - min_ordinal + 1; 83260484Sobrien exported_symbols = (int *) xmalloc (export_table_size * sizeof (int)); 83360484Sobrien for (i = 0; i < export_table_size; i++) 83460484Sobrien exported_symbols[i] = -1; 83560484Sobrien 83677298Sobrien /* Now we need to assign ordinals to those that don't have them. */ 83760484Sobrien for (i = 0; i < NE; i++) 83860484Sobrien { 83960484Sobrien if (exported_symbol_sections[i]) 84060484Sobrien { 84160484Sobrien if (pe_def_file->exports[i].ordinal != -1) 84260484Sobrien { 84360484Sobrien int ei = pe_def_file->exports[i].ordinal - min_ordinal; 84460484Sobrien int pi = exported_symbols[ei]; 84589857Sobrien 84660484Sobrien if (pi != -1) 84760484Sobrien { 84860484Sobrien /* xgettext:c-format */ 84977298Sobrien einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"), 85060484Sobrien pe_def_file->exports[i].ordinal, 85160484Sobrien pe_def_file->exports[i].name, 85260484Sobrien pe_def_file->exports[pi].name); 85360484Sobrien } 85460484Sobrien exported_symbols[ei] = i; 85560484Sobrien } 85660484Sobrien name_table_size += strlen (pe_def_file->exports[i].name) + 1; 85760484Sobrien } 85860484Sobrien } 85960484Sobrien 86060484Sobrien next_ordinal = min_ordinal; 86160484Sobrien for (i = 0; i < NE; i++) 86260484Sobrien if (exported_symbol_sections[i]) 86360484Sobrien if (pe_def_file->exports[i].ordinal == -1) 86460484Sobrien { 86560484Sobrien while (exported_symbols[next_ordinal - min_ordinal] != -1) 86689857Sobrien next_ordinal ++; 86789857Sobrien 86860484Sobrien exported_symbols[next_ordinal - min_ordinal] = i; 86960484Sobrien pe_def_file->exports[i].ordinal = next_ordinal; 87060484Sobrien } 87160484Sobrien 87277298Sobrien /* OK, now we can allocate some memory. */ 87389857Sobrien edata_sz = (40 /* directory */ 87489857Sobrien + 4 * export_table_size /* addresses */ 87560484Sobrien + 4 * count_exported_byname /* name ptrs */ 87660484Sobrien + 2 * count_exported_byname /* ordinals */ 87760484Sobrien + name_table_size + strlen (dll_name) + 1); 87860484Sobrien} 87960484Sobrien 88060484Sobrien/* Fill the exported symbol offsets. The preliminary work has already 88160484Sobrien been done in process_def_file(). */ 88260484Sobrien 88360484Sobrienstatic void 88460484Sobrienfill_exported_offsets (abfd, info) 88560484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 88660484Sobrien struct bfd_link_info *info; 88760484Sobrien{ 88860484Sobrien int i; 88960484Sobrien struct bfd_link_hash_entry *blhe; 89077298Sobrien 89160484Sobrien for (i = 0; i < pe_def_file->num_exports; i++) 89260484Sobrien { 89360484Sobrien char *name = (char *) xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2); 89489857Sobrien 89560484Sobrien if (pe_details->underscored) 89660484Sobrien { 89760484Sobrien *name = '_'; 89860484Sobrien strcpy (name + 1, pe_def_file->exports[i].internal_name); 89960484Sobrien } 90060484Sobrien else 90160484Sobrien strcpy (name, pe_def_file->exports[i].internal_name); 90260484Sobrien 90360484Sobrien blhe = bfd_link_hash_lookup (info->hash, 90460484Sobrien name, 90560484Sobrien false, false, true); 90660484Sobrien 90760484Sobrien if (blhe && (blhe->type == bfd_link_hash_defined)) 90889857Sobrien exported_symbol_offsets[i] = blhe->u.def.value; 90989857Sobrien 91060484Sobrien free (name); 91160484Sobrien } 91260484Sobrien} 91360484Sobrien 91460484Sobrienstatic void 91560484Sobrienfill_edata (abfd, info) 91660484Sobrien bfd *abfd; 91760484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 91860484Sobrien{ 91960484Sobrien int i, hint; 92060484Sobrien unsigned char *edirectory; 92160484Sobrien unsigned long *eaddresses; 92260484Sobrien unsigned long *enameptrs; 92360484Sobrien unsigned short *eordinals; 92460484Sobrien unsigned char *enamestr; 92560484Sobrien time_t now; 92660484Sobrien 92760484Sobrien time (&now); 92860484Sobrien 92960484Sobrien edata_d = (unsigned char *) xmalloc (edata_sz); 93060484Sobrien 93177298Sobrien /* Note use of array pointer math here. */ 93260484Sobrien edirectory = edata_d; 93360484Sobrien eaddresses = (unsigned long *) (edata_d + 40); 93460484Sobrien enameptrs = eaddresses + export_table_size; 93560484Sobrien eordinals = (unsigned short *) (enameptrs + count_exported_byname); 93660484Sobrien enamestr = (char *) (eordinals + count_exported_byname); 93760484Sobrien 93860484Sobrien#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) + edata_s->output_section->vma - image_base) 93960484Sobrien 94077298Sobrien memset (edata_d, 0, edata_sz); 94160484Sobrien bfd_put_32 (abfd, now, edata_d + 4); 94260484Sobrien if (pe_def_file->version_major != -1) 94360484Sobrien { 94460484Sobrien bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8); 94560484Sobrien bfd_put_16 (abfd, pe_def_file->version_minor, edata_d + 10); 94660484Sobrien } 94789857Sobrien 94860484Sobrien bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12); 94960484Sobrien strcpy (enamestr, dll_name); 95060484Sobrien enamestr += strlen (enamestr) + 1; 95160484Sobrien bfd_put_32 (abfd, min_ordinal, edata_d + 16); 95260484Sobrien bfd_put_32 (abfd, export_table_size, edata_d + 20); 95360484Sobrien bfd_put_32 (abfd, count_exported_byname, edata_d + 24); 95460484Sobrien bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28); 95560484Sobrien bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32); 95660484Sobrien bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36); 95760484Sobrien 95860484Sobrien fill_exported_offsets (abfd, info); 95960484Sobrien 96077298Sobrien /* Ok, now for the filling in part. */ 96160484Sobrien hint = 0; 96260484Sobrien for (i = 0; i < export_table_size; i++) 96360484Sobrien { 96460484Sobrien int s = exported_symbols[i]; 96589857Sobrien 96660484Sobrien if (s != -1) 96760484Sobrien { 96860484Sobrien struct sec *ssec = exported_symbol_sections[s]; 96960484Sobrien unsigned long srva = (exported_symbol_offsets[s] 97060484Sobrien + ssec->output_section->vma 97160484Sobrien + ssec->output_offset); 97277298Sobrien int ord = pe_def_file->exports[s].ordinal; 97360484Sobrien 97477298Sobrien bfd_put_32 (abfd, srva - image_base, 97577298Sobrien (void *) (eaddresses + ord - min_ordinal)); 97689857Sobrien 97760484Sobrien if (!pe_def_file->exports[s].flag_noname) 97860484Sobrien { 97960484Sobrien char *ename = pe_def_file->exports[s].name; 98060484Sobrien bfd_put_32 (abfd, ERVA (enamestr), (void *) enameptrs); 98177298Sobrien enameptrs++; 98260484Sobrien strcpy (enamestr, ename); 98360484Sobrien enamestr += strlen (enamestr) + 1; 98477298Sobrien bfd_put_16 (abfd, ord - min_ordinal, (void *) eordinals); 98577298Sobrien eordinals++; 98660484Sobrien pe_def_file->exports[s].hint = hint++; 98760484Sobrien } 98860484Sobrien } 98960484Sobrien } 99060484Sobrien} 99160484Sobrien 99260484Sobrien 99389857Sobrienstatic struct sec *current_sec; 99460484Sobrien 99589857Sobrienvoid 99689857Sobrienpe_walk_relocs_of_symbol (info, name, cb) 99789857Sobrien struct bfd_link_info *info; 99889857Sobrien const char *name; 99989857Sobrien int (*cb) (arelent *, asection *); 100089857Sobrien{ 100189857Sobrien bfd *b; 100289857Sobrien asection *s; 100360484Sobrien 100489857Sobrien for (b = info->input_bfds; b; b = b->link_next) 100589857Sobrien { 100689857Sobrien asymbol **symbols; 100789857Sobrien int nsyms, symsize; 100889857Sobrien 100989857Sobrien symsize = bfd_get_symtab_upper_bound (b); 101089857Sobrien symbols = (asymbol **) xmalloc (symsize); 101189857Sobrien nsyms = bfd_canonicalize_symtab (b, symbols); 101289857Sobrien 101389857Sobrien for (s = b->sections; s; s = s->next) 101489857Sobrien { 101589857Sobrien arelent **relocs; 101689857Sobrien int relsize, nrelocs, i; 101789857Sobrien int flags = bfd_get_section_flags (b, s); 101889857Sobrien 101989857Sobrien /* Skip discarded linkonce sections. */ 102089857Sobrien if (flags & SEC_LINK_ONCE 102189857Sobrien && s->output_section == bfd_abs_section_ptr) 102289857Sobrien continue; 102389857Sobrien 102489857Sobrien current_sec = s; 102589857Sobrien 102689857Sobrien relsize = bfd_get_reloc_upper_bound (b, s); 102789857Sobrien relocs = (arelent **) xmalloc ((size_t) relsize); 102889857Sobrien nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols); 102989857Sobrien 103089857Sobrien for (i = 0; i < nrelocs; i++) 103189857Sobrien { 103289857Sobrien struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr; 103389857Sobrien 103489857Sobrien if (!strcmp (name, sym->name)) 103589857Sobrien cb (relocs[i], s); 103689857Sobrien } 103789857Sobrien 103889857Sobrien free (relocs); 103989857Sobrien 104089857Sobrien /* Warning: the allocated symbols are remembered in BFD and reused 104189857Sobrien later, so don't free them! */ 104289857Sobrien /* free (symbols); */ 104389857Sobrien } 104489857Sobrien } 104589857Sobrien} 104689857Sobrien 104789857Sobrien/* Gather all the relocations and build the .reloc section. */ 104889857Sobrien 104960484Sobrienstatic void 105060484Sobriengenerate_reloc (abfd, info) 105160484Sobrien bfd *abfd; 105260484Sobrien struct bfd_link_info *info; 105360484Sobrien{ 105460484Sobrien 105577298Sobrien /* For .reloc stuff. */ 105660484Sobrien reloc_data_type *reloc_data; 105760484Sobrien int total_relocs = 0; 105860484Sobrien int i; 105960484Sobrien unsigned long sec_page = (unsigned long) (-1); 106060484Sobrien unsigned long page_ptr, page_count; 106160484Sobrien int bi; 106260484Sobrien bfd *b; 106360484Sobrien struct sec *s; 106460484Sobrien 106560484Sobrien total_relocs = 0; 106660484Sobrien for (b = info->input_bfds; b; b = b->link_next) 106760484Sobrien for (s = b->sections; s; s = s->next) 106860484Sobrien total_relocs += s->reloc_count; 106960484Sobrien 107089857Sobrien reloc_data = 107189857Sobrien (reloc_data_type *) xmalloc (total_relocs * sizeof (reloc_data_type)); 107260484Sobrien 107360484Sobrien total_relocs = 0; 107460484Sobrien bi = 0; 107560484Sobrien for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next) 107660484Sobrien { 107760484Sobrien arelent **relocs; 107860484Sobrien int relsize, nrelocs, i; 107960484Sobrien 108060484Sobrien for (s = b->sections; s; s = s->next) 108160484Sobrien { 108260484Sobrien unsigned long sec_vma = s->output_section->vma + s->output_offset; 108360484Sobrien asymbol **symbols; 108460484Sobrien int nsyms, symsize; 108560484Sobrien 108677298Sobrien /* If it's not loaded, we don't need to relocate it this way. */ 108760484Sobrien if (!(s->output_section->flags & SEC_LOAD)) 108860484Sobrien continue; 108960484Sobrien 109060484Sobrien /* I don't know why there would be a reloc for these, but I've 109177298Sobrien seen it happen - DJ */ 109260484Sobrien if (s->output_section == &bfd_abs_section) 109360484Sobrien continue; 109460484Sobrien 109560484Sobrien if (s->output_section->vma == 0) 109660484Sobrien { 109777298Sobrien /* Huh? Shouldn't happen, but punt if it does. */ 109860484Sobrien einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n", 109960484Sobrien s->output_section->name, s->output_section->index, 110060484Sobrien s->output_section->flags); 110160484Sobrien continue; 110260484Sobrien } 110360484Sobrien 110460484Sobrien symsize = bfd_get_symtab_upper_bound (b); 110560484Sobrien symbols = (asymbol **) xmalloc (symsize); 110660484Sobrien nsyms = bfd_canonicalize_symtab (b, symbols); 110760484Sobrien 110860484Sobrien relsize = bfd_get_reloc_upper_bound (b, s); 110960484Sobrien relocs = (arelent **) xmalloc ((size_t) relsize); 111060484Sobrien nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols); 111160484Sobrien 111260484Sobrien for (i = 0; i < nrelocs; i++) 111360484Sobrien { 111489857Sobrien if (pe_dll_extra_pe_debug) 111589857Sobrien { 111689857Sobrien struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr; 111789857Sobrien printf("rel: %s\n",sym->name); 111889857Sobrien } 111960484Sobrien if (!relocs[i]->howto->pc_relative 112060484Sobrien && relocs[i]->howto->type != pe_details->imagebase_reloc) 112160484Sobrien { 112260484Sobrien bfd_vma sym_vma; 112360484Sobrien struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr; 112489857Sobrien 112560484Sobrien sym_vma = (relocs[i]->addend 112660484Sobrien + sym->value 112760484Sobrien + sym->section->vma 112860484Sobrien + sym->section->output_offset 112960484Sobrien + sym->section->output_section->vma); 113060484Sobrien reloc_data[total_relocs].vma = sec_vma + relocs[i]->address; 113177298Sobrien 113260484Sobrien#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift) 113377298Sobrien 113460484Sobrien switch BITS_AND_SHIFT (relocs[i]->howto->bitsize, 113560484Sobrien relocs[i]->howto->rightshift) 113660484Sobrien { 113760484Sobrien case BITS_AND_SHIFT (32, 0): 113860484Sobrien reloc_data[total_relocs].type = 3; 113960484Sobrien total_relocs++; 114060484Sobrien break; 114160484Sobrien case BITS_AND_SHIFT (16, 0): 114260484Sobrien reloc_data[total_relocs].type = 2; 114360484Sobrien total_relocs++; 114460484Sobrien break; 114560484Sobrien case BITS_AND_SHIFT (16, 16): 114660484Sobrien reloc_data[total_relocs].type = 4; 114777298Sobrien /* FIXME: we can't know the symbol's right value 114877298Sobrien yet, but we probably can safely assume that 114977298Sobrien CE will relocate us in 64k blocks, so leaving 115077298Sobrien it zero is safe. */ 115160484Sobrien reloc_data[total_relocs].extra = 0; 115260484Sobrien total_relocs++; 115360484Sobrien break; 115460484Sobrien case BITS_AND_SHIFT (26, 2): 115560484Sobrien reloc_data[total_relocs].type = 5; 115660484Sobrien total_relocs++; 115760484Sobrien break; 115860484Sobrien default: 115960484Sobrien /* xgettext:c-format */ 116060484Sobrien einfo (_("%XError: %d-bit reloc in dll\n"), 116160484Sobrien relocs[i]->howto->bitsize); 116260484Sobrien break; 116360484Sobrien } 116460484Sobrien } 116560484Sobrien } 116660484Sobrien free (relocs); 116777298Sobrien /* Warning: the allocated symbols are remembered in BFD and 116877298Sobrien reused later, so don't free them! */ 116977298Sobrien#if 0 117077298Sobrien free (symbol); 117177298Sobrien#endif 117260484Sobrien } 117360484Sobrien } 117460484Sobrien 117560484Sobrien /* At this point, we have total_relocs relocation addresses in 117660484Sobrien reloc_addresses, which are all suitable for the .reloc section. 117777298Sobrien We must now create the new sections. */ 117860484Sobrien qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort); 117960484Sobrien 118060484Sobrien for (i = 0; i < total_relocs; i++) 118160484Sobrien { 118260484Sobrien unsigned long this_page = (reloc_data[i].vma >> 12); 118377298Sobrien 118460484Sobrien if (this_page != sec_page) 118560484Sobrien { 118689857Sobrien reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */ 118760484Sobrien reloc_sz += 8; 118860484Sobrien sec_page = this_page; 118960484Sobrien } 119077298Sobrien 119160484Sobrien reloc_sz += 2; 119277298Sobrien 119360484Sobrien if (reloc_data[i].type == 4) 119460484Sobrien reloc_sz += 2; 119560484Sobrien } 119689857Sobrien 119789857Sobrien reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */ 119860484Sobrien reloc_d = (unsigned char *) xmalloc (reloc_sz); 119960484Sobrien sec_page = (unsigned long) (-1); 120060484Sobrien reloc_sz = 0; 120160484Sobrien page_ptr = (unsigned long) (-1); 120260484Sobrien page_count = 0; 120389857Sobrien 120460484Sobrien for (i = 0; i < total_relocs; i++) 120560484Sobrien { 120660484Sobrien unsigned long rva = reloc_data[i].vma - image_base; 120760484Sobrien unsigned long this_page = (rva & ~0xfff); 120889857Sobrien 120960484Sobrien if (this_page != sec_page) 121060484Sobrien { 121160484Sobrien while (reloc_sz & 3) 121260484Sobrien reloc_d[reloc_sz++] = 0; 121389857Sobrien 121460484Sobrien if (page_ptr != (unsigned long) (-1)) 121560484Sobrien bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4); 121689857Sobrien 121760484Sobrien bfd_put_32 (abfd, this_page, reloc_d + reloc_sz); 121860484Sobrien page_ptr = reloc_sz; 121960484Sobrien reloc_sz += 8; 122060484Sobrien sec_page = this_page; 122160484Sobrien page_count = 0; 122260484Sobrien } 122389857Sobrien 122477298Sobrien bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12), 122560484Sobrien reloc_d + reloc_sz); 122660484Sobrien reloc_sz += 2; 122789857Sobrien 122860484Sobrien if (reloc_data[i].type == 4) 122960484Sobrien { 123060484Sobrien bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz); 123160484Sobrien reloc_sz += 2; 123260484Sobrien } 123389857Sobrien 123460484Sobrien page_count++; 123560484Sobrien } 123689857Sobrien 123760484Sobrien while (reloc_sz & 3) 123860484Sobrien reloc_d[reloc_sz++] = 0; 123989857Sobrien 124060484Sobrien if (page_ptr != (unsigned long) (-1)) 124160484Sobrien bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4); 124289857Sobrien 124360484Sobrien while (reloc_sz < reloc_s->_raw_size) 124460484Sobrien reloc_d[reloc_sz++] = 0; 124560484Sobrien} 124660484Sobrien 124789857Sobrien/* Given the exiting def_file structure, print out a .DEF file that 124889857Sobrien corresponds to it. */ 124960484Sobrien 125060484Sobrienstatic void 125160484Sobrienquoteput (s, f, needs_quotes) 125260484Sobrien char *s; 125377298Sobrien FILE *f; 125460484Sobrien int needs_quotes; 125560484Sobrien{ 125660484Sobrien char *cp; 125789857Sobrien 125860484Sobrien for (cp = s; *cp; cp++) 125960484Sobrien if (*cp == '\'' 126060484Sobrien || *cp == '"' 126160484Sobrien || *cp == '\\' 126289857Sobrien || ISSPACE (*cp) 126360484Sobrien || *cp == ',' 126460484Sobrien || *cp == ';') 126560484Sobrien needs_quotes = 1; 126689857Sobrien 126760484Sobrien if (needs_quotes) 126860484Sobrien { 126960484Sobrien putc ('"', f); 127089857Sobrien 127160484Sobrien while (*s) 127260484Sobrien { 127360484Sobrien if (*s == '"' || *s == '\\') 127460484Sobrien putc ('\\', f); 127589857Sobrien 127660484Sobrien putc (*s, f); 127760484Sobrien s++; 127860484Sobrien } 127989857Sobrien 128060484Sobrien putc ('"', f); 128160484Sobrien } 128260484Sobrien else 128360484Sobrien fputs (s, f); 128460484Sobrien} 128560484Sobrien 128660484Sobrienvoid 128760484Sobrienpe_dll_generate_def_file (pe_out_def_filename) 128860484Sobrien const char *pe_out_def_filename; 128960484Sobrien{ 129060484Sobrien int i; 129160484Sobrien FILE *out = fopen (pe_out_def_filename, "w"); 129289857Sobrien 129360484Sobrien if (out == NULL) 129489857Sobrien /* xgettext:c-format */ 129589857Sobrien einfo (_("%s: Can't open output def file %s\n"), 129689857Sobrien program_name, pe_out_def_filename); 129760484Sobrien 129860484Sobrien if (pe_def_file) 129960484Sobrien { 130060484Sobrien if (pe_def_file->name) 130160484Sobrien { 130260484Sobrien if (pe_def_file->is_dll) 130360484Sobrien fprintf (out, "LIBRARY "); 130460484Sobrien else 130560484Sobrien fprintf (out, "NAME "); 130689857Sobrien 130760484Sobrien quoteput (pe_def_file->name, out, 1); 130889857Sobrien 130960484Sobrien if (pe_data (output_bfd)->pe_opthdr.ImageBase) 131060484Sobrien fprintf (out, " BASE=0x%lx", 131160484Sobrien (unsigned long) pe_data (output_bfd)->pe_opthdr.ImageBase); 131260484Sobrien fprintf (out, "\n"); 131360484Sobrien } 131460484Sobrien 131560484Sobrien if (pe_def_file->description) 131660484Sobrien { 131760484Sobrien fprintf (out, "DESCRIPTION "); 131860484Sobrien quoteput (pe_def_file->description, out, 1); 131960484Sobrien fprintf (out, "\n"); 132060484Sobrien } 132160484Sobrien 132260484Sobrien if (pe_def_file->version_minor != -1) 132360484Sobrien fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major, 132460484Sobrien pe_def_file->version_minor); 132560484Sobrien else if (pe_def_file->version_major != -1) 132660484Sobrien fprintf (out, "VERSION %d\n", pe_def_file->version_major); 132760484Sobrien 132860484Sobrien if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1) 132960484Sobrien fprintf (out, "\n"); 133060484Sobrien 133160484Sobrien if (pe_def_file->stack_commit != -1) 133260484Sobrien fprintf (out, "STACKSIZE 0x%x,0x%x\n", 133360484Sobrien pe_def_file->stack_reserve, pe_def_file->stack_commit); 133460484Sobrien else if (pe_def_file->stack_reserve != -1) 133560484Sobrien fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve); 133689857Sobrien 133760484Sobrien if (pe_def_file->heap_commit != -1) 133860484Sobrien fprintf (out, "HEAPSIZE 0x%x,0x%x\n", 133960484Sobrien pe_def_file->heap_reserve, pe_def_file->heap_commit); 134060484Sobrien else if (pe_def_file->heap_reserve != -1) 134160484Sobrien fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve); 134260484Sobrien 134360484Sobrien if (pe_def_file->num_section_defs > 0) 134460484Sobrien { 134560484Sobrien fprintf (out, "\nSECTIONS\n\n"); 134689857Sobrien 134760484Sobrien for (i = 0; i < pe_def_file->num_section_defs; i++) 134860484Sobrien { 134960484Sobrien fprintf (out, " "); 135060484Sobrien quoteput (pe_def_file->section_defs[i].name, out, 0); 135189857Sobrien 135260484Sobrien if (pe_def_file->section_defs[i].class) 135360484Sobrien { 135460484Sobrien fprintf (out, " CLASS "); 135560484Sobrien quoteput (pe_def_file->section_defs[i].class, out, 0); 135660484Sobrien } 135789857Sobrien 135860484Sobrien if (pe_def_file->section_defs[i].flag_read) 135960484Sobrien fprintf (out, " READ"); 136089857Sobrien 136160484Sobrien if (pe_def_file->section_defs[i].flag_write) 136260484Sobrien fprintf (out, " WRITE"); 136389857Sobrien 136460484Sobrien if (pe_def_file->section_defs[i].flag_execute) 136560484Sobrien fprintf (out, " EXECUTE"); 136689857Sobrien 136760484Sobrien if (pe_def_file->section_defs[i].flag_shared) 136860484Sobrien fprintf (out, " SHARED"); 136989857Sobrien 137060484Sobrien fprintf (out, "\n"); 137160484Sobrien } 137260484Sobrien } 137360484Sobrien 137460484Sobrien if (pe_def_file->num_exports > 0) 137560484Sobrien { 137689857Sobrien fprintf (out, "EXPORTS\n"); 137789857Sobrien 137860484Sobrien for (i = 0; i < pe_def_file->num_exports; i++) 137960484Sobrien { 138060484Sobrien def_file_export *e = pe_def_file->exports + i; 138160484Sobrien fprintf (out, " "); 138260484Sobrien quoteput (e->name, out, 0); 138389857Sobrien 138460484Sobrien if (e->internal_name && strcmp (e->internal_name, e->name)) 138560484Sobrien { 138660484Sobrien fprintf (out, " = "); 138760484Sobrien quoteput (e->internal_name, out, 0); 138860484Sobrien } 138989857Sobrien 139060484Sobrien if (e->ordinal != -1) 139160484Sobrien fprintf (out, " @%d", e->ordinal); 139289857Sobrien 139360484Sobrien if (e->flag_private) 139460484Sobrien fprintf (out, " PRIVATE"); 139589857Sobrien 139660484Sobrien if (e->flag_constant) 139760484Sobrien fprintf (out, " CONSTANT"); 139889857Sobrien 139960484Sobrien if (e->flag_noname) 140060484Sobrien fprintf (out, " NONAME"); 140189857Sobrien 140260484Sobrien if (e->flag_data) 140360484Sobrien fprintf (out, " DATA"); 140460484Sobrien 140560484Sobrien fprintf (out, "\n"); 140660484Sobrien } 140760484Sobrien } 140860484Sobrien 140960484Sobrien if (pe_def_file->num_imports > 0) 141060484Sobrien { 141160484Sobrien fprintf (out, "\nIMPORTS\n\n"); 141289857Sobrien 141360484Sobrien for (i = 0; i < pe_def_file->num_imports; i++) 141460484Sobrien { 141560484Sobrien def_file_import *im = pe_def_file->imports + i; 141660484Sobrien fprintf (out, " "); 141789857Sobrien 141860484Sobrien if (im->internal_name 141960484Sobrien && (!im->name || strcmp (im->internal_name, im->name))) 142060484Sobrien { 142160484Sobrien quoteput (im->internal_name, out, 0); 142260484Sobrien fprintf (out, " = "); 142360484Sobrien } 142489857Sobrien 142560484Sobrien quoteput (im->module->name, out, 0); 142660484Sobrien fprintf (out, "."); 142789857Sobrien 142860484Sobrien if (im->name) 142960484Sobrien quoteput (im->name, out, 0); 143060484Sobrien else 143160484Sobrien fprintf (out, "%d", im->ordinal); 143289857Sobrien 143360484Sobrien fprintf (out, "\n"); 143460484Sobrien } 143560484Sobrien } 143660484Sobrien } 143760484Sobrien else 143860484Sobrien fprintf (out, _("; no contents available\n")); 143960484Sobrien 144060484Sobrien if (fclose (out) == EOF) 144189857Sobrien /* xgettext:c-format */ 144289857Sobrien einfo (_("%P: Error closing file `%s'\n"), pe_out_def_filename); 144360484Sobrien} 144460484Sobrien 144589857Sobrien/* Generate the import library. */ 144660484Sobrien 144760484Sobrienstatic asymbol **symtab; 144860484Sobrienstatic int symptr; 144960484Sobrienstatic int tmp_seq; 145060484Sobrienstatic const char *dll_filename; 145160484Sobrienstatic char *dll_symname; 145260484Sobrien 145360484Sobrien#define UNDSEC (asection *) &bfd_und_section 145460484Sobrien 145560484Sobrienstatic asection * 145677298Sobrienquick_section (abfd, name, flags, align) 145760484Sobrien bfd *abfd; 145860484Sobrien const char *name; 145960484Sobrien int flags; 146060484Sobrien int align; 146160484Sobrien{ 146260484Sobrien asection *sec; 146360484Sobrien asymbol *sym; 146460484Sobrien 146560484Sobrien sec = bfd_make_section_old_way (abfd, name); 146677298Sobrien bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP); 146760484Sobrien bfd_set_section_alignment (abfd, sec, align); 146877298Sobrien /* Remember to undo this before trying to link internally! */ 146960484Sobrien sec->output_section = sec; 147060484Sobrien 147160484Sobrien sym = bfd_make_empty_symbol (abfd); 147260484Sobrien symtab[symptr++] = sym; 147360484Sobrien sym->name = sec->name; 147460484Sobrien sym->section = sec; 147560484Sobrien sym->flags = BSF_LOCAL; 147660484Sobrien sym->value = 0; 147760484Sobrien 147860484Sobrien return sec; 147960484Sobrien} 148060484Sobrien 148160484Sobrienstatic void 148260484Sobrienquick_symbol (abfd, n1, n2, n3, sec, flags, addr) 148360484Sobrien bfd *abfd; 148489857Sobrien const char *n1; 148589857Sobrien const char *n2; 148689857Sobrien const char *n3; 148760484Sobrien asection *sec; 148860484Sobrien int flags; 148960484Sobrien int addr; 149060484Sobrien{ 149160484Sobrien asymbol *sym; 149260484Sobrien char *name = (char *) xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1); 149389857Sobrien 149460484Sobrien strcpy (name, n1); 149560484Sobrien strcat (name, n2); 149660484Sobrien strcat (name, n3); 149760484Sobrien sym = bfd_make_empty_symbol (abfd); 149860484Sobrien sym->name = name; 149960484Sobrien sym->section = sec; 150060484Sobrien sym->flags = flags; 150160484Sobrien sym->value = addr; 150260484Sobrien symtab[symptr++] = sym; 150360484Sobrien} 150460484Sobrien 150560484Sobrienstatic arelent *reltab = 0; 150660484Sobrienstatic int relcount = 0, relsize = 0; 150760484Sobrien 150860484Sobrienstatic void 150960484Sobrienquick_reloc (abfd, address, which_howto, symidx) 151060484Sobrien bfd *abfd; 151160484Sobrien int address; 151260484Sobrien int which_howto; 151360484Sobrien int symidx; 151460484Sobrien{ 151577298Sobrien if (relcount >= (relsize - 1)) 151660484Sobrien { 151760484Sobrien relsize += 10; 151860484Sobrien if (reltab) 151960484Sobrien reltab = (arelent *) xrealloc (reltab, relsize * sizeof (arelent)); 152060484Sobrien else 152160484Sobrien reltab = (arelent *) xmalloc (relsize * sizeof (arelent)); 152260484Sobrien } 152360484Sobrien reltab[relcount].address = address; 152460484Sobrien reltab[relcount].addend = 0; 152560484Sobrien reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto); 152660484Sobrien reltab[relcount].sym_ptr_ptr = symtab + symidx; 152760484Sobrien relcount++; 152860484Sobrien} 152960484Sobrien 153060484Sobrienstatic void 153160484Sobriensave_relocs (asection *sec) 153260484Sobrien{ 153360484Sobrien int i; 153489857Sobrien 153560484Sobrien sec->relocation = reltab; 153660484Sobrien sec->reloc_count = relcount; 153777298Sobrien sec->orelocation = (arelent **) xmalloc ((relcount + 1) * sizeof (arelent *)); 153877298Sobrien for (i = 0; i < relcount; i++) 153960484Sobrien sec->orelocation[i] = sec->relocation + i; 154060484Sobrien sec->orelocation[relcount] = 0; 154160484Sobrien sec->flags |= SEC_RELOC; 154260484Sobrien reltab = 0; 154360484Sobrien relcount = relsize = 0; 154460484Sobrien} 154560484Sobrien 154689857Sobrien/* .section .idata$2 154789857Sobrien .global __head_my_dll 154889857Sobrien __head_my_dll: 154989857Sobrien .rva hname 155089857Sobrien .long 0 155189857Sobrien .long 0 155289857Sobrien .rva __my_dll_iname 155389857Sobrien .rva fthunk 155489857Sobrien 155589857Sobrien .section .idata$5 155689857Sobrien .long 0 155789857Sobrien fthunk: 155889857Sobrien 155989857Sobrien .section .idata$4 156089857Sobrien .long 0 156189857Sobrien hname: */ 156260484Sobrien 156360484Sobrienstatic bfd * 156460484Sobrienmake_head (parent) 156560484Sobrien bfd *parent; 156660484Sobrien{ 156760484Sobrien asection *id2, *id5, *id4; 156860484Sobrien unsigned char *d2, *d5, *d4; 156960484Sobrien char *oname; 157060484Sobrien bfd *abfd; 157160484Sobrien 157260484Sobrien oname = (char *) xmalloc (20); 157360484Sobrien sprintf (oname, "d%06d.o", tmp_seq); 157460484Sobrien tmp_seq++; 157560484Sobrien 157660484Sobrien abfd = bfd_create (oname, parent); 157760484Sobrien bfd_find_target (pe_details->object_target, abfd); 157860484Sobrien bfd_make_writable (abfd); 157960484Sobrien 158060484Sobrien bfd_set_format (abfd, bfd_object); 158160484Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 158260484Sobrien 158360484Sobrien symptr = 0; 158460484Sobrien symtab = (asymbol **) xmalloc (6 * sizeof (asymbol *)); 158560484Sobrien id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2); 158660484Sobrien id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); 158760484Sobrien id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); 158877298Sobrien quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0); 158977298Sobrien quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0); 159060484Sobrien 159160484Sobrien /* OK, pay attention here. I got confused myself looking back at 159260484Sobrien it. We create a four-byte section to mark the beginning of the 159360484Sobrien list, and we include an offset of 4 in the section, so that the 159460484Sobrien pointer to the list points to the *end* of this section, which is 159577298Sobrien the start of the list of sections from other objects. */ 159660484Sobrien 159760484Sobrien bfd_set_section_size (abfd, id2, 20); 159860484Sobrien d2 = (unsigned char *) xmalloc (20); 159960484Sobrien id2->contents = d2; 160060484Sobrien memset (d2, 0, 20); 160189857Sobrien d2[0] = d2[16] = 4; /* Reloc addend. */ 160260484Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); 160360484Sobrien quick_reloc (abfd, 12, BFD_RELOC_RVA, 4); 160460484Sobrien quick_reloc (abfd, 16, BFD_RELOC_RVA, 1); 160560484Sobrien save_relocs (id2); 160660484Sobrien 160760484Sobrien bfd_set_section_size (abfd, id5, 4); 160860484Sobrien d5 = (unsigned char *) xmalloc (4); 160960484Sobrien id5->contents = d5; 161060484Sobrien memset (d5, 0, 4); 161160484Sobrien 161260484Sobrien bfd_set_section_size (abfd, id4, 4); 161360484Sobrien d4 = (unsigned char *) xmalloc (4); 161460484Sobrien id4->contents = d4; 161560484Sobrien memset (d4, 0, 4); 161660484Sobrien 161760484Sobrien bfd_set_symtab (abfd, symtab, symptr); 161860484Sobrien 161960484Sobrien bfd_set_section_contents (abfd, id2, d2, 0, 20); 162060484Sobrien bfd_set_section_contents (abfd, id5, d5, 0, 4); 162160484Sobrien bfd_set_section_contents (abfd, id4, d4, 0, 4); 162277298Sobrien 162360484Sobrien bfd_make_readable (abfd); 162460484Sobrien return abfd; 162560484Sobrien} 162660484Sobrien 162789857Sobrien/* .section .idata$4 162889857Sobrien .long 0 162989857Sobrien .section .idata$5 163089857Sobrien .long 0 163189857Sobrien .section idata$7 163289857Sobrien .global __my_dll_iname 163389857Sobrien __my_dll_iname: 163489857Sobrien .asciz "my.dll" */ 163560484Sobrien 163660484Sobrienstatic bfd * 163760484Sobrienmake_tail (parent) 163860484Sobrien bfd *parent; 163960484Sobrien{ 164060484Sobrien asection *id4, *id5, *id7; 164160484Sobrien unsigned char *d4, *d5, *d7; 164260484Sobrien int len; 164360484Sobrien char *oname; 164460484Sobrien bfd *abfd; 164560484Sobrien 164660484Sobrien oname = (char *) xmalloc (20); 164760484Sobrien sprintf (oname, "d%06d.o", tmp_seq); 164860484Sobrien tmp_seq++; 164960484Sobrien 165060484Sobrien abfd = bfd_create (oname, parent); 165160484Sobrien bfd_find_target (pe_details->object_target, abfd); 165260484Sobrien bfd_make_writable (abfd); 165360484Sobrien 165460484Sobrien bfd_set_format (abfd, bfd_object); 165560484Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 165660484Sobrien 165760484Sobrien symptr = 0; 165860484Sobrien symtab = (asymbol **) xmalloc (5 * sizeof (asymbol *)); 165960484Sobrien id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); 166060484Sobrien id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); 166160484Sobrien id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2); 166277298Sobrien quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0); 166360484Sobrien 166460484Sobrien bfd_set_section_size (abfd, id4, 4); 166560484Sobrien d4 = (unsigned char *) xmalloc (4); 166660484Sobrien id4->contents = d4; 166760484Sobrien memset (d4, 0, 4); 166860484Sobrien 166960484Sobrien bfd_set_section_size (abfd, id5, 4); 167060484Sobrien d5 = (unsigned char *) xmalloc (4); 167160484Sobrien id5->contents = d5; 167260484Sobrien memset (d5, 0, 4); 167360484Sobrien 167477298Sobrien len = strlen (dll_filename) + 1; 167560484Sobrien if (len & 1) 167677298Sobrien len++; 167760484Sobrien bfd_set_section_size (abfd, id7, len); 167860484Sobrien d7 = (unsigned char *) xmalloc (len); 167960484Sobrien id7->contents = d7; 168060484Sobrien strcpy (d7, dll_filename); 168160484Sobrien 168260484Sobrien bfd_set_symtab (abfd, symtab, symptr); 168360484Sobrien 168460484Sobrien bfd_set_section_contents (abfd, id4, d4, 0, 4); 168560484Sobrien bfd_set_section_contents (abfd, id5, d5, 0, 4); 168660484Sobrien bfd_set_section_contents (abfd, id7, d7, 0, len); 168760484Sobrien 168860484Sobrien bfd_make_readable (abfd); 168960484Sobrien return abfd; 169060484Sobrien} 169160484Sobrien 169289857Sobrien/* .text 169389857Sobrien .global _function 169489857Sobrien .global ___imp_function 169589857Sobrien .global __imp__function 169689857Sobrien _function: 169789857Sobrien jmp *__imp__function: 169889857Sobrien 169989857Sobrien .section idata$7 170089857Sobrien .long __head_my_dll 170189857Sobrien 170289857Sobrien .section .idata$5 170389857Sobrien ___imp_function: 170489857Sobrien __imp__function: 170589857Sobrien iat? 170689857Sobrien .section .idata$4 170789857Sobrien iat? 170889857Sobrien .section .idata$6 170989857Sobrien ID<ordinal>: 171089857Sobrien .short <hint> 171189857Sobrien .asciz "function" xlate? (add underscore, kill at) */ 171260484Sobrien 171389857Sobrienstatic unsigned char jmp_ix86_bytes[] = 171489857Sobrien{ 171560484Sobrien 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 171660484Sobrien}; 171760484Sobrien 171889857Sobrien/* _function: 171989857Sobrien mov.l ip+8,r0 172089857Sobrien mov.l @r0,r0 172189857Sobrien jmp @r0 172289857Sobrien nop 172389857Sobrien .dw __imp_function */ 172460484Sobrien 172589857Sobrienstatic unsigned char jmp_sh_bytes[] = 172689857Sobrien{ 172760484Sobrien 0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 172860484Sobrien}; 172960484Sobrien 173089857Sobrien/* _function: 173189857Sobrien lui $t0,<high:__imp_function> 173289857Sobrien lw $t0,<low:__imp_function> 173389857Sobrien jr $t0 173489857Sobrien nop */ 173560484Sobrien 173689857Sobrienstatic unsigned char jmp_mips_bytes[] = 173789857Sobrien{ 173860484Sobrien 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d, 173960484Sobrien 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 174060484Sobrien}; 174160484Sobrien 174260484Sobrienstatic bfd * 174360484Sobrienmake_one (exp, parent) 174460484Sobrien def_file_export *exp; 174560484Sobrien bfd *parent; 174660484Sobrien{ 174760484Sobrien asection *tx, *id7, *id5, *id4, *id6; 174877298Sobrien unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL; 174960484Sobrien int len; 175060484Sobrien char *oname; 175160484Sobrien bfd *abfd; 175260484Sobrien unsigned char *jmp_bytes = NULL; 175360484Sobrien int jmp_byte_count = 0; 175460484Sobrien 175560484Sobrien switch (pe_details->pe_arch) 175660484Sobrien { 175760484Sobrien case PE_ARCH_i386: 175860484Sobrien jmp_bytes = jmp_ix86_bytes; 175960484Sobrien jmp_byte_count = sizeof (jmp_ix86_bytes); 176060484Sobrien break; 176160484Sobrien case PE_ARCH_sh: 176260484Sobrien jmp_bytes = jmp_sh_bytes; 176360484Sobrien jmp_byte_count = sizeof (jmp_sh_bytes); 176460484Sobrien break; 176560484Sobrien case PE_ARCH_mips: 176660484Sobrien jmp_bytes = jmp_mips_bytes; 176760484Sobrien jmp_byte_count = sizeof (jmp_mips_bytes); 176860484Sobrien break; 176989857Sobrien default: 177089857Sobrien abort (); 177160484Sobrien } 177260484Sobrien 177360484Sobrien oname = (char *) xmalloc (20); 177460484Sobrien sprintf (oname, "d%06d.o", tmp_seq); 177560484Sobrien tmp_seq++; 177660484Sobrien 177760484Sobrien abfd = bfd_create (oname, parent); 177860484Sobrien bfd_find_target (pe_details->object_target, abfd); 177960484Sobrien bfd_make_writable (abfd); 178060484Sobrien 178160484Sobrien bfd_set_format (abfd, bfd_object); 178260484Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 178360484Sobrien 178460484Sobrien symptr = 0; 178589857Sobrien symtab = (asymbol **) xmalloc (11 * sizeof (asymbol *)); 178660484Sobrien tx = quick_section (abfd, ".text", SEC_CODE|SEC_HAS_CONTENTS, 2); 178760484Sobrien id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2); 178860484Sobrien id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2); 178960484Sobrien id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); 179060484Sobrien id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2); 179160484Sobrien if (! exp->flag_data) 179277298Sobrien quick_symbol (abfd, U (""), exp->internal_name, "", tx, BSF_GLOBAL, 0); 179377298Sobrien quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, BSF_GLOBAL, 0); 179477298Sobrien quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5, BSF_GLOBAL, 0); 179589857Sobrien /* Symbol to reference ord/name of imported 179689857Sobrien symbol, used to implement auto-import. */ 179789857Sobrien quick_symbol (abfd, U("_nm__"), exp->internal_name, "", id6, BSF_GLOBAL, 0); 179860484Sobrien if (pe_dll_compat_implib) 179977298Sobrien quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", 180077298Sobrien id5, BSF_GLOBAL, 0); 180160484Sobrien 180277298Sobrien if (! exp->flag_data) 180389857Sobrien { 180489857Sobrien bfd_set_section_size (abfd, tx, jmp_byte_count); 180589857Sobrien td = (unsigned char *) xmalloc (jmp_byte_count); 180689857Sobrien tx->contents = td; 180789857Sobrien memcpy (td, jmp_bytes, jmp_byte_count); 180860484Sobrien 180989857Sobrien switch (pe_details->pe_arch) 181089857Sobrien { 181189857Sobrien case PE_ARCH_i386: 181289857Sobrien quick_reloc (abfd, 2, BFD_RELOC_32, 2); 181389857Sobrien break; 181489857Sobrien case PE_ARCH_sh: 181589857Sobrien quick_reloc (abfd, 8, BFD_RELOC_32, 2); 181689857Sobrien break; 181789857Sobrien case PE_ARCH_mips: 181889857Sobrien quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2); 181989857Sobrien quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */ 182089857Sobrien quick_reloc (abfd, 4, BFD_RELOC_LO16, 2); 182189857Sobrien break; 182289857Sobrien default: 182389857Sobrien abort (); 182489857Sobrien } 182589857Sobrien save_relocs (tx); 182689857Sobrien } 182789857Sobrien 182860484Sobrien bfd_set_section_size (abfd, id7, 4); 182960484Sobrien d7 = (unsigned char *) xmalloc (4); 183060484Sobrien id7->contents = d7; 183160484Sobrien memset (d7, 0, 4); 183260484Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 6); 183360484Sobrien save_relocs (id7); 183460484Sobrien 183560484Sobrien bfd_set_section_size (abfd, id5, 4); 183660484Sobrien d5 = (unsigned char *) xmalloc (4); 183760484Sobrien id5->contents = d5; 183860484Sobrien memset (d5, 0, 4); 183989857Sobrien 184060484Sobrien if (exp->flag_noname) 184160484Sobrien { 184260484Sobrien d5[0] = exp->ordinal; 184360484Sobrien d5[1] = exp->ordinal >> 8; 184460484Sobrien d5[3] = 0x80; 184560484Sobrien } 184660484Sobrien else 184760484Sobrien { 184860484Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); 184960484Sobrien save_relocs (id5); 185060484Sobrien } 185160484Sobrien 185260484Sobrien bfd_set_section_size (abfd, id4, 4); 185360484Sobrien d4 = (unsigned char *) xmalloc (4); 185460484Sobrien id4->contents = d4; 185560484Sobrien memset (d4, 0, 4); 185689857Sobrien 185760484Sobrien if (exp->flag_noname) 185860484Sobrien { 185977298Sobrien d4[0] = exp->ordinal; 186077298Sobrien d4[1] = exp->ordinal >> 8; 186177298Sobrien d4[3] = 0x80; 186260484Sobrien } 186360484Sobrien else 186460484Sobrien { 186560484Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 4); 186660484Sobrien save_relocs (id4); 186760484Sobrien } 186860484Sobrien 186960484Sobrien if (exp->flag_noname) 187060484Sobrien { 187160484Sobrien len = 0; 187260484Sobrien bfd_set_section_size (abfd, id6, 0); 187360484Sobrien } 187460484Sobrien else 187560484Sobrien { 187660484Sobrien len = strlen (exp->name) + 3; 187760484Sobrien if (len & 1) 187860484Sobrien len++; 187960484Sobrien bfd_set_section_size (abfd, id6, len); 188060484Sobrien d6 = (unsigned char *) xmalloc (len); 188160484Sobrien id6->contents = d6; 188260484Sobrien memset (d6, 0, len); 188360484Sobrien d6[0] = exp->hint & 0xff; 188460484Sobrien d6[1] = exp->hint >> 8; 188577298Sobrien strcpy (d6 + 2, exp->name); 188660484Sobrien } 188760484Sobrien 188860484Sobrien bfd_set_symtab (abfd, symtab, symptr); 188960484Sobrien 189060484Sobrien bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count); 189160484Sobrien bfd_set_section_contents (abfd, id7, d7, 0, 4); 189260484Sobrien bfd_set_section_contents (abfd, id5, d5, 0, 4); 189360484Sobrien bfd_set_section_contents (abfd, id4, d4, 0, 4); 189460484Sobrien if (!exp->flag_noname) 189560484Sobrien bfd_set_section_contents (abfd, id6, d6, 0, len); 189660484Sobrien 189760484Sobrien bfd_make_readable (abfd); 189860484Sobrien return abfd; 189960484Sobrien} 190060484Sobrien 190189857Sobrienstatic bfd * 190289857Sobrienmake_singleton_name_thunk (import, parent) 190389857Sobrien const char *import; 190489857Sobrien bfd *parent; 190589857Sobrien{ 190689857Sobrien /* Name thunks go to idata$4. */ 190789857Sobrien asection *id4; 190889857Sobrien unsigned char *d4; 190989857Sobrien char *oname; 191089857Sobrien bfd *abfd; 191189857Sobrien 191289857Sobrien oname = (char *) xmalloc (20); 191389857Sobrien sprintf (oname, "nmth%06d.o", tmp_seq); 191489857Sobrien tmp_seq++; 191589857Sobrien 191689857Sobrien abfd = bfd_create (oname, parent); 191789857Sobrien bfd_find_target (pe_details->object_target, abfd); 191889857Sobrien bfd_make_writable (abfd); 191989857Sobrien 192089857Sobrien bfd_set_format (abfd, bfd_object); 192189857Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 192289857Sobrien 192389857Sobrien symptr = 0; 192489857Sobrien symtab = (asymbol **) xmalloc (3 * sizeof (asymbol *)); 192589857Sobrien id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2); 192689857Sobrien quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0); 192789857Sobrien quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0); 192889857Sobrien 192989857Sobrien bfd_set_section_size (abfd, id4, 8); 193089857Sobrien d4 = (unsigned char *) xmalloc (4); 193189857Sobrien id4->contents = d4; 193289857Sobrien memset (d4, 0, 8); 193389857Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 2); 193489857Sobrien save_relocs (id4); 193589857Sobrien 193689857Sobrien bfd_set_symtab (abfd, symtab, symptr); 193789857Sobrien 193889857Sobrien bfd_set_section_contents (abfd, id4, d4, 0, 8); 193989857Sobrien 194089857Sobrien bfd_make_readable (abfd); 194189857Sobrien return abfd; 194289857Sobrien} 194389857Sobrien 194489857Sobrienstatic char * 194589857Sobrienmake_import_fixup_mark (rel) 194689857Sobrien arelent *rel; 194789857Sobrien{ 194889857Sobrien /* We convert reloc to symbol, for later reference. */ 194989857Sobrien static int counter; 195089857Sobrien static char *fixup_name = NULL; 195189857Sobrien static size_t buffer_len = 0; 195289857Sobrien 195389857Sobrien struct symbol_cache_entry *sym = *rel->sym_ptr_ptr; 195489857Sobrien 195589857Sobrien bfd *abfd = bfd_asymbol_bfd (sym); 195689857Sobrien struct coff_link_hash_entry *myh = NULL; 195789857Sobrien 195889857Sobrien if (!fixup_name) 195989857Sobrien { 196089857Sobrien fixup_name = (char *) xmalloc (384); 196189857Sobrien buffer_len = 384; 196289857Sobrien } 196389857Sobrien 196489857Sobrien if (strlen (sym->name) + 25 > buffer_len) 196589857Sobrien /* Assume 25 chars for "__fu" + counter + "_". If counter is 196689857Sobrien bigger than 20 digits long, we've got worse problems than 196789857Sobrien overflowing this buffer... */ 196889857Sobrien { 196989857Sobrien free (fixup_name); 197089857Sobrien /* New buffer size is length of symbol, plus 25, but then 197189857Sobrien rounded up to the nearest multiple of 128. */ 197289857Sobrien buffer_len = ((strlen (sym->name) + 25) + 127) & ~127; 197389857Sobrien fixup_name = (char *) xmalloc (buffer_len); 197489857Sobrien } 197589857Sobrien 197689857Sobrien sprintf (fixup_name, "__fu%d_%s", counter++, sym->name); 197789857Sobrien 197889857Sobrien bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL, 197989857Sobrien current_sec, /* sym->section, */ 198089857Sobrien rel->address, NULL, true, false, 198189857Sobrien (struct bfd_link_hash_entry **) &myh); 198289857Sobrien 198389857Sobrien#if 0 198489857Sobrien printf ("type:%d\n", myh->type); 198589857Sobrien printf ("%s\n", myh->root.u.def.section->name); 198689857Sobrien#endif 198789857Sobrien return fixup_name; 198889857Sobrien} 198989857Sobrien 199089857Sobrien/* .section .idata$3 199189857Sobrien .rva __nm_thnk_SYM (singleton thunk with name of func) 199289857Sobrien .long 0 199389857Sobrien .long 0 199489857Sobrien .rva __my_dll_iname (name of dll) 199589857Sobrien .rva __fuNN_SYM (pointer to reference (address) in text) */ 199689857Sobrien 199789857Sobrienstatic bfd * 199889857Sobrienmake_import_fixup_entry (name, fixup_name, dll_symname,parent) 199989857Sobrien const char *name; 200089857Sobrien const char *fixup_name; 200189857Sobrien const char *dll_symname; 200289857Sobrien bfd *parent; 200389857Sobrien{ 200489857Sobrien asection *id3; 200589857Sobrien unsigned char *d3; 200689857Sobrien char *oname; 200789857Sobrien bfd *abfd; 200889857Sobrien 200989857Sobrien oname = (char *) xmalloc (20); 201089857Sobrien sprintf (oname, "fu%06d.o", tmp_seq); 201189857Sobrien tmp_seq++; 201289857Sobrien 201389857Sobrien abfd = bfd_create (oname, parent); 201489857Sobrien bfd_find_target (pe_details->object_target, abfd); 201589857Sobrien bfd_make_writable (abfd); 201689857Sobrien 201789857Sobrien bfd_set_format (abfd, bfd_object); 201889857Sobrien bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0); 201989857Sobrien 202089857Sobrien symptr = 0; 202189857Sobrien symtab = (asymbol **) xmalloc (6 * sizeof (asymbol *)); 202289857Sobrien id3 = quick_section (abfd, ".idata$3", SEC_HAS_CONTENTS, 2); 202389857Sobrien 202489857Sobrien#if 0 202589857Sobrien quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0); 202689857Sobrien#endif 202789857Sobrien quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0); 202889857Sobrien quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0); 202989857Sobrien quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0); 203089857Sobrien 203189857Sobrien bfd_set_section_size (abfd, id3, 20); 203289857Sobrien d3 = (unsigned char *) xmalloc (20); 203389857Sobrien id3->contents = d3; 203489857Sobrien memset (d3, 0, 20); 203589857Sobrien 203689857Sobrien quick_reloc (abfd, 0, BFD_RELOC_RVA, 1); 203789857Sobrien quick_reloc (abfd, 12, BFD_RELOC_RVA, 2); 203889857Sobrien quick_reloc (abfd, 16, BFD_RELOC_RVA, 3); 203989857Sobrien save_relocs (id3); 204089857Sobrien 204189857Sobrien bfd_set_symtab (abfd, symtab, symptr); 204289857Sobrien 204389857Sobrien bfd_set_section_contents (abfd, id3, d3, 0, 20); 204489857Sobrien 204589857Sobrien bfd_make_readable (abfd); 204689857Sobrien return abfd; 204789857Sobrien} 204889857Sobrien 204960484Sobrienvoid 205089857Sobrienpe_create_import_fixup (rel) 205189857Sobrien arelent *rel; 205289857Sobrien{ 205389857Sobrien char buf[300]; 205489857Sobrien struct symbol_cache_entry *sym = *rel->sym_ptr_ptr; 205589857Sobrien struct bfd_link_hash_entry *name_thunk_sym; 205689857Sobrien const char *name = sym->name; 205789857Sobrien char *fixup_name = make_import_fixup_mark (rel); 205889857Sobrien 205989857Sobrien sprintf (buf, U ("_nm_thnk_%s"), name); 206089857Sobrien 206189857Sobrien name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1); 206289857Sobrien 206389857Sobrien if (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined) 206489857Sobrien { 206589857Sobrien bfd *b = make_singleton_name_thunk (name, output_bfd); 206689857Sobrien add_bfd_to_link (b, b->filename, &link_info); 206789857Sobrien 206889857Sobrien /* If we ever use autoimport, we have to cast text section writable. */ 206989857Sobrien config.text_read_only = false; 207089857Sobrien } 207189857Sobrien 207289857Sobrien { 207389857Sobrien extern char * pe_data_import_dll; 207489857Sobrien char * dll_symname = pe_data_import_dll ? pe_data_import_dll : "unknown"; 207589857Sobrien 207689857Sobrien bfd *b = make_import_fixup_entry (name, fixup_name, dll_symname, 207789857Sobrien output_bfd); 207889857Sobrien add_bfd_to_link (b, b->filename, &link_info); 207989857Sobrien } 208089857Sobrien} 208189857Sobrien 208289857Sobrien 208389857Sobrienvoid 208460484Sobrienpe_dll_generate_implib (def, impfilename) 208560484Sobrien def_file *def; 208660484Sobrien const char *impfilename; 208760484Sobrien{ 208860484Sobrien int i; 208960484Sobrien bfd *ar_head; 209060484Sobrien bfd *ar_tail; 209160484Sobrien bfd *outarch; 209260484Sobrien bfd *head = 0; 209360484Sobrien 209460484Sobrien dll_filename = (def->name) ? def->name : dll_name; 209560484Sobrien dll_symname = xstrdup (dll_filename); 209677298Sobrien for (i = 0; dll_symname[i]; i++) 209789857Sobrien if (!ISALNUM (dll_symname[i])) 209860484Sobrien dll_symname[i] = '_'; 209960484Sobrien 210060484Sobrien unlink (impfilename); 210160484Sobrien 210260484Sobrien outarch = bfd_openw (impfilename, 0); 210360484Sobrien 210460484Sobrien if (!outarch) 210560484Sobrien { 210660484Sobrien /* xgettext:c-format */ 210760484Sobrien einfo (_("%XCan't open .lib file: %s\n"), impfilename); 210860484Sobrien return; 210960484Sobrien } 211060484Sobrien 211160484Sobrien /* xgettext:c-format */ 211260484Sobrien einfo (_("Creating library file: %s\n"), impfilename); 211377298Sobrien 211460484Sobrien bfd_set_format (outarch, bfd_archive); 211560484Sobrien outarch->has_armap = 1; 211660484Sobrien 211777298Sobrien /* Work out a reasonable size of things to put onto one line. */ 211860484Sobrien ar_head = make_head (outarch); 211960484Sobrien 212077298Sobrien for (i = 0; i < def->num_exports; i++) 212160484Sobrien { 212277298Sobrien /* The import library doesn't know about the internal name. */ 212360484Sobrien char *internal = def->exports[i].internal_name; 212460484Sobrien bfd *n; 212589857Sobrien 212660484Sobrien def->exports[i].internal_name = def->exports[i].name; 212777298Sobrien n = make_one (def->exports + i, outarch); 212860484Sobrien n->next = head; 212960484Sobrien head = n; 213060484Sobrien def->exports[i].internal_name = internal; 213160484Sobrien } 213260484Sobrien 213360484Sobrien ar_tail = make_tail (outarch); 213460484Sobrien 213560484Sobrien if (ar_head == NULL || ar_tail == NULL) 213660484Sobrien return; 213760484Sobrien 213877298Sobrien /* Now stick them all into the archive. */ 213960484Sobrien ar_head->next = head; 214060484Sobrien ar_tail->next = ar_head; 214160484Sobrien head = ar_tail; 214260484Sobrien 214360484Sobrien if (! bfd_set_archive_head (outarch, head)) 214460484Sobrien einfo ("%Xbfd_set_archive_head: %s\n", bfd_errmsg (bfd_get_error ())); 214577298Sobrien 214660484Sobrien if (! bfd_close (outarch)) 214760484Sobrien einfo ("%Xbfd_close %s: %s\n", impfilename, bfd_errmsg (bfd_get_error ())); 214860484Sobrien 214960484Sobrien while (head != NULL) 215060484Sobrien { 215160484Sobrien bfd *n = head->next; 215260484Sobrien bfd_close (head); 215360484Sobrien head = n; 215460484Sobrien } 215560484Sobrien} 215660484Sobrien 215760484Sobrienstatic void 215860484Sobrienadd_bfd_to_link (abfd, name, link_info) 215960484Sobrien bfd *abfd; 216089857Sobrien const char *name; 216160484Sobrien struct bfd_link_info *link_info; 216260484Sobrien{ 216360484Sobrien lang_input_statement_type *fake_file; 216489857Sobrien 216560484Sobrien fake_file = lang_add_input_file (name, 216660484Sobrien lang_input_file_is_fake_enum, 216760484Sobrien NULL); 216860484Sobrien fake_file->the_bfd = abfd; 216960484Sobrien ldlang_add_file (fake_file); 217089857Sobrien 217160484Sobrien if (!bfd_link_add_symbols (abfd, link_info)) 217260484Sobrien einfo ("%Xaddsym %s: %s\n", name, bfd_errmsg (bfd_get_error ())); 217360484Sobrien} 217460484Sobrien 217560484Sobrienvoid 217660484Sobrienpe_process_import_defs (output_bfd, link_info) 217760484Sobrien bfd *output_bfd; 217860484Sobrien struct bfd_link_info *link_info; 217960484Sobrien{ 218060484Sobrien def_file_module *module; 218189857Sobrien 218277298Sobrien pe_dll_id_target (bfd_get_target (output_bfd)); 218360484Sobrien 218460484Sobrien if (!pe_def_file) 218560484Sobrien return; 218660484Sobrien 218760484Sobrien for (module = pe_def_file->modules; module; module = module->next) 218860484Sobrien { 218960484Sobrien int i, do_this_dll; 219060484Sobrien 219160484Sobrien dll_filename = module->name; 219260484Sobrien dll_symname = xstrdup (module->name); 219377298Sobrien for (i = 0; dll_symname[i]; i++) 219489857Sobrien if (!ISALNUM (dll_symname[i])) 219560484Sobrien dll_symname[i] = '_'; 219660484Sobrien 219760484Sobrien do_this_dll = 0; 219860484Sobrien 219977298Sobrien for (i = 0; i < pe_def_file->num_imports; i++) 220060484Sobrien if (pe_def_file->imports[i].module == module) 220160484Sobrien { 220260484Sobrien def_file_export exp; 220360484Sobrien struct bfd_link_hash_entry *blhe; 220460484Sobrien 220577298Sobrien /* See if we need this import. */ 220677298Sobrien char *name = (char *) xmalloc (strlen (pe_def_file->imports[i].internal_name) + 2 + 6); 220777298Sobrien sprintf (name, "%s%s", U (""), pe_def_file->imports[i].internal_name); 220860484Sobrien blhe = bfd_link_hash_lookup (link_info->hash, name, 220960484Sobrien false, false, false); 221077298Sobrien if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)) 221177298Sobrien { 221277298Sobrien sprintf (name, "%s%s", U ("_imp__"), 221377298Sobrien pe_def_file->imports[i].internal_name); 221477298Sobrien blhe = bfd_link_hash_lookup (link_info->hash, name, 221577298Sobrien false, false, false); 221677298Sobrien } 221760484Sobrien free (name); 221860484Sobrien if (blhe && blhe->type == bfd_link_hash_undefined) 221960484Sobrien { 222060484Sobrien bfd *one; 222177298Sobrien /* We do. */ 222260484Sobrien if (!do_this_dll) 222360484Sobrien { 222460484Sobrien bfd *ar_head = make_head (output_bfd); 222560484Sobrien add_bfd_to_link (ar_head, ar_head->filename, link_info); 222660484Sobrien do_this_dll = 1; 222760484Sobrien } 222860484Sobrien exp.internal_name = pe_def_file->imports[i].internal_name; 222960484Sobrien exp.name = pe_def_file->imports[i].name; 223060484Sobrien exp.ordinal = pe_def_file->imports[i].ordinal; 223160484Sobrien exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0; 223260484Sobrien exp.flag_private = 0; 223360484Sobrien exp.flag_constant = 0; 223460484Sobrien exp.flag_data = 0; 223560484Sobrien exp.flag_noname = exp.name ? 0 : 1; 223660484Sobrien one = make_one (&exp, output_bfd); 223760484Sobrien add_bfd_to_link (one, one->filename, link_info); 223860484Sobrien } 223960484Sobrien } 224060484Sobrien if (do_this_dll) 224160484Sobrien { 224260484Sobrien bfd *ar_tail = make_tail (output_bfd); 224360484Sobrien add_bfd_to_link (ar_tail, ar_tail->filename, link_info); 224460484Sobrien } 224560484Sobrien 224660484Sobrien free (dll_symname); 224760484Sobrien } 224860484Sobrien} 224960484Sobrien 225089857Sobrien/* We were handed a *.DLL file. Parse it and turn it into a set of 225189857Sobrien IMPORTS directives in the def file. Return true if the file was 225289857Sobrien handled, false if not. */ 225360484Sobrien 225460484Sobrienstatic unsigned int 225560484Sobrienpe_get16 (abfd, where) 225660484Sobrien bfd *abfd; 225760484Sobrien int where; 225860484Sobrien{ 225960484Sobrien unsigned char b[2]; 226089857Sobrien 226189857Sobrien bfd_seek (abfd, (file_ptr) where, SEEK_SET); 226289857Sobrien bfd_bread (b, (bfd_size_type) 2, abfd); 226377298Sobrien return b[0] + (b[1] << 8); 226460484Sobrien} 226560484Sobrien 226660484Sobrienstatic unsigned int 226760484Sobrienpe_get32 (abfd, where) 226860484Sobrien bfd *abfd; 226960484Sobrien int where; 227060484Sobrien{ 227160484Sobrien unsigned char b[4]; 227289857Sobrien 227389857Sobrien bfd_seek (abfd, (file_ptr) where, SEEK_SET); 227489857Sobrien bfd_bread (b, (bfd_size_type) 4, abfd); 227577298Sobrien return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); 227660484Sobrien} 227760484Sobrien 227860484Sobrien#if 0 /* This is not currently used. */ 227960484Sobrien 228060484Sobrienstatic unsigned int 228160484Sobrienpe_as16 (ptr) 228260484Sobrien void *ptr; 228360484Sobrien{ 228460484Sobrien unsigned char *b = ptr; 228589857Sobrien 228677298Sobrien return b[0] + (b[1] << 8); 228760484Sobrien} 228860484Sobrien 228960484Sobrien#endif 229060484Sobrien 229160484Sobrienstatic unsigned int 229260484Sobrienpe_as32 (ptr) 229360484Sobrien void *ptr; 229460484Sobrien{ 229560484Sobrien unsigned char *b = ptr; 229689857Sobrien 229777298Sobrien return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); 229860484Sobrien} 229960484Sobrien 230060484Sobrienboolean 230160484Sobrienpe_implied_import_dll (filename) 230260484Sobrien const char *filename; 230360484Sobrien{ 230460484Sobrien bfd *dll; 230560484Sobrien unsigned long pe_header_offset, opthdr_ofs, num_entries, i; 230660484Sobrien unsigned long export_rva, export_size, nsections, secptr, expptr; 230760484Sobrien unsigned char *expdata, *erva; 230860484Sobrien unsigned long name_rvas, ordinals, nexp, ordbase; 230960484Sobrien const char *dll_name; 231060484Sobrien 231160484Sobrien /* No, I can't use bfd here. kernel32.dll puts its export table in 231277298Sobrien the middle of the .rdata section. */ 231360484Sobrien dll = bfd_openr (filename, pe_details->target_name); 231460484Sobrien if (!dll) 231560484Sobrien { 231660484Sobrien einfo ("%Xopen %s: %s\n", filename, bfd_errmsg (bfd_get_error ())); 231760484Sobrien return false; 231860484Sobrien } 231989857Sobrien 232077298Sobrien /* PEI dlls seem to be bfd_objects. */ 232160484Sobrien if (!bfd_check_format (dll, bfd_object)) 232260484Sobrien { 232360484Sobrien einfo ("%X%s: this doesn't appear to be a DLL\n", filename); 232460484Sobrien return false; 232560484Sobrien } 232660484Sobrien 232760484Sobrien dll_name = filename; 232877298Sobrien for (i = 0; filename[i]; i++) 232960484Sobrien if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') 233060484Sobrien dll_name = filename + i + 1; 233160484Sobrien 233260484Sobrien pe_header_offset = pe_get32 (dll, 0x3c); 233360484Sobrien opthdr_ofs = pe_header_offset + 4 + 20; 233460484Sobrien num_entries = pe_get32 (dll, opthdr_ofs + 92); 233589857Sobrien 233689857Sobrien if (num_entries < 1) /* No exports. */ 233760484Sobrien return false; 233889857Sobrien 233960484Sobrien export_rva = pe_get32 (dll, opthdr_ofs + 96); 234060484Sobrien export_size = pe_get32 (dll, opthdr_ofs + 100); 234160484Sobrien nsections = pe_get16 (dll, pe_header_offset + 4 + 2); 234260484Sobrien secptr = (pe_header_offset + 4 + 20 + 234360484Sobrien pe_get16 (dll, pe_header_offset + 4 + 16)); 234460484Sobrien expptr = 0; 234589857Sobrien 234677298Sobrien for (i = 0; i < nsections; i++) 234760484Sobrien { 234860484Sobrien char sname[8]; 234960484Sobrien unsigned long secptr1 = secptr + 40 * i; 235060484Sobrien unsigned long vaddr = pe_get32 (dll, secptr1 + 12); 235160484Sobrien unsigned long vsize = pe_get32 (dll, secptr1 + 16); 235260484Sobrien unsigned long fptr = pe_get32 (dll, secptr1 + 20); 235389857Sobrien 235489857Sobrien bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); 235589857Sobrien bfd_bread (sname, (bfd_size_type) 8, dll); 235689857Sobrien 235777298Sobrien if (vaddr <= export_rva && vaddr + vsize > export_rva) 235860484Sobrien { 235960484Sobrien expptr = fptr + (export_rva - vaddr); 236060484Sobrien if (export_rva + export_size > vaddr + vsize) 236160484Sobrien export_size = vsize - (export_rva - vaddr); 236260484Sobrien break; 236360484Sobrien } 236460484Sobrien } 236560484Sobrien 236660484Sobrien expdata = (unsigned char *) xmalloc (export_size); 236789857Sobrien bfd_seek (dll, (file_ptr) expptr, SEEK_SET); 236889857Sobrien bfd_bread (expdata, (bfd_size_type) export_size, dll); 236960484Sobrien erva = expdata - export_rva; 237060484Sobrien 237160484Sobrien if (pe_def_file == 0) 237277298Sobrien pe_def_file = def_file_empty (); 237360484Sobrien 237477298Sobrien nexp = pe_as32 (expdata + 24); 237577298Sobrien name_rvas = pe_as32 (expdata + 32); 237677298Sobrien ordinals = pe_as32 (expdata + 36); 237777298Sobrien ordbase = pe_as32 (expdata + 16); 237889857Sobrien 237977298Sobrien for (i = 0; i < nexp; i++) 238060484Sobrien { 238177298Sobrien unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); 238260484Sobrien def_file_import *imp; 238389857Sobrien 238477298Sobrien imp = def_file_add_import (pe_def_file, erva + name_rva, dll_name, 238560484Sobrien i, 0); 238660484Sobrien } 238760484Sobrien 238860484Sobrien return true; 238960484Sobrien} 239060484Sobrien 239189857Sobrien/* These are the main functions, called from the emulation. The first 239289857Sobrien is called after the bfds are read, so we can guess at how much space 239389857Sobrien we need. The second is called after everything is placed, so we 239489857Sobrien can put the right values in place. */ 239560484Sobrien 239660484Sobrienvoid 239760484Sobrienpe_dll_build_sections (abfd, info) 239860484Sobrien bfd *abfd; 239960484Sobrien struct bfd_link_info *info; 240060484Sobrien{ 240160484Sobrien pe_dll_id_target (bfd_get_target (abfd)); 240260484Sobrien process_def_file (abfd, info); 240360484Sobrien 240460484Sobrien generate_edata (abfd, info); 240560484Sobrien build_filler_bfd (1); 240660484Sobrien} 240760484Sobrien 240860484Sobrienvoid 240960484Sobrienpe_exe_build_sections (abfd, info) 241060484Sobrien bfd *abfd; 241160484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 241260484Sobrien{ 241360484Sobrien pe_dll_id_target (bfd_get_target (abfd)); 241460484Sobrien build_filler_bfd (0); 241560484Sobrien} 241660484Sobrien 241760484Sobrienvoid 241860484Sobrienpe_dll_fill_sections (abfd, info) 241960484Sobrien bfd *abfd; 242060484Sobrien struct bfd_link_info *info; 242160484Sobrien{ 242260484Sobrien pe_dll_id_target (bfd_get_target (abfd)); 242360484Sobrien image_base = pe_data (abfd)->pe_opthdr.ImageBase; 242460484Sobrien 242560484Sobrien generate_reloc (abfd, info); 242660484Sobrien if (reloc_sz > 0) 242760484Sobrien { 242860484Sobrien bfd_set_section_size (filler_bfd, reloc_s, reloc_sz); 242960484Sobrien 243060484Sobrien /* Resize the sections. */ 243160484Sobrien lang_size_sections (stat_ptr->head, abs_output_section, 243289857Sobrien &stat_ptr->head, 0, (bfd_vma) 0, NULL); 243360484Sobrien 243460484Sobrien /* Redo special stuff. */ 243560484Sobrien ldemul_after_allocation (); 243660484Sobrien 243760484Sobrien /* Do the assignments again. */ 243860484Sobrien lang_do_assignments (stat_ptr->head, 243960484Sobrien abs_output_section, 244060484Sobrien (fill_type) 0, (bfd_vma) 0); 244160484Sobrien } 244260484Sobrien 244360484Sobrien fill_edata (abfd, info); 244460484Sobrien 244560484Sobrien pe_data (abfd)->dll = 1; 244660484Sobrien 244760484Sobrien edata_s->contents = edata_d; 244860484Sobrien reloc_s->contents = reloc_d; 244960484Sobrien} 245060484Sobrien 245160484Sobrienvoid 245260484Sobrienpe_exe_fill_sections (abfd, info) 245360484Sobrien bfd *abfd; 245460484Sobrien struct bfd_link_info *info; 245560484Sobrien{ 245660484Sobrien pe_dll_id_target (bfd_get_target (abfd)); 245760484Sobrien image_base = pe_data (abfd)->pe_opthdr.ImageBase; 245860484Sobrien 245960484Sobrien generate_reloc (abfd, info); 246060484Sobrien if (reloc_sz > 0) 246160484Sobrien { 246260484Sobrien bfd_set_section_size (filler_bfd, reloc_s, reloc_sz); 246360484Sobrien 246460484Sobrien /* Resize the sections. */ 246560484Sobrien lang_size_sections (stat_ptr->head, abs_output_section, 246689857Sobrien &stat_ptr->head, 0, (bfd_vma) 0, NULL); 246760484Sobrien 246860484Sobrien /* Redo special stuff. */ 246960484Sobrien ldemul_after_allocation (); 247060484Sobrien 247160484Sobrien /* Do the assignments again. */ 247260484Sobrien lang_do_assignments (stat_ptr->head, 247360484Sobrien abs_output_section, 247460484Sobrien (fill_type) 0, (bfd_vma) 0); 247560484Sobrien } 247660484Sobrien reloc_s->contents = reloc_d; 247760484Sobrien} 2478