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]

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


Hi,

I made a patch which makes readelf -c dump archive index like nm -s.
The following is the changelog and the patch.

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_index): New.
	(process_archive): Call process_archive_index.

Patch

--- readelf.old.c	2007-08-28 12:49:32.000000000 +0800
+++ readelf.c	2007-08-28 12:54:09.000000000 +0800
@@ -201,6 +201,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
@@ -2727,6 +2728,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'},
@@ -2765,6 +2767,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\
@@ -2868,7 +2871,7 @@ parse_args (int argc, char **argv)
     usage (stderr);

   while ((c = getopt_long
-	  (argc, argv, "ersuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
+	  (argc, argv, "ersuachnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
     {
       char *cp;
       int section;
@@ -2895,6 +2898,10 @@ parse_args (int argc, char **argv)
 	  do_histogram++;
 	  do_arch++;
 	  do_notes++;
+	  do_archive_index++;
+	  break;
+	case 'c':
+	  do_archive_index++;
 	  break;
 	case 'g':
 	  do_section_groups++;
@@ -3127,7 +3134,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)
     {
@@ -9673,6 +9680,140 @@ process_object (char *file_name, FILE *f
   return 0;
 }

+static int
+process_archive_index (char *file_name, FILE *file, char *long_names,
+		       unsigned long longnames_size)
+{
+  struct ar_hdr arhdr;
+  unsigned long size;
+  size_t got;
+  unsigned int index_num;
+  unsigned int *index_array;
+  unsigned int i, j, k, l;
+  char elf_name[16];
+  char *sym_table;
+
+  /*move to the archive index header*/
+  if (fseek (file, SARMAG, SEEK_SET) != 0)
+    {
+      error (_("%s: failed to seek to archive header\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 (memcmp (arhdr.ar_name, "/               ", 16) == 0)
+    {
+      /* We have the archive index table. */
+      size = strtoul (arhdr.ar_size, NULL, 10);
+      printf (_("Archive index:\n"));
+      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);
+	  free (index_array);
+	  return 1;
+	}
+
+      size -= sizeof(unsigned int) * index_num;
+      sym_table = (char*)malloc (size);
+      if (sym_table == NULL)
+	{
+	  error (_("Out of memory\n"));
+	  free (index_array);
+	  return 1;
+	}
+      got = fread (sym_table, 1, size, file);
+      if (got != size)
+	{
+	  error (_("%s: failed to read archive index symbol table\n"), file_name);
+	  free (index_array);
+	  free (sym_table);
+	  return 1;
+	}
+
+      i = l = 0;
+      while(i < index_num)
+	{
+	  printf ("%s in ", sym_table+l);
+	  while ((l < size) && (sym_table[l] != '\0'))
+	    l++;
+	  l++;
+	
+	  index_array[i] = byte_get_big_endian ((unsigned char*)(index_array+i),
+						sizeof(unsigned int));
+	  if (fseek (file, index_array[i], SEEK_SET) != 0)
+	    {
+	      error (_("%s: failed to seek to next file name\n"), file_name);
+	      free (index_array);
+	      free (sym_table);
+	      return 1;
+	    }
+	  got = fread(elf_name, 1, 16, file);
+	  if ( got != 16)
+	    {
+	      error (_("%s: failed to read file name\n"), file_name);
+	      free (index_array);
+	      free (sym_table);
+	      return 1;
+	    }
+
+	  if (elf_name[0] == '/')
+	    {
+	      /*long name*/
+	      k = j = strtoul(elf_name+1, NULL, 10);
+	      while ((j<longnames_size) && (long_names[j] != '/'))
+		j++;
+	      long_names[j] = '\0';
+	      printf("%s\n", long_names+k);
+	      long_names[j] = '/';
+	    }
+	  else
+	    {
+	      j = 0;
+	      while ((elf_name[j] != '/') && (j < 16))
+		j++;
+	      elf_name[j] = '\0';
+	      printf("%s\n", elf_name);
+	
+	    }
+	  i++;
+	}
+      free (index_array);
+      free (sym_table);
+    }
+  else
+    {
+      printf(_("%s has no archive index\n"), file_name);
+    }
+
+    return 0;
+}
+
 /* Process an ELF archive.  The file is positioned just after the
    ARMAG string.  */

@@ -9681,7 +9822,7 @@ process_archive (char *file_name, FILE *
 {
   struct ar_hdr arhdr;
   size_t got;
-  unsigned long size;
+  unsigned long size, current_pos;
   char *longnames = NULL;
   unsigned long longnames_size = 0;
   size_t file_name_size;
@@ -9703,7 +9844,7 @@ process_archive (char *file_name, FILE *
       || const_strneq (arhdr.ar_name, "/SYM64/         "))
     {
       /* This is the archive symbol table.  Skip it.
-	 FIXME: We should have an option to dump it.  */
+	 We will dump in after long names is read.  */
       size = strtoul (arhdr.ar_size, NULL, 10);
       if (fseek (file, size + (size & 1), SEEK_CUR) != 0)
 	{
@@ -9758,6 +9899,31 @@ process_archive (char *file_name, FILE *
 	  return 1;
 	}
     }
+
+  if (do_archive_index)
+    {
+      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)
+	{
+	  /* archive index only*/
+	  return process_archive_index (file_name, file, longnames,
+					longnames_size);
+	}
+      else
+	{
+	  current_pos = ftell (file);
+	  if (process_archive_index (file_name, file, longnames,
+				     longnames_size) != 0)
+	    return 1;
+	  if( fseek (file, current_pos, SEEK_SET) != 0)
+	    {
+	      error (_("%s: failed to seek back\n"), file_name);
+	      return 1;
+	    }
+	}
+    }

   file_name_size = strlen (file_name);
   ret = 0;

-- 
Best Regards,



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