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 + -
显示快捷键?