pe-dll.c

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

C
1,946
字号
				     lang_input_file_is_fake_enum,				     NULL);  filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", output_bfd);  if (filler_bfd == NULL      || !bfd_set_arch_mach (filler_bfd,			     bfd_get_arch (output_bfd),			     bfd_get_mach (output_bfd)))    {      einfo ("%X%P: can not create BFD %E\n");      return;    }  if (include_edata)    {      edata_s = bfd_make_section_old_way (filler_bfd, ".edata");      if (edata_s == NULL	  || !bfd_set_section_flags (filler_bfd, edata_s,				     (SEC_HAS_CONTENTS				      | SEC_ALLOC				      | SEC_LOAD				      | SEC_KEEP				      | SEC_IN_MEMORY)))	{	  einfo ("%X%P: can not create .edata section: %E\n");	  return;	}      bfd_set_section_size (filler_bfd, edata_s, edata_sz);    }  reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc");  if (reloc_s == NULL      || !bfd_set_section_flags (filler_bfd, reloc_s,				 (SEC_HAS_CONTENTS				  | SEC_ALLOC				  | SEC_LOAD				  | SEC_KEEP				  | SEC_IN_MEMORY)))    {      einfo ("%X%P: can not create .reloc section: %E\n");      return;    }  bfd_set_section_size (filler_bfd, reloc_s, 0);  ldlang_add_file (filler_file);}/************************************************************************ Gather all the exported symbols and build the .edata section ************************************************************************/static voidgenerate_edata (abfd, info)     bfd *abfd;     struct bfd_link_info *info ATTRIBUTE_UNUSED;{  int i, next_ordinal;  int name_table_size = 0;  const char *dlnp;  /* First, we need to know how many exported symbols there are,     and what the range of ordinals is.  */  if (pe_def_file->name)    {      dll_name = pe_def_file->name;    }  else    {      dll_name = abfd->filename;      for (dlnp = dll_name; *dlnp; dlnp++)	{	  if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':')	    dll_name = dlnp + 1;	}    }  if (count_with_ordinals && max_ordinal > count_exported)    {      if (min_ordinal > max_ordinal - count_exported + 1)	min_ordinal = max_ordinal - count_exported + 1;    }  else    {      min_ordinal = 1;      max_ordinal = count_exported;    }  export_table_size = max_ordinal - min_ordinal + 1;  exported_symbols = (int *) xmalloc (export_table_size * sizeof (int));  for (i = 0; i < export_table_size; i++)    exported_symbols[i] = -1;  /* Now we need to assign ordinals to those that don't have them.  */  for (i = 0; i < NE; i++)    {      if (exported_symbol_sections[i])	{	  if (pe_def_file->exports[i].ordinal != -1)	    {	      int ei = pe_def_file->exports[i].ordinal - min_ordinal;	      int pi = exported_symbols[ei];	      if (pi != -1)		{		  /* xgettext:c-format */		  einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"),			 pe_def_file->exports[i].ordinal,			 pe_def_file->exports[i].name,			 pe_def_file->exports[pi].name);		}	      exported_symbols[ei] = i;	    }	  name_table_size += strlen (pe_def_file->exports[i].name) + 1;	}    }  next_ordinal = min_ordinal;  for (i = 0; i < NE; i++)    if (exported_symbol_sections[i])      if (pe_def_file->exports[i].ordinal == -1)	{	  while (exported_symbols[next_ordinal - min_ordinal] != -1)	    next_ordinal++;	  exported_symbols[next_ordinal - min_ordinal] = i;	  pe_def_file->exports[i].ordinal = next_ordinal;	}  /* OK, now we can allocate some memory.  */  edata_sz = (40		/* directory */	      + 4 * export_table_size	/* addresses */	      + 4 * count_exported_byname	/* name ptrs */	      + 2 * count_exported_byname	/* ordinals */	      + name_table_size + strlen (dll_name) + 1);}/* Fill the exported symbol offsets. The preliminary work has already   been done in process_def_file().  */static voidfill_exported_offsets (abfd, info)     bfd *abfd ATTRIBUTE_UNUSED;     struct bfd_link_info *info;{  int i;  struct bfd_link_hash_entry *blhe;  for (i = 0; i < pe_def_file->num_exports; 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))	{	  exported_symbol_offsets[i] = blhe->u.def.value;	}      free (name);    }}static voidfill_edata (abfd, info)     bfd *abfd;     struct bfd_link_info *info ATTRIBUTE_UNUSED;{  int i, hint;  unsigned char *edirectory;  unsigned long *eaddresses;  unsigned long *enameptrs;  unsigned short *eordinals;  unsigned char *enamestr;  time_t now;  time (&now);  edata_d = (unsigned char *) xmalloc (edata_sz);  /* Note use of array pointer math here.  */  edirectory = edata_d;  eaddresses = (unsigned long *) (edata_d + 40);  enameptrs = eaddresses + export_table_size;  eordinals = (unsigned short *) (enameptrs + count_exported_byname);  enamestr = (char *) (eordinals + count_exported_byname);#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) + edata_s->output_section->vma - image_base)  memset (edata_d, 0, edata_sz);  bfd_put_32 (abfd, now, edata_d + 4);  if (pe_def_file->version_major != -1)    {      bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8);      bfd_put_16 (abfd, pe_def_file->version_minor, edata_d + 10);    }  bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12);  strcpy (enamestr, dll_name);  enamestr += strlen (enamestr) + 1;  bfd_put_32 (abfd, min_ordinal, edata_d + 16);  bfd_put_32 (abfd, export_table_size, edata_d + 20);  bfd_put_32 (abfd, count_exported_byname, edata_d + 24);  bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28);  bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32);  bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36);  fill_exported_offsets (abfd, info);  /* Ok, now for the filling in part.  */  hint = 0;  for (i = 0; i < export_table_size; i++)    {      int s = exported_symbols[i];      if (s != -1)	{	  struct sec *ssec = exported_symbol_sections[s];	  unsigned long srva = (exported_symbol_offsets[s]				+ ssec->output_section->vma				+ ssec->output_offset);	  int ord = pe_def_file->exports[s].ordinal;	  bfd_put_32 (abfd, srva - image_base,		      (void *) (eaddresses + ord - min_ordinal));	  if (!pe_def_file->exports[s].flag_noname)	    {	      char *ename = pe_def_file->exports[s].name;	      bfd_put_32 (abfd, ERVA (enamestr), (void *) enameptrs);	      enameptrs++;	      strcpy (enamestr, ename);	      enamestr += strlen (enamestr) + 1;	      bfd_put_16 (abfd, ord - min_ordinal, (void *) eordinals);	      eordinals++;	      pe_def_file->exports[s].hint = hint++;	    }	}    }}/************************************************************************ Gather all the relocations and build the .reloc section ************************************************************************/static voidgenerate_reloc (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  /* For .reloc stuff.  */  reloc_data_type *reloc_data;  int total_relocs = 0;  int i;  unsigned long sec_page = (unsigned long) (-1);  unsigned long page_ptr, page_count;  int bi;  bfd *b;  struct sec *s;  total_relocs = 0;  for (b = info->input_bfds; b; b = b->link_next)    for (s = b->sections; s; s = s->next)      total_relocs += s->reloc_count;  reloc_data = (reloc_data_type *) xmalloc (total_relocs * sizeof (reloc_data_type));  total_relocs = 0;  bi = 0;  for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next)    {      arelent **relocs;      int relsize, nrelocs, i;      for (s = b->sections; s; s = s->next)	{	  unsigned long sec_vma = s->output_section->vma + s->output_offset;	  asymbol **symbols;	  int nsyms, symsize;	  /* If it's not loaded, we don't need to relocate it this way.  */	  if (!(s->output_section->flags & SEC_LOAD))	    continue;	  /* I don't know why there would be a reloc for these, but I've	     seen it happen - DJ  */	  if (s->output_section == &bfd_abs_section)	    continue;	  if (s->output_section->vma == 0)	    {	      /* Huh?  Shouldn't happen, but punt if it does.  */	      einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n",		     s->output_section->name, s->output_section->index,		     s->output_section->flags);	      continue;	    }	  symsize = bfd_get_symtab_upper_bound (b);	  symbols = (asymbol **) xmalloc (symsize);	  nsyms = bfd_canonicalize_symtab (b, symbols);	  relsize = bfd_get_reloc_upper_bound (b, s);	  relocs = (arelent **) xmalloc ((size_t) relsize);	  nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);	  for (i = 0; i < nrelocs; i++)	    {	      if (!relocs[i]->howto->pc_relative		  && relocs[i]->howto->type != pe_details->imagebase_reloc)		{		  bfd_vma sym_vma;		  struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;		  sym_vma = (relocs[i]->addend			     + sym->value			     + sym->section->vma			     + sym->section->output_offset			     + sym->section->output_section->vma);		  reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)		  switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,					 relocs[i]->howto->rightshift)		    {		    case BITS_AND_SHIFT (32, 0):		      reloc_data[total_relocs].type = 3;		      total_relocs++;		      break;		    case BITS_AND_SHIFT (16, 0):		      reloc_data[total_relocs].type = 2;		      total_relocs++;		      break;		    case BITS_AND_SHIFT (16, 16):		      reloc_data[total_relocs].type = 4;		      /* FIXME: we can't know the symbol's right value			 yet, but we probably can safely assume that			 CE will relocate us in 64k blocks, so leaving			 it zero is safe.  */		      reloc_data[total_relocs].extra = 0;		      total_relocs++;		      break;		    case BITS_AND_SHIFT (26, 2):		      reloc_data[total_relocs].type = 5;		      total_relocs++;		      break;		    default:		      /* xgettext:c-format */		      einfo (_("%XError: %d-bit reloc in dll\n"),			     relocs[i]->howto->bitsize);		      break;		    }		}	    }	  free (relocs);	  /* Warning: the allocated symbols are remembered in BFD and	     reused later, so don't free them!  */#if 0	  free (symbol);#endif	}    }  /* At this point, we have total_relocs relocation addresses in     reloc_addresses, which are all suitable for the .reloc section.     We must now create the new sections.  */  qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort);  for (i = 0; i < total_relocs; i++)    {      unsigned long this_page = (reloc_data[i].vma >> 12);      if (this_page != sec_page)	{	  reloc_sz = (reloc_sz + 3) & ~3;	/* 4-byte align */	  reloc_sz += 8;	  sec_page = this_page;	}      reloc_sz += 2;      if (reloc_data[i].type == 4)	reloc_sz += 2;    }  reloc_sz = (reloc_sz + 3) & ~3;	/* 4-byte align */  reloc_d = (unsigned char *) xmalloc (reloc_sz);  sec_page = (unsigned long) (-1);  reloc_sz = 0;  page_ptr = (unsigned long) (-1);  page_count = 0;  for (i = 0; i < total_relocs; i++)    {      unsigned long rva = reloc_data[i].vma - image_base;      unsigned long this_page = (rva & ~0xfff);      if (this_page != sec_page)	{	  while (reloc_sz & 3)	    reloc_d[reloc_sz++] = 0;	  if (page_ptr != (unsigned long) (-1))	    bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);	  bfd_put_32 (abfd, this_page, reloc_d + reloc_sz);	  page_ptr = reloc_sz;	  reloc_sz += 8;	  sec_page = this_page;	  page_count = 0;	}      bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),		  reloc_d + reloc_sz);      reloc_sz += 2;      if (reloc_data[i].type == 4)	{	  bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);	  reloc_sz += 2;	}      page_count++;    }  while (reloc_sz & 3)    reloc_d[reloc_sz++] = 0;  if (page_ptr != (unsigned long) (-1))    bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);  while (reloc_sz < reloc_s->_raw_size)    reloc_d[reloc_sz++] = 0;}/************************************************************************ Given the exiting def_file structure, print out a .DEF file that corresponds to it. ************************************************************************/static voidquoteput (s, f, needs_quotes)     char *s;     FILE *f;     int needs_quotes;{  char *cp;  for (cp = s; *cp; cp++)    if (*cp == '\''	|| *cp == '"'	|| *cp == '\\'	|| isspace ((unsigned char) *cp)	|| *cp == ','	|| *cp == ';')      needs_quotes = 1;  if (needs_quotes)    {      putc ('"', f);      while (*s)	{	  if (*s == '"' || *s == '\\')	    putc ('\\', f);	  putc (*s, f);	  s++;	}      putc ('"', f);    }  else    fputs (s, f);}voidpe_dll_generate_def_file (pe_out_def_filename)     const char *pe_out_def_filename;{  int i;  FILE *out = fopen (pe_out_def_filename, "w");  if (out == NULL)    {      /* xgettext:c-format */      einfo (_("%s: Can't open output def file %s\n"),	     program_name, pe_out_def_filename);    }  if (pe_def_file)

⌨️ 快捷键说明

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