FreeBSD/contrib/binutils/binutils/readelf.c
/* Process an ELF archive.  The file is positioned just after the
   ARMAG string.  */
Process an ELF archive.  The file is positioned just after the
ARMAG string.
Process an ELF archive . The file is positioned just after the ARMAG string .
static int
process_archive (char *file_name, FILE *file)
{
  struct ar_hdr arhdr;
  size_t got;
  unsigned long size;
  char *longnames = NULL;
  unsigned long longnames_size = 0;
  size_t file_name_size;
  int ret;
  show_name = 1;
  got = fread (&arhdr, 1, sizeof arhdr, file);
  if (got != sizeof arhdr)
    {
      if (got == 0)
	return 0;
      error (_("%s: failed to read archive header\n"), file_name);
      return 1;
    }
  if (const_strneq (arhdr.ar_name, "/               "))
    {
      size = strtoul (arhdr.ar_size, NULL, 10);
      if (fseek (file, size + (size & 1), SEEK_CUR) != 0)
	{
	  error (_("%s: failed to skip archive symbol table\n"), file_name);
	  return 1;
	}
      got = fread (&arhdr, 1, sizeof arhdr, file);
      if (got != sizeof arhdr)
	{
	  if (got == 0)
	    return 0;
	  error (_("%s: failed to read archive header\n"), file_name);
	  return 1;
	}
    }
  if (const_strneq (arhdr.ar_name, "//              "))
    {
      longnames_size = strtoul (arhdr.ar_size, NULL, 10);
      longnames = malloc (longnames_size);
      if (longnames == NULL)
	{
	  error (_("Out of memory\n"));
	  return 1;
	}
      if (fread (longnames, longnames_size, 1, file) != 1)
	{
	  free (longnames);
	  error (_("%s: failed to read string table\n"), file_name);
	  return 1;
	}
      if ((longnames_size & 1) != 0)
	(void) getc (file);
      got = fread (&arhdr, 1, sizeof arhdr, file);
      if (got != sizeof arhdr)
	{
	  free (longnames);
	  if (got == 0)
	    return 0;
	  error (_("%s: failed to read archive header\n"), file_name);
	  return 1;
	}
    }
  file_name_size = strlen (file_name);
  ret = 0;
  while (1)
    {
      char *name;
      char *nameend;
      char *namealc;
      if (arhdr.ar_name[0] == '/')
	{
	  unsigned long off;
	  off = strtoul (arhdr.ar_name + 1, NULL, 10);
	  if (off >= longnames_size)
	    {
	      error (_("%s: invalid archive string table offset %lu\n"), file_name, off);
	      ret = 1;
	      break;
	    }
	  name = longnames + off;
	  nameend = memchr (name, '/', longnames_size - off);
	}
      else
	{
	  name = arhdr.ar_name;
	  nameend = memchr (name, '/', 16);
	}
      if (nameend == NULL)
	{
	  error (_("%s: bad archive file name\n"), file_name);
	  ret = 1;
	  break;
	}
      namealc = malloc (file_name_size + (nameend - name) + 3);
      if (namealc == NULL)
	{
	  error (_("Out of memory\n"));
	  ret = 1;
	  break;
	}
      memcpy (namealc, file_name, file_name_size);
      namealc[file_name_size] = '(';
      memcpy (namealc + file_name_size + 1, name, nameend - name);
      namealc[file_name_size + 1 + (nameend - name)] = ')';
      namealc[file_name_size + 2 + (nameend - name)] = '\0';
      archive_file_offset = ftell (file);
      archive_file_size = strtoul (arhdr.ar_size, NULL, 10);
      ret |= process_object (namealc, file);
      free (namealc);
      if (fseek (file,
		 (archive_file_offset
		  + archive_file_size
		  + (archive_file_size & 1)),
		 SEEK_SET) != 0)
	{
	  error (_("%s: failed to seek to next archive header\n"), file_name);
	  ret = 1;
	  break;
	}
      got = fread (&arhdr, 1, sizeof arhdr, file);
      if (got != sizeof arhdr)
	{
	  if (got == 0)
	    break;
	  error (_("%s: failed to read archive header\n"), file_name);
	  ret = 1;
	  break;
	}
    }
  if (longnames != 0)
    free (longnames);
  return ret;
}
static int process_archive ( char * file_name , FILE * file ) { struct ar_hdr arhdr ; size_t got ; unsigned long size ; char * longnames = NULL ; unsigned long longnames_size = 0 ; size_t file_name_size ; int ret ; show_name = 1 ; got = fread ( & arhdr , 1 , sizeof arhdr , file ) ; if ( got != sizeof arhdr ) { if ( got == 0 ) return 0 ; error ( _ ( " \n " ) , file_name ) ; return 1 ; } if ( const_strneq ( arhdr . ar_name , " " ) ) { size = strtoul ( arhdr . ar_size , NULL , 10 ) ; if ( fseek ( file , size + ( size & 1 ) , SEEK_CUR ) != 0 ) { error ( _ ( " \n " ) , file_name ) ; return 1 ; } got = fread ( & arhdr , 1 , sizeof arhdr , file ) ; if ( got != sizeof arhdr ) { if ( got == 0 ) return 0 ; error ( _ ( " \n " ) , file_name ) ; return 1 ; } } if ( const_strneq ( arhdr . ar_name , " " ) ) { longnames_size = strtoul ( arhdr . ar_size , NULL , 10 ) ; longnames = malloc ( longnames_size ) ; if ( longnames == NULL ) { error ( _ ( " \n " ) ) ; return 1 ; } if ( fread ( longnames , longnames_size , 1 , file ) != 1 ) { free ( longnames ) ; error ( _ ( " \n " ) , file_name ) ; return 1 ; } if ( ( longnames_size & 1 ) != 0 ) ( void ) getc ( file ) ; got = fread ( & arhdr , 1 , sizeof arhdr , file ) ; if ( got != sizeof arhdr ) { free ( longnames ) ; if ( got == 0 ) return 0 ; error ( _ ( " \n " ) , file_name ) ; return 1 ; } } file_name_size = strlen ( file_name ) ; ret = 0 ; while ( 1 ) { char * name ; char * nameend ; char * namealc ; if ( arhdr . ar_name [ 0 ] == ' ' ) { unsigned long off ; off = strtoul ( arhdr . ar_name + 1 , NULL , 10 ) ; if ( off >= longnames_size ) { error ( _ ( " \n " ) , file_name , off ) ; ret = 1 ; break ; } name = longnames + off ; nameend = memchr ( name , ' ' , longnames_size - off ) ; } else { name = arhdr . ar_name ; nameend = memchr ( name , ' ' , 16 ) ; } if ( nameend == NULL ) { error ( _ ( " \n " ) , file_name ) ; ret = 1 ; break ; } namealc = malloc ( file_name_size + ( nameend - name ) + 3 ) ; if ( namealc == NULL ) { error ( _ ( " \n " ) ) ; ret = 1 ; break ; } memcpy ( namealc , file_name , file_name_size ) ; namealc [ file_name_size ] = ' ' ; memcpy ( namealc + file_name_size + 1 , name , nameend - name ) ; namealc [ file_name_size + 1 + ( nameend - name ) ] = ' ' ; namealc [ file_name_size + 2 + ( nameend - name ) ] = ' \0 ' ; archive_file_offset = ftell ( file ) ; archive_file_size = strtoul ( arhdr . ar_size , NULL , 10 ) ; ret |= process_object ( namealc , file ) ; free ( namealc ) ; if ( fseek ( file , ( archive_file_offset + archive_file_size + ( archive_file_size & 1 ) ) , SEEK_SET ) != 0 ) { error ( _ ( " \n " ) , file_name ) ; ret = 1 ; break ; } got = fread ( & arhdr , 1 , sizeof arhdr , file ) ; if ( got != sizeof arhdr ) { if ( got == 0 ) break ; error ( _ ( " \n " ) , file_name ) ; ret = 1 ; break ; } } if ( longnames != 0 ) free ( longnames ) ; return ret ; }
Process an ELF archive.
Process an ELF archive .
/* This is the archive symbol table.  Skip it.
	 FIXME: We should have an option to dump it.  */ /* This is the archive string table holding long member
	 names.  */