m68klinux.c

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

C
774
字号
	  return true;	}    }  /* Do the usual procedure for adding a symbol.  */  if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,					  value, string, copy, collect,					  hashp))    return false;  /* Insert a pointer to our table in the set vector.  The dynamic     linker requires this information */  if (insert)    {      asection *s;      /* Here we do our special thing to add the pointer to the	 dynamic section in the SHARABLE_CONFLICTS set vector.  */      s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,				   ".linux-dynamic");      BFD_ASSERT (s != NULL);      if (! (_bfd_generic_link_add_one_symbol	     (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,	      BSF_GLOBAL | BSF_CONSTRUCTOR, s, 0, NULL, false, false, NULL)))	return false;    }  return true;}/* We will crawl the hash table and come here for every global symbol.   We will examine each entry and see if there are indications that we   need to add a fixup.  There are two possible cases - one is where   you have duplicate definitions of PLT or GOT symbols - these will   have already been caught and added as "builtin" fixups.  If we find   that the corresponding non PLT/GOT symbol is also present, we   convert it to a regular fixup instead.   This function is called via linux_link_hash_traverse.  */static booleanlinux_tally_symbols (h, data)     struct linux_link_hash_entry *h;     PTR data;{  struct bfd_link_info *info = (struct bfd_link_info *) data;  struct fixup *f, *f1;  int is_plt;  struct linux_link_hash_entry *h1, *h2;  boolean exists;  if (h->root.root.type == bfd_link_hash_undefined      && strncmp (h->root.root.root.string, NEEDS_SHRLIB,		  sizeof NEEDS_SHRLIB - 1) == 0)    {      const char *name;      char *p;      char *alloc = NULL;      name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;      p = strrchr (name, '_');      if (p != NULL)	alloc = (char *) bfd_malloc (strlen (name) + 1);      if (p == NULL || alloc == NULL)	(*_bfd_error_handler) (_("Output file requires shared library `%s'\n"),			       name);      else	{	  strcpy (alloc, name);	  p = strrchr (alloc, '_');	  *p++ = '\0';	  (*_bfd_error_handler)	    (_("Output file requires shared library `%s.so.%s'\n"),	     alloc, p);	  free (alloc);	}      abort ();    }  /* If this symbol is not a PLT/GOT, we do not even need to look at it */  is_plt = IS_PLT_SYM (h->root.root.root.string);  if (is_plt || IS_GOT_SYM (h->root.root.root.string))    {      /* Look up this symbol twice.  Once just as a regular lookup,	 and then again following all of the indirect links until we	 reach a real symbol.  */      h1 = linux_link_hash_lookup (linux_hash_table (info),				   (h->root.root.root.string				    + sizeof PLT_REF_PREFIX - 1),				   false, false, true);      /* h2 does not follow indirect symbols.  */      h2 = linux_link_hash_lookup (linux_hash_table (info),				   (h->root.root.root.string				    + sizeof PLT_REF_PREFIX - 1),				   false, false, false);      /* The real symbol must exist but if it is also an ABS symbol,	 there is no need to have a fixup.  This is because they both	 came from the same library.  If on the other hand, we had to	 use an indirect symbol to get to the real symbol, we add the	 fixup anyway, since there are cases where these symbols come	 from different shared libraries */      if (h1 != NULL	  && (((h1->root.root.type == bfd_link_hash_defined		|| h1->root.root.type == bfd_link_hash_defweak)	       && ! bfd_is_abs_section (h1->root.root.u.def.section))	      || h2->root.root.type == bfd_link_hash_indirect))	{	  /* See if there is a "builtin" fixup already present	     involving this symbol.  If so, convert it to a regular	     fixup.  In the end, this relaxes some of the requirements	     about the order of performing fixups.  */	  exists = false;	  for (f1 = linux_hash_table (info)->fixup_list;	       f1 != NULL;	       f1 = f1->next)	    {	      if ((f1->h != h && f1->h != h1)		  || (! f1->builtin && ! f1->jump))		continue;	      if (f1->h == h1)		exists = true;	      if (! exists		  && bfd_is_abs_section (h->root.root.u.def.section))		{		  f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0);		  f->jump = is_plt;		}	      f1->h = h1;	      f1->jump = is_plt;	      f1->builtin = 0;	      exists = true;	    }	  if (! exists	      && bfd_is_abs_section (h->root.root.u.def.section))	    {	      f = new_fixup (info, h1, h->root.root.u.def.value, 0);	      if (f == NULL)		{		  /* FIXME: No way to return error.  */		  abort ();		}	      f->jump = is_plt;	    }	}      /* Quick and dirty way of stripping these symbols from the	 symtab.  */      if (bfd_is_abs_section (h->root.root.u.def.section))	h->root.written = true;    }  return true;}/* This is called to set the size of the .linux-dynamic section is.   It is called by the Linux linker emulation before_allocation   routine.  We have finished reading all of the input files, and now   we just scan the hash tables to find out how many additional fixups   are required.  */booleanbfd_m68klinux_size_dynamic_sections (output_bfd, info)     bfd *output_bfd;     struct bfd_link_info *info;{  struct fixup *f;  asection *s;  if (output_bfd->xvec != &MY(vec))    return true;  /* First find the fixups...  */  linux_link_hash_traverse (linux_hash_table (info),			    linux_tally_symbols,			    (PTR) info);  /* If there are builtin fixups, leave room for a marker.  This is     used by the dynamic linker so that it knows that all that follow     are builtin fixups instead of regular fixups.  */  for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)    {      if (f->builtin)	{	  ++linux_hash_table (info)->fixup_count;	  ++linux_hash_table (info)->local_builtins;	  break;	}    }  if (linux_hash_table (info)->dynobj == NULL)    {      if (linux_hash_table (info)->fixup_count > 0)	abort ();      return true;    }  /* Allocate memory for our fixup table.  We will fill it in later.  */  s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,			       ".linux-dynamic");  if (s != NULL)    {      s->_raw_size = 8 + linux_hash_table (info)->fixup_count * 8;      s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);      if (s->contents == NULL)	{	  bfd_set_error (bfd_error_no_memory);	  return false;	}      memset (s->contents, 0, (size_t) s->_raw_size);    }  return true;}/* We come here once we are ready to actually write the fixup table to   the output file.  Scan the fixup tables and so forth and generate   the stuff we need.  */static booleanlinux_finish_dynamic_link (output_bfd, info)     bfd *output_bfd;     struct bfd_link_info *info;{  asection *s, *os, *is;  bfd_byte *fixup_table;  struct linux_link_hash_entry *h;  struct fixup *f;  unsigned int new_addr;  int section_offset;  unsigned int fixups_written;  if (linux_hash_table (info)->dynobj == NULL)    return true;  s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,			       ".linux-dynamic");  BFD_ASSERT (s != NULL);  os = s->output_section;  fixups_written = 0;#ifdef LINUX_LINK_DEBUG  printf ("Fixup table file offset: %x  VMA: %x\n",	  os->filepos + s->output_offset,	  os->vma + s->output_offset);#endif  fixup_table = s->contents;  bfd_put_32 (output_bfd, linux_hash_table (info)->fixup_count, fixup_table);  fixup_table += 4;  /* Fill in fixup table.  */  for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)    {      if (f->builtin)	continue;      if (f->h->root.root.type != bfd_link_hash_defined	  && f->h->root.root.type != bfd_link_hash_defweak)	{	  (*_bfd_error_handler)	    (_("Symbol %s not defined for fixups\n"),	     f->h->root.root.root.string);	  continue;	}      is = f->h->root.root.u.def.section;      section_offset = is->output_section->vma + is->output_offset;      new_addr = f->h->root.root.u.def.value + section_offset;#ifdef LINUX_LINK_DEBUG      printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string,	      new_addr, f->value);#endif      if (f->jump)	{	  bfd_put_32 (output_bfd, new_addr, fixup_table);	  fixup_table += 4;	  bfd_put_32 (output_bfd, f->value + 2, fixup_table);	  fixup_table += 4;	}      else	{	  bfd_put_32 (output_bfd, new_addr, fixup_table);	  fixup_table += 4;	  bfd_put_32 (output_bfd, f->value, fixup_table);	  fixup_table += 4;	}      ++fixups_written;    }  if (linux_hash_table (info)->local_builtins != 0)    {      /* Special marker so we know to switch to the other type of fixup */      bfd_put_32 (output_bfd, 0, fixup_table);      fixup_table += 4;      bfd_put_32 (output_bfd, 0, fixup_table);      fixup_table += 4;      ++fixups_written;      for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)	{	  if (! f->builtin)	    continue;	  if (f->h->root.root.type != bfd_link_hash_defined	      && f->h->root.root.type != bfd_link_hash_defweak)	    {	      (*_bfd_error_handler)		(_("Symbol %s not defined for fixups\n"),		 f->h->root.root.root.string);	      continue;	    }	  is = f->h->root.root.u.def.section;	  section_offset = is->output_section->vma + is->output_offset;	  new_addr = f->h->root.root.u.def.value + section_offset;#ifdef LINUX_LINK_DEBUG	  printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string,		  new_addr, f->value);#endif	  bfd_put_32 (output_bfd, new_addr, fixup_table);	  fixup_table += 4;	  bfd_put_32 (output_bfd, f->value, fixup_table);	  fixup_table += 4;	  ++fixups_written;	}  }  if (linux_hash_table (info)->fixup_count != fixups_written)    {      (*_bfd_error_handler) (_("Warning: fixup count mismatch\n"));      while (linux_hash_table (info)->fixup_count > fixups_written)	{	  bfd_put_32 (output_bfd, 0, fixup_table);	  fixup_table += 4;	  bfd_put_32 (output_bfd, 0, fixup_table);	  fixup_table += 4;	  ++fixups_written;	}    }  h = linux_link_hash_lookup (linux_hash_table (info),			      "__BUILTIN_FIXUPS__",			      false, false, false);  if (h != NULL      && (h->root.root.type == bfd_link_hash_defined	  || h->root.root.type == bfd_link_hash_defweak))    {      is = h->root.root.u.def.section;      section_offset = is->output_section->vma + is->output_offset;      new_addr = h->root.root.u.def.value + section_offset;#ifdef LINUX_LINK_DEBUG      printf ("Builtin fixup table at %x\n", new_addr);#endif      bfd_put_32 (output_bfd, new_addr, fixup_table);    }  else    bfd_put_32 (output_bfd, 0, fixup_table);  if (bfd_seek (output_bfd, os->filepos + s->output_offset, SEEK_SET) != 0)    return false;  if (bfd_write ((PTR) s->contents, 1, s->_raw_size, output_bfd)      != s->_raw_size)    return false;  return true;}#define MY_bfd_link_hash_table_create linux_link_hash_table_create#define MY_add_one_symbol linux_add_one_symbol#define MY_finish_dynamic_link linux_finish_dynamic_link#define MY_zmagic_contiguous 1#include "aout-target.h"

⌨️ 快捷键说明

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