This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [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, nickc at redhat dot com
- Date: Wed, 12 Sep 2007 21:45:50 +0900
- Subject: 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