This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch] readelf -c dump archive index like nm -s


Hi Nick,

The new patch is attached.

The Changelog is followed.

Changelog
binutils/
* readelf.c (do_archive_index): New.
(options): Add -c and --archive-index option.
(usage): Add c option.
(parse_args): Add c option parsing.
(process_archive): Dump archive index.

Best Regards,
Shen Feng

Index: NEWS
===================================================================
RCS file: /cvs/src/src/binutils/NEWS,v
retrieving revision 1.65
diff -u -r1.65 NEWS
--- NEWS	30 Aug 2007 13:47:35 -0000	1.65
+++ NEWS	12 Sep 2007 10:04:03 -0000
@@ -1,4 +1,6 @@
 -*- text -*-
+* Added -c switch to readelf to allow string dumps of archive symbol index.
+
 * Added -p switch to readelf to allow string dumps of sections.
 
 Changes in 2.18:
Index: readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.376
diff -u -p -r1.376 readelf.c
--- readelf.c	30 Aug 2007 13:47:35 -0000	1.376
+++ readelf.c	12 Sep 2007 09:56:03 -0000
@@ -202,6 +202,7 @@ static int do_histogram;
 static int do_debugging;
 static int do_arch;
 static int do_notes;
+static int do_archive_index;
 static int is_32bit_elf;
 
 struct group_list
@@ -2732,6 +2733,7 @@ get_section_type_name (unsigned int sh_t
 static struct option options[] =
 {
   {"all",	       no_argument, 0, 'a'},
+  {"archive-index",   no_argument, 0, 'c'},
   {"file-header",      no_argument, 0, 'h'},
   {"program-headers",  no_argument, 0, 'l'},
   {"headers",	       no_argument, 0, 'e'},
@@ -2771,6 +2773,7 @@ usage (FILE *stream)
   fprintf (stream, _(" Display information about the contents of ELF format files\n"));
   fprintf (stream, _(" Options are:\n\
   -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I\n\
+  -c --archive-index     Display the archive file index\n\
   -h --file-header       Display the ELF file header\n\
   -l --program-headers   Display the program headers\n\
      --segments          An alias for --program-headers\n\
@@ -2877,7 +2880,7 @@ parse_args (int argc, char **argv)
     usage (stderr);
 
   while ((c = getopt_long
-	  (argc, argv, "ersuahnldSDAINtgw::x:i:vVWHp:", options, NULL)) != EOF)
+	  (argc, argv, "ersuachnldSDAINtgw::x:i:vVWHp:", options, NULL)) != EOF)
     {
       char *cp;
       int section;
@@ -2905,6 +2908,9 @@ parse_args (int argc, char **argv)
 	  do_arch++;
 	  do_notes++;
 	  break;
+	case 'c':
+	  do_archive_index++;
+	  break;
 	case 'g':
 	  do_section_groups++;
 	  break;
@@ -3139,7 +3145,7 @@ parse_args (int argc, char **argv)
   if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
       && !do_segments && !do_header && !do_dump && !do_version
       && !do_histogram && !do_debugging && !do_arch && !do_notes
-      && !do_section_groups)
+      && !do_section_groups && !do_archive_index)
     usage (stderr);
   else if (argc < 3)
     {
@@ -9774,9 +9780,15 @@ process_archive (char *file_name, FILE *
 {
   struct ar_hdr arhdr;
   size_t got;
-  unsigned long size;
+  unsigned long size, current_pos;
+  unsigned int index_num;
+  unsigned int *index_array = NULL;
+  char *sym_table = NULL;
+  unsigned long sym_size =0;
   char *longnames = NULL;
   unsigned long longnames_size = 0;
+  char elf_name[16];
+  unsigned int i, j, k, l;
   size_t file_name_size;
   int ret;
 
@@ -9795,25 +9807,79 @@ process_archive (char *file_name, FILE *
   if (const_strneq (arhdr.ar_name, "/               ")
       || const_strneq (arhdr.ar_name, "/SYM64/         "))
     {
-      /* This is the archive symbol table.  Skip it.
-	 FIXME: We should have an option to dump it.  */
+      /* This is the archive symbol table.  */
       size = strtoul (arhdr.ar_size, NULL, 10);
-      if (fseek (file, size + (size & 1), SEEK_CUR) != 0)
+      if (do_archive_index)
 	{
-	  error (_("%s: failed to skip archive symbol table\n"), file_name);
-	  return 1;
-	}
+	  /* Read the archive index table.  */
+	  size = size + (size & 1);
+	  got = fread(&index_num, 1, sizeof (index_num), file);
+	  if (got != sizeof (index_num))
+	    {
+	      error (_("%s: failed to read archive index\n"), file_name);
+	      return 1;
+	    }
+	  index_num = byte_get_big_endian ((unsigned char*)&index_num,
+				       sizeof(index_num));
+	  size -= sizeof(index_num);
+	  index_array = (unsigned int*)malloc (index_num*sizeof(unsigned int));
+	  if (index_array == NULL)
+	    {
+	      error (_("Out of memory\n"));
+	      return 1;
+	    }
+	  got = fread (index_array, sizeof(unsigned int), index_num, file);
+	  if (got != index_num)
+	    {
+	      error (_("%s: failed to read archive index\n"), file_name);
+	      ret = 1;
+	      goto out;
+	    }
 
+	  size -= sizeof(unsigned int) * index_num;
+	  sym_table = (char*)malloc (size);
+	  sym_size = size;
+	  if (sym_table == NULL)
+	    {
+	      error (_("Out of memory\n"));
+	      ret = 1;
+	      goto out;
+	    }
+	  got = fread (sym_table, 1, size, file);
+	  if (got != size)
+	    {
+	      error (_("%s: failed to read archive index symbol table\n"), file_name);
+	      ret = 1;
+	      goto out;
+	    }	  
+  	}
+      else
+	{
+	  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;
+	    {
+	      ret = 0;
+	      goto out;
+	    }
 
 	  error (_("%s: failed to read archive header\n"), file_name);
-	  return 1;
+	  ret = 1;
+	  goto out;
 	}
     }
+  else
+    {
+      if (do_archive_index)
+	printf(_("%s has no archive index\n"), file_name);
+    }
 
   if (const_strneq (arhdr.ar_name, "//              "))
     {
@@ -9831,9 +9897,9 @@ process_archive (char *file_name, FILE *
 
       if (fread (longnames, longnames_size, 1, file) != 1)
 	{
-	  free (longnames);
 	  error (_("%s: failed to read string table\n"), file_name);
-	  return 1;
+	  ret = 1;
+	  goto out;
 	}
 
       if ((longnames_size & 1) != 0)
@@ -9842,16 +9908,87 @@ process_archive (char *file_name, FILE *
       got = fread (&arhdr, 1, sizeof arhdr, file);
       if (got != sizeof arhdr)
 	{
-	  free (longnames);
-
 	  if (got == 0)
-	    return 0;
+	    {
+	      ret = 0;
+	      goto out;
+	    }
 
 	  error (_("%s: failed to read archive header\n"), file_name);
+	  ret = 1;
+	  goto out;
+	}
+    }
+
+  if (do_archive_index)
+    {
+      /* Print index symbol from each object file.  */
+      printf(_("Index of archive %s:\n"), file_name);
+      current_pos = ftell (file);
+      i = l = 0;
+      while(i < index_num)
+	{
+	  index_array[i] = byte_get_big_endian ((unsigned char*)(index_array+i),
+						sizeof(unsigned int));
+	  if ((i == 0) || ((i>0) && (index_array[i] != index_array[i-1])))
+	    {
+	      if (fseek (file, index_array[i], SEEK_SET) != 0)
+		{
+		  error (_("%s: failed to seek to next file name\n"), file_name);
+		  ret = 1;
+		  goto out;
+		}
+	      got = fread(elf_name, 1, 16, file);
+	      if ( got != 16)
+		{
+		  error (_("%s: failed to read file name\n"), file_name);
+		  ret = 1;
+		  goto out;
+		}
+	      
+	      if (elf_name[0] == '/')
+		{
+		  /*long name*/
+		  k = j = strtoul(elf_name+1, NULL, 10);
+		  while ((j<longnames_size) && (longnames[j] != '/'))
+		    j++;
+		  longnames[j] = '\0';
+		  printf(_("Binary %s contains:\n"), longnames+k);
+		  longnames[j] = '/';
+		}
+	      else
+		{
+		  j = 0;
+		  while ((elf_name[j] != '/') && (j < 16))
+		    j++;
+		  elf_name[j] = '\0';
+		  printf(_("Binary %s contains:\n"), elf_name);
+		}
+	    }
+	  printf ("\t%s\n", sym_table+l);
+	  while ((l < sym_size) && (sym_table[l] != '\0'))
+	    l++;
+	  l++;
+	  i++;
+	}
+      free (index_array);
+      index_array = NULL;
+      free (sym_table);
+      sym_table = NULL;
+      if (fseek (file, current_pos, SEEK_SET) != 0)
+	{
+	  error (_("%s: failed to seek back to object file\n"), file_name);
 	  return 1;
 	}
     }
 
+
+  if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
+      && !do_segments && !do_header && !do_dump && !do_version
+      && !do_histogram && !do_debugging && !do_arch && !do_notes
+      && !do_section_groups)
+    return 0; /* Archive index only.  */
+
   file_name_size = strlen (file_name);
   ret = 0;
 
@@ -9933,7 +10070,12 @@ process_archive (char *file_name, FILE *
 	}
     }
 
-  if (longnames != 0)
+ out:
+  if (index_array != NULL)
+    free (index_array);
+  if (sym_table != NULL)
+    free (sym_table);
+  if (longnames != NULL)
     free (longnames);
 
   return ret;
@@ -9981,6 +10123,11 @@ process_file (char *file_name)
     ret = process_archive (file_name, file);
   else
     {
+      if (do_archive_index)
+	{
+	  error(_("File %s is not an archive so its index cannot be displayed.\n"),
+		file_name);
+	}
       rewind (file);
       archive_file_size = archive_file_offset = 0;
       ret = process_object (file_name, file);
Index: binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.114
diff -u -r1.114 binutils.texi
--- binutils.texi	30 Aug 2007 13:47:35 -0000	1.114
+++ binutils.texi	12 Sep 2007 10:01:38 -0000
@@ -3586,6 +3586,7 @@
 @smallexample
 @c man begin SYNOPSIS readelf
 readelf [@option{-a}|@option{--all}]
+        [@option{-c}|@option{--archive-index}]
         [@option{-h}|@option{--file-header}]
         [@option{-l}|@option{--program-headers}|@option{--segments}]
         [@option{-S}|@option{--section-headers}|@option{--sections}]
@@ -3641,6 +3642,12 @@
 @option{--relocs}, @option{--dynamic}, @option{--notes} and
 @option{--version-info}.
 
+@item -c
+@itemx --archive-index
+@cindex Archive file symbol index information
+Displays the archive file symbol index infomation contained in the 
+archive header.
+
 @item -h
 @itemx --file-header
 @cindex ELF file header information

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]