160484Sobrien/* Routines to help build PEI-format DLLs (Win32 etc)
2218822Sdim   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
3130561Sobrien   Free Software Foundation, Inc.
460484Sobrien   Written by DJ Delorie <dj@cygnus.com>
560484Sobrien
660484Sobrien   This file is part of GLD, the Gnu Linker.
760484Sobrien
860484Sobrien   GLD is free software; you can redistribute it and/or modify
960484Sobrien   it under the terms of the GNU General Public License as published by
1060484Sobrien   the Free Software Foundation; either version 2, or (at your option)
1160484Sobrien   any later version.
1260484Sobrien
1360484Sobrien   GLD is distributed in the hope that it will be useful,
1460484Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1560484Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1660484Sobrien   GNU General Public License for more details.
1760484Sobrien
1860484Sobrien   You should have received a copy of the GNU General Public License
1960484Sobrien   along with GLD; see the file COPYING.  If not, write to the Free
20218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21218822Sdim   02110-1301, USA.  */
2260484Sobrien
23218822Sdim#include "sysdep.h"
2460484Sobrien#include "bfd.h"
2560484Sobrien#include "bfdlink.h"
2660484Sobrien#include "libiberty.h"
2789857Sobrien#include "safe-ctype.h"
2860484Sobrien
2960484Sobrien#include <time.h>
3060484Sobrien
3160484Sobrien#include "ld.h"
3260484Sobrien#include "ldexp.h"
3360484Sobrien#include "ldlang.h"
3460484Sobrien#include "ldwrite.h"
3560484Sobrien#include "ldmisc.h"
36107492Sobrien#include <ldgram.h>
3760484Sobrien#include "ldmain.h"
3877298Sobrien#include "ldfile.h"
3960484Sobrien#include "ldemul.h"
4060484Sobrien#include "coff/internal.h"
4160484Sobrien#include "../bfd/libcoff.h"
4260484Sobrien#include "deffile.h"
4360484Sobrien#include "pe-dll.h"
4460484Sobrien
45218822Sdim#ifdef pe_use_x86_64
46218822Sdim
47218822Sdim#define PE_IDATA4_SIZE	8
48218822Sdim#define PE_IDATA5_SIZE	8
49218822Sdim#include "pep-dll.h"
50218822Sdim#undef  AOUTSZ
51218822Sdim#define AOUTSZ		PEPAOUTSZ
52218822Sdim#define PEAOUTHDR	PEPAOUTHDR
53218822Sdim
54218822Sdim#else
55218822Sdim
56218822Sdim#include "pe-dll.h"
57218822Sdim
58218822Sdim#endif
59218822Sdim
60218822Sdim#ifndef PE_IDATA4_SIZE
61218822Sdim#define PE_IDATA4_SIZE	4
62218822Sdim#endif
63218822Sdim
64218822Sdim#ifndef PE_IDATA5_SIZE
65218822Sdim#define PE_IDATA5_SIZE	4
66218822Sdim#endif
67218822Sdim
6889857Sobrien/*  This file turns a regular Windows PE image into a DLL.  Because of
6989857Sobrien    the complexity of this operation, it has been broken down into a
7089857Sobrien    number of separate modules which are all called by the main function
7189857Sobrien    at the end of this file.  This function is not re-entrant and is
7289857Sobrien    normally only called once, so static variables are used to reduce
7389857Sobrien    the number of parameters and return values required.
74104834Sobrien
75218822Sdim    See also: ld/emultempl/pe.em and ld/emultempl/pep.em.  */
7660484Sobrien
7789857Sobrien/*  Auto-import feature by Paul Sokolovsky
7860484Sobrien
7989857Sobrien    Quick facts:
8060484Sobrien
8189857Sobrien    1. With this feature on, DLL clients can import variables from DLL
8289857Sobrien    without any concern from their side (for example, without any source
8389857Sobrien    code modifications).
8460484Sobrien
8589857Sobrien    2. This is done completely in bounds of the PE specification (to be fair,
86130561Sobrien    there's a place where it pokes nose out of, but in practice it works).
8789857Sobrien    So, resulting module can be used with any other PE compiler/linker.
8860484Sobrien
8989857Sobrien    3. Auto-import is fully compatible with standard import method and they
9089857Sobrien    can be mixed together.
9189857Sobrien
9289857Sobrien    4. Overheads: space: 8 bytes per imported symbol, plus 20 for each
9389857Sobrien    reference to it; load time: negligible; virtual/physical memory: should be
9489857Sobrien    less than effect of DLL relocation, and I sincerely hope it doesn't affect
9589857Sobrien    DLL sharability (too much).
9689857Sobrien
9789857Sobrien    Idea
9889857Sobrien
9989857Sobrien    The obvious and only way to get rid of dllimport insanity is to make client
10089857Sobrien    access variable directly in the DLL, bypassing extra dereference. I.e.,
101130561Sobrien    whenever client contains something like
10289857Sobrien
10389857Sobrien    mov dll_var,%eax,
10489857Sobrien
10589857Sobrien    address of dll_var in the command should be relocated to point into loaded
10689857Sobrien    DLL. The aim is to make OS loader do so, and than make ld help with that.
10789857Sobrien    Import section of PE made following way: there's a vector of structures
10889857Sobrien    each describing imports from particular DLL. Each such structure points
109130561Sobrien    to two other parallel vectors: one holding imported names, and one which
11089857Sobrien    will hold address of corresponding imported name. So, the solution is
11189857Sobrien    de-vectorize these structures, making import locations be sparse and
11289857Sobrien    pointing directly into code. Before continuing, it is worth a note that,
11389857Sobrien    while authors strives to make PE act ELF-like, there're some other people
11489857Sobrien    make ELF act PE-like: elfvector, ;-) .
11589857Sobrien
11689857Sobrien    Implementation
11789857Sobrien
11889857Sobrien    For each reference of data symbol to be imported from DLL (to set of which
11989857Sobrien    belong symbols with name <sym>, if __imp_<sym> is found in implib), the
12089857Sobrien    import fixup entry is generated. That entry is of type
121218822Sdim    IMAGE_IMPORT_DESCRIPTOR and stored in .idata$2 subsection. Each
12289857Sobrien    fixup entry contains pointer to symbol's address within .text section
12389857Sobrien    (marked with __fuN_<sym> symbol, where N is integer), pointer to DLL name
12489857Sobrien    (so, DLL name is referenced by multiple entries), and pointer to symbol
12589857Sobrien    name thunk. Symbol name thunk is singleton vector (__nm_th_<symbol>)
12689857Sobrien    pointing to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) directly
127218822Sdim    containing imported name. Here comes that "on the edge" problem mentioned
12889857Sobrien    above: PE specification rambles that name vector (OriginalFirstThunk)
12989857Sobrien    should run in parallel with addresses vector (FirstThunk), i.e. that they
13089857Sobrien    should have same number of elements and terminated with zero. We violate
131130561Sobrien    this, since FirstThunk points directly into machine code. But in practice,
13289857Sobrien    OS loader implemented the sane way: it goes thru OriginalFirstThunk and
13389857Sobrien    puts addresses to FirstThunk, not something else. It once again should be
13489857Sobrien    noted that dll and symbol name structures are reused across fixup entries
13589857Sobrien    and should be there anyway to support standard import stuff, so sustained
13689857Sobrien    overhead is 20 bytes per reference. Other question is whether having several
13789857Sobrien    IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible. Answer is yes, it is
13889857Sobrien    done even by native compiler/linker (libth32's functions are in fact reside
13989857Sobrien    in windows9x kernel32.dll, so if you use it, you have two
14089857Sobrien    IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other question is whether
14189857Sobrien    referencing the same PE structures several times is valid. The answer is why
142130561Sobrien    not, prohibiting that (detecting violation) would require more work on
14389857Sobrien    behalf of loader than not doing it.
14489857Sobrien
145218822Sdim    See also: ld/emultempl/pe.em and ld/emultempl/pep.em.  */
14689857Sobrien
147130561Sobrienstatic void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *);
14889857Sobrien
14989857Sobrien/* For emultempl/pe.em.  */
15089857Sobrien
15189857Sobriendef_file * pe_def_file = 0;
15260484Sobrienint pe_dll_export_everything = 0;
15360484Sobrienint pe_dll_do_default_excludes = 1;
15460484Sobrienint pe_dll_kill_ats = 0;
15560484Sobrienint pe_dll_stdcall_aliases = 0;
15660484Sobrienint pe_dll_warn_dup_exports = 0;
15760484Sobrienint pe_dll_compat_implib = 0;
15889857Sobrienint pe_dll_extra_pe_debug = 0;
15960484Sobrien
16089857Sobrien/* Static variables and types.  */
16160484Sobrien
16260484Sobrienstatic bfd_vma image_base;
16360484Sobrienstatic bfd *filler_bfd;
164130561Sobrienstatic struct bfd_section *edata_s, *reloc_s;
16560484Sobrienstatic unsigned char *edata_d, *reloc_d;
16660484Sobrienstatic size_t edata_sz, reloc_sz;
167130561Sobrienstatic int runtime_pseudo_relocs_created = 0;
16860484Sobrien
16989857Sobrientypedef struct
170218822Sdim{
171218822Sdim  const char *name;
172218822Sdim  int len;
173218822Sdim}
174218822Sdimautofilter_entry_type;
17560484Sobrien
17689857Sobrientypedef struct
177218822Sdim{
178218822Sdim  const char *target_name;
179218822Sdim  const char *object_target;
180218822Sdim  unsigned int imagebase_reloc;
181218822Sdim  int pe_arch;
182218822Sdim  int bfd_arch;
183218822Sdim  bfd_boolean underscored;
184218822Sdim  const autofilter_entry_type* autofilter_symbollist;
185218822Sdim}
186218822Sdimpe_details_type;
18789857Sobrien
188218822Sdimstatic const autofilter_entry_type autofilter_symbollist_generic[] =
189218822Sdim{
190218822Sdim  { STRING_COMMA_LEN (".text") },
191218822Sdim  /* Entry point symbols.  */
192218822Sdim  { STRING_COMMA_LEN ("DllMain") },
193218822Sdim  { STRING_COMMA_LEN ("DllMainCRTStartup") },
194218822Sdim  { STRING_COMMA_LEN ("_DllMainCRTStartup") },
195218822Sdim  /* Runtime pseudo-reloc.  */
196218822Sdim  { STRING_COMMA_LEN ("_pei386_runtime_relocator") },
197218822Sdim  { STRING_COMMA_LEN ("do_pseudo_reloc") },
198218822Sdim  { STRING_COMMA_LEN (NULL) }
199218822Sdim};
200218822Sdim
201218822Sdimstatic const autofilter_entry_type autofilter_symbollist_i386[] =
202218822Sdim{
203218822Sdim  { STRING_COMMA_LEN (".text") },
204218822Sdim  /* Entry point symbols, and entry hooks.  */
205218822Sdim  { STRING_COMMA_LEN ("cygwin_crt0") },
206218822Sdim  { STRING_COMMA_LEN ("DllMain@12") },
207218822Sdim  { STRING_COMMA_LEN ("DllEntryPoint@0") },
208218822Sdim  { STRING_COMMA_LEN ("DllMainCRTStartup@12") },
209218822Sdim  { STRING_COMMA_LEN ("_cygwin_dll_entry@12") },
210218822Sdim  { STRING_COMMA_LEN ("_cygwin_crt0_common@8") },
211218822Sdim  { STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry@12") },
212218822Sdim  { STRING_COMMA_LEN ("cygwin_attach_dll") },
213218822Sdim  { STRING_COMMA_LEN ("cygwin_premain0") },
214218822Sdim  { STRING_COMMA_LEN ("cygwin_premain1") },
215218822Sdim  { STRING_COMMA_LEN ("cygwin_premain2") },
216218822Sdim  { STRING_COMMA_LEN ("cygwin_premain3") },
217218822Sdim  /* Runtime pseudo-reloc.  */
218218822Sdim  { STRING_COMMA_LEN ("_pei386_runtime_relocator") },
219218822Sdim  { STRING_COMMA_LEN ("do_pseudo_reloc") },
220218822Sdim  /* Global vars that should not be exported.  */
221218822Sdim  { STRING_COMMA_LEN ("impure_ptr") },
222218822Sdim  { STRING_COMMA_LEN ("_impure_ptr") },
223218822Sdim  { STRING_COMMA_LEN ("_fmode") },
224218822Sdim  { STRING_COMMA_LEN ("environ") },
225218822Sdim  { STRING_COMMA_LEN (NULL) }
226218822Sdim};
227218822Sdim
228218822Sdim#define PE_ARCH_i386	 1
229218822Sdim#define PE_ARCH_sh	 2
230218822Sdim#define PE_ARCH_mips	 3
231218822Sdim#define PE_ARCH_arm	 4
23289857Sobrien#define PE_ARCH_arm_epoc 5
233218822Sdim#define PE_ARCH_arm_wince 6
23460484Sobrien
235218822Sdimstatic const pe_details_type pe_detail_list[] =
23689857Sobrien{
23760484Sobrien  {
238218822Sdim#ifdef pe_use_x86_64
239218822Sdim    "pei-x86-64",
240218822Sdim    "pe-x86-64",
241218822Sdim    3 /* R_IMAGEBASE */,
242218822Sdim#else
24360484Sobrien    "pei-i386",
24460484Sobrien    "pe-i386",
24560484Sobrien    7 /* R_IMAGEBASE */,
246218822Sdim#endif
24760484Sobrien    PE_ARCH_i386,
24860484Sobrien    bfd_arch_i386,
249218822Sdim    TRUE,
250218822Sdim    autofilter_symbollist_i386
25160484Sobrien  },
25260484Sobrien  {
25360484Sobrien    "pei-shl",
25460484Sobrien    "pe-shl",
25560484Sobrien    16 /* R_SH_IMAGEBASE */,
25660484Sobrien    PE_ARCH_sh,
25760484Sobrien    bfd_arch_sh,
258218822Sdim    TRUE,
259218822Sdim    autofilter_symbollist_generic
26060484Sobrien  },
26160484Sobrien  {
26260484Sobrien    "pei-mips",
26360484Sobrien    "pe-mips",
26460484Sobrien    34 /* MIPS_R_RVA */,
26560484Sobrien    PE_ARCH_mips,
26660484Sobrien    bfd_arch_mips,
267218822Sdim    FALSE,
268218822Sdim    autofilter_symbollist_generic
26960484Sobrien  },
27060484Sobrien  {
27160484Sobrien    "pei-arm-little",
27260484Sobrien    "pe-arm-little",
27360484Sobrien    11 /* ARM_RVA32 */,
27460484Sobrien    PE_ARCH_arm,
27560484Sobrien    bfd_arch_arm,
276218822Sdim    TRUE,
277218822Sdim    autofilter_symbollist_generic
27860484Sobrien  },
27989857Sobrien  {
28089857Sobrien    "epoc-pei-arm-little",
28189857Sobrien    "epoc-pe-arm-little",
28289857Sobrien    11 /* ARM_RVA32 */,
28389857Sobrien    PE_ARCH_arm_epoc,
28489857Sobrien    bfd_arch_arm,
285218822Sdim    FALSE,
286218822Sdim    autofilter_symbollist_generic
28789857Sobrien  },
288218822Sdim  {
289218822Sdim    "pei-arm-wince-little",
290218822Sdim    "pe-arm-wince-little",
291218822Sdim    2,  /* ARM_RVA32 on Windows CE, see bfd/coff-arm.c.  */
292218822Sdim    PE_ARCH_arm_wince,
293218822Sdim    bfd_arch_arm,
294218822Sdim    FALSE,
295218822Sdim    autofilter_symbollist_generic
296218822Sdim  },
297218822Sdim  { NULL, NULL, 0, 0, 0, FALSE, NULL }
29860484Sobrien};
29960484Sobrien
300218822Sdimstatic const pe_details_type *pe_details;
30160484Sobrien
30289857Sobrien/* Do not specify library suffix explicitly, to allow for dllized versions.  */
303218822Sdimstatic const autofilter_entry_type autofilter_liblist[] =
30489857Sobrien{
305218822Sdim  { STRING_COMMA_LEN ("libcegcc") },
306218822Sdim  { STRING_COMMA_LEN ("libcygwin") },
307218822Sdim  { STRING_COMMA_LEN ("libgcc") },
308218822Sdim  { STRING_COMMA_LEN ("libstdc++") },
309218822Sdim  { STRING_COMMA_LEN ("libmingw32") },
310218822Sdim  { STRING_COMMA_LEN ("libmingwex") },
311218822Sdim  { STRING_COMMA_LEN ("libg2c") },
312218822Sdim  { STRING_COMMA_LEN ("libsupc++") },
313218822Sdim  { STRING_COMMA_LEN ("libobjc") },
314218822Sdim  { STRING_COMMA_LEN ("libgcj") },
315218822Sdim  { STRING_COMMA_LEN (NULL) }
31689857Sobrien};
31789857Sobrien
318218822Sdimstatic const autofilter_entry_type autofilter_objlist[] =
31989857Sobrien{
320218822Sdim  { STRING_COMMA_LEN ("crt0.o") },
321218822Sdim  { STRING_COMMA_LEN ("crt1.o") },
322218822Sdim  { STRING_COMMA_LEN ("crt2.o") },
323218822Sdim  { STRING_COMMA_LEN ("dllcrt1.o") },
324218822Sdim  { STRING_COMMA_LEN ("dllcrt2.o") },
325218822Sdim  { STRING_COMMA_LEN ("gcrt0.o") },
326218822Sdim  { STRING_COMMA_LEN ("gcrt1.o") },
327218822Sdim  { STRING_COMMA_LEN ("gcrt2.o") },
328218822Sdim  { STRING_COMMA_LEN ("crtbegin.o") },
329218822Sdim  { STRING_COMMA_LEN ("crtend.o") },
330218822Sdim  { STRING_COMMA_LEN (NULL) }
33189857Sobrien};
33289857Sobrien
333218822Sdimstatic const autofilter_entry_type autofilter_symbolprefixlist[] =
33489857Sobrien{
335218822Sdim  /* _imp_ is treated specially, as it is always underscored.  */
336218822Sdim  /* { STRING_COMMA_LEN ("_imp_") },  */
337218822Sdim  /* Don't export some c++ symbols.  */
338218822Sdim  { STRING_COMMA_LEN ("__rtti_") },
339218822Sdim  { STRING_COMMA_LEN ("__builtin_") },
340107492Sobrien  /* Don't re-export auto-imported symbols.  */
341218822Sdim  { STRING_COMMA_LEN ("_nm_") },
34289857Sobrien  /* Don't export symbols specifying internal DLL layout.  */
343218822Sdim  { STRING_COMMA_LEN ("_head_") },
344218822Sdim  { STRING_COMMA_LEN (NULL) }
34589857Sobrien};
34689857Sobrien
347218822Sdimstatic const autofilter_entry_type autofilter_symbolsuffixlist[] =
34889857Sobrien{
349218822Sdim  { STRING_COMMA_LEN ("_iname") },
350218822Sdim  { STRING_COMMA_LEN (NULL) }
35189857Sobrien};
35289857Sobrien
35360484Sobrien#define U(str) (pe_details->underscored ? "_" str : str)
35460484Sobrien
35560484Sobrienvoid
356130561Sobrienpe_dll_id_target (const char *target)
35760484Sobrien{
35860484Sobrien  int i;
35989857Sobrien
36077298Sobrien  for (i = 0; pe_detail_list[i].target_name; i++)
36177298Sobrien    if (strcmp (pe_detail_list[i].target_name, target) == 0
36277298Sobrien	|| strcmp (pe_detail_list[i].object_target, target) == 0)
36360484Sobrien      {
36477298Sobrien	pe_details = pe_detail_list + i;
36560484Sobrien	return;
36660484Sobrien      }
36760484Sobrien  einfo (_("%XUnsupported PEI architecture: %s\n"), target);
36860484Sobrien  exit (1);
36960484Sobrien}
37060484Sobrien
371104834Sobrien/* Helper functions for qsort.  Relocs must be sorted so that we can write
37289857Sobrien   them out by pages.  */
37360484Sobrien
37489857Sobrientypedef struct
37589857Sobrien  {
37689857Sobrien    bfd_vma vma;
37789857Sobrien    char type;
37889857Sobrien    short extra;
37989857Sobrien  }
38089857Sobrienreloc_data_type;
38160484Sobrien
38260484Sobrienstatic int
383130561Sobrienreloc_sort (const void *va, const void *vb)
38460484Sobrien{
385130561Sobrien  bfd_vma a = ((const reloc_data_type *) va)->vma;
386130561Sobrien  bfd_vma b = ((const reloc_data_type *) vb)->vma;
38789857Sobrien
38860484Sobrien  return (a > b) ? 1 : ((a < b) ? -1 : 0);
38960484Sobrien}
39060484Sobrien
39160484Sobrienstatic int
392130561Sobrienpe_export_sort (const void *va, const void *vb)
39360484Sobrien{
394130561Sobrien  const def_file_export *a = va;
395130561Sobrien  const def_file_export *b = vb;
39689857Sobrien
39760484Sobrien  return strcmp (a->name, b->name);
39860484Sobrien}
39960484Sobrien
40089857Sobrien/* Read and process the .DEF file.  */
40160484Sobrien
40260484Sobrien/* These correspond to the entries in pe_def_file->exports[].  I use
40360484Sobrien   exported_symbol_sections[i] to tag whether or not the symbol was
40477298Sobrien   defined, since we can't export symbols we don't have.  */
40560484Sobrien
40660484Sobrienstatic bfd_vma *exported_symbol_offsets;
407130561Sobrienstatic struct bfd_section **exported_symbol_sections;
40860484Sobrienstatic int export_table_size;
40960484Sobrienstatic int count_exported;
41060484Sobrienstatic int count_exported_byname;
41160484Sobrienstatic int count_with_ordinals;
41260484Sobrienstatic const char *dll_name;
41360484Sobrienstatic int min_ordinal, max_ordinal;
41460484Sobrienstatic int *exported_symbols;
41560484Sobrien
41689857Sobrientypedef struct exclude_list_struct
41789857Sobrien  {
41889857Sobrien    char *string;
41989857Sobrien    struct exclude_list_struct *next;
420104834Sobrien    int type;
42189857Sobrien  }
42289857Sobrienexclude_list_struct;
42377298Sobrien
42460484Sobrienstatic struct exclude_list_struct *excludes = 0;
42560484Sobrien
42660484Sobrienvoid
427130561Sobrienpe_dll_add_excludes (const char *new_excludes, const int type)
42860484Sobrien{
42960484Sobrien  char *local_copy;
43060484Sobrien  char *exclude_string;
43160484Sobrien
43260484Sobrien  local_copy = xstrdup (new_excludes);
43360484Sobrien
43460484Sobrien  exclude_string = strtok (local_copy, ",:");
43560484Sobrien  for (; exclude_string; exclude_string = strtok (NULL, ",:"))
43660484Sobrien    {
43760484Sobrien      struct exclude_list_struct *new_exclude;
43860484Sobrien
439130561Sobrien      new_exclude = xmalloc (sizeof (struct exclude_list_struct));
440130561Sobrien      new_exclude->string = xmalloc (strlen (exclude_string) + 1);
44160484Sobrien      strcpy (new_exclude->string, exclude_string);
442104834Sobrien      new_exclude->type = type;
44360484Sobrien      new_exclude->next = excludes;
44460484Sobrien      excludes = new_exclude;
44560484Sobrien    }
44660484Sobrien
44760484Sobrien  free (local_copy);
44860484Sobrien}
44960484Sobrien
450218822Sdimstatic bfd_boolean
451218822Sdimis_import (const char* n)
452218822Sdim{
453218822Sdim  return (CONST_STRNEQ (n, "__imp_"));
454218822Sdim}
455104834Sobrien
45689857Sobrien/* abfd is a bfd containing n (or NULL)
45789857Sobrien   It can be used for contextual checks.  */
45889857Sobrien
45960484Sobrienstatic int
460130561Sobrienauto_export (bfd *abfd, def_file *d, const char *n)
46160484Sobrien{
46260484Sobrien  int i;
46360484Sobrien  struct exclude_list_struct *ex;
464218822Sdim  const autofilter_entry_type *afptr;
465104834Sobrien  const char * libname = 0;
466104834Sobrien  if (abfd && abfd->my_archive)
467104834Sobrien    libname = lbasename (abfd->my_archive->filename);
46889857Sobrien
46960484Sobrien  for (i = 0; i < d->num_exports; i++)
47060484Sobrien    if (strcmp (d->exports[i].name, n) == 0)
47160484Sobrien      return 0;
47289857Sobrien
47360484Sobrien  if (pe_dll_do_default_excludes)
47460484Sobrien    {
47589857Sobrien      const char * p;
47689857Sobrien      int    len;
47789857Sobrien
47889857Sobrien      if (pe_dll_extra_pe_debug)
47989857Sobrien	printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n",
48089857Sobrien		n, abfd, abfd->my_archive);
48189857Sobrien
48289857Sobrien      /* First of all, make context checks:
483130561Sobrien	 Don't export anything from standard libs.  */
484104834Sobrien      if (libname)
48589857Sobrien	{
48689857Sobrien	  afptr = autofilter_liblist;
48789857Sobrien
48889857Sobrien	  while (afptr->name)
48989857Sobrien	    {
490104834Sobrien	      if (strncmp (libname, afptr->name, afptr->len) == 0 )
49189857Sobrien		return 0;
49289857Sobrien	      afptr++;
49389857Sobrien	    }
49489857Sobrien	}
49589857Sobrien
49689857Sobrien      /* Next, exclude symbols from certain startup objects.  */
49789857Sobrien
49889857Sobrien      if (abfd && (p = lbasename (abfd->filename)))
49989857Sobrien	{
500104834Sobrien	  afptr = autofilter_objlist;
501104834Sobrien	  while (afptr->name)
50289857Sobrien	    {
503104834Sobrien	      if (strcmp (p, afptr->name) == 0)
504104834Sobrien		return 0;
50589857Sobrien	      afptr++;
50689857Sobrien	    }
50789857Sobrien	}
50889857Sobrien
50989857Sobrien      /* Don't try to blindly exclude all symbols
51089857Sobrien	 that begin with '__'; this was tried and
511218822Sdim	 it is too restrictive.  Instead we have
512218822Sdim	 a target specific list to use:  */
513218822Sdim      afptr = pe_details->autofilter_symbollist;
51489857Sobrien
51589857Sobrien      while (afptr->name)
51689857Sobrien	{
51789857Sobrien	  if (strcmp (n, afptr->name) == 0)
51889857Sobrien	    return 0;
51989857Sobrien
520104834Sobrien	  afptr++;
52189857Sobrien	}
52289857Sobrien
52389857Sobrien      /* Next, exclude symbols starting with ...  */
52489857Sobrien      afptr = autofilter_symbolprefixlist;
52589857Sobrien      while (afptr->name)
52689857Sobrien	{
52789857Sobrien	  if (strncmp (n, afptr->name, afptr->len) == 0)
52889857Sobrien	    return 0;
52989857Sobrien
530104834Sobrien	  afptr++;
53189857Sobrien	}
53289857Sobrien
53389857Sobrien      /* Finally, exclude symbols ending with ...  */
53489857Sobrien      len = strlen (n);
53589857Sobrien      afptr = autofilter_symbolsuffixlist;
53689857Sobrien      while (afptr->name)
53789857Sobrien	{
538104834Sobrien	  if ((len >= afptr->len)
53989857Sobrien	      /* Add 1 to insure match with trailing '\0'.  */
540104834Sobrien	      && strncmp (n + len - afptr->len, afptr->name,
541104834Sobrien			  afptr->len + 1) == 0)
54289857Sobrien	    return 0;
54389857Sobrien
544104834Sobrien	  afptr++;
54589857Sobrien	}
54660484Sobrien    }
54789857Sobrien
54860484Sobrien  for (ex = excludes; ex; ex = ex->next)
549104834Sobrien    {
550104834Sobrien      if (ex->type == 1) /* exclude-libs */
551104834Sobrien	{
552104834Sobrien	  if (libname
553104834Sobrien	      && ((strcmp (libname, ex->string) == 0)
554104834Sobrien		   || (strcasecmp ("ALL", ex->string) == 0)))
555104834Sobrien	    return 0;
556104834Sobrien	}
557104834Sobrien      else if (strcmp (n, ex->string) == 0)
558104834Sobrien	return 0;
559104834Sobrien    }
56089857Sobrien
56160484Sobrien  return 1;
56260484Sobrien}
56360484Sobrien
56460484Sobrienstatic void
565130561Sobrienprocess_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
56660484Sobrien{
56760484Sobrien  int i, j;
56860484Sobrien  struct bfd_link_hash_entry *blhe;
56960484Sobrien  bfd *b;
570130561Sobrien  struct bfd_section *s;
57177298Sobrien  def_file_export *e = 0;
57260484Sobrien
57360484Sobrien  if (!pe_def_file)
57460484Sobrien    pe_def_file = def_file_empty ();
57560484Sobrien
57660484Sobrien  /* First, run around to all the objects looking for the .drectve
57777298Sobrien     sections, and push those into the def file too.  */
57860484Sobrien  for (b = info->input_bfds; b; b = b->link_next)
57960484Sobrien    {
58060484Sobrien      s = bfd_get_section_by_name (b, ".drectve");
58160484Sobrien      if (s)
58260484Sobrien	{
583218822Sdim	  long size = s->size;
58460484Sobrien	  char *buf = xmalloc (size);
58589857Sobrien
58660484Sobrien	  bfd_get_section_contents (b, s, buf, 0, size);
58760484Sobrien	  def_file_add_directive (pe_def_file, buf, size);
58860484Sobrien	  free (buf);
58960484Sobrien	}
59060484Sobrien    }
59160484Sobrien
592130561Sobrien  /* If we are not building a DLL, when there are no exports
593130561Sobrien     we do not build an export table at all.  */
594130561Sobrien  if (!pe_dll_export_everything && pe_def_file->num_exports == 0
595218822Sdim      && info->executable)
596130561Sobrien    return;
597130561Sobrien
59877298Sobrien  /* Now, maybe export everything else the default way.  */
59960484Sobrien  if (pe_dll_export_everything || pe_def_file->num_exports == 0)
60060484Sobrien    {
60160484Sobrien      for (b = info->input_bfds; b; b = b->link_next)
60260484Sobrien	{
60360484Sobrien	  asymbol **symbols;
60460484Sobrien	  int nsyms, symsize;
60560484Sobrien
60660484Sobrien	  symsize = bfd_get_symtab_upper_bound (b);
607130561Sobrien	  symbols = xmalloc (symsize);
60860484Sobrien	  nsyms = bfd_canonicalize_symtab (b, symbols);
60960484Sobrien
61060484Sobrien	  for (j = 0; j < nsyms; j++)
61160484Sobrien	    {
61277298Sobrien	      /* We should export symbols which are either global or not
613130561Sobrien		 anything at all.  (.bss data is the latter)
614130561Sobrien		 We should not export undefined symbols.  */
61589857Sobrien	      if (symbols[j]->section != &bfd_und_section
61689857Sobrien		  && ((symbols[j]->flags & BSF_GLOBAL)
61789857Sobrien		      || (symbols[j]->flags == BFD_FORT_COMM_DEFAULT_VALUE)))
61860484Sobrien		{
61960484Sobrien		  const char *sn = symbols[j]->name;
62089857Sobrien
62189857Sobrien		  /* We should not re-export imported stuff.  */
62289857Sobrien		  {
623218822Sdim		    char *name;
624218822Sdim		    if (is_import (sn))
625218822Sdim			  continue;
62689857Sobrien
627218822Sdim		    name = xmalloc (strlen ("__imp_") + strlen (sn) + 1);
628218822Sdim		    sprintf (name, "%s%s", "__imp_", sn);
629218822Sdim
63089857Sobrien		    blhe = bfd_link_hash_lookup (info->hash, name,
631130561Sobrien						 FALSE, FALSE, FALSE);
63289857Sobrien		    free (name);
63389857Sobrien
634104834Sobrien		    if (blhe && blhe->type == bfd_link_hash_defined)
63589857Sobrien		      continue;
63689857Sobrien		  }
63789857Sobrien
638218822Sdim		  if (pe_details->underscored && *sn == '_')
63960484Sobrien		    sn++;
64089857Sobrien
64189857Sobrien		  if (auto_export (b, pe_def_file, sn))
64289857Sobrien		    {
64389857Sobrien		      def_file_export *p;
64489857Sobrien		      p=def_file_add_export (pe_def_file, sn, 0, -1);
64589857Sobrien		      /* Fill data flag properly, from dlltool.c.  */
64689857Sobrien		      p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
64789857Sobrien		    }
64860484Sobrien		}
64960484Sobrien	    }
65060484Sobrien	}
65160484Sobrien    }
65260484Sobrien
65360484Sobrien#undef NE
65460484Sobrien#define NE pe_def_file->num_exports
65560484Sobrien
65677298Sobrien  /* Canonicalize the export list.  */
65760484Sobrien  if (pe_dll_kill_ats)
65860484Sobrien    {
65960484Sobrien      for (i = 0; i < NE; i++)
66060484Sobrien	{
66160484Sobrien	  if (strchr (pe_def_file->exports[i].name, '@'))
66260484Sobrien	    {
66377298Sobrien	      /* This will preserve internal_name, which may have been
664130561Sobrien		 pointing to the same memory as name, or might not
665130561Sobrien		 have.  */
666130561Sobrien	      int lead_at = (*pe_def_file->exports[i].name == '@');
667130561Sobrien	      char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
668218822Sdim	      char *tmp_at = strchr (tmp, '@');
66989857Sobrien
670218822Sdim	      if (tmp_at)
671218822Sdim	        *tmp_at = 0;
672218822Sdim	      else
673218822Sdim	        einfo (_("%XCannot export %s: invalid export name\n"),
674218822Sdim		       pe_def_file->exports[i].name);
67560484Sobrien	      pe_def_file->exports[i].name = tmp;
67660484Sobrien	    }
67760484Sobrien	}
67860484Sobrien    }
67960484Sobrien
68060484Sobrien  if (pe_dll_stdcall_aliases)
68160484Sobrien    {
68260484Sobrien      for (i = 0; i < NE; i++)
68360484Sobrien	{
684218822Sdim	  if (is_import (pe_def_file->exports[i].name))
685218822Sdim	    continue;
686218822Sdim
68760484Sobrien	  if (strchr (pe_def_file->exports[i].name, '@'))
68860484Sobrien	    {
689130561Sobrien	      int lead_at = (*pe_def_file->exports[i].name == '@');
690130561Sobrien	      char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
69189857Sobrien
69260484Sobrien	      *(strchr (tmp, '@')) = 0;
69389857Sobrien	      if (auto_export (NULL, pe_def_file, tmp))
69460484Sobrien		def_file_add_export (pe_def_file, tmp,
69589857Sobrien				     pe_def_file->exports[i].internal_name,
69689857Sobrien				     -1);
69760484Sobrien	      else
69860484Sobrien		free (tmp);
69960484Sobrien	    }
70060484Sobrien	}
70160484Sobrien    }
70260484Sobrien
70377298Sobrien  /* Convenience, but watch out for it changing.  */
70477298Sobrien  e = pe_def_file->exports;
70560484Sobrien
706130561Sobrien  exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
707130561Sobrien  exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
70860484Sobrien
709130561Sobrien  memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
71060484Sobrien  max_ordinal = 0;
71160484Sobrien  min_ordinal = 65536;
71260484Sobrien  count_exported = 0;
71360484Sobrien  count_exported_byname = 0;
71460484Sobrien  count_with_ordinals = 0;
71560484Sobrien
716130561Sobrien  qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]),
717130561Sobrien	 pe_export_sort);
71860484Sobrien  for (i = 0, j = 0; i < NE; i++)
71960484Sobrien    {
72060484Sobrien      if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)
72160484Sobrien	{
72260484Sobrien	  /* This is a duplicate.  */
72360484Sobrien	  if (e[j - 1].ordinal != -1
72460484Sobrien	      && e[i].ordinal != -1
72560484Sobrien	      && e[j - 1].ordinal != e[i].ordinal)
72660484Sobrien	    {
72760484Sobrien	      if (pe_dll_warn_dup_exports)
72860484Sobrien		/* xgettext:c-format */
72977298Sobrien		einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"),
73060484Sobrien		       e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);
73160484Sobrien	    }
73260484Sobrien	  else
73360484Sobrien	    {
73460484Sobrien	      if (pe_dll_warn_dup_exports)
73560484Sobrien		/* xgettext:c-format */
73660484Sobrien		einfo (_("Warning, duplicate EXPORT: %s\n"),
73760484Sobrien		       e[j - 1].name);
73860484Sobrien	    }
73989857Sobrien
74077298Sobrien	  if (e[i].ordinal != -1)
74160484Sobrien	    e[j - 1].ordinal = e[i].ordinal;
74260484Sobrien	  e[j - 1].flag_private |= e[i].flag_private;
74360484Sobrien	  e[j - 1].flag_constant |= e[i].flag_constant;
74460484Sobrien	  e[j - 1].flag_noname |= e[i].flag_noname;
74560484Sobrien	  e[j - 1].flag_data |= e[i].flag_data;
74660484Sobrien	}
74760484Sobrien      else
74860484Sobrien	{
74960484Sobrien	  if (i != j)
75060484Sobrien	    e[j] = e[i];
75160484Sobrien	  j++;
75260484Sobrien	}
75360484Sobrien    }
75460484Sobrien  pe_def_file->num_exports = j;	/* == NE */
75560484Sobrien
75660484Sobrien  for (i = 0; i < NE; i++)
75760484Sobrien    {
758130561Sobrien      char *name;
75989857Sobrien
760218822Sdim      /* Check for forward exports */
761218822Sdim      if (strchr (pe_def_file->exports[i].internal_name, '.'))
762218822Sdim	{
763218822Sdim	  count_exported++;
764218822Sdim	  if (!pe_def_file->exports[i].flag_noname)
765218822Sdim	    count_exported_byname++;
766218822Sdim
767218822Sdim	  pe_def_file->exports[i].flag_forward = 1;
768218822Sdim
769218822Sdim	  if (pe_def_file->exports[i].ordinal != -1)
770218822Sdim	    {
771218822Sdim	      if (max_ordinal < pe_def_file->exports[i].ordinal)
772218822Sdim		max_ordinal = pe_def_file->exports[i].ordinal;
773218822Sdim	      if (min_ordinal > pe_def_file->exports[i].ordinal)
774218822Sdim		min_ordinal = pe_def_file->exports[i].ordinal;
775218822Sdim	      count_with_ordinals++;
776218822Sdim	    }
777218822Sdim
778218822Sdim	  continue;
779218822Sdim	}
780218822Sdim
781130561Sobrien      name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
782130561Sobrien      if (pe_details->underscored
783130561Sobrien 	  && (*pe_def_file->exports[i].internal_name != '@'))
78460484Sobrien	{
78560484Sobrien	  *name = '_';
78660484Sobrien	  strcpy (name + 1, pe_def_file->exports[i].internal_name);
78760484Sobrien	}
78860484Sobrien      else
78960484Sobrien	strcpy (name, pe_def_file->exports[i].internal_name);
79060484Sobrien
79160484Sobrien      blhe = bfd_link_hash_lookup (info->hash,
79260484Sobrien				   name,
793130561Sobrien				   FALSE, FALSE, TRUE);
79460484Sobrien
79560484Sobrien      if (blhe
79677298Sobrien	  && (blhe->type == bfd_link_hash_defined
79760484Sobrien	      || (blhe->type == bfd_link_hash_common)))
79860484Sobrien	{
79960484Sobrien	  count_exported++;
80060484Sobrien	  if (!pe_def_file->exports[i].flag_noname)
80160484Sobrien	    count_exported_byname++;
80260484Sobrien
80360484Sobrien	  /* Only fill in the sections. The actual offsets are computed
80460484Sobrien	     in fill_exported_offsets() after common symbols are laid
80560484Sobrien	     out.  */
80677298Sobrien	  if (blhe->type == bfd_link_hash_defined)
80760484Sobrien	    exported_symbol_sections[i] = blhe->u.def.section;
80860484Sobrien	  else
80960484Sobrien	    exported_symbol_sections[i] = blhe->u.c.p->section;
81077298Sobrien
81160484Sobrien	  if (pe_def_file->exports[i].ordinal != -1)
81260484Sobrien	    {
81360484Sobrien	      if (max_ordinal < pe_def_file->exports[i].ordinal)
81460484Sobrien		max_ordinal = pe_def_file->exports[i].ordinal;
81560484Sobrien	      if (min_ordinal > pe_def_file->exports[i].ordinal)
81660484Sobrien		min_ordinal = pe_def_file->exports[i].ordinal;
81760484Sobrien	      count_with_ordinals++;
81860484Sobrien	    }
81960484Sobrien	}
82060484Sobrien      else if (blhe && blhe->type == bfd_link_hash_undefined)
82160484Sobrien	{
82260484Sobrien	  /* xgettext:c-format */
82360484Sobrien	  einfo (_("%XCannot export %s: symbol not defined\n"),
82460484Sobrien		 pe_def_file->exports[i].internal_name);
82560484Sobrien	}
82660484Sobrien      else if (blhe)
82760484Sobrien	{
82860484Sobrien	  /* xgettext:c-format */
82960484Sobrien	  einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"),
83060484Sobrien		 pe_def_file->exports[i].internal_name,
83160484Sobrien		 blhe->type, bfd_link_hash_defined);
83260484Sobrien	}
83360484Sobrien      else
83460484Sobrien	{
83560484Sobrien	  /* xgettext:c-format */
83660484Sobrien	  einfo (_("%XCannot export %s: symbol not found\n"),
83760484Sobrien		 pe_def_file->exports[i].internal_name);
83860484Sobrien	}
83960484Sobrien      free (name);
84060484Sobrien    }
84160484Sobrien}
84260484Sobrien
84389857Sobrien/* Build the bfd that will contain .edata and .reloc sections.  */
84460484Sobrien
84560484Sobrienstatic void
846130561Sobrienbuild_filler_bfd (int include_edata)
84760484Sobrien{
84860484Sobrien  lang_input_statement_type *filler_file;
84960484Sobrien  filler_file = lang_add_input_file ("dll stuff",
85060484Sobrien				     lang_input_file_is_fake_enum,
85160484Sobrien				     NULL);
85260484Sobrien  filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", output_bfd);
85360484Sobrien  if (filler_bfd == NULL
85460484Sobrien      || !bfd_set_arch_mach (filler_bfd,
85560484Sobrien			     bfd_get_arch (output_bfd),
85660484Sobrien			     bfd_get_mach (output_bfd)))
85760484Sobrien    {
858218822Sdim      einfo ("%X%P: can not create BFD: %E\n");
85960484Sobrien      return;
86060484Sobrien    }
86160484Sobrien
86260484Sobrien  if (include_edata)
86360484Sobrien    {
86460484Sobrien      edata_s = bfd_make_section_old_way (filler_bfd, ".edata");
86560484Sobrien      if (edata_s == NULL
86660484Sobrien	  || !bfd_set_section_flags (filler_bfd, edata_s,
86760484Sobrien				     (SEC_HAS_CONTENTS
86860484Sobrien				      | SEC_ALLOC
86960484Sobrien				      | SEC_LOAD
87060484Sobrien				      | SEC_KEEP
87160484Sobrien				      | SEC_IN_MEMORY)))
87260484Sobrien	{
87360484Sobrien	  einfo ("%X%P: can not create .edata section: %E\n");
87460484Sobrien	  return;
87560484Sobrien	}
87660484Sobrien      bfd_set_section_size (filler_bfd, edata_s, edata_sz);
87760484Sobrien    }
87860484Sobrien
87960484Sobrien  reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc");
88060484Sobrien  if (reloc_s == NULL
88160484Sobrien      || !bfd_set_section_flags (filler_bfd, reloc_s,
88260484Sobrien				 (SEC_HAS_CONTENTS
88360484Sobrien				  | SEC_ALLOC
88460484Sobrien				  | SEC_LOAD
88560484Sobrien				  | SEC_KEEP
88660484Sobrien				  | SEC_IN_MEMORY)))
88760484Sobrien    {
88860484Sobrien      einfo ("%X%P: can not create .reloc section: %E\n");
88960484Sobrien      return;
89060484Sobrien    }
89189857Sobrien
89260484Sobrien  bfd_set_section_size (filler_bfd, reloc_s, 0);
89360484Sobrien
89460484Sobrien  ldlang_add_file (filler_file);
89560484Sobrien}
89660484Sobrien
89789857Sobrien/* Gather all the exported symbols and build the .edata section.  */
89860484Sobrien
89960484Sobrienstatic void
900130561Sobriengenerate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
90160484Sobrien{
90260484Sobrien  int i, next_ordinal;
90360484Sobrien  int name_table_size = 0;
90460484Sobrien  const char *dlnp;
90560484Sobrien
90660484Sobrien  /* First, we need to know how many exported symbols there are,
90777298Sobrien     and what the range of ordinals is.  */
90860484Sobrien  if (pe_def_file->name)
90989857Sobrien    dll_name = pe_def_file->name;
91060484Sobrien  else
91160484Sobrien    {
91260484Sobrien      dll_name = abfd->filename;
91389857Sobrien
91460484Sobrien      for (dlnp = dll_name; *dlnp; dlnp++)
91589857Sobrien	if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':')
91689857Sobrien	  dll_name = dlnp + 1;
91760484Sobrien    }
91860484Sobrien
91960484Sobrien  if (count_with_ordinals && max_ordinal > count_exported)
92060484Sobrien    {
92160484Sobrien      if (min_ordinal > max_ordinal - count_exported + 1)
92260484Sobrien	min_ordinal = max_ordinal - count_exported + 1;
92360484Sobrien    }
92460484Sobrien  else
92560484Sobrien    {
92660484Sobrien      min_ordinal = 1;
92760484Sobrien      max_ordinal = count_exported;
92860484Sobrien    }
92989857Sobrien
93060484Sobrien  export_table_size = max_ordinal - min_ordinal + 1;
931130561Sobrien  exported_symbols = xmalloc (export_table_size * sizeof (int));
93260484Sobrien  for (i = 0; i < export_table_size; i++)
93360484Sobrien    exported_symbols[i] = -1;
93460484Sobrien
93577298Sobrien  /* Now we need to assign ordinals to those that don't have them.  */
93660484Sobrien  for (i = 0; i < NE; i++)
93760484Sobrien    {
938218822Sdim      if (exported_symbol_sections[i] ||
939218822Sdim          pe_def_file->exports[i].flag_forward)
94060484Sobrien	{
94160484Sobrien	  if (pe_def_file->exports[i].ordinal != -1)
94260484Sobrien	    {
94360484Sobrien	      int ei = pe_def_file->exports[i].ordinal - min_ordinal;
94460484Sobrien	      int pi = exported_symbols[ei];
94589857Sobrien
94660484Sobrien	      if (pi != -1)
94760484Sobrien		{
94860484Sobrien		  /* xgettext:c-format */
94977298Sobrien		  einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"),
95060484Sobrien			 pe_def_file->exports[i].ordinal,
95160484Sobrien			 pe_def_file->exports[i].name,
95260484Sobrien			 pe_def_file->exports[pi].name);
95360484Sobrien		}
95460484Sobrien	      exported_symbols[ei] = i;
95560484Sobrien	    }
95660484Sobrien	  name_table_size += strlen (pe_def_file->exports[i].name) + 1;
95760484Sobrien	}
958218822Sdim
959218822Sdim      /* Reserve space for the forward name. */
960218822Sdim      if (pe_def_file->exports[i].flag_forward)
961218822Sdim	{
962218822Sdim	  name_table_size += strlen (pe_def_file->exports[i].internal_name) + 1;
963218822Sdim	}
96460484Sobrien    }
96560484Sobrien
96660484Sobrien  next_ordinal = min_ordinal;
96760484Sobrien  for (i = 0; i < NE; i++)
968218822Sdim    if ((exported_symbol_sections[i] ||
969218822Sdim         pe_def_file->exports[i].flag_forward) &&
970218822Sdim        pe_def_file->exports[i].ordinal == -1)
971218822Sdim      {
972218822Sdim	while (exported_symbols[next_ordinal - min_ordinal] != -1)
973218822Sdim	  next_ordinal++;
97489857Sobrien
975218822Sdim	exported_symbols[next_ordinal - min_ordinal] = i;
976218822Sdim	pe_def_file->exports[i].ordinal = next_ordinal;
977218822Sdim      }
97860484Sobrien
97977298Sobrien  /* OK, now we can allocate some memory.  */
98089857Sobrien  edata_sz = (40				/* directory */
98189857Sobrien	      + 4 * export_table_size		/* addresses */
98260484Sobrien	      + 4 * count_exported_byname	/* name ptrs */
98360484Sobrien	      + 2 * count_exported_byname	/* ordinals */
98460484Sobrien	      + name_table_size + strlen (dll_name) + 1);
98560484Sobrien}
98660484Sobrien
98760484Sobrien/* Fill the exported symbol offsets. The preliminary work has already
98860484Sobrien   been done in process_def_file().  */
98960484Sobrien
99060484Sobrienstatic void
991130561Sobrienfill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
99260484Sobrien{
99360484Sobrien  int i;
99460484Sobrien  struct bfd_link_hash_entry *blhe;
99577298Sobrien
99660484Sobrien  for (i = 0; i < pe_def_file->num_exports; i++)
99760484Sobrien    {
998130561Sobrien      char *name;
99989857Sobrien
1000130561Sobrien      name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
1001130561Sobrien      if (pe_details->underscored
1002130561Sobrien 	  && *pe_def_file->exports[i].internal_name != '@')
100360484Sobrien	{
100460484Sobrien	  *name = '_';
100560484Sobrien	  strcpy (name + 1, pe_def_file->exports[i].internal_name);
100660484Sobrien	}
100760484Sobrien      else
100860484Sobrien	strcpy (name, pe_def_file->exports[i].internal_name);
100960484Sobrien
101060484Sobrien      blhe = bfd_link_hash_lookup (info->hash,
101160484Sobrien				   name,
1012130561Sobrien				   FALSE, FALSE, TRUE);
101360484Sobrien
1014130561Sobrien      if (blhe && blhe->type == bfd_link_hash_defined)
101589857Sobrien	exported_symbol_offsets[i] = blhe->u.def.value;
101689857Sobrien
101760484Sobrien      free (name);
101860484Sobrien    }
101960484Sobrien}
102060484Sobrien
102160484Sobrienstatic void
1022130561Sobrienfill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
102360484Sobrien{
1024130561Sobrien  int s, hint;
102560484Sobrien  unsigned char *edirectory;
1026130561Sobrien  unsigned char *eaddresses;
1027130561Sobrien  unsigned char *enameptrs;
1028130561Sobrien  unsigned char *eordinals;
1029218822Sdim  char *enamestr;
103060484Sobrien  time_t now;
103160484Sobrien
103260484Sobrien  time (&now);
103360484Sobrien
1034130561Sobrien  edata_d = xmalloc (edata_sz);
103560484Sobrien
103677298Sobrien  /* Note use of array pointer math here.  */
103760484Sobrien  edirectory = edata_d;
1038130561Sobrien  eaddresses = edata_d + 40;
1039130561Sobrien  enameptrs = eaddresses + 4 * export_table_size;
1040130561Sobrien  eordinals = enameptrs + 4 * count_exported_byname;
1041218822Sdim  enamestr = (char *) eordinals + 2 * count_exported_byname;
104260484Sobrien
1043130561Sobrien#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \
1044130561Sobrien		   + edata_s->output_section->vma - image_base)
104560484Sobrien
104677298Sobrien  memset (edata_d, 0, edata_sz);
104760484Sobrien  bfd_put_32 (abfd, now, edata_d + 4);
104860484Sobrien  if (pe_def_file->version_major != -1)
104960484Sobrien    {
105060484Sobrien      bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8);
105160484Sobrien      bfd_put_16 (abfd, pe_def_file->version_minor, edata_d + 10);
105260484Sobrien    }
105389857Sobrien
105460484Sobrien  bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12);
105560484Sobrien  strcpy (enamestr, dll_name);
105660484Sobrien  enamestr += strlen (enamestr) + 1;
105760484Sobrien  bfd_put_32 (abfd, min_ordinal, edata_d + 16);
105860484Sobrien  bfd_put_32 (abfd, export_table_size, edata_d + 20);
105960484Sobrien  bfd_put_32 (abfd, count_exported_byname, edata_d + 24);
106060484Sobrien  bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28);
106160484Sobrien  bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32);
106260484Sobrien  bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36);
106360484Sobrien
106460484Sobrien  fill_exported_offsets (abfd, info);
106560484Sobrien
1066130561Sobrien  /* Ok, now for the filling in part.
1067130561Sobrien     Scan alphabetically - ie the ordering in the exports[] table,
1068130561Sobrien     rather than by ordinal - the ordering in the exported_symbol[]
1069130561Sobrien     table.  See dlltool.c and:
1070130561Sobrien        http://sources.redhat.com/ml/binutils/2003-04/msg00379.html
1071130561Sobrien     for more information.  */
107260484Sobrien  hint = 0;
1073130561Sobrien  for (s = 0; s < NE; s++)
107460484Sobrien    {
1075130561Sobrien      struct bfd_section *ssec = exported_symbol_sections[s];
1076218822Sdim      if (pe_def_file->exports[s].ordinal != -1 &&
1077218822Sdim          (pe_def_file->exports[s].flag_forward || ssec != NULL))
107860484Sobrien	{
107977298Sobrien	  int ord = pe_def_file->exports[s].ordinal;
108060484Sobrien
1081218822Sdim	  if (pe_def_file->exports[s].flag_forward)
1082218822Sdim	    {
1083218822Sdim	      bfd_put_32 (abfd, ERVA (enamestr),
1084218822Sdim		          eaddresses + 4 * (ord - min_ordinal));
108589857Sobrien
1086218822Sdim	      strcpy (enamestr, pe_def_file->exports[s].internal_name);
1087218822Sdim	      enamestr += strlen (pe_def_file->exports[s].internal_name) + 1;
1088218822Sdim	    }
1089218822Sdim	  else
1090218822Sdim	    {
1091218822Sdim	      unsigned long srva = (exported_symbol_offsets[s]
1092218822Sdim				    + ssec->output_section->vma
1093218822Sdim				    + ssec->output_offset);
1094218822Sdim
1095218822Sdim	      bfd_put_32 (abfd, srva - image_base,
1096218822Sdim		          eaddresses + 4 * (ord - min_ordinal));
1097218822Sdim	    }
1098218822Sdim
109960484Sobrien	  if (!pe_def_file->exports[s].flag_noname)
110060484Sobrien	    {
110160484Sobrien	      char *ename = pe_def_file->exports[s].name;
1102130561Sobrien
1103130561Sobrien	      bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
1104130561Sobrien	      enameptrs += 4;
110560484Sobrien	      strcpy (enamestr, ename);
110660484Sobrien	      enamestr += strlen (enamestr) + 1;
1107130561Sobrien	      bfd_put_16 (abfd, ord - min_ordinal, eordinals);
1108130561Sobrien	      eordinals += 2;
110960484Sobrien	      pe_def_file->exports[s].hint = hint++;
111060484Sobrien	    }
111160484Sobrien	}
111260484Sobrien    }
111360484Sobrien}
111460484Sobrien
111560484Sobrien
1116130561Sobrienstatic struct bfd_section *current_sec;
111760484Sobrien
111889857Sobrienvoid
1119130561Sobrienpe_walk_relocs_of_symbol (struct bfd_link_info *info,
1120130561Sobrien			  const char *name,
1121130561Sobrien			  int (*cb) (arelent *, asection *))
112289857Sobrien{
112389857Sobrien  bfd *b;
112489857Sobrien  asection *s;
112560484Sobrien
112689857Sobrien  for (b = info->input_bfds; b; b = b->link_next)
112789857Sobrien    {
112889857Sobrien      asymbol **symbols;
112989857Sobrien      int nsyms, symsize;
113089857Sobrien
113189857Sobrien      symsize = bfd_get_symtab_upper_bound (b);
1132130561Sobrien      symbols = xmalloc (symsize);
113389857Sobrien      nsyms   = bfd_canonicalize_symtab (b, symbols);
113489857Sobrien
113589857Sobrien      for (s = b->sections; s; s = s->next)
113689857Sobrien	{
113789857Sobrien	  arelent **relocs;
113889857Sobrien	  int relsize, nrelocs, i;
113989857Sobrien	  int flags = bfd_get_section_flags (b, s);
114089857Sobrien
114189857Sobrien	  /* Skip discarded linkonce sections.  */
114289857Sobrien	  if (flags & SEC_LINK_ONCE
114389857Sobrien	      && s->output_section == bfd_abs_section_ptr)
114489857Sobrien	    continue;
114589857Sobrien
114689857Sobrien	  current_sec = s;
114789857Sobrien
114889857Sobrien	  relsize = bfd_get_reloc_upper_bound (b, s);
1149130561Sobrien	  relocs = xmalloc (relsize);
115089857Sobrien	  nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
115189857Sobrien
115289857Sobrien	  for (i = 0; i < nrelocs; i++)
115389857Sobrien	    {
1154130561Sobrien	      struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
115589857Sobrien
115689857Sobrien	      if (!strcmp (name, sym->name))
115789857Sobrien		cb (relocs[i], s);
115889857Sobrien	    }
115989857Sobrien
116089857Sobrien	  free (relocs);
116189857Sobrien
116289857Sobrien	  /* Warning: the allocated symbols are remembered in BFD and reused
116389857Sobrien	     later, so don't free them! */
116489857Sobrien	  /* free (symbols); */
116589857Sobrien	}
116689857Sobrien    }
116789857Sobrien}
116889857Sobrien
116989857Sobrien/* Gather all the relocations and build the .reloc section.  */
117089857Sobrien
117160484Sobrienstatic void
1172130561Sobriengenerate_reloc (bfd *abfd, struct bfd_link_info *info)
117360484Sobrien{
117460484Sobrien
117577298Sobrien  /* For .reloc stuff.  */
117660484Sobrien  reloc_data_type *reloc_data;
117760484Sobrien  int total_relocs = 0;
117860484Sobrien  int i;
1179130561Sobrien  unsigned long sec_page = (unsigned long) -1;
118060484Sobrien  unsigned long page_ptr, page_count;
118160484Sobrien  int bi;
118260484Sobrien  bfd *b;
1183130561Sobrien  struct bfd_section *s;
118460484Sobrien
118560484Sobrien  total_relocs = 0;
118660484Sobrien  for (b = info->input_bfds; b; b = b->link_next)
118760484Sobrien    for (s = b->sections; s; s = s->next)
118860484Sobrien      total_relocs += s->reloc_count;
118960484Sobrien
1190130561Sobrien  reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type));
119160484Sobrien
119260484Sobrien  total_relocs = 0;
119360484Sobrien  bi = 0;
119460484Sobrien  for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next)
119560484Sobrien    {
119660484Sobrien      arelent **relocs;
119760484Sobrien      int relsize, nrelocs, i;
119860484Sobrien
119960484Sobrien      for (s = b->sections; s; s = s->next)
120060484Sobrien	{
120160484Sobrien	  unsigned long sec_vma = s->output_section->vma + s->output_offset;
120260484Sobrien	  asymbol **symbols;
120360484Sobrien	  int nsyms, symsize;
120460484Sobrien
120577298Sobrien	  /* If it's not loaded, we don't need to relocate it this way.  */
120660484Sobrien	  if (!(s->output_section->flags & SEC_LOAD))
120760484Sobrien	    continue;
120860484Sobrien
120960484Sobrien	  /* I don't know why there would be a reloc for these, but I've
121077298Sobrien	     seen it happen - DJ  */
121160484Sobrien	  if (s->output_section == &bfd_abs_section)
121260484Sobrien	    continue;
121360484Sobrien
121460484Sobrien	  if (s->output_section->vma == 0)
121560484Sobrien	    {
121677298Sobrien	      /* Huh?  Shouldn't happen, but punt if it does.  */
121760484Sobrien	      einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n",
121860484Sobrien		     s->output_section->name, s->output_section->index,
121960484Sobrien		     s->output_section->flags);
122060484Sobrien	      continue;
122160484Sobrien	    }
122260484Sobrien
122360484Sobrien	  symsize = bfd_get_symtab_upper_bound (b);
1224130561Sobrien	  symbols = xmalloc (symsize);
122560484Sobrien	  nsyms = bfd_canonicalize_symtab (b, symbols);
122660484Sobrien
122760484Sobrien	  relsize = bfd_get_reloc_upper_bound (b, s);
1228130561Sobrien	  relocs = xmalloc (relsize);
122960484Sobrien	  nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
123060484Sobrien
123160484Sobrien	  for (i = 0; i < nrelocs; i++)
123260484Sobrien	    {
123389857Sobrien	      if (pe_dll_extra_pe_debug)
1234104834Sobrien		{
1235130561Sobrien		  struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
1236104834Sobrien		  printf ("rel: %s\n", sym->name);
123789857Sobrien		}
123860484Sobrien	      if (!relocs[i]->howto->pc_relative
123960484Sobrien		  && relocs[i]->howto->type != pe_details->imagebase_reloc)
124060484Sobrien		{
124160484Sobrien		  bfd_vma sym_vma;
1242130561Sobrien		  struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
124389857Sobrien
124460484Sobrien		  sym_vma = (relocs[i]->addend
124560484Sobrien			     + sym->value
124660484Sobrien			     + sym->section->vma
124760484Sobrien			     + sym->section->output_offset
124860484Sobrien			     + sym->section->output_section->vma);
124960484Sobrien		  reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
125077298Sobrien
125160484Sobrien#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
125277298Sobrien
125360484Sobrien		  switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
125460484Sobrien					 relocs[i]->howto->rightshift)
125560484Sobrien		    {
1256218822Sdim#ifdef pe_use_x86_64
1257218822Sdim		    case BITS_AND_SHIFT (64, 0):
1258218822Sdim		      reloc_data[total_relocs].type = 10;
1259218822Sdim		      total_relocs++;
1260218822Sdim		      break;
1261218822Sdim#endif
126260484Sobrien		    case BITS_AND_SHIFT (32, 0):
126360484Sobrien		      reloc_data[total_relocs].type = 3;
126460484Sobrien		      total_relocs++;
126560484Sobrien		      break;
126660484Sobrien		    case BITS_AND_SHIFT (16, 0):
126760484Sobrien		      reloc_data[total_relocs].type = 2;
126860484Sobrien		      total_relocs++;
126960484Sobrien		      break;
127060484Sobrien		    case BITS_AND_SHIFT (16, 16):
127160484Sobrien		      reloc_data[total_relocs].type = 4;
127277298Sobrien		      /* FIXME: we can't know the symbol's right value
127377298Sobrien			 yet, but we probably can safely assume that
127477298Sobrien			 CE will relocate us in 64k blocks, so leaving
127577298Sobrien			 it zero is safe.  */
127660484Sobrien		      reloc_data[total_relocs].extra = 0;
127760484Sobrien		      total_relocs++;
127860484Sobrien		      break;
127960484Sobrien		    case BITS_AND_SHIFT (26, 2):
128060484Sobrien		      reloc_data[total_relocs].type = 5;
128160484Sobrien		      total_relocs++;
128260484Sobrien		      break;
1283130561Sobrien		    case BITS_AND_SHIFT (24, 2):
1284130561Sobrien		      /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c
1285130561Sobrien			 Those ARM_xxx definitions should go in proper
1286130561Sobrien			 header someday.  */
1287130561Sobrien		      if (relocs[i]->howto->type == 0
1288130561Sobrien			  /* Older GNU linkers used 5 instead of 0 for this reloc.  */
1289130561Sobrien			  || relocs[i]->howto->type == 5)
1290130561Sobrien			/* This is an ARM_26D reloc, which is an ARM_26 reloc
1291130561Sobrien			   that has already been fully processed during a
1292130561Sobrien			   previous link stage, so ignore it here.  */
1293130561Sobrien			break;
1294130561Sobrien		      /* Fall through.  */
129560484Sobrien		    default:
129660484Sobrien		      /* xgettext:c-format */
129760484Sobrien		      einfo (_("%XError: %d-bit reloc in dll\n"),
129860484Sobrien			     relocs[i]->howto->bitsize);
129960484Sobrien		      break;
130060484Sobrien		    }
130160484Sobrien		}
130260484Sobrien	    }
130360484Sobrien	  free (relocs);
130477298Sobrien	  /* Warning: the allocated symbols are remembered in BFD and
130577298Sobrien	     reused later, so don't free them!  */
130660484Sobrien	}
130760484Sobrien    }
130860484Sobrien
130960484Sobrien  /* At this point, we have total_relocs relocation addresses in
131060484Sobrien     reloc_addresses, which are all suitable for the .reloc section.
131177298Sobrien     We must now create the new sections.  */
131260484Sobrien  qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort);
131360484Sobrien
131460484Sobrien  for (i = 0; i < total_relocs; i++)
131560484Sobrien    {
131660484Sobrien      unsigned long this_page = (reloc_data[i].vma >> 12);
131777298Sobrien
131860484Sobrien      if (this_page != sec_page)
131960484Sobrien	{
132089857Sobrien	  reloc_sz = (reloc_sz + 3) & ~3;	/* 4-byte align.  */
132160484Sobrien	  reloc_sz += 8;
132260484Sobrien	  sec_page = this_page;
132360484Sobrien	}
132477298Sobrien
132560484Sobrien      reloc_sz += 2;
132677298Sobrien
132760484Sobrien      if (reloc_data[i].type == 4)
132860484Sobrien	reloc_sz += 2;
132960484Sobrien    }
1330104834Sobrien
133189857Sobrien  reloc_sz = (reloc_sz + 3) & ~3;	/* 4-byte align.  */
1332130561Sobrien  reloc_d = xmalloc (reloc_sz);
1333130561Sobrien  sec_page = (unsigned long) -1;
133460484Sobrien  reloc_sz = 0;
1335130561Sobrien  page_ptr = (unsigned long) -1;
133660484Sobrien  page_count = 0;
133789857Sobrien
133860484Sobrien  for (i = 0; i < total_relocs; i++)
133960484Sobrien    {
134060484Sobrien      unsigned long rva = reloc_data[i].vma - image_base;
134160484Sobrien      unsigned long this_page = (rva & ~0xfff);
134289857Sobrien
134360484Sobrien      if (this_page != sec_page)
134460484Sobrien	{
134560484Sobrien	  while (reloc_sz & 3)
134660484Sobrien	    reloc_d[reloc_sz++] = 0;
134789857Sobrien
1348130561Sobrien	  if (page_ptr != (unsigned long) -1)
134960484Sobrien	    bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
135089857Sobrien
135160484Sobrien	  bfd_put_32 (abfd, this_page, reloc_d + reloc_sz);
135260484Sobrien	  page_ptr = reloc_sz;
135360484Sobrien	  reloc_sz += 8;
135460484Sobrien	  sec_page = this_page;
135560484Sobrien	  page_count = 0;
135660484Sobrien	}
135789857Sobrien
135877298Sobrien      bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
135960484Sobrien		  reloc_d + reloc_sz);
136060484Sobrien      reloc_sz += 2;
136189857Sobrien
136260484Sobrien      if (reloc_data[i].type == 4)
136360484Sobrien	{
136460484Sobrien	  bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
136560484Sobrien	  reloc_sz += 2;
136660484Sobrien	}
136789857Sobrien
136860484Sobrien      page_count++;
136960484Sobrien    }
137089857Sobrien
137160484Sobrien  while (reloc_sz & 3)
137260484Sobrien    reloc_d[reloc_sz++] = 0;
137389857Sobrien
1374130561Sobrien  if (page_ptr != (unsigned long) -1)
137560484Sobrien    bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
137689857Sobrien
1377218822Sdim  while (reloc_sz < reloc_s->size)
137860484Sobrien    reloc_d[reloc_sz++] = 0;
137960484Sobrien}
138060484Sobrien
138189857Sobrien/* Given the exiting def_file structure, print out a .DEF file that
138289857Sobrien   corresponds to it.  */
138360484Sobrien
138460484Sobrienstatic void
1385130561Sobrienquoteput (char *s, FILE *f, int needs_quotes)
138660484Sobrien{
138760484Sobrien  char *cp;
138889857Sobrien
138960484Sobrien  for (cp = s; *cp; cp++)
139060484Sobrien    if (*cp == '\''
139160484Sobrien	|| *cp == '"'
139260484Sobrien	|| *cp == '\\'
139389857Sobrien	|| ISSPACE (*cp)
139460484Sobrien	|| *cp == ','
139560484Sobrien	|| *cp == ';')
139660484Sobrien      needs_quotes = 1;
139789857Sobrien
139860484Sobrien  if (needs_quotes)
139960484Sobrien    {
140060484Sobrien      putc ('"', f);
140189857Sobrien
140260484Sobrien      while (*s)
140360484Sobrien	{
140460484Sobrien	  if (*s == '"' || *s == '\\')
140560484Sobrien	    putc ('\\', f);
140689857Sobrien
140760484Sobrien	  putc (*s, f);
140860484Sobrien	  s++;
140960484Sobrien	}
141089857Sobrien
141160484Sobrien      putc ('"', f);
141260484Sobrien    }
141360484Sobrien  else
141460484Sobrien    fputs (s, f);
141560484Sobrien}
141660484Sobrien
141760484Sobrienvoid
1418130561Sobrienpe_dll_generate_def_file (const char *pe_out_def_filename)
141960484Sobrien{
142060484Sobrien  int i;
142160484Sobrien  FILE *out = fopen (pe_out_def_filename, "w");
142289857Sobrien
142360484Sobrien  if (out == NULL)
142489857Sobrien    /* xgettext:c-format */
142589857Sobrien    einfo (_("%s: Can't open output def file %s\n"),
142689857Sobrien	   program_name, pe_out_def_filename);
142760484Sobrien
142860484Sobrien  if (pe_def_file)
142960484Sobrien    {
143060484Sobrien      if (pe_def_file->name)
143160484Sobrien	{
143260484Sobrien	  if (pe_def_file->is_dll)
143360484Sobrien	    fprintf (out, "LIBRARY ");
143460484Sobrien	  else
143560484Sobrien	    fprintf (out, "NAME ");
143689857Sobrien
143760484Sobrien	  quoteput (pe_def_file->name, out, 1);
143889857Sobrien
143960484Sobrien	  if (pe_data (output_bfd)->pe_opthdr.ImageBase)
144060484Sobrien	    fprintf (out, " BASE=0x%lx",
144160484Sobrien		     (unsigned long) pe_data (output_bfd)->pe_opthdr.ImageBase);
144260484Sobrien	  fprintf (out, "\n");
144360484Sobrien	}
144460484Sobrien
144560484Sobrien      if (pe_def_file->description)
144660484Sobrien	{
144760484Sobrien	  fprintf (out, "DESCRIPTION ");
144860484Sobrien	  quoteput (pe_def_file->description, out, 1);
144960484Sobrien	  fprintf (out, "\n");
145060484Sobrien	}
145160484Sobrien
145260484Sobrien      if (pe_def_file->version_minor != -1)
145360484Sobrien	fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major,
145460484Sobrien		 pe_def_file->version_minor);
145560484Sobrien      else if (pe_def_file->version_major != -1)
145660484Sobrien	fprintf (out, "VERSION %d\n", pe_def_file->version_major);
145760484Sobrien
145860484Sobrien      if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1)
145960484Sobrien	fprintf (out, "\n");
146060484Sobrien
146160484Sobrien      if (pe_def_file->stack_commit != -1)
146260484Sobrien	fprintf (out, "STACKSIZE 0x%x,0x%x\n",
146360484Sobrien		 pe_def_file->stack_reserve, pe_def_file->stack_commit);
146460484Sobrien      else if (pe_def_file->stack_reserve != -1)
146560484Sobrien	fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve);
146689857Sobrien
146760484Sobrien      if (pe_def_file->heap_commit != -1)
146860484Sobrien	fprintf (out, "HEAPSIZE 0x%x,0x%x\n",
146960484Sobrien		 pe_def_file->heap_reserve, pe_def_file->heap_commit);
147060484Sobrien      else if (pe_def_file->heap_reserve != -1)
147160484Sobrien	fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve);
147260484Sobrien
147360484Sobrien      if (pe_def_file->num_section_defs > 0)
147460484Sobrien	{
147560484Sobrien	  fprintf (out, "\nSECTIONS\n\n");
147689857Sobrien
147760484Sobrien	  for (i = 0; i < pe_def_file->num_section_defs; i++)
147860484Sobrien	    {
147960484Sobrien	      fprintf (out, "    ");
148060484Sobrien	      quoteput (pe_def_file->section_defs[i].name, out, 0);
148189857Sobrien
148260484Sobrien	      if (pe_def_file->section_defs[i].class)
148360484Sobrien		{
148460484Sobrien		  fprintf (out, " CLASS ");
148560484Sobrien		  quoteput (pe_def_file->section_defs[i].class, out, 0);
148660484Sobrien		}
148789857Sobrien
148860484Sobrien	      if (pe_def_file->section_defs[i].flag_read)
148960484Sobrien		fprintf (out, " READ");
149089857Sobrien
149160484Sobrien	      if (pe_def_file->section_defs[i].flag_write)
149260484Sobrien		fprintf (out, " WRITE");
149389857Sobrien
149460484Sobrien	      if (pe_def_file->section_defs[i].flag_execute)
149560484Sobrien		fprintf (out, " EXECUTE");
149689857Sobrien
149760484Sobrien	      if (pe_def_file->section_defs[i].flag_shared)
149860484Sobrien		fprintf (out, " SHARED");
149989857Sobrien
150060484Sobrien	      fprintf (out, "\n");
150160484Sobrien	    }
150260484Sobrien	}
150360484Sobrien
150460484Sobrien      if (pe_def_file->num_exports > 0)
150560484Sobrien	{
150689857Sobrien	  fprintf (out, "EXPORTS\n");
150789857Sobrien
150860484Sobrien	  for (i = 0; i < pe_def_file->num_exports; i++)
150960484Sobrien	    {
151060484Sobrien	      def_file_export *e = pe_def_file->exports + i;
151160484Sobrien	      fprintf (out, "    ");
151260484Sobrien	      quoteput (e->name, out, 0);
151389857Sobrien
151460484Sobrien	      if (e->internal_name && strcmp (e->internal_name, e->name))
151560484Sobrien		{
151660484Sobrien		  fprintf (out, " = ");
151760484Sobrien		  quoteput (e->internal_name, out, 0);
151860484Sobrien		}
151989857Sobrien
152060484Sobrien	      if (e->ordinal != -1)
152160484Sobrien		fprintf (out, " @%d", e->ordinal);
152289857Sobrien
152360484Sobrien	      if (e->flag_private)
152460484Sobrien		fprintf (out, " PRIVATE");
152589857Sobrien
152660484Sobrien	      if (e->flag_constant)
152760484Sobrien		fprintf (out, " CONSTANT");
152889857Sobrien
152960484Sobrien	      if (e->flag_noname)
153060484Sobrien		fprintf (out, " NONAME");
153189857Sobrien
153260484Sobrien	      if (e->flag_data)
153360484Sobrien		fprintf (out, " DATA");
153460484Sobrien
153560484Sobrien	      fprintf (out, "\n");
153660484Sobrien	    }
153760484Sobrien	}
153860484Sobrien
153960484Sobrien      if (pe_def_file->num_imports > 0)
154060484Sobrien	{
154160484Sobrien	  fprintf (out, "\nIMPORTS\n\n");
154289857Sobrien
154360484Sobrien	  for (i = 0; i < pe_def_file->num_imports; i++)
154460484Sobrien	    {
154560484Sobrien	      def_file_import *im = pe_def_file->imports + i;
154660484Sobrien	      fprintf (out, "    ");
154789857Sobrien
154860484Sobrien	      if (im->internal_name
154960484Sobrien		  && (!im->name || strcmp (im->internal_name, im->name)))
155060484Sobrien		{
155160484Sobrien		  quoteput (im->internal_name, out, 0);
155260484Sobrien		  fprintf (out, " = ");
155360484Sobrien		}
155489857Sobrien
155560484Sobrien	      quoteput (im->module->name, out, 0);
155660484Sobrien	      fprintf (out, ".");
155789857Sobrien
155860484Sobrien	      if (im->name)
155960484Sobrien		quoteput (im->name, out, 0);
156060484Sobrien	      else
156160484Sobrien		fprintf (out, "%d", im->ordinal);
156289857Sobrien
156360484Sobrien	      fprintf (out, "\n");
156460484Sobrien	    }
156560484Sobrien	}
156660484Sobrien    }
156760484Sobrien  else
156860484Sobrien    fprintf (out, _("; no contents available\n"));
156960484Sobrien
157060484Sobrien  if (fclose (out) == EOF)
157189857Sobrien    /* xgettext:c-format */
157289857Sobrien    einfo (_("%P: Error closing file `%s'\n"), pe_out_def_filename);
157360484Sobrien}
157460484Sobrien
157589857Sobrien/* Generate the import library.  */
157660484Sobrien
157760484Sobrienstatic asymbol **symtab;
157860484Sobrienstatic int symptr;
157960484Sobrienstatic int tmp_seq;
158060484Sobrienstatic const char *dll_filename;
158160484Sobrienstatic char *dll_symname;
158260484Sobrien
158360484Sobrien#define UNDSEC (asection *) &bfd_und_section
158460484Sobrien
158560484Sobrienstatic asection *
1586130561Sobrienquick_section (bfd *abfd, const char *name, int flags, int align)
158760484Sobrien{
158860484Sobrien  asection *sec;
158960484Sobrien  asymbol *sym;
159060484Sobrien
159160484Sobrien  sec = bfd_make_section_old_way (abfd, name);
159277298Sobrien  bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP);
159360484Sobrien  bfd_set_section_alignment (abfd, sec, align);
159477298Sobrien  /* Remember to undo this before trying to link internally!  */
159560484Sobrien  sec->output_section = sec;
159660484Sobrien
159760484Sobrien  sym = bfd_make_empty_symbol (abfd);
159860484Sobrien  symtab[symptr++] = sym;
159960484Sobrien  sym->name = sec->name;
160060484Sobrien  sym->section = sec;
160160484Sobrien  sym->flags = BSF_LOCAL;
160260484Sobrien  sym->value = 0;
160360484Sobrien
160460484Sobrien  return sec;
160560484Sobrien}
160660484Sobrien
160760484Sobrienstatic void
1608130561Sobrienquick_symbol (bfd *abfd,
1609130561Sobrien	      const char *n1,
1610130561Sobrien	      const char *n2,
1611130561Sobrien	      const char *n3,
1612130561Sobrien	      asection *sec,
1613130561Sobrien	      int flags,
1614130561Sobrien	      int addr)
161560484Sobrien{
161660484Sobrien  asymbol *sym;
1617130561Sobrien  char *name = xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1);
161889857Sobrien
161960484Sobrien  strcpy (name, n1);
162060484Sobrien  strcat (name, n2);
162160484Sobrien  strcat (name, n3);
162260484Sobrien  sym = bfd_make_empty_symbol (abfd);
162360484Sobrien  sym->name = name;
162460484Sobrien  sym->section = sec;
162560484Sobrien  sym->flags = flags;
162660484Sobrien  sym->value = addr;
162760484Sobrien  symtab[symptr++] = sym;
162860484Sobrien}
162960484Sobrien
163060484Sobrienstatic arelent *reltab = 0;
163160484Sobrienstatic int relcount = 0, relsize = 0;
163260484Sobrien
163360484Sobrienstatic void
1634130561Sobrienquick_reloc (bfd *abfd, int address, int which_howto, int symidx)
163560484Sobrien{
1636130561Sobrien  if (relcount >= relsize - 1)
163760484Sobrien    {
163860484Sobrien      relsize += 10;
163960484Sobrien      if (reltab)
1640130561Sobrien	reltab = xrealloc (reltab, relsize * sizeof (arelent));
164160484Sobrien      else
1642130561Sobrien	reltab = xmalloc (relsize * sizeof (arelent));
164360484Sobrien    }
164460484Sobrien  reltab[relcount].address = address;
164560484Sobrien  reltab[relcount].addend = 0;
164660484Sobrien  reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto);
164760484Sobrien  reltab[relcount].sym_ptr_ptr = symtab + symidx;
164860484Sobrien  relcount++;
164960484Sobrien}
165060484Sobrien
165160484Sobrienstatic void
165260484Sobriensave_relocs (asection *sec)
165360484Sobrien{
165460484Sobrien  int i;
165589857Sobrien
165660484Sobrien  sec->relocation = reltab;
165760484Sobrien  sec->reloc_count = relcount;
1658130561Sobrien  sec->orelocation = xmalloc ((relcount + 1) * sizeof (arelent *));
165977298Sobrien  for (i = 0; i < relcount; i++)
166060484Sobrien    sec->orelocation[i] = sec->relocation + i;
166160484Sobrien  sec->orelocation[relcount] = 0;
166260484Sobrien  sec->flags |= SEC_RELOC;
166360484Sobrien  reltab = 0;
166460484Sobrien  relcount = relsize = 0;
166560484Sobrien}
166660484Sobrien
166789857Sobrien/*	.section	.idata$2
166889857Sobrien 	.global		__head_my_dll
166989857Sobrien   __head_my_dll:
167089857Sobrien 	.rva		hname
167189857Sobrien 	.long		0
167289857Sobrien 	.long		0
167389857Sobrien 	.rva		__my_dll_iname
167489857Sobrien 	.rva		fthunk
1675104834Sobrien
167689857Sobrien 	.section	.idata$5
167789857Sobrien 	.long		0
167889857Sobrien   fthunk:
1679104834Sobrien
168089857Sobrien 	.section	.idata$4
168189857Sobrien 	.long		0
168289857Sobrien   hname:                              */
168360484Sobrien
168460484Sobrienstatic bfd *
1685130561Sobrienmake_head (bfd *parent)
168660484Sobrien{
168760484Sobrien  asection *id2, *id5, *id4;
168860484Sobrien  unsigned char *d2, *d5, *d4;
168960484Sobrien  char *oname;
169060484Sobrien  bfd *abfd;
169160484Sobrien
1692130561Sobrien  oname = xmalloc (20);
169360484Sobrien  sprintf (oname, "d%06d.o", tmp_seq);
169460484Sobrien  tmp_seq++;
169560484Sobrien
169660484Sobrien  abfd = bfd_create (oname, parent);
169760484Sobrien  bfd_find_target (pe_details->object_target, abfd);
169860484Sobrien  bfd_make_writable (abfd);
169960484Sobrien
170060484Sobrien  bfd_set_format (abfd, bfd_object);
170160484Sobrien  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
170260484Sobrien
170360484Sobrien  symptr = 0;
1704130561Sobrien  symtab = xmalloc (6 * sizeof (asymbol *));
170560484Sobrien  id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
170660484Sobrien  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
170760484Sobrien  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
170877298Sobrien  quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0);
170977298Sobrien  quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
171060484Sobrien
171160484Sobrien  /* OK, pay attention here.  I got confused myself looking back at
171260484Sobrien     it.  We create a four-byte section to mark the beginning of the
171360484Sobrien     list, and we include an offset of 4 in the section, so that the
171460484Sobrien     pointer to the list points to the *end* of this section, which is
171577298Sobrien     the start of the list of sections from other objects.  */
171660484Sobrien
171760484Sobrien  bfd_set_section_size (abfd, id2, 20);
1718130561Sobrien  d2 = xmalloc (20);
171960484Sobrien  id2->contents = d2;
172060484Sobrien  memset (d2, 0, 20);
172189857Sobrien  d2[0] = d2[16] = 4; /* Reloc addend.  */
172260484Sobrien  quick_reloc (abfd,  0, BFD_RELOC_RVA, 2);
172360484Sobrien  quick_reloc (abfd, 12, BFD_RELOC_RVA, 4);
172460484Sobrien  quick_reloc (abfd, 16, BFD_RELOC_RVA, 1);
172560484Sobrien  save_relocs (id2);
172660484Sobrien
1727218822Sdim  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
1728218822Sdim  d5 = xmalloc (PE_IDATA5_SIZE);
172960484Sobrien  id5->contents = d5;
1730218822Sdim  memset (d5, 0, PE_IDATA5_SIZE);
173160484Sobrien
1732218822Sdim  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
1733218822Sdim  d4 = xmalloc (PE_IDATA4_SIZE);
173460484Sobrien  id4->contents = d4;
1735218822Sdim  memset (d4, 0, PE_IDATA4_SIZE);
173660484Sobrien
173760484Sobrien  bfd_set_symtab (abfd, symtab, symptr);
173860484Sobrien
173960484Sobrien  bfd_set_section_contents (abfd, id2, d2, 0, 20);
1740218822Sdim  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
1741218822Sdim  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
174277298Sobrien
174360484Sobrien  bfd_make_readable (abfd);
174460484Sobrien  return abfd;
174560484Sobrien}
174660484Sobrien
174789857Sobrien/*	.section	.idata$4
174889857Sobrien 	.long		0
1749218822Sdim	[.long		0] for PE+
175089857Sobrien 	.section	.idata$5
175189857Sobrien 	.long		0
1752218822Sdim	[.long		0] for PE+
175389857Sobrien 	.section	idata$7
175489857Sobrien 	.global		__my_dll_iname
175589857Sobrien  __my_dll_iname:
175689857Sobrien 	.asciz		"my.dll"       */
175760484Sobrien
175860484Sobrienstatic bfd *
1759130561Sobrienmake_tail (bfd *parent)
176060484Sobrien{
176160484Sobrien  asection *id4, *id5, *id7;
176260484Sobrien  unsigned char *d4, *d5, *d7;
176360484Sobrien  int len;
176460484Sobrien  char *oname;
176560484Sobrien  bfd *abfd;
176660484Sobrien
1767130561Sobrien  oname = xmalloc (20);
176860484Sobrien  sprintf (oname, "d%06d.o", tmp_seq);
176960484Sobrien  tmp_seq++;
177060484Sobrien
177160484Sobrien  abfd = bfd_create (oname, parent);
177260484Sobrien  bfd_find_target (pe_details->object_target, abfd);
177360484Sobrien  bfd_make_writable (abfd);
177460484Sobrien
177560484Sobrien  bfd_set_format (abfd, bfd_object);
177660484Sobrien  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
177760484Sobrien
177860484Sobrien  symptr = 0;
1779130561Sobrien  symtab = xmalloc (5 * sizeof (asymbol *));
178060484Sobrien  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
178160484Sobrien  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
178260484Sobrien  id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
178377298Sobrien  quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0);
178460484Sobrien
1785218822Sdim  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
1786218822Sdim  d4 = xmalloc (PE_IDATA4_SIZE);
178760484Sobrien  id4->contents = d4;
1788218822Sdim  memset (d4, 0, PE_IDATA4_SIZE);
178960484Sobrien
1790218822Sdim  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
1791218822Sdim  d5 = xmalloc (PE_IDATA5_SIZE);
179260484Sobrien  id5->contents = d5;
1793218822Sdim  memset (d5, 0, PE_IDATA5_SIZE);
179460484Sobrien
179577298Sobrien  len = strlen (dll_filename) + 1;
179660484Sobrien  if (len & 1)
179777298Sobrien    len++;
179860484Sobrien  bfd_set_section_size (abfd, id7, len);
1799130561Sobrien  d7 = xmalloc (len);
180060484Sobrien  id7->contents = d7;
1801218822Sdim  strcpy ((char *) d7, dll_filename);
1802218822Sdim  /* If len was odd, the above
1803218822Sdim     strcpy leaves behind an undefined byte. That is harmless,
1804218822Sdim     but we set it to 0 just so the binary dumps are pretty.  */
1805218822Sdim  d7[len - 1] = 0;
180660484Sobrien
180760484Sobrien  bfd_set_symtab (abfd, symtab, symptr);
180860484Sobrien
1809218822Sdim  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
1810218822Sdim  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
181160484Sobrien  bfd_set_section_contents (abfd, id7, d7, 0, len);
181260484Sobrien
181360484Sobrien  bfd_make_readable (abfd);
181460484Sobrien  return abfd;
181560484Sobrien}
181660484Sobrien
181789857Sobrien/*	.text
181889857Sobrien 	.global		_function
181989857Sobrien 	.global		___imp_function
182089857Sobrien 	.global		__imp__function
182189857Sobrien  _function:
182289857Sobrien 	jmp		*__imp__function:
1823104834Sobrien
182489857Sobrien 	.section	idata$7
182589857Sobrien 	.long		__head_my_dll
1826104834Sobrien
182789857Sobrien 	.section	.idata$5
182889857Sobrien  ___imp_function:
182989857Sobrien  __imp__function:
183089857Sobrien  iat?
183189857Sobrien  	.section	.idata$4
183289857Sobrien  iat?
183389857Sobrien 	.section	.idata$6
183489857Sobrien  ID<ordinal>:
183589857Sobrien 	.short		<hint>
183689857Sobrien 	.asciz		"function" xlate? (add underscore, kill at)  */
183760484Sobrien
1838218822Sdimstatic const unsigned char jmp_ix86_bytes[] =
183989857Sobrien{
184060484Sobrien  0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
184160484Sobrien};
184260484Sobrien
184389857Sobrien/* _function:
184489857Sobrien 	mov.l	ip+8,r0
184589857Sobrien 	mov.l	@r0,r0
184689857Sobrien 	jmp	@r0
184789857Sobrien 	nop
184889857Sobrien 	.dw	__imp_function   */
184960484Sobrien
1850218822Sdimstatic const unsigned char jmp_sh_bytes[] =
185189857Sobrien{
185260484Sobrien  0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00
185360484Sobrien};
185460484Sobrien
185589857Sobrien/* _function:
185689857Sobrien 	lui	$t0,<high:__imp_function>
185789857Sobrien 	lw	$t0,<low:__imp_function>
185889857Sobrien 	jr	$t0
185989857Sobrien 	nop                              */
186060484Sobrien
1861218822Sdimstatic const unsigned char jmp_mips_bytes[] =
186289857Sobrien{
186360484Sobrien  0x00, 0x00, 0x08, 0x3c,  0x00, 0x00, 0x08, 0x8d,
186460484Sobrien  0x08, 0x00, 0x00, 0x01,  0x00, 0x00, 0x00, 0x00
186560484Sobrien};
186660484Sobrien
1867218822Sdimstatic const unsigned char jmp_arm_bytes[] =
1868218822Sdim{
1869218822Sdim  0x00, 0xc0, 0x9f, 0xe5,	/* ldr  ip, [pc] */
1870218822Sdim  0x00, 0xf0, 0x9c, 0xe5,	/* ldr  pc, [ip] */
1871218822Sdim  0,    0,    0,    0
1872218822Sdim};
1873218822Sdim
1874218822Sdim
187560484Sobrienstatic bfd *
1876218822Sdimmake_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
187760484Sobrien{
187860484Sobrien  asection *tx, *id7, *id5, *id4, *id6;
187977298Sobrien  unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL;
188060484Sobrien  int len;
188160484Sobrien  char *oname;
188260484Sobrien  bfd *abfd;
1883218822Sdim  const unsigned char *jmp_bytes = NULL;
188460484Sobrien  int jmp_byte_count = 0;
188560484Sobrien
1886218822Sdim  /* Include the jump stub section only if it is needed. A jump
1887218822Sdim     stub is needed if the symbol being imported <sym> is a function
1888218822Sdim     symbol and there is at least one undefined reference to that
1889218822Sdim     symbol. In other words, if all the import references to <sym> are
1890218822Sdim     explicitly through _declspec(dllimport) then the jump stub is not
1891218822Sdim     needed.  */
1892218822Sdim  if (include_jmp_stub)
189360484Sobrien    {
1894218822Sdim      switch (pe_details->pe_arch)
1895218822Sdim	{
1896218822Sdim	case PE_ARCH_i386:
1897218822Sdim	  jmp_bytes = jmp_ix86_bytes;
1898218822Sdim	  jmp_byte_count = sizeof (jmp_ix86_bytes);
1899218822Sdim	  break;
1900218822Sdim	case PE_ARCH_sh:
1901218822Sdim	  jmp_bytes = jmp_sh_bytes;
1902218822Sdim	  jmp_byte_count = sizeof (jmp_sh_bytes);
1903218822Sdim	  break;
1904218822Sdim	case PE_ARCH_mips:
1905218822Sdim	  jmp_bytes = jmp_mips_bytes;
1906218822Sdim	  jmp_byte_count = sizeof (jmp_mips_bytes);
1907218822Sdim	  break;
1908218822Sdim	case PE_ARCH_arm:
1909218822Sdim	case PE_ARCH_arm_epoc:
1910218822Sdim	case PE_ARCH_arm_wince:
1911218822Sdim	  jmp_bytes = jmp_arm_bytes;
1912218822Sdim	  jmp_byte_count = sizeof (jmp_arm_bytes);
1913218822Sdim	  break;
1914218822Sdim	default:
1915218822Sdim	  abort ();
1916218822Sdim	}
191760484Sobrien    }
191860484Sobrien
1919130561Sobrien  oname = xmalloc (20);
192060484Sobrien  sprintf (oname, "d%06d.o", tmp_seq);
192160484Sobrien  tmp_seq++;
192260484Sobrien
192360484Sobrien  abfd = bfd_create (oname, parent);
192460484Sobrien  bfd_find_target (pe_details->object_target, abfd);
192560484Sobrien  bfd_make_writable (abfd);
192660484Sobrien
192760484Sobrien  bfd_set_format (abfd, bfd_object);
192860484Sobrien  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
192960484Sobrien
193060484Sobrien  symptr = 0;
1931130561Sobrien  symtab = xmalloc (11 * sizeof (asymbol *));
193260484Sobrien  tx  = quick_section (abfd, ".text",    SEC_CODE|SEC_HAS_CONTENTS, 2);
193360484Sobrien  id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
193460484Sobrien  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
193560484Sobrien  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
193660484Sobrien  id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
1937130561Sobrien
1938130561Sobrien  if  (*exp->internal_name == '@')
1939130561Sobrien    {
1940130561Sobrien      quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
1941130561Sobrien		    BSF_GLOBAL, 0);
1942218822Sdim      if (include_jmp_stub)
1943130561Sobrien	quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
1944218822Sdim      quick_symbol (abfd, "__imp_", exp->internal_name, "", id5,
1945130561Sobrien		    BSF_GLOBAL, 0);
1946130561Sobrien      /* Fastcall applies only to functions,
1947130561Sobrien	 so no need for auto-import symbol.  */
1948130561Sobrien    }
1949130561Sobrien  else
1950130561Sobrien    {
1951130561Sobrien      quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
1952130561Sobrien		    BSF_GLOBAL, 0);
1953218822Sdim      if (include_jmp_stub)
1954130561Sobrien	quick_symbol (abfd, U (""), exp->internal_name, "", tx,
1955130561Sobrien		      BSF_GLOBAL, 0);
1956218822Sdim      quick_symbol (abfd, "__imp_", U (""), exp->internal_name, id5,
1957130561Sobrien		    BSF_GLOBAL, 0);
1958130561Sobrien      /* Symbol to reference ord/name of imported
1959130561Sobrien	 data symbol, used to implement auto-import.  */
1960130561Sobrien      if (exp->flag_data)
1961218822Sdim	quick_symbol (abfd, U ("_nm_"), U (""), exp->internal_name, id6,
1962130561Sobrien		      BSF_GLOBAL,0);
1963130561Sobrien    }
196460484Sobrien  if (pe_dll_compat_implib)
1965130561Sobrien    quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", id5,
1966130561Sobrien		  BSF_GLOBAL, 0);
196760484Sobrien
1968218822Sdim  if (include_jmp_stub)
196989857Sobrien    {
197089857Sobrien      bfd_set_section_size (abfd, tx, jmp_byte_count);
1971130561Sobrien      td = xmalloc (jmp_byte_count);
197289857Sobrien      tx->contents = td;
197389857Sobrien      memcpy (td, jmp_bytes, jmp_byte_count);
197460484Sobrien
197589857Sobrien      switch (pe_details->pe_arch)
197689857Sobrien	{
197789857Sobrien	case PE_ARCH_i386:
1978218822Sdim#ifdef pe_use_x86_64
1979218822Sdim	  quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2);
1980218822Sdim#else
1981218822Sdim          quick_reloc (abfd, 2, BFD_RELOC_32, 2);
1982218822Sdim#endif
198389857Sobrien	  break;
198489857Sobrien	case PE_ARCH_sh:
198589857Sobrien	  quick_reloc (abfd, 8, BFD_RELOC_32, 2);
198689857Sobrien	  break;
198789857Sobrien	case PE_ARCH_mips:
198889857Sobrien	  quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2);
198989857Sobrien	  quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */
199089857Sobrien	  quick_reloc (abfd, 4, BFD_RELOC_LO16, 2);
199189857Sobrien	  break;
1992218822Sdim	case PE_ARCH_arm:
1993218822Sdim 	case PE_ARCH_arm_epoc:
1994218822Sdim 	case PE_ARCH_arm_wince:
1995218822Sdim	  quick_reloc (abfd, 8, BFD_RELOC_32, 2);
1996218822Sdim	  break;
199789857Sobrien	default:
199889857Sobrien	  abort ();
199989857Sobrien	}
200089857Sobrien      save_relocs (tx);
200189857Sobrien    }
2002218822Sdim  else
2003218822Sdim    bfd_set_section_size (abfd, tx, 0);
200489857Sobrien
200560484Sobrien  bfd_set_section_size (abfd, id7, 4);
2006130561Sobrien  d7 = xmalloc (4);
200760484Sobrien  id7->contents = d7;
200860484Sobrien  memset (d7, 0, 4);
2009130561Sobrien  quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
201060484Sobrien  save_relocs (id7);
201160484Sobrien
2012218822Sdim  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
2013218822Sdim  d5 = xmalloc (PE_IDATA5_SIZE);
201460484Sobrien  id5->contents = d5;
2015218822Sdim  memset (d5, 0, PE_IDATA5_SIZE);
201689857Sobrien
201760484Sobrien  if (exp->flag_noname)
201860484Sobrien    {
201960484Sobrien      d5[0] = exp->ordinal;
202060484Sobrien      d5[1] = exp->ordinal >> 8;
2021218822Sdim      d5[PE_IDATA5_SIZE - 1] = 0x80;
202260484Sobrien    }
202360484Sobrien  else
202460484Sobrien    {
202560484Sobrien      quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
202660484Sobrien      save_relocs (id5);
202760484Sobrien    }
202860484Sobrien
2029218822Sdim  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
2030218822Sdim  d4 = xmalloc (PE_IDATA4_SIZE);
203160484Sobrien  id4->contents = d4;
2032218822Sdim  memset (d4, 0, PE_IDATA4_SIZE);
203389857Sobrien
203460484Sobrien  if (exp->flag_noname)
203560484Sobrien    {
203677298Sobrien      d4[0] = exp->ordinal;
203777298Sobrien      d4[1] = exp->ordinal >> 8;
2038218822Sdim      d4[PE_IDATA4_SIZE - 1] = 0x80;
203960484Sobrien    }
204060484Sobrien  else
204160484Sobrien    {
204260484Sobrien      quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
204360484Sobrien      save_relocs (id4);
204460484Sobrien    }
204560484Sobrien
204660484Sobrien  if (exp->flag_noname)
204760484Sobrien    {
204860484Sobrien      len = 0;
204960484Sobrien      bfd_set_section_size (abfd, id6, 0);
205060484Sobrien    }
205160484Sobrien  else
205260484Sobrien    {
2053218822Sdim      /* { short, asciz }  */
2054218822Sdim      len = 2 + strlen (exp->name) + 1;
205560484Sobrien      if (len & 1)
205660484Sobrien	len++;
205760484Sobrien      bfd_set_section_size (abfd, id6, len);
2058130561Sobrien      d6 = xmalloc (len);
205960484Sobrien      id6->contents = d6;
206060484Sobrien      memset (d6, 0, len);
206160484Sobrien      d6[0] = exp->hint & 0xff;
206260484Sobrien      d6[1] = exp->hint >> 8;
2063218822Sdim      strcpy ((char *) d6 + 2, exp->name);
206460484Sobrien    }
206560484Sobrien
206660484Sobrien  bfd_set_symtab (abfd, symtab, symptr);
206760484Sobrien
2068218822Sdim  if (include_jmp_stub)
2069218822Sdim    bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count);
207060484Sobrien  bfd_set_section_contents (abfd, id7, d7, 0, 4);
2071218822Sdim  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
2072218822Sdim  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
207360484Sobrien  if (!exp->flag_noname)
207460484Sobrien    bfd_set_section_contents (abfd, id6, d6, 0, len);
207560484Sobrien
207660484Sobrien  bfd_make_readable (abfd);
207760484Sobrien  return abfd;
207860484Sobrien}
207960484Sobrien
208089857Sobrienstatic bfd *
2081130561Sobrienmake_singleton_name_thunk (const char *import, bfd *parent)
208289857Sobrien{
208389857Sobrien  /* Name thunks go to idata$4.  */
208489857Sobrien  asection *id4;
208589857Sobrien  unsigned char *d4;
208689857Sobrien  char *oname;
208789857Sobrien  bfd *abfd;
208889857Sobrien
2089130561Sobrien  oname = xmalloc (20);
209089857Sobrien  sprintf (oname, "nmth%06d.o", tmp_seq);
209189857Sobrien  tmp_seq++;
209289857Sobrien
209389857Sobrien  abfd = bfd_create (oname, parent);
209489857Sobrien  bfd_find_target (pe_details->object_target, abfd);
209589857Sobrien  bfd_make_writable (abfd);
209689857Sobrien
209789857Sobrien  bfd_set_format (abfd, bfd_object);
209889857Sobrien  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
209989857Sobrien
210089857Sobrien  symptr = 0;
2101130561Sobrien  symtab = xmalloc (3 * sizeof (asymbol *));
210289857Sobrien  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
210389857Sobrien  quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);
210489857Sobrien  quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);
210589857Sobrien
2106218822Sdim  /* We need space for the real thunk and for the null terminator.  */
2107218822Sdim  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE * 2);
2108218822Sdim  d4 = xmalloc (PE_IDATA4_SIZE * 2);
210989857Sobrien  id4->contents = d4;
2110218822Sdim  memset (d4, 0, PE_IDATA4_SIZE * 2);
211189857Sobrien  quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
211289857Sobrien  save_relocs (id4);
211389857Sobrien
211489857Sobrien  bfd_set_symtab (abfd, symtab, symptr);
211589857Sobrien
2116218822Sdim  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE * 2);
211789857Sobrien
211889857Sobrien  bfd_make_readable (abfd);
211989857Sobrien  return abfd;
212089857Sobrien}
212189857Sobrien
212289857Sobrienstatic char *
2123130561Sobrienmake_import_fixup_mark (arelent *rel)
212489857Sobrien{
212589857Sobrien  /* We convert reloc to symbol, for later reference.  */
212689857Sobrien  static int counter;
212789857Sobrien  static char *fixup_name = NULL;
212889857Sobrien  static size_t buffer_len = 0;
2129104834Sobrien
2130130561Sobrien  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
2131104834Sobrien
213289857Sobrien  bfd *abfd = bfd_asymbol_bfd (sym);
2133107492Sobrien  struct bfd_link_hash_entry *bh;
213489857Sobrien
213589857Sobrien  if (!fixup_name)
213689857Sobrien    {
2137130561Sobrien      fixup_name = xmalloc (384);
213889857Sobrien      buffer_len = 384;
213989857Sobrien    }
214089857Sobrien
214189857Sobrien  if (strlen (sym->name) + 25 > buffer_len)
2142104834Sobrien  /* Assume 25 chars for "__fu" + counter + "_".  If counter is
214389857Sobrien     bigger than 20 digits long, we've got worse problems than
214489857Sobrien     overflowing this buffer...  */
214589857Sobrien    {
214689857Sobrien      free (fixup_name);
2147130561Sobrien      /* New buffer size is length of symbol, plus 25, but
2148130561Sobrien	 then rounded up to the nearest multiple of 128.  */
214989857Sobrien      buffer_len = ((strlen (sym->name) + 25) + 127) & ~127;
2150130561Sobrien      fixup_name = xmalloc (buffer_len);
215189857Sobrien    }
2152104834Sobrien
215389857Sobrien  sprintf (fixup_name, "__fu%d_%s", counter++, sym->name);
215489857Sobrien
2155107492Sobrien  bh = NULL;
2156104834Sobrien  bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL,
215789857Sobrien				current_sec, /* sym->section, */
2158130561Sobrien				rel->address, NULL, TRUE, FALSE, &bh);
215989857Sobrien
216089857Sobrien  return fixup_name;
216189857Sobrien}
216289857Sobrien
2163218822Sdim/*	.section	.idata$2
216489857Sobrien  	.rva		__nm_thnk_SYM (singleton thunk with name of func)
216589857Sobrien 	.long		0
216689857Sobrien 	.long		0
216789857Sobrien 	.rva		__my_dll_iname (name of dll)
216889857Sobrien 	.rva		__fuNN_SYM (pointer to reference (address) in text)  */
216989857Sobrien
217089857Sobrienstatic bfd *
2171130561Sobrienmake_import_fixup_entry (const char *name,
2172130561Sobrien			 const char *fixup_name,
2173130561Sobrien			 const char *dll_symname,
2174130561Sobrien			 bfd *parent)
217589857Sobrien{
2176218822Sdim  asection *id2;
2177218822Sdim  unsigned char *d2;
217889857Sobrien  char *oname;
217989857Sobrien  bfd *abfd;
218089857Sobrien
2181130561Sobrien  oname = xmalloc (20);
218289857Sobrien  sprintf (oname, "fu%06d.o", tmp_seq);
218389857Sobrien  tmp_seq++;
218489857Sobrien
218589857Sobrien  abfd = bfd_create (oname, parent);
218689857Sobrien  bfd_find_target (pe_details->object_target, abfd);
218789857Sobrien  bfd_make_writable (abfd);
218889857Sobrien
218989857Sobrien  bfd_set_format (abfd, bfd_object);
219089857Sobrien  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
219189857Sobrien
219289857Sobrien  symptr = 0;
2193130561Sobrien  symtab = xmalloc (6 * sizeof (asymbol *));
2194218822Sdim  id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
219589857Sobrien
219689857Sobrien  quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0);
219789857Sobrien  quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
219889857Sobrien  quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
219989857Sobrien
2200218822Sdim  bfd_set_section_size (abfd, id2, 20);
2201218822Sdim  d2 = xmalloc (20);
2202218822Sdim  id2->contents = d2;
2203218822Sdim  memset (d2, 0, 20);
220489857Sobrien
220589857Sobrien  quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
220689857Sobrien  quick_reloc (abfd, 12, BFD_RELOC_RVA, 2);
220789857Sobrien  quick_reloc (abfd, 16, BFD_RELOC_RVA, 3);
2208218822Sdim  save_relocs (id2);
220989857Sobrien
221089857Sobrien  bfd_set_symtab (abfd, symtab, symptr);
221189857Sobrien
2212218822Sdim  bfd_set_section_contents (abfd, id2, d2, 0, 20);
221389857Sobrien
221489857Sobrien  bfd_make_readable (abfd);
221589857Sobrien  return abfd;
221689857Sobrien}
221789857Sobrien
2218130561Sobrien/*	.section	.rdata_runtime_pseudo_reloc
2219130561Sobrien 	.long		addend
2220130561Sobrien 	.rva		__fuNN_SYM (pointer to reference (address) in text)  */
2221130561Sobrien
2222130561Sobrienstatic bfd *
2223130561Sobrienmake_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
2224130561Sobrien			   const char *fixup_name,
2225130561Sobrien			   int addend,
2226130561Sobrien			   bfd *parent)
2227130561Sobrien{
2228130561Sobrien  asection *rt_rel;
2229130561Sobrien  unsigned char *rt_rel_d;
2230130561Sobrien  char *oname;
2231130561Sobrien  bfd *abfd;
2232130561Sobrien
2233130561Sobrien  oname = xmalloc (20);
2234130561Sobrien  sprintf (oname, "rtr%06d.o", tmp_seq);
2235130561Sobrien  tmp_seq++;
2236130561Sobrien
2237130561Sobrien  abfd = bfd_create (oname, parent);
2238130561Sobrien  bfd_find_target (pe_details->object_target, abfd);
2239130561Sobrien  bfd_make_writable (abfd);
2240130561Sobrien
2241130561Sobrien  bfd_set_format (abfd, bfd_object);
2242130561Sobrien  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
2243130561Sobrien
2244130561Sobrien  symptr = 0;
2245130561Sobrien  symtab = xmalloc (2 * sizeof (asymbol *));
2246130561Sobrien  rt_rel = quick_section (abfd, ".rdata_runtime_pseudo_reloc",
2247130561Sobrien			  SEC_HAS_CONTENTS, 2);
2248130561Sobrien
2249130561Sobrien  quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
2250130561Sobrien
2251130561Sobrien  bfd_set_section_size (abfd, rt_rel, 8);
2252130561Sobrien  rt_rel_d = xmalloc (8);
2253130561Sobrien  rt_rel->contents = rt_rel_d;
2254130561Sobrien  memset (rt_rel_d, 0, 8);
2255130561Sobrien  bfd_put_32 (abfd, addend, rt_rel_d);
2256130561Sobrien
2257130561Sobrien  quick_reloc (abfd, 4, BFD_RELOC_RVA, 1);
2258130561Sobrien  save_relocs (rt_rel);
2259130561Sobrien
2260130561Sobrien  bfd_set_symtab (abfd, symtab, symptr);
2261130561Sobrien
2262130561Sobrien  bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8);
2263130561Sobrien
2264130561Sobrien  bfd_make_readable (abfd);
2265130561Sobrien  return abfd;
2266130561Sobrien}
2267130561Sobrien
2268130561Sobrien/*	.section	.rdata
2269130561Sobrien 	.rva		__pei386_runtime_relocator  */
2270130561Sobrien
2271130561Sobrienstatic bfd *
2272130561Sobrienpe_create_runtime_relocator_reference (bfd *parent)
2273130561Sobrien{
2274130561Sobrien  asection *extern_rt_rel;
2275130561Sobrien  unsigned char *extern_rt_rel_d;
2276130561Sobrien  char *oname;
2277130561Sobrien  bfd *abfd;
2278130561Sobrien
2279130561Sobrien  oname = xmalloc (20);
2280130561Sobrien  sprintf (oname, "ertr%06d.o", tmp_seq);
2281130561Sobrien  tmp_seq++;
2282130561Sobrien
2283130561Sobrien  abfd = bfd_create (oname, parent);
2284130561Sobrien  bfd_find_target (pe_details->object_target, abfd);
2285130561Sobrien  bfd_make_writable (abfd);
2286130561Sobrien
2287130561Sobrien  bfd_set_format (abfd, bfd_object);
2288130561Sobrien  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
2289130561Sobrien
2290130561Sobrien  symptr = 0;
2291130561Sobrien  symtab = xmalloc (2 * sizeof (asymbol *));
2292130561Sobrien  extern_rt_rel = quick_section (abfd, ".rdata", SEC_HAS_CONTENTS, 2);
2293130561Sobrien
2294218822Sdim  quick_symbol (abfd, "", U ("_pei386_runtime_relocator"), "", UNDSEC,
2295130561Sobrien		BSF_NO_FLAGS, 0);
2296130561Sobrien
2297130561Sobrien  bfd_set_section_size (abfd, extern_rt_rel, 4);
2298130561Sobrien  extern_rt_rel_d = xmalloc (4);
2299130561Sobrien  extern_rt_rel->contents = extern_rt_rel_d;
2300130561Sobrien
2301130561Sobrien  quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
2302130561Sobrien  save_relocs (extern_rt_rel);
2303130561Sobrien
2304130561Sobrien  bfd_set_symtab (abfd, symtab, symptr);
2305130561Sobrien
2306130561Sobrien  bfd_set_section_contents (abfd, extern_rt_rel, extern_rt_rel_d, 0, 4);
2307130561Sobrien
2308130561Sobrien  bfd_make_readable (abfd);
2309130561Sobrien  return abfd;
2310130561Sobrien}
2311130561Sobrien
231260484Sobrienvoid
2313130561Sobrienpe_create_import_fixup (arelent *rel, asection *s, int addend)
231489857Sobrien{
231589857Sobrien  char buf[300];
2316130561Sobrien  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
231789857Sobrien  struct bfd_link_hash_entry *name_thunk_sym;
231889857Sobrien  const char *name = sym->name;
231989857Sobrien  char *fixup_name = make_import_fixup_mark (rel);
2320130561Sobrien  bfd *b;
232189857Sobrien
232289857Sobrien  sprintf (buf, U ("_nm_thnk_%s"), name);
232389857Sobrien
232489857Sobrien  name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
232589857Sobrien
232689857Sobrien  if (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined)
232789857Sobrien    {
232889857Sobrien      bfd *b = make_singleton_name_thunk (name, output_bfd);
232989857Sobrien      add_bfd_to_link (b, b->filename, &link_info);
233089857Sobrien
233189857Sobrien      /* If we ever use autoimport, we have to cast text section writable.  */
2332130561Sobrien      config.text_read_only = FALSE;
2333130561Sobrien      output_bfd->flags &= ~WP_TEXT;
233489857Sobrien    }
233589857Sobrien
2336130561Sobrien  if (addend == 0 || link_info.pei386_runtime_pseudo_reloc)
2337130561Sobrien    {
2338130561Sobrien      extern char * pe_data_import_dll;
2339130561Sobrien      char * dll_symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
234089857Sobrien
2341130561Sobrien      b = make_import_fixup_entry (name, fixup_name, dll_symname, output_bfd);
2342130561Sobrien      add_bfd_to_link (b, b->filename, &link_info);
2343130561Sobrien    }
2344130561Sobrien
2345130561Sobrien  if (addend != 0)
2346130561Sobrien    {
2347130561Sobrien      if (link_info.pei386_runtime_pseudo_reloc)
2348130561Sobrien	{
2349130561Sobrien	  if (pe_dll_extra_pe_debug)
2350130561Sobrien	    printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n",
2351130561Sobrien		   fixup_name, addend);
2352130561Sobrien	  b = make_runtime_pseudo_reloc (name, fixup_name, addend, output_bfd);
2353130561Sobrien	  add_bfd_to_link (b, b->filename, &link_info);
2354130561Sobrien
2355130561Sobrien	  if (runtime_pseudo_relocs_created == 0)
2356130561Sobrien	    {
2357130561Sobrien	      b = pe_create_runtime_relocator_reference (output_bfd);
2358130561Sobrien	      add_bfd_to_link (b, b->filename, &link_info);
2359130561Sobrien	    }
2360130561Sobrien	  runtime_pseudo_relocs_created++;
2361130561Sobrien	}
2362130561Sobrien      else
2363130561Sobrien	{
2364130561Sobrien	  einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"),
2365130561Sobrien		 s->owner, s, rel->address, sym->name);
2366130561Sobrien	  einfo ("%X");
2367130561Sobrien	}
2368130561Sobrien    }
236989857Sobrien}
237089857Sobrien
237189857Sobrien
237289857Sobrienvoid
2373130561Sobrienpe_dll_generate_implib (def_file *def, const char *impfilename)
237460484Sobrien{
237560484Sobrien  int i;
237660484Sobrien  bfd *ar_head;
237760484Sobrien  bfd *ar_tail;
237860484Sobrien  bfd *outarch;
237960484Sobrien  bfd *head = 0;
238060484Sobrien
238160484Sobrien  dll_filename = (def->name) ? def->name : dll_name;
238260484Sobrien  dll_symname = xstrdup (dll_filename);
238377298Sobrien  for (i = 0; dll_symname[i]; i++)
238489857Sobrien    if (!ISALNUM (dll_symname[i]))
238560484Sobrien      dll_symname[i] = '_';
238660484Sobrien
2387218822Sdim  unlink_if_ordinary (impfilename);
238860484Sobrien
238960484Sobrien  outarch = bfd_openw (impfilename, 0);
239060484Sobrien
239160484Sobrien  if (!outarch)
239260484Sobrien    {
239360484Sobrien      /* xgettext:c-format */
239460484Sobrien      einfo (_("%XCan't open .lib file: %s\n"), impfilename);
239560484Sobrien      return;
239660484Sobrien    }
239760484Sobrien
239860484Sobrien  /* xgettext:c-format */
2399218822Sdim  info_msg (_("Creating library file: %s\n"), impfilename);
2400218822Sdim
240160484Sobrien  bfd_set_format (outarch, bfd_archive);
240260484Sobrien  outarch->has_armap = 1;
240360484Sobrien
240477298Sobrien  /* Work out a reasonable size of things to put onto one line.  */
240560484Sobrien  ar_head = make_head (outarch);
240660484Sobrien
240777298Sobrien  for (i = 0; i < def->num_exports; i++)
240860484Sobrien    {
240977298Sobrien      /* The import library doesn't know about the internal name.  */
241060484Sobrien      char *internal = def->exports[i].internal_name;
241160484Sobrien      bfd *n;
241289857Sobrien
2413130561Sobrien      /* Don't add PRIVATE entries to import lib.  */
2414130561Sobrien      if (pe_def_file->exports[i].flag_private)
2415130561Sobrien	continue;
241660484Sobrien      def->exports[i].internal_name = def->exports[i].name;
2417218822Sdim      n = make_one (def->exports + i, outarch,
2418218822Sdim		    ! (def->exports + i)->flag_data);
2419218822Sdim      n->archive_next = head;
242060484Sobrien      head = n;
242160484Sobrien      def->exports[i].internal_name = internal;
242260484Sobrien    }
242360484Sobrien
242460484Sobrien  ar_tail = make_tail (outarch);
242560484Sobrien
242660484Sobrien  if (ar_head == NULL || ar_tail == NULL)
242760484Sobrien    return;
242860484Sobrien
242977298Sobrien  /* Now stick them all into the archive.  */
2430218822Sdim  ar_head->archive_next = head;
2431218822Sdim  ar_tail->archive_next = ar_head;
243260484Sobrien  head = ar_tail;
243360484Sobrien
243460484Sobrien  if (! bfd_set_archive_head (outarch, head))
2435218822Sdim    einfo ("%Xbfd_set_archive_head: %E\n");
243677298Sobrien
243760484Sobrien  if (! bfd_close (outarch))
2438218822Sdim    einfo ("%Xbfd_close %s: %E\n", impfilename);
243960484Sobrien
244060484Sobrien  while (head != NULL)
244160484Sobrien    {
2442218822Sdim      bfd *n = head->archive_next;
244360484Sobrien      bfd_close (head);
244460484Sobrien      head = n;
244560484Sobrien    }
244660484Sobrien}
244760484Sobrien
244860484Sobrienstatic void
2449130561Sobrienadd_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info)
245060484Sobrien{
245160484Sobrien  lang_input_statement_type *fake_file;
245289857Sobrien
245360484Sobrien  fake_file = lang_add_input_file (name,
245460484Sobrien				   lang_input_file_is_fake_enum,
245560484Sobrien				   NULL);
245660484Sobrien  fake_file->the_bfd = abfd;
245760484Sobrien  ldlang_add_file (fake_file);
245889857Sobrien
245960484Sobrien  if (!bfd_link_add_symbols (abfd, link_info))
2460218822Sdim    einfo ("%Xaddsym %s: %E\n", name);
246160484Sobrien}
246260484Sobrien
246360484Sobrienvoid
2464130561Sobrienpe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
246560484Sobrien{
246660484Sobrien  def_file_module *module;
246789857Sobrien
246877298Sobrien  pe_dll_id_target (bfd_get_target (output_bfd));
246960484Sobrien
247060484Sobrien  if (!pe_def_file)
247160484Sobrien    return;
247260484Sobrien
247360484Sobrien  for (module = pe_def_file->modules; module; module = module->next)
247460484Sobrien    {
247560484Sobrien      int i, do_this_dll;
247660484Sobrien
247760484Sobrien      dll_filename = module->name;
247860484Sobrien      dll_symname = xstrdup (module->name);
247977298Sobrien      for (i = 0; dll_symname[i]; i++)
248089857Sobrien	if (!ISALNUM (dll_symname[i]))
248160484Sobrien	  dll_symname[i] = '_';
248260484Sobrien
248360484Sobrien      do_this_dll = 0;
248460484Sobrien
248577298Sobrien      for (i = 0; i < pe_def_file->num_imports; i++)
248660484Sobrien	if (pe_def_file->imports[i].module == module)
248760484Sobrien	  {
248860484Sobrien	    def_file_export exp;
248960484Sobrien	    struct bfd_link_hash_entry *blhe;
2490130561Sobrien	    int lead_at = (*pe_def_file->imports[i].internal_name == '@');
2491130561Sobrien	    /* See if we need this import.  */
2492130561Sobrien	    size_t len = strlen (pe_def_file->imports[i].internal_name);
2493130561Sobrien	    char *name = xmalloc (len + 2 + 6);
2494218822Sdim	    bfd_boolean include_jmp_stub = FALSE;
249560484Sobrien
2496130561Sobrien 	    if (lead_at)
2497218822Sdim	      sprintf (name, "%s",
2498130561Sobrien		       pe_def_file->imports[i].internal_name);
2499130561Sobrien	    else
2500130561Sobrien	      sprintf (name, "%s%s",U (""),
2501130561Sobrien		       pe_def_file->imports[i].internal_name);
2502130561Sobrien
250360484Sobrien	    blhe = bfd_link_hash_lookup (link_info->hash, name,
2504130561Sobrien					 FALSE, FALSE, FALSE);
2505130561Sobrien
2506218822Sdim	    /* Include the jump stub for <sym> only if the <sym>
2507218822Sdim	       is undefined.  */
250877298Sobrien	    if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
250977298Sobrien	      {
2510130561Sobrien		if (lead_at)
2511218822Sdim		  sprintf (name, "%s%s", "__imp_",
2512130561Sobrien			   pe_def_file->imports[i].internal_name);
2513130561Sobrien		else
2514218822Sdim		  sprintf (name, "%s%s%s", "__imp_", U (""),
2515130561Sobrien			   pe_def_file->imports[i].internal_name);
2516130561Sobrien
251777298Sobrien		blhe = bfd_link_hash_lookup (link_info->hash, name,
2518130561Sobrien					     FALSE, FALSE, FALSE);
251977298Sobrien	      }
2520218822Sdim	    else
2521218822Sdim	      include_jmp_stub = TRUE;
2522218822Sdim
252360484Sobrien	    free (name);
2524130561Sobrien
252560484Sobrien	    if (blhe && blhe->type == bfd_link_hash_undefined)
252660484Sobrien	      {
252760484Sobrien		bfd *one;
252877298Sobrien		/* We do.  */
252960484Sobrien		if (!do_this_dll)
253060484Sobrien		  {
253160484Sobrien		    bfd *ar_head = make_head (output_bfd);
253260484Sobrien		    add_bfd_to_link (ar_head, ar_head->filename, link_info);
253360484Sobrien		    do_this_dll = 1;
253460484Sobrien		  }
253560484Sobrien		exp.internal_name = pe_def_file->imports[i].internal_name;
253660484Sobrien		exp.name = pe_def_file->imports[i].name;
253760484Sobrien		exp.ordinal = pe_def_file->imports[i].ordinal;
253860484Sobrien		exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
253960484Sobrien		exp.flag_private = 0;
254060484Sobrien		exp.flag_constant = 0;
2541130561Sobrien		exp.flag_data = pe_def_file->imports[i].data;
254260484Sobrien		exp.flag_noname = exp.name ? 0 : 1;
2543218822Sdim		one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub);
254460484Sobrien		add_bfd_to_link (one, one->filename, link_info);
254560484Sobrien	      }
254660484Sobrien	  }
254760484Sobrien      if (do_this_dll)
254860484Sobrien	{
254960484Sobrien	  bfd *ar_tail = make_tail (output_bfd);
255060484Sobrien	  add_bfd_to_link (ar_tail, ar_tail->filename, link_info);
255160484Sobrien	}
255260484Sobrien
255360484Sobrien      free (dll_symname);
255460484Sobrien    }
255560484Sobrien}
255660484Sobrien
255789857Sobrien/* We were handed a *.DLL file.  Parse it and turn it into a set of
2558130561Sobrien   IMPORTS directives in the def file.  Return TRUE if the file was
2559130561Sobrien   handled, FALSE if not.  */
256060484Sobrien
256160484Sobrienstatic unsigned int
2562130561Sobrienpe_get16 (bfd *abfd, int where)
256360484Sobrien{
256460484Sobrien  unsigned char b[2];
256589857Sobrien
256689857Sobrien  bfd_seek (abfd, (file_ptr) where, SEEK_SET);
256789857Sobrien  bfd_bread (b, (bfd_size_type) 2, abfd);
256877298Sobrien  return b[0] + (b[1] << 8);
256960484Sobrien}
257060484Sobrien
257160484Sobrienstatic unsigned int
2572130561Sobrienpe_get32 (bfd *abfd, int where)
257360484Sobrien{
257460484Sobrien  unsigned char b[4];
257589857Sobrien
257689857Sobrien  bfd_seek (abfd, (file_ptr) where, SEEK_SET);
257789857Sobrien  bfd_bread (b, (bfd_size_type) 4, abfd);
257877298Sobrien  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
257960484Sobrien}
258060484Sobrien
258160484Sobrienstatic unsigned int
2582130561Sobrienpe_as32 (void *ptr)
258360484Sobrien{
258460484Sobrien  unsigned char *b = ptr;
258589857Sobrien
258677298Sobrien  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
258760484Sobrien}
258860484Sobrien
2589130561Sobrienbfd_boolean
2590130561Sobrienpe_implied_import_dll (const char *filename)
259160484Sobrien{
259260484Sobrien  bfd *dll;
259360484Sobrien  unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
259460484Sobrien  unsigned long export_rva, export_size, nsections, secptr, expptr;
2595130561Sobrien  unsigned long exp_funcbase;
2596218822Sdim  unsigned char *expdata;
2597218822Sdim  char *erva;
259860484Sobrien  unsigned long name_rvas, ordinals, nexp, ordbase;
259960484Sobrien  const char *dll_name;
2600130561Sobrien  /* Initialization with start > end guarantees that is_data
2601130561Sobrien     will not be set by mistake, and avoids compiler warning.  */
2602130561Sobrien  unsigned long data_start = 1;
2603130561Sobrien  unsigned long data_end = 0;
2604130561Sobrien  unsigned long rdata_start = 1;
2605130561Sobrien  unsigned long rdata_end = 0;
2606130561Sobrien  unsigned long bss_start = 1;
2607130561Sobrien  unsigned long bss_end = 0;
260860484Sobrien
260960484Sobrien  /* No, I can't use bfd here.  kernel32.dll puts its export table in
261077298Sobrien     the middle of the .rdata section.  */
261160484Sobrien  dll = bfd_openr (filename, pe_details->target_name);
261260484Sobrien  if (!dll)
261360484Sobrien    {
2614218822Sdim      einfo ("%Xopen %s: %E\n", filename);
2615130561Sobrien      return FALSE;
261660484Sobrien    }
261789857Sobrien
261877298Sobrien  /* PEI dlls seem to be bfd_objects.  */
261960484Sobrien  if (!bfd_check_format (dll, bfd_object))
262060484Sobrien    {
262160484Sobrien      einfo ("%X%s: this doesn't appear to be a DLL\n", filename);
2622130561Sobrien      return FALSE;
262360484Sobrien    }
262460484Sobrien
2625130561Sobrien  /* Get pe_header, optional header and numbers of export entries.  */
262660484Sobrien  pe_header_offset = pe_get32 (dll, 0x3c);
262760484Sobrien  opthdr_ofs = pe_header_offset + 4 + 20;
2628218822Sdim#ifdef pe_use_x86_64
2629218822Sdim  num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4); /*  & NumberOfRvaAndSizes.  */
2630218822Sdim#else
263160484Sobrien  num_entries = pe_get32 (dll, opthdr_ofs + 92);
2632218822Sdim#endif
263389857Sobrien
263489857Sobrien  if (num_entries < 1) /* No exports.  */
2635130561Sobrien    return FALSE;
263689857Sobrien
2637218822Sdim#ifdef pe_use_x86_64
2638218822Sdim  export_rva  = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4);
2639218822Sdim  export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4);
2640218822Sdim#else
264160484Sobrien  export_rva = pe_get32 (dll, opthdr_ofs + 96);
264260484Sobrien  export_size = pe_get32 (dll, opthdr_ofs + 100);
2643218822Sdim#endif
2644218822Sdim
264560484Sobrien  nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
264660484Sobrien  secptr = (pe_header_offset + 4 + 20 +
264760484Sobrien	    pe_get16 (dll, pe_header_offset + 4 + 16));
264860484Sobrien  expptr = 0;
264989857Sobrien
2650130561Sobrien  /* Get the rva and size of the export section.  */
265177298Sobrien  for (i = 0; i < nsections; i++)
265260484Sobrien    {
265360484Sobrien      char sname[8];
265460484Sobrien      unsigned long secptr1 = secptr + 40 * i;
265560484Sobrien      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
265660484Sobrien      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
265760484Sobrien      unsigned long fptr = pe_get32 (dll, secptr1 + 20);
265889857Sobrien
265989857Sobrien      bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
266089857Sobrien      bfd_bread (sname, (bfd_size_type) 8, dll);
266189857Sobrien
266277298Sobrien      if (vaddr <= export_rva && vaddr + vsize > export_rva)
266360484Sobrien	{
266460484Sobrien	  expptr = fptr + (export_rva - vaddr);
266560484Sobrien	  if (export_rva + export_size > vaddr + vsize)
266660484Sobrien	    export_size = vsize - (export_rva - vaddr);
266760484Sobrien	  break;
266860484Sobrien	}
266960484Sobrien    }
267060484Sobrien
2671130561Sobrien  /* Scan sections and store the base and size of the
2672130561Sobrien     data and bss segments in data/base_start/end.  */
2673130561Sobrien  for (i = 0; i < nsections; i++)
2674130561Sobrien    {
2675130561Sobrien      unsigned long secptr1 = secptr + 40 * i;
2676130561Sobrien      unsigned long vsize = pe_get32 (dll, secptr1 + 8);
2677130561Sobrien      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
2678130561Sobrien      unsigned long flags = pe_get32 (dll, secptr1 + 36);
2679130561Sobrien      char sec_name[9];
2680130561Sobrien
2681130561Sobrien      sec_name[8] = '\0';
2682130561Sobrien      bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
2683130561Sobrien      bfd_bread (sec_name, (bfd_size_type) 8, dll);
2684130561Sobrien
2685130561Sobrien      if (strcmp(sec_name,".data") == 0)
2686130561Sobrien	{
2687130561Sobrien	  data_start = vaddr;
2688130561Sobrien	  data_end = vaddr + vsize;
2689130561Sobrien
2690130561Sobrien	  if (pe_dll_extra_pe_debug)
2691130561Sobrien	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
2692130561Sobrien		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
2693130561Sobrien	}
2694130561Sobrien      else if (strcmp(sec_name,".rdata") == 0)
2695130561Sobrien	{
2696130561Sobrien	  rdata_start = vaddr;
2697130561Sobrien	  rdata_end = vaddr + vsize;
2698130561Sobrien
2699130561Sobrien	  if (pe_dll_extra_pe_debug)
2700130561Sobrien	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
2701130561Sobrien		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
2702130561Sobrien	}
2703130561Sobrien      else if (strcmp (sec_name,".bss") == 0)
2704130561Sobrien	{
2705130561Sobrien	  bss_start = vaddr;
2706130561Sobrien	  bss_end = vaddr + vsize;
2707130561Sobrien
2708130561Sobrien	  if (pe_dll_extra_pe_debug)
2709130561Sobrien	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
2710130561Sobrien		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
2711130561Sobrien	}
2712130561Sobrien    }
2713130561Sobrien
2714130561Sobrien  expdata = xmalloc (export_size);
271589857Sobrien  bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
271689857Sobrien  bfd_bread (expdata, (bfd_size_type) export_size, dll);
2717218822Sdim  erva = (char *) expdata - export_rva;
271860484Sobrien
271960484Sobrien  if (pe_def_file == 0)
272077298Sobrien    pe_def_file = def_file_empty ();
272160484Sobrien
272277298Sobrien  nexp = pe_as32 (expdata + 24);
272377298Sobrien  name_rvas = pe_as32 (expdata + 32);
272477298Sobrien  ordinals = pe_as32 (expdata + 36);
272577298Sobrien  ordbase = pe_as32 (expdata + 16);
2726130561Sobrien  exp_funcbase = pe_as32 (expdata + 28);
272789857Sobrien
2728130561Sobrien  /* Use internal dll name instead of filename
2729130561Sobrien     to enable symbolic dll linking.  */
2730218822Sdim  dll_name = erva + pe_as32 (expdata + 12);
2731130561Sobrien
2732130561Sobrien  /* Check to see if the dll has already been added to
2733130561Sobrien     the definition list and if so return without error.
2734130561Sobrien     This avoids multiple symbol definitions.  */
2735130561Sobrien  if (def_get_module (pe_def_file, dll_name))
2736130561Sobrien    {
2737130561Sobrien      if (pe_dll_extra_pe_debug)
2738130561Sobrien	printf ("%s is already loaded\n", dll_name);
2739130561Sobrien      return TRUE;
2740130561Sobrien    }
2741130561Sobrien
2742130561Sobrien  /* Iterate through the list of symbols.  */
274377298Sobrien  for (i = 0; i < nexp; i++)
274460484Sobrien    {
2745130561Sobrien      /* Pointer to the names vector.  */
274677298Sobrien      unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
274760484Sobrien      def_file_import *imp;
2748130561Sobrien      /* Pointer to the function address vector.  */
2749130561Sobrien      unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);
2750130561Sobrien      int is_data = 0;
275189857Sobrien
2752130561Sobrien      /* Skip unwanted symbols, which are
2753130561Sobrien	 exported in buggy auto-import releases.  */
2754218822Sdim      if (! CONST_STRNEQ (erva + name_rva, "_nm_"))
2755130561Sobrien 	{
2756130561Sobrien 	  /* is_data is true if the address is in the data, rdata or bss
2757130561Sobrien	     segment.  */
2758130561Sobrien 	  is_data =
2759130561Sobrien	    (func_rva >= data_start && func_rva < data_end)
2760130561Sobrien	    || (func_rva >= rdata_start && func_rva < rdata_end)
2761130561Sobrien	    || (func_rva >= bss_start && func_rva < bss_end);
2762130561Sobrien
2763130561Sobrien	  imp = def_file_add_import (pe_def_file, erva + name_rva,
2764130561Sobrien				     dll_name, i, 0);
2765130561Sobrien 	  /* Mark symbol type.  */
2766130561Sobrien 	  imp->data = is_data;
2767130561Sobrien
2768130561Sobrien 	  if (pe_dll_extra_pe_debug)
2769130561Sobrien	    printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
2770130561Sobrien		    __FUNCTION__, dll_name, erva + name_rva,
2771130561Sobrien		    func_rva, is_data ? "(data)" : "");
2772130561Sobrien 	}
277360484Sobrien    }
277460484Sobrien
2775130561Sobrien  return TRUE;
277660484Sobrien}
277760484Sobrien
277889857Sobrien/* These are the main functions, called from the emulation.  The first
277989857Sobrien   is called after the bfds are read, so we can guess at how much space
278089857Sobrien   we need.  The second is called after everything is placed, so we
278189857Sobrien   can put the right values in place.  */
278260484Sobrien
278360484Sobrienvoid
2784130561Sobrienpe_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
278560484Sobrien{
278660484Sobrien  pe_dll_id_target (bfd_get_target (abfd));
278760484Sobrien  process_def_file (abfd, info);
278860484Sobrien
2789130561Sobrien  if (pe_def_file->num_exports == 0 && !info->shared)
2790130561Sobrien    return;
2791130561Sobrien
279260484Sobrien  generate_edata (abfd, info);
279360484Sobrien  build_filler_bfd (1);
279460484Sobrien}
279560484Sobrien
279660484Sobrienvoid
2797130561Sobrienpe_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
279860484Sobrien{
279960484Sobrien  pe_dll_id_target (bfd_get_target (abfd));
280060484Sobrien  build_filler_bfd (0);
280160484Sobrien}
280260484Sobrien
280360484Sobrienvoid
2804130561Sobrienpe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
280560484Sobrien{
280660484Sobrien  pe_dll_id_target (bfd_get_target (abfd));
280760484Sobrien  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
280860484Sobrien
280960484Sobrien  generate_reloc (abfd, info);
281060484Sobrien  if (reloc_sz > 0)
281160484Sobrien    {
281260484Sobrien      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
281360484Sobrien
281460484Sobrien      /* Resize the sections.  */
2815218822Sdim      lang_reset_memory_regions ();
2816218822Sdim      lang_size_sections (NULL, TRUE);
281760484Sobrien
281860484Sobrien      /* Redo special stuff.  */
281960484Sobrien      ldemul_after_allocation ();
282060484Sobrien
282160484Sobrien      /* Do the assignments again.  */
2822218822Sdim      lang_do_assignments ();
282360484Sobrien    }
282460484Sobrien
282560484Sobrien  fill_edata (abfd, info);
282660484Sobrien
2827218822Sdim  if (info->shared && !info->pie)
2828130561Sobrien    pe_data (abfd)->dll = 1;
282960484Sobrien
283060484Sobrien  edata_s->contents = edata_d;
283160484Sobrien  reloc_s->contents = reloc_d;
283260484Sobrien}
283360484Sobrien
283460484Sobrienvoid
2835130561Sobrienpe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
283660484Sobrien{
283760484Sobrien  pe_dll_id_target (bfd_get_target (abfd));
283860484Sobrien  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
283960484Sobrien
284060484Sobrien  generate_reloc (abfd, info);
284160484Sobrien  if (reloc_sz > 0)
284260484Sobrien    {
284360484Sobrien      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
284460484Sobrien
284560484Sobrien      /* Resize the sections.  */
2846218822Sdim      lang_reset_memory_regions ();
2847218822Sdim      lang_size_sections (NULL, TRUE);
284860484Sobrien
284960484Sobrien      /* Redo special stuff.  */
285060484Sobrien      ldemul_after_allocation ();
285160484Sobrien
285260484Sobrien      /* Do the assignments again.  */
2853218822Sdim      lang_do_assignments ();
285460484Sobrien    }
285560484Sobrien  reloc_s->contents = reloc_d;
285660484Sobrien}
2857218822Sdim
2858218822Sdimbfd_boolean
2859218822Sdimpe_bfd_is_dll (bfd *abfd)
2860218822Sdim{
2861218822Sdim  return (bfd_get_format (abfd) == bfd_object
2862218822Sdim          && obj_pe (abfd)
2863218822Sdim          && pe_data (abfd)->dll);
2864218822Sdim}
2865