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