nlmconv.c

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

C
2,181
字号
      || ! bfd_set_section_alignment (inbfd, stub_sec, 2))    bfd_fatal (".stubs");  /* Get the TOC section, which is named .got.  */  got_sec = bfd_get_section_by_name (inbfd, ".got");  if (got_sec == (asection *) NULL)    {      got_sec = bfd_make_section (inbfd, ".got");      if (got_sec == (asection *) NULL	  || ! bfd_set_section_flags (inbfd, got_sec,				      (SEC_DATA				       | SEC_RELOC				       | SEC_ALLOC				       | SEC_LOAD				       | SEC_HAS_CONTENTS))	  || ! bfd_set_section_alignment (inbfd, got_sec, 2))	bfd_fatal (".got");    }  powerpc_initial_got_size = bfd_section_size (inbfd, got_sec);  got_base = powerpc_initial_got_size;  got_base = (got_base + 3) &~ 3;  stubcount = 0;  symcount = *symcount_ptr;  for (i = 0; i < symcount; i++)    {      asymbol *sym;      asymbol *newsym;      char *newname;      struct powerpc_stub *item;      sym = (*symbols_ptr)[i];      /* We must make a stub for every undefined symbol whose name	 starts with '.'.  */      if (bfd_asymbol_name (sym)[0] != '.'	  || ! bfd_is_und_section (bfd_get_section (sym)))	continue;      /* Make a new undefined symbol with the same name but without	 the leading `.'.  */      newsym = (asymbol *) xmalloc (sizeof (asymbol));      *newsym = *sym;      newname = (char *) xmalloc (strlen (bfd_asymbol_name (sym)));      strcpy (newname, bfd_asymbol_name (sym) + 1);      newsym->name = newname;      /* Define the `.' symbol to be in the stub section.  */      sym->section = stub_sec;      sym->value = stubcount * POWERPC_STUB_SIZE;      /* We set the BSF_DYNAMIC flag here so that we can check it when	 we are mangling relocs.  FIXME: This is a hack.  */      sym->flags = BSF_LOCAL | BSF_DYNAMIC;      /* Add this stub to the linked list.  */      item = (struct powerpc_stub *) xmalloc (sizeof (struct powerpc_stub));      item->start = sym;      item->reloc = newsym;      item->toc_index = got_base + stubcount * POWERPC_STUB_TOC_ENTRY_SIZE;      item->next = powerpc_stubs;      powerpc_stubs = item;            ++stubcount;    }  if (stubcount > 0)    {      asymbol **s;      struct powerpc_stub *l;      /* Add the new symbols we just created to the symbol table.  */      *symbols_ptr = (asymbol **) xrealloc ((char *) *symbols_ptr,					    ((symcount + stubcount)					     * sizeof (asymbol)));      *symcount_ptr += stubcount;      s = &(*symbols_ptr)[symcount];      for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)	*s++ = l->reloc;      /* Set the size of the .stubs section and increase the size of	 the .got section.  */      if (! bfd_set_section_size (inbfd, stub_sec,				  stubcount * POWERPC_STUB_SIZE)	  || ! bfd_set_section_size (inbfd, got_sec,				     (got_base				      + (stubcount					 * POWERPC_STUB_TOC_ENTRY_SIZE))))	bfd_fatal (_("stub section sizes"));    }}/* Resolve all the stubs for PowerPC NetWare.  We fill in the contents   of the output section, and create new relocs in the TOC.  */static voidpowerpc_resolve_stubs (inbfd, outbfd)     bfd *inbfd;     bfd *outbfd;{  bfd_byte buf[POWERPC_STUB_SIZE];  unsigned int i;  unsigned int stubcount;  arelent **relocs;  asection *got_sec;  arelent **r;  struct powerpc_stub *l;  if (powerpc_stubs == (struct powerpc_stub *) NULL)    return;  for (i = 0; i < POWERPC_STUB_INSN_COUNT; i++)    bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[i], buf + i * 4);  got_sec = bfd_get_section_by_name (inbfd, ".got");  assert (got_sec != (asection *) NULL);  assert (got_sec->output_section->orelocation == (arelent **) NULL);  stubcount = 0;  for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)    ++stubcount;  relocs = (arelent **) xmalloc (stubcount * sizeof (arelent *));  r = relocs;  for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)    {      arelent *reloc;      /* Adjust the first instruction to use the right TOC index.  */      bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[0] + l->toc_index, buf);      /* Write this stub out.  */      if (! bfd_set_section_contents (outbfd,				      bfd_get_section (l->start),				      buf,				      l->start->value,				      POWERPC_STUB_SIZE))	bfd_fatal (_("writing stub"));      /* Create a new reloc for the TOC entry.  */      reloc = (arelent *) xmalloc (sizeof (arelent));      reloc->sym_ptr_ptr = &l->reloc;      reloc->address = l->toc_index + got_sec->output_offset;      reloc->addend = 0;      reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32);				            *r++ = reloc;    }  bfd_set_reloc (outbfd, got_sec->output_section, relocs, stubcount);}/* Adjust relocation entries for PowerPC NetWare.  We do not output   TOC relocations.  The object code already contains the offset from   the TOC pointer.  When the function is called, the TOC register,   r2, will be set to the correct TOC value, so there is no need for   any further reloc.  *//*ARGSUSED*/static voidpowerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,		       contents_size)     bfd *outbfd;     asection *insec;     register arelent ***relocs_ptr;     long *reloc_count_ptr;     char *contents;     bfd_size_type contents_size;{  reloc_howto_type *toc_howto;  long reloc_count;  register arelent **relocs;  register long i;  toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16);  if (toc_howto == (reloc_howto_type *) NULL)    abort ();  /* If this is the .got section, clear out all the contents beyond     the initial size.  We must do this here because copy_sections is     going to write out whatever we return in the contents field.  */  if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0)    memset (contents + powerpc_initial_got_size, 0,	    (size_t) (bfd_get_section_size_after_reloc (insec)		      - powerpc_initial_got_size));  reloc_count = *reloc_count_ptr;  relocs = *relocs_ptr;  for (i = 0; i < reloc_count; i++)    {      arelent *rel;      asymbol *sym;      bfd_vma sym_value;      rel = *relocs++;      sym = *rel->sym_ptr_ptr;      /* Convert any relocs against the .bss section into relocs         against the .data section.  */      if (strcmp (bfd_get_section_name (outbfd, bfd_get_section (sym)),		  NLM_UNINITIALIZED_DATA_NAME) == 0)	{	  asection *datasec;	  datasec = bfd_get_section_by_name (outbfd,					     NLM_INITIALIZED_DATA_NAME);	  if (datasec != NULL)	    {	      rel->addend += (bfd_get_section_vma (outbfd,						   bfd_get_section (sym))			      + sym->value);	      rel->sym_ptr_ptr = datasec->symbol_ptr_ptr;	      sym = *rel->sym_ptr_ptr;	    }	}      /* We must be able to resolve all PC relative relocs at this	 point.  If we get a branch to an undefined symbol we build a	 stub, since NetWare will resolve undefined symbols into a	 pointer to a function descriptor.  */      if (rel->howto->pc_relative)	{	  /* This check for whether a symbol is in the same section as	     the reloc will be wrong if there is a PC relative reloc	     between two sections both of which were placed in the	     same output section.  This should not happen.  */	  if (bfd_get_section (sym) != insec->output_section)	    non_fatal (_("unresolved PC relative reloc against %s"),		       bfd_asymbol_name (sym));	  else	    {	      bfd_vma val;	      assert (rel->howto->size == 2 && rel->howto->pcrel_offset);	      val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);	      val = ((val &~ rel->howto->dst_mask)		     | (((val & rel->howto->src_mask)			 + (sym->value - rel->address)			 + rel->addend)			& rel->howto->dst_mask));	      bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);	      /* If this reloc is against an stubbed symbol and the		 next instruction is		     cror 31,31,31		 then we replace the next instruction with		     lwz  r2,20(r1)		 This reloads the TOC pointer after a stub call.  */	      if (bfd_asymbol_name (sym)[0] == '.'		  && (sym->flags & BSF_DYNAMIC) != 0		  && (bfd_get_32 (outbfd,				  (bfd_byte *) contents + rel->address + 4)		      == 0x4ffffb82)) /* cror 31,31,31 */		bfd_put_32 (outbfd, (bfd_vma) 0x80410014, /* lwz r2,20(r1) */			    (bfd_byte *) contents + rel->address + 4);	      --*reloc_count_ptr;	      --relocs;	      memmove (relocs, relocs + 1,		       (size_t) ((reloc_count - 1) * sizeof (arelent *)));	      continue;	    }	}      /* When considering a TOC reloc, we do not want to include the	 symbol value.  The symbol will be start of the TOC section	 (which is named .got).  We do want to include the addend.  */      if (rel->howto == toc_howto)	sym_value = 0;      else	sym_value = sym->value;      /* If this is a relocation against a symbol with a value, or	 there is a reloc addend, we need to update the addend in the	 object file.  */      if (sym_value + rel->addend != 0)	{	  bfd_vma val;	  switch (rel->howto->size)	    {	    case 1:	      val = bfd_get_16 (outbfd,				(bfd_byte *) contents + rel->address);	      val = ((val &~ rel->howto->dst_mask)		     | (((val & rel->howto->src_mask)			 + sym_value			 + rel->addend)			& rel->howto->dst_mask));	      if ((bfd_signed_vma) val < - 0x8000		  || (bfd_signed_vma) val >= 0x8000)		non_fatal (_("overflow when adjusting relocation against %s"),			   bfd_asymbol_name (sym));	      bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address);	      break;	    case 2:	      val = bfd_get_32 (outbfd,				(bfd_byte *) contents + rel->address);	      val = ((val &~ rel->howto->dst_mask)		     | (((val & rel->howto->src_mask)			 + sym_value			 + rel->addend)			& rel->howto->dst_mask));	      bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);	      break;	    default:	      abort ();	    }	  if (! bfd_is_und_section (bfd_get_section (sym)))	    rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;	  rel->addend = 0;	}      /* Now that we have incorporated the addend, remove any TOC	 relocs.  */      if (rel->howto == toc_howto)	{	  --*reloc_count_ptr;	  --relocs;	  memmove (relocs, relocs + 1,		   (size_t) ((reloc_count - i) * sizeof (arelent *)));	  continue;	}      rel->address += insec->output_offset;    }}#endif /* NLMCONV_POWERPC *//* Name of linker.  */#ifndef LD_NAME#define LD_NAME "ld"#endif/* The user has specified several input files.  Invoke the linker to   link them all together, and convert and delete the resulting output   file.  */static char *link_inputs (inputs, ld)     struct string_list *inputs;     char *ld;{  size_t c;  struct string_list *q;  char **argv;  size_t i;  int pid;  int status;  char *errfmt;  char *errarg;  c = 0;  for (q = inputs; q != NULL; q = q->next)    ++c;  argv = (char **) alloca ((c + 5) * sizeof(char *));#ifndef __MSDOS__  if (ld == NULL)    {      char *p;      /* Find the linker to invoke based on how nlmconv was run.  */      p = program_name + strlen (program_name);      while (p != program_name)	{	  if (p[-1] == '/')	    {	      ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1);	      memcpy (ld, program_name, p - program_name);	      strcpy (ld + (p - program_name), LD_NAME);	      break;	    }	  --p;	}    }#endif  if (ld == NULL)    ld = (char *) LD_NAME;  unlink_on_exit = make_temp_file (".O");  argv[0] = ld;  argv[1] = (char *) "-Ur";  argv[2] = (char *) "-o";  argv[3] = unlink_on_exit;  i = 4;  for (q = inputs; q != NULL; q = q->next, i++)    argv[i] = q->string;  argv[i] = NULL;  if (debug)    {      for (i = 0; argv[i] != NULL; i++)	fprintf (stderr, " %s", argv[i]);      fprintf (stderr, "\n");    }  pid = pexecute (ld, argv, program_name, (char *) NULL, &errfmt, &errarg,		  PEXECUTE_SEARCH | PEXECUTE_ONE);  if (pid == -1)    {      fprintf (stderr, _("%s: execution of %s failed: "), program_name, ld);      fprintf (stderr, errfmt, errarg);      unlink (unlink_on_exit);      exit (1);    }  if (pwait (pid, &status, 0) < 0)    {      perror ("pwait");      unlink (unlink_on_exit);      exit (1);    }  if (status != 0)    {      non_fatal (_("Execution of %s failed"), ld);      unlink (unlink_on_exit);      exit (1);    }  return unlink_on_exit;}

⌨️ 快捷键说明

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