coff-alpha.c

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

C
2,226
字号
	  /* Store a value from the reloc stack into a bitfield.  If	     we are generating relocateable output, all we do is	     adjust the address of the reloc.  */	  if (! info->relocateable)	    {	      bfd_vma mask;	      bfd_vma val;	      if (tos == 0)		abort ();	      /* Get the relocation mask.  The separate steps and the		 casts to bfd_vma are attempts to avoid a bug in the		 Alpha OSF 1.3 C compiler.  See reloc.c for more		 details.  */	      mask = 1;	      mask <<= (bfd_vma) r_size;	      mask -= 1;	      /* FIXME: I don't know what kind of overflow checking,		 if any, should be done here.  */	      val = bfd_get_64 (input_bfd,				contents + r_vaddr - input_section->vma);	      val &=~ mask << (bfd_vma) r_offset;	      val |= (stack[--tos] & mask) << (bfd_vma) r_offset;	      bfd_put_64 (input_bfd, val,			  contents + r_vaddr - input_section->vma);	    }	  break;	case ALPHA_R_GPVALUE:	  /* I really don't know if this does the right thing.  */	  gp = ecoff_data (input_bfd)->gp + r_symndx;	  gp_undefined = false;	  break;	}      if (relocatep)	{	  reloc_howto_type *howto;	  struct ecoff_link_hash_entry *h = NULL;	  asection *s = NULL;	  bfd_vma relocation;	  bfd_reloc_status_type r;	  /* Perform a relocation.  */	  howto = &alpha_howto_table[r_type];	  if (r_extern)	    {	      h = sym_hashes[r_symndx];	      /* If h is NULL, that means that there is a reloc		 against an external symbol which we thought was just		 a debugging symbol.  This should not happen.  */	      if (h == (struct ecoff_link_hash_entry *) NULL)		abort ();	    }	  else	    {	      if (r_symndx >= NUM_RELOC_SECTIONS)		s = NULL;	      else		s = symndx_to_section[r_symndx];	      if (s == (asection *) NULL)		abort ();	    }	  if (info->relocateable)	    {	      /* We are generating relocateable output, and must		 convert the existing reloc.  */	      if (r_extern)		{		  if (h->root.type != bfd_link_hash_defined		      && h->root.type != bfd_link_hash_defweak		      && h->indx == -1)		    {		      /* This symbol is not being written out.  */		      if (! ((*info->callbacks->unattached_reloc)			     (info, h->root.root.string, input_bfd,			      input_section, r_vaddr - input_section->vma)))			return false;		    }		  relocation = alpha_convert_external_reloc (output_bfd,							     info,							     input_bfd,							     ext_rel,							     h);		}	      else		{		  /* This is a relocation against a section.  Adjust		     the value by the amount the section moved.  */		  relocation = (s->output_section->vma				+ s->output_offset				- s->vma);		}	      /* If this is PC relative, the existing object file		 appears to already have the reloc worked out.  We		 must subtract out the old value and add in the new		 one.  */	      if (howto->pc_relative)		relocation -= (input_section->output_section->vma			       + input_section->output_offset			       - input_section->vma);	      /* Put in any addend.  */	      relocation += addend;	      /* Adjust the contents.  */	      r = _bfd_relocate_contents (howto, input_bfd, relocation,					  (contents					   + r_vaddr					   - input_section->vma));	    }	  else	    {	      /* We are producing a final executable.  */	      if (r_extern)		{		  /* This is a reloc against a symbol.  */		  if (h->root.type == bfd_link_hash_defined		      || h->root.type == bfd_link_hash_defweak)		    {		      asection *hsec;		      hsec = h->root.u.def.section;		      relocation = (h->root.u.def.value				    + hsec->output_section->vma				    + hsec->output_offset);		    }		  else		    {		      if (! ((*info->callbacks->undefined_symbol)			     (info, h->root.root.string, input_bfd,			      input_section,			      r_vaddr - input_section->vma, true)))			return false;		      relocation = 0;		    }		}	      else		{		  /* This is a reloc against a section.  */		  relocation = (s->output_section->vma				+ s->output_offset				- s->vma);		  /* Adjust a PC relative relocation by removing the		     reference to the original source section.  */		  if (howto->pc_relative)		    relocation += input_section->vma;		}	      r = _bfd_final_link_relocate (howto,					    input_bfd,					    input_section,					    contents,					    r_vaddr - input_section->vma,					    relocation,					    addend);	    }	  if (r != bfd_reloc_ok)	    {	      switch (r)		{		default:		case bfd_reloc_outofrange:		  abort ();		case bfd_reloc_overflow:		  {		    const char *name;		    if (r_extern)		      name = sym_hashes[r_symndx]->root.root.string;		    else		      name = bfd_section_name (input_bfd,					       symndx_to_section[r_symndx]);		    if (! ((*info->callbacks->reloc_overflow)			   (info, name, alpha_howto_table[r_type].name,			    (bfd_vma) 0, input_bfd, input_section,			    r_vaddr - input_section->vma)))		      return false;		  }		  break;		}	    }	}      if (info->relocateable && adjust_addrp)	{	  /* Change the address of the relocation.  */	  bfd_h_put_64 (input_bfd,			(input_section->output_section->vma			 + input_section->output_offset			 - input_section->vma			 + r_vaddr),			(bfd_byte *) ext_rel->r_vaddr);	}      if (gp_usedp && gp_undefined)	{	  if (! ((*info->callbacks->reloc_dangerous)		 (info, _("GP relative relocation when GP not defined"),		  input_bfd, input_section, r_vaddr - input_section->vma)))	    return false;	  /* Only give the error once per link.  */	  gp = 4;	  _bfd_set_gp_value (output_bfd, gp);	  gp_undefined = false;	}    }  if (tos != 0)    abort ();  return true;}/* Do final adjustments to the filehdr and the aouthdr.  This routine   sets the dynamic bits in the file header.  */static booleanalpha_adjust_headers (abfd, fhdr, ahdr)     bfd *abfd;     struct internal_filehdr *fhdr;     struct internal_aouthdr *ahdr ATTRIBUTE_UNUSED;{  if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P))    fhdr->f_flags |= F_ALPHA_CALL_SHARED;  else if ((abfd->flags & DYNAMIC) != 0)    fhdr->f_flags |= F_ALPHA_SHARABLE;  return true;}/* Archive handling.  In OSF/1 (or Digital Unix) v3.2, Digital   introduced archive packing, in which the elements in an archive are   optionally compressed using a simple dictionary scheme.  We know   how to read such archives, but we don't write them.  */#define alpha_ecoff_slurp_armap _bfd_ecoff_slurp_armap#define alpha_ecoff_slurp_extended_name_table \  _bfd_ecoff_slurp_extended_name_table#define alpha_ecoff_construct_extended_name_table \  _bfd_ecoff_construct_extended_name_table#define alpha_ecoff_truncate_arname _bfd_ecoff_truncate_arname#define alpha_ecoff_write_armap _bfd_ecoff_write_armap#define alpha_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt#define alpha_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp/* A compressed file uses this instead of ARFMAG.  */#define ARFZMAG "Z\012"/* Read an archive header.  This is like the standard routine, but it   also accepts ARFZMAG.  */static PTRalpha_ecoff_read_ar_hdr (abfd)     bfd *abfd;{  struct areltdata *ret;  struct ar_hdr *h;  ret = (struct areltdata *) _bfd_generic_read_ar_hdr_mag (abfd, ARFZMAG);  if (ret == NULL)    return NULL;  h = (struct ar_hdr *) ret->arch_header;  if (strncmp (h->ar_fmag, ARFZMAG, 2) == 0)    {      bfd_byte ab[8];      /* This is a compressed file.  We must set the size correctly.         The size is the eight bytes after the dummy file header.  */      if (bfd_seek (abfd, FILHSZ, SEEK_CUR) != 0	  || bfd_read (ab, 1, 8, abfd) != 8	  || bfd_seek (abfd, - (FILHSZ + 8), SEEK_CUR) != 0)	return NULL;      ret->parsed_size = bfd_h_get_64 (abfd, ab);    }  return (PTR) ret;}/* Get an archive element at a specified file position.  This is where   we uncompress the archive element if necessary.  */static bfd *alpha_ecoff_get_elt_at_filepos (archive, filepos)     bfd *archive;     file_ptr filepos;{  bfd *nbfd = NULL;  struct areltdata *tdata;  struct ar_hdr *hdr;  bfd_byte ab[8];  bfd_size_type size;  bfd_byte *buf, *p;  struct bfd_in_memory *bim;  nbfd = _bfd_get_elt_at_filepos (archive, filepos);  if (nbfd == NULL)    goto error_return;  if ((nbfd->flags & BFD_IN_MEMORY) != 0)    {      /* We have already expanded this BFD.  */      return nbfd;    }  tdata = (struct areltdata *) nbfd->arelt_data;  hdr = (struct ar_hdr *) tdata->arch_header;  if (strncmp (hdr->ar_fmag, ARFZMAG, 2) != 0)    return nbfd;  /* We must uncompress this element.  We do this by copying it into a     memory buffer, and making bfd_read and bfd_seek use that buffer.     This can use a lot of memory, but it's simpler than getting a     temporary file, making that work with the file descriptor caching     code, and making sure that it is deleted at all appropriate     times.  It can be changed if it ever becomes important.  */  /* The compressed file starts with a dummy ECOFF file header.  */  if (bfd_seek (nbfd, FILHSZ, SEEK_SET) != 0)    goto error_return;  /* The next eight bytes are the real file size.  */  if (bfd_read (ab, 1, 8, nbfd) != 8)    goto error_return;  size = bfd_h_get_64 (nbfd, ab);  if (size == 0)    buf = NULL;  else    {      bfd_size_type left;      bfd_byte dict[4096];      unsigned int h;      bfd_byte b;      buf = (bfd_byte *) bfd_alloc (nbfd, size);      if (buf == NULL)	goto error_return;      p = buf;      left = size;      /* I don't know what the next eight bytes are for.  */      if (bfd_read (ab, 1, 8, nbfd) != 8)	goto error_return;      /* This is the uncompression algorithm.  It's a simple	 dictionary based scheme in which each character is predicted	 by a hash of the previous three characters.  A control byte	 indicates whether the character is predicted or whether it	 appears in the input stream; each control byte manages the	 next eight bytes in the output stream.  */      memset (dict, 0, sizeof dict);      h = 0;      while (bfd_read (&b, 1, 1, nbfd) == 1)	{	  unsigned int i;	  for (i = 0; i < 8; i++, b >>= 1)	    {	      bfd_byte n;	      if ((b & 1) == 0)		n = dict[h];	      else		{		  if (! bfd_read (&n, 1, 1, nbfd))		    goto error_return;		  dict[h] = n;		}	      *p++ = n;	      --left;	      if (left == 0)		break;	      h <<= 4;	      h ^= n;	      h &= sizeof dict - 1;	    }	  if (left == 0)	    break;	}    }  /* Now the uncompressed file contents are in buf.  */  bim = ((struct bfd_in_memory *)	 bfd_alloc (nbfd, sizeof (struct bfd_in_memory)));  if (bim == NULL)    goto error_return;  bim->size = size;  bim->buffer = buf;  nbfd->mtime_set = true;  nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10);  nbfd->flags |= BFD_IN_MEMORY;  nbfd->iostream = (PTR) bim;  BFD_ASSERT (! nbfd->cacheable);  return nbfd; error_return:  if (nbfd != NULL)    bfd_close (nbfd);  return NULL;}/* Open the next archived file.  */static bfd *alpha_ecoff_openr_next_archived_file (archive, last_file)     bfd *archive;     bfd *last_file;{  file_ptr filestart;  if (last_file == NULL)    filestart = bfd_ardata (archive)->first_file_filepos;  else    {      struct areltdata *t;      struct ar_hdr *h;      bfd_size_type size;      /* We can't use arelt_size here, because that uses parsed_size,         which is the uncompressed size.  We need the compressed size.  */      t = (struct arel

⌨️ 快捷键说明

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