archive.c

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

C
2,234
字号
	  e = memchr (hdr.ar_name, '/', ar_maxnamelen (abfd));	  if (e == NULL)	    e = memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd));	}      if (e != NULL)	namelen = e - hdr.ar_name;      else	{	  /* If we didn't find a termination character, then the name	     must be the entire field.  */	  namelen = ar_maxnamelen (abfd);	}      allocsize += namelen + 1;    }  if (!allocptr)    {      allocptr = bfd_zalloc (abfd, allocsize);      if (allocptr == NULL)	return NULL;    }  ared = (struct areltdata *) allocptr;  ared->arch_header = allocptr + sizeof (struct areltdata);  memcpy ((char *) ared->arch_header, (char *) &hdr, sizeof (struct ar_hdr));  ared->parsed_size = parsed_size;  if (filename != NULL)    ared->filename = filename;  else    {      ared->filename = allocptr + (sizeof (struct areltdata) +				   sizeof (struct ar_hdr));      if (namelen)	memcpy (ared->filename, hdr.ar_name, namelen);      ared->filename[namelen] = '\0';    }  return (PTR) ared;}/* This is an internal function; it's mainly used when indexing   through the archive symbol table, but also used to get the next   element, since it handles the bookkeeping so nicely for us.  */bfd *_bfd_get_elt_at_filepos (archive, filepos)     bfd *archive;     file_ptr filepos;{  struct areltdata *new_areldata;  bfd *n_nfd;  n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);  if (n_nfd)    return n_nfd;  if (0 > bfd_seek (archive, filepos, SEEK_SET))    return NULL;  if ((new_areldata = (struct areltdata *) _bfd_read_ar_hdr (archive)) == NULL)    return NULL;  n_nfd = _bfd_create_empty_archive_element_shell (archive);  if (n_nfd == NULL)    {      bfd_release (archive, (PTR) new_areldata);      return NULL;    }  n_nfd->origin = bfd_tell (archive);  n_nfd->arelt_data = (PTR) new_areldata;  n_nfd->filename = new_areldata->filename;  if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))    return n_nfd;  /* Huh?  */  bfd_release (archive, (PTR) n_nfd);  bfd_release (archive, (PTR) new_areldata);  return NULL;}/* Return the BFD which is referenced by the symbol in ABFD indexed by   INDEX.  INDEX should have been returned by bfd_get_next_mapent.  */bfd *_bfd_generic_get_elt_at_index (abfd, index)     bfd *abfd;     symindex index;{  carsym *entry;  entry = bfd_ardata (abfd)->symdefs + index;  return _bfd_get_elt_at_filepos (abfd, entry->file_offset);}/*FUNCTION	bfd_openr_next_archived_fileSYNOPSIS	bfd *bfd_openr_next_archived_file(bfd *archive, bfd *previous);DESCRIPTION	Provided a BFD, @var{archive}, containing an archive and NULL, open	an input BFD on the first contained element and returns that.	Subsequent calls should pass	the archive and the previous return value to return a created	BFD to the next contained element. NULL is returned when there	are no more.*/bfd *bfd_openr_next_archived_file (archive, last_file)     bfd *archive;     bfd *last_file;{  if ((bfd_get_format (archive) != bfd_archive) ||      (archive->direction == write_direction))    {      bfd_set_error (bfd_error_invalid_operation);      return NULL;    }  return BFD_SEND (archive,		   openr_next_archived_file,		   (archive,		    last_file));}bfd *bfd_generic_openr_next_archived_file (archive, last_file)     bfd *archive;     bfd *last_file;{  file_ptr filestart;  if (!last_file)    filestart = bfd_ardata (archive)->first_file_filepos;  else    {      unsigned int size = arelt_size (last_file);      /* Pad to an even boundary...	 Note that last_file->origin can be odd in the case of	 BSD-4.4-style element with a long odd size.  */      filestart = last_file->origin + size;      filestart += filestart % 2;    }  return _bfd_get_elt_at_filepos (archive, filestart);}const bfd_target *bfd_generic_archive_p (abfd)     bfd *abfd;{  struct artdata *tdata_hold;  char armag[SARMAG + 1];  tdata_hold = abfd->tdata.aout_ar_data;  if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG)    {      if (bfd_get_error () != bfd_error_system_call)	bfd_set_error (bfd_error_wrong_format);      return NULL;    }#ifdef GNU960  if (strncmp (armag, BFD_GNU960_ARMAG (abfd), SARMAG) != 0)    return 0;#else  if (strncmp (armag, ARMAG, SARMAG) != 0 &&      strncmp (armag, ARMAGB, SARMAG) != 0)    return 0;#endif  /* We are setting bfd_ardata(abfd) here, but since bfd_ardata     involves a cast, we can't do it as the left operand of assignment.  */  abfd->tdata.aout_ar_data = ((struct artdata *)			      bfd_zalloc (abfd, sizeof (struct artdata)));  if (bfd_ardata (abfd) == NULL)    return NULL;  bfd_ardata (abfd)->first_file_filepos = SARMAG;  bfd_ardata (abfd)->cache = NULL;  bfd_ardata (abfd)->archive_head = NULL;  bfd_ardata (abfd)->symdefs = NULL;  bfd_ardata (abfd)->extended_names = NULL;  bfd_ardata (abfd)->tdata = NULL;  if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd)))    {      bfd_release (abfd, bfd_ardata (abfd));      abfd->tdata.aout_ar_data = tdata_hold;      if (bfd_get_error () != bfd_error_system_call)	bfd_set_error (bfd_error_wrong_format);      return NULL;    }  if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))    {      bfd_release (abfd, bfd_ardata (abfd));      abfd->tdata.aout_ar_data = tdata_hold;      if (bfd_get_error () != bfd_error_system_call)	bfd_set_error (bfd_error_wrong_format);      return NULL;    }  if (bfd_has_map (abfd))    {      bfd *first;      /* This archive has a map, so we may presume that the contents	 are object files.  Make sure that if the first file in the	 archive can be recognized as an object file, it is for this	 target.  If not, assume that this is the wrong format.  If	 the first file is not an object file, somebody is doing	 something weird, and we permit it so that ar -t will work.	 This is done because any normal format will recognize any	 normal archive, regardless of the format of the object files.	 We do accept an empty archive.  */      first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);      if (first != NULL)	{	  boolean fail;	  first->target_defaulted = false;	  fail = false;	  if (bfd_check_format (first, bfd_object)	      && first->xvec != abfd->xvec)	    {	      (void) bfd_close (first);	      bfd_release (abfd, bfd_ardata (abfd));	      abfd->tdata.aout_ar_data = tdata_hold;	      bfd_set_error (bfd_error_wrong_format);	      return NULL;	    }	  /* We ought to close first here, but we can't, because we             have no way to remove it from the archive cache.  FIXME.  */	}    }  return abfd->xvec;}/* Some constants for a 32 bit BSD archive structure.  We do not   support 64 bit archives presently; so far as I know, none actually   exist.  Supporting them would require changing these constants, and   changing some bfd_h_get_32 to bfd_h_get_64.  *//* The size of an external symdef structure.  */#define BSD_SYMDEF_SIZE 8/* The offset from the start of a symdef structure to the file offset.  */#define BSD_SYMDEF_OFFSET_SIZE 4/* The size of the symdef count.  */#define BSD_SYMDEF_COUNT_SIZE 4/* The size of the string count.  */#define BSD_STRING_COUNT_SIZE 4/* Returns false on error, true otherwise */static booleando_slurp_bsd_armap (abfd)     bfd *abfd;{  struct areltdata *mapdata;  unsigned int counter;  bfd_byte *raw_armap, *rbase;  struct artdata *ardata = bfd_ardata (abfd);  char *stringbase;  unsigned int parsed_size;  carsym *set;  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);  if (mapdata == NULL)    return false;  parsed_size = mapdata->parsed_size;  bfd_release (abfd, (PTR) mapdata);	/* Don't need it any more.  */  raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size);  if (raw_armap == (bfd_byte *) NULL)    return false;  if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size)    {      if (bfd_get_error () != bfd_error_system_call)	bfd_set_error (bfd_error_malformed_archive);    byebye:      bfd_release (abfd, (PTR) raw_armap);      return false;    }  ardata->symdef_count = bfd_h_get_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE;  if (ardata->symdef_count * BSD_SYMDEF_SIZE >      parsed_size - BSD_SYMDEF_COUNT_SIZE)    {      /* Probably we're using the wrong byte ordering.  */      bfd_set_error (bfd_error_wrong_format);      goto byebye;    }  ardata->cache = 0;  rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;  stringbase = ((char *) rbase		+ ardata->symdef_count * BSD_SYMDEF_SIZE		+ BSD_STRING_COUNT_SIZE);  ardata->symdefs = (carsym *) bfd_alloc (abfd,					  (ardata->symdef_count					   * sizeof (carsym)));  if (!ardata->symdefs)    return false;  for (counter = 0, set = ardata->symdefs;       counter < ardata->symdef_count;       counter++, set++, rbase += BSD_SYMDEF_SIZE)    {      set->name = bfd_h_get_32 (abfd, rbase) + stringbase;      set->file_offset = bfd_h_get_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);    }  ardata->first_file_filepos = bfd_tell (abfd);  /* Pad to an even boundary if you have to.  */  ardata->first_file_filepos += (ardata->first_file_filepos) % 2;  /* FIXME, we should provide some way to free raw_ardata when     we are done using the strings from it.  For now, it seems     to be allocated on an objalloc anyway...  */  bfd_has_map (abfd) = true;  return true;}/* Returns false on error, true otherwise.  */static booleando_slurp_coff_armap (abfd)     bfd *abfd;{  struct areltdata *mapdata;  int *raw_armap, *rawptr;  struct artdata *ardata = bfd_ardata (abfd);  char *stringbase;  unsigned int stringsize;  unsigned int parsed_size;  carsym *carsyms;  unsigned int nsymz;		/* Number of symbols in armap.  */  bfd_vma (*swap) PARAMS ((const bfd_byte *));  char int_buf[sizeof (long)];  unsigned int carsym_size, ptrsize, i;  mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);  if (mapdata == NULL)    return false;  parsed_size = mapdata->parsed_size;  bfd_release (abfd, (PTR) mapdata);	/* Don't need it any more.  */  if (bfd_read ((PTR) int_buf, 1, 4, abfd) != 4)    {      if (bfd_get_error () != bfd_error_system_call)	bfd_set_error (bfd_error_malformed_archive);      return false;    }  /* It seems that all numeric information in a coff archive is always     in big endian format, nomatter the host or target.  */  swap = bfd_getb32;  nsymz = bfd_getb32 ((PTR) int_buf);  stringsize = parsed_size - (4 * nsymz) - 4;#if 1  /* ... except that some archive formats are broken, and it may be our     fault - the i960 little endian coff sometimes has big and sometimes     little, because our tools changed.  Here's a horrible hack to clean     up the crap.  */  if (stringsize > 0xfffff      && bfd_get_arch (abfd) == bfd_arch_i960      && bfd_get_flavour (abfd) == bfd_target_coff_flavour)    {      /* This looks dangerous, let's do it the other way around.  */      nsymz = bfd_getl32 ((PTR) int_buf);      stringsize = parsed_size - (4 * nsymz) - 4;      swap = bfd_getl32;    }#endif  /* The coff armap must be read sequentially.  So we construct a     bsd-style one in core all at once, for simplicity.  */  carsym_size = (nsymz * sizeof (carsym));  ptrsize = (4 * nsymz);  ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1);  if (ardata->symdefs == NULL)    return false;  carsyms = ardata->symdefs;  stringbase = ((char *) ardata->symdefs) + carsym_size;  /* Allocate and read in the raw offsets.  */  raw_armap = (int *) bfd_alloc (abfd, ptrsize);  if (raw_armap == NULL)    goto release_symdefs;  if (bfd_read ((PTR) raw_armap, 1, ptrsize, abfd) != ptrsize      || bfd_read ((PTR) stringbase, 1, stringsize, abfd) != stringsize)    {      if (bfd_get_error () != bfd_error_system_call)	bfd_set_error (bfd_error_malformed_archive);      goto release_raw_armap;    }  /* OK, build the carsyms.  */  for (i = 0; i < nsymz; i++)    {      rawptr = raw_armap + i;      carsyms->file_offset = swap ((PTR) rawptr);      carsyms->name = stringbase;      stringbase += strlen (stringbase) + 1;      carsyms++;    }  *stringbase = 0;  ardata->symdef_count = nsymz;  ardata->first_file_filepos = bfd_tell (abfd);  /* Pad to an even boundary if you have to.  */  ardata->first_file_filepos += (ardata->first_file_filepos) % 2;  bfd_has_map (abfd) = true;  bfd_release (abfd, (PTR) raw_armap);  /* Check for a second archive header (as used by PE).  */  {    struct areltdata *tmp;    bfd_seek (abfd,   ardata->first_file_filepos, SEEK_SET);    tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd);    if (tmp != NULL)      {

⌨️ 快捷键说明

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