pe-dll.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,946 行 · 第 1/4 页

C
1,946
字号
/* Routines to help build PEI-format DLLs (Win32 etc)   Copyright 1998, 1999, 2000 Free Software Foundation, Inc.   Written by DJ Delorie <dj@cygnus.com>   This file is part of GLD, the Gnu Linker.   GLD is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   GLD is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with GLD; see the file COPYING.  If not, write to the Free   Software Foundation, 59 Temple Place - Suite 330, Boston, MA   02111-1307, USA.  */#include "bfd.h"#include "sysdep.h"#include "bfdlink.h"#include "libiberty.h"#include <time.h>#include <ctype.h>#include "ld.h"#include "ldexp.h"#include "ldlang.h"#include "ldwrite.h"#include "ldmisc.h"#include "ldgram.h"#include "ldmain.h"#include "ldfile.h"#include "ldemul.h"#include "coff/internal.h"#include "../bfd/libcoff.h"#include "deffile.h"#include "pe-dll.h"/************************************************************************ This file turns a regular Windows PE image into a DLL.  Because of the complexity of this operation, it has been broken down into a number of separate modules which are all called by the main function at the end of this file.  This function is not re-entrant and is normally only called once, so static variables are used to reduce the number of parameters and return values required. See also: ld/emultempl/pe.em ************************************************************************//* for emultempl/pe.em */def_file *pe_def_file = 0;int pe_dll_export_everything = 0;int pe_dll_do_default_excludes = 1;int pe_dll_kill_ats = 0;int pe_dll_stdcall_aliases = 0;int pe_dll_warn_dup_exports = 0;int pe_dll_compat_implib = 0;/************************************************************************ static variables and types ************************************************************************/static bfd_vma image_base;static bfd *filler_bfd;static struct sec *edata_s, *reloc_s;static unsigned char *edata_d, *reloc_d;static size_t edata_sz, reloc_sz;typedef struct {  char *target_name;  char *object_target;  unsigned int imagebase_reloc;  int pe_arch;  int bfd_arch;  int underscored;} pe_details_type;#define PE_ARCH_i386	1#define PE_ARCH_sh	2#define PE_ARCH_mips	3#define PE_ARCH_arm	4static pe_details_type pe_detail_list[] = {  {    "pei-i386",    "pe-i386",    7 /* R_IMAGEBASE */,    PE_ARCH_i386,    bfd_arch_i386,    1  },  {    "pei-shl",    "pe-shl",    16 /* R_SH_IMAGEBASE */,    PE_ARCH_sh,    bfd_arch_sh,    1  },  {    "pei-mips",    "pe-mips",    34 /* MIPS_R_RVA */,    PE_ARCH_mips,    bfd_arch_mips,    0  },  {    "pei-arm-little",    "pe-arm-little",    11 /* ARM_RVA32 */,    PE_ARCH_arm,    bfd_arch_arm,    0  },  { NULL, NULL, 0, 0, 0, 0 }};static pe_details_type *pe_details;#define U(str) (pe_details->underscored ? "_" str : str)voidpe_dll_id_target (target)     const char *target;{  int i;  for (i = 0; pe_detail_list[i].target_name; i++)    if (strcmp (pe_detail_list[i].target_name, target) == 0	|| strcmp (pe_detail_list[i].object_target, target) == 0)      {	pe_details = pe_detail_list + i;	return;      }  einfo (_("%XUnsupported PEI architecture: %s\n"), target);  exit (1);}/************************************************************************ Helper functions for qsort.  Relocs must be sorted so that we can write them out by pages. ************************************************************************/typedef struct {  bfd_vma vma;  char type;  short extra;} reloc_data_type;static intreloc_sort (va, vb)     const void *va, *vb;{  bfd_vma a = ((reloc_data_type *) va)->vma;  bfd_vma b = ((reloc_data_type *) vb)->vma;  return (a > b) ? 1 : ((a < b) ? -1 : 0);}static intpe_export_sort (va, vb)     const void *va, *vb;{  def_file_export *a = (def_file_export *) va;  def_file_export *b = (def_file_export *) vb;  return strcmp (a->name, b->name);}/************************************************************************ Read and process the .DEF file ************************************************************************//* These correspond to the entries in pe_def_file->exports[].  I use   exported_symbol_sections[i] to tag whether or not the symbol was   defined, since we can't export symbols we don't have.  */static bfd_vma *exported_symbol_offsets;static struct sec **exported_symbol_sections;static int export_table_size;static int count_exported;static int count_exported_byname;static int count_with_ordinals;static const char *dll_name;static int min_ordinal, max_ordinal;static int *exported_symbols;typedef struct exclude_list_struct {  char *string;  struct exclude_list_struct *next;} exclude_list_struct;static struct exclude_list_struct *excludes = 0;voidpe_dll_add_excludes (new_excludes)     const char *new_excludes;{  char *local_copy;  char *exclude_string;  local_copy = xstrdup (new_excludes);  exclude_string = strtok (local_copy, ",:");  for (; exclude_string; exclude_string = strtok (NULL, ",:"))    {      struct exclude_list_struct *new_exclude;      new_exclude = ((struct exclude_list_struct *)		     xmalloc (sizeof (struct exclude_list_struct)));      new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 1);      strcpy (new_exclude->string, exclude_string);      new_exclude->next = excludes;      excludes = new_exclude;    }  free (local_copy);}static intauto_export (d, n)     def_file *d;     const char *n;{  int i;  struct exclude_list_struct *ex;  for (i = 0; i < d->num_exports; i++)    if (strcmp (d->exports[i].name, n) == 0)      return 0;  if (pe_dll_do_default_excludes)    {      if (strcmp (n, "DllMain@12") == 0)	return 0;      if (strcmp (n, "DllEntryPoint@0") == 0)	return 0;      if (strcmp (n, "impure_ptr") == 0)	return 0;    }  for (ex = excludes; ex; ex = ex->next)    if (strcmp (n, ex->string) == 0)      return 0;  return 1;}static voidprocess_def_file (abfd, info)     bfd *abfd ATTRIBUTE_UNUSED;     struct bfd_link_info *info;{  int i, j;  struct bfd_link_hash_entry *blhe;  bfd *b;  struct sec *s;  def_file_export *e = 0;  if (!pe_def_file)    pe_def_file = def_file_empty ();  /* First, run around to all the objects looking for the .drectve     sections, and push those into the def file too.  */  for (b = info->input_bfds; b; b = b->link_next)    {      s = bfd_get_section_by_name (b, ".drectve");      if (s)	{	  int size = bfd_get_section_size_before_reloc (s);	  char *buf = xmalloc (size);	  bfd_get_section_contents (b, s, buf, 0, size);	  def_file_add_directive (pe_def_file, buf, size);	  free (buf);	}    }  /* Now, maybe export everything else the default way.  */  if (pe_dll_export_everything || pe_def_file->num_exports == 0)    {      for (b = info->input_bfds; b; b = b->link_next)	{	  asymbol **symbols;	  int nsyms, symsize;	  symsize = bfd_get_symtab_upper_bound (b);	  symbols = (asymbol **) xmalloc (symsize);	  nsyms = bfd_canonicalize_symtab (b, symbols);	  for (j = 0; j < nsyms; j++)	    {	      /* We should export symbols which are either global or not	         anything at all.  (.bss data is the latter)  */	      if ((symbols[j]->flags & BSF_GLOBAL)		  || (symbols[j]->flags == BSF_NO_FLAGS))		{		  const char *sn = symbols[j]->name;		  if (*sn == '_')		    sn++;		  if (auto_export (pe_def_file, sn))                    {                      def_file_export *p;                      p=def_file_add_export (pe_def_file, sn, 0, -1);                      /* Fill data flag properly, from dlltool.c */                      p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);                    }		}	    }	}    }#undef NE#define NE pe_def_file->num_exports  /* Canonicalize the export list.  */  if (pe_dll_kill_ats)    {      for (i = 0; i < NE; i++)	{	  if (strchr (pe_def_file->exports[i].name, '@'))	    {	      /* This will preserve internal_name, which may have been	         pointing to the same memory as name, or might not	         have.  */	      char *tmp = xstrdup (pe_def_file->exports[i].name);	      *(strchr (tmp, '@')) = 0;	      pe_def_file->exports[i].name = tmp;	    }	}    }  if (pe_dll_stdcall_aliases)    {      for (i = 0; i < NE; i++)	{	  if (strchr (pe_def_file->exports[i].name, '@'))	    {	      char *tmp = xstrdup (pe_def_file->exports[i].name);	      *(strchr (tmp, '@')) = 0;	      if (auto_export (pe_def_file, tmp))		def_file_add_export (pe_def_file, tmp,				     pe_def_file->exports[i].internal_name, -1);	      else		free (tmp);	    }	}    }  /* Convenience, but watch out for it changing.  */  e = pe_def_file->exports;  exported_symbol_offsets = (bfd_vma *) xmalloc (NE * sizeof (bfd_vma));  exported_symbol_sections = (struct sec **) xmalloc (NE * sizeof (struct sec *));  memset (exported_symbol_sections, 0, NE * sizeof (struct sec *));  max_ordinal = 0;  min_ordinal = 65536;  count_exported = 0;  count_exported_byname = 0;  count_with_ordinals = 0;  qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]), pe_export_sort);  for (i = 0, j = 0; i < NE; i++)    {      if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)	{	  /* This is a duplicate.  */	  if (e[j - 1].ordinal != -1	      && e[i].ordinal != -1	      && e[j - 1].ordinal != e[i].ordinal)	    {	      if (pe_dll_warn_dup_exports)		/* xgettext:c-format */		einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"),		       e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);	    }	  else	    {	      if (pe_dll_warn_dup_exports)		/* xgettext:c-format */		einfo (_("Warning, duplicate EXPORT: %s\n"),		       e[j - 1].name);	    }	  if (e[i].ordinal != -1)	    e[j - 1].ordinal = e[i].ordinal;	  e[j - 1].flag_private |= e[i].flag_private;	  e[j - 1].flag_constant |= e[i].flag_constant;	  e[j - 1].flag_noname |= e[i].flag_noname;	  e[j - 1].flag_data |= e[i].flag_data;	}      else	{	  if (i != j)	    e[j] = e[i];	  j++;	}    }  pe_def_file->num_exports = j;	/* == NE */  for (i = 0; i < NE; i++)    {      char *name = (char *) xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);      if (pe_details->underscored)	{	  *name = '_';	  strcpy (name + 1, pe_def_file->exports[i].internal_name);	}      else	strcpy (name, pe_def_file->exports[i].internal_name);      blhe = bfd_link_hash_lookup (info->hash,				   name,				   false, false, true);      if (blhe	  && (blhe->type == bfd_link_hash_defined	      || (blhe->type == bfd_link_hash_common)))	{	  count_exported++;	  if (!pe_def_file->exports[i].flag_noname)	    count_exported_byname++;	  /* Only fill in the sections. The actual offsets are computed	     in fill_exported_offsets() after common symbols are laid	     out.  */	  if (blhe->type == bfd_link_hash_defined)	    exported_symbol_sections[i] = blhe->u.def.section;	  else	    exported_symbol_sections[i] = blhe->u.c.p->section;	  if (pe_def_file->exports[i].ordinal != -1)	    {	      if (max_ordinal < pe_def_file->exports[i].ordinal)		max_ordinal = pe_def_file->exports[i].ordinal;	      if (min_ordinal > pe_def_file->exports[i].ordinal)		min_ordinal = pe_def_file->exports[i].ordinal;	      count_with_ordinals++;	    }	}      else if (blhe && blhe->type == bfd_link_hash_undefined)	{	  /* xgettext:c-format */	  einfo (_("%XCannot export %s: symbol not defined\n"),		 pe_def_file->exports[i].internal_name);	}      else if (blhe)	{	  /* xgettext:c-format */	  einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"),		 pe_def_file->exports[i].internal_name,		 blhe->type, bfd_link_hash_defined);	}      else	{	  /* xgettext:c-format */	  einfo (_("%XCannot export %s: symbol not found\n"),		 pe_def_file->exports[i].internal_name);	}      free (name);    }}/************************************************************************ Build the bfd that will contain .edata and .reloc sections ************************************************************************/static voidbuild_filler_bfd (include_edata)     int include_edata;{  lang_input_statement_type *filler_file;  filler_file = lang_add_input_file ("dll stuff",

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?