This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Patch] readelf -c dump archive index like nm -s
- From: Shen Feng <shen at cn dot fujitsu dot com>
- To: binutils at sourceware dot org
- Date: Tue, 28 Aug 2007 13:15:57 +0800
- Subject: [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,