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