aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog22
-rw-r--r--binutils/Makefile.am2
-rw-r--r--binutils/Makefile.in10
-rw-r--r--binutils/NEWS2
-rw-r--r--binutils/doc/Makefile.in4
-rw-r--r--binutils/doc/binutils.texi7
-rw-r--r--binutils/readelf.c180
-rw-r--r--binutils/testsuite/ChangeLog5
-rw-r--r--binutils/testsuite/binutils-all/dumptest.s2
-rw-r--r--binutils/testsuite/binutils-all/readelf.exp66
10 files changed, 244 insertions, 56 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 430b954..0f6b075 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,25 @@
+2007-08-30 Nick Clifton <nickc@redhat.com>
+
+ * readelf.c (dump_type): New type used to classify the kinds of
+ dump requested by the user.
+ (dump_sects, cmdline_dump_sects): Use the new type.
+ (options): Add --string-dump option.
+ (request_dump): Rename to request_dump_bynumber. Use dump_type.
+ (request_dump_byname): Use dump_type.
+ (parse_args): Parse --string-dump option.
+ (process_section_headers): Fix calls to request_dump.
+ (initialise_dumps_byname): Likewise.
+ (dump_section): Rename to dump_section_as_bytes.
+ (dump_section_as_strings): New function. Display the contents of
+ a section as printable strings.
+ (process_section_contents): String dump the section if requested.
+ (process_object): Use dump_type.
+ (main): Likewise.
+ * Makefile.am: Add dependency for readelf.c on safe-ctype.h.
+ * Makefile.in: Regenerate.
+ * NEWS: Mention the new feature.
+ * doc/binutils.texi: Document the new feature.
+
2007-08-30 Nathan Sidwell <nathan@codesourcery.com>
* bucomm.c (bfd_nonfatal_message): New.
diff --git a/binutils/Makefile.am b/binutils/Makefile.am
index 047622c..9590b18 100644
--- a/binutils/Makefile.am
+++ b/binutils/Makefile.am
@@ -593,7 +593,7 @@ readelf.o: readelf.c sysdep.h $(INCDIR)/ansidecl.h \
$(INCDIR)/elf/spu.h $(INCDIR)/elf/v850.h $(INCDIR)/elf/vax.h \
$(INCDIR)/elf/x86-64.h $(INCDIR)/elf/xstormy16.h $(INCDIR)/elf/xtensa.h \
$(INCDIR)/aout/ar.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
- unwind-ia64.h
+ unwind-ia64.h $(INCDIR)/safe-ctype.h
rename.o: rename.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h bucomm.h
diff --git a/binutils/Makefile.in b/binutils/Makefile.in
index eead9ef..e0fc8f3 100644
--- a/binutils/Makefile.in
+++ b/binutils/Makefile.in
@@ -532,15 +532,15 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- echo ' cd $(srcdir) && $(AUTOMAKE) --cygnus '; \
- cd $(srcdir) && $(AUTOMAKE) --cygnus \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
&& exit 0; \
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
cd $(top_srcdir) && \
- $(AUTOMAKE) --cygnus Makefile
+ $(AUTOMAKE) --foreign Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -1343,7 +1343,7 @@ readelf.o: readelf.c sysdep.h $(INCDIR)/ansidecl.h \
$(INCDIR)/elf/spu.h $(INCDIR)/elf/v850.h $(INCDIR)/elf/vax.h \
$(INCDIR)/elf/x86-64.h $(INCDIR)/elf/xstormy16.h $(INCDIR)/elf/xtensa.h \
$(INCDIR)/aout/ar.h $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
- unwind-ia64.h
+ unwind-ia64.h $(INCDIR)/safe-ctype.h
rename.o: rename.c sysdep.h $(INCDIR)/ansidecl.h ../bfd/bfdver.h \
config.h $(INCDIR)/fopen-same.h ../bfd/bfd.h $(INCDIR)/ansidecl.h \
$(INCDIR)/symcat.h bucomm.h
diff --git a/binutils/NEWS b/binutils/NEWS
index 20070d7..0009c6f 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,4 +1,6 @@
-*- text -*-
+* Added -p switch to readelf to allow string dumps of sections.
+
Changes in 2.18:
* Resolved 37 coding problems in bfd including static array overruns, null
pointer dereferences and use of a malloc buffer after it has been freed, as
diff --git a/binutils/doc/Makefile.in b/binutils/doc/Makefile.in
index d258024..8136d2a 100644
--- a/binutils/doc/Makefile.in
+++ b/binutils/doc/Makefile.in
@@ -282,9 +282,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --cygnus doc/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
cd $(top_srcdir) && \
- $(AUTOMAKE) --cygnus doc/Makefile
+ $(AUTOMAKE) --foreign doc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 52787f7..a2768bf 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -3601,6 +3601,7 @@ readelf [@option{-a}|@option{--all}]
[@option{-A}|@option{--arch-specific}]
[@option{-D}|@option{--use-dynamic}]
[@option{-x} <number or name>|@option{--hex-dump=}<number or name>]
+ [@option{-p} <number or name>|@option{--string-dump=}<number or name>]
[@option{-w[liaprmfFsoR]}|
@option{--debug-dump}[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]]
[@option{-I}|@option{-histogram}]
@@ -3726,6 +3727,12 @@ Displays the contents of the indicated section as a hexadecimal dump.
A number identifies a particular section by index in the section table;
any other string identifies all sections with that name in the object file.
+@item -p <number or name>
+@itemx --string-dump=<number or name>
+Displays the contents of the indicated section as printable strings.
+A number identifies a particular section by index in the section table;
+any other string identifies all sections with that name in the object file.
+
@item -w[liaprmfFsoR]
@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]
Displays the contents of the debug sections in the file, if any are
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 9fc8e0c..e166dca 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -158,6 +158,7 @@
#include "getopt.h"
#include "libiberty.h"
+#include "safe-ctype.h"
char *program_name = "readelf";
static long archive_file_offset;
@@ -219,33 +220,37 @@ static size_t group_count;
static struct group *section_groups;
static struct group **section_headers_groups;
-/* A linked list of the section names for which dumps were requested
- by name. */
+
+/* Flag bits indicating particular types of dump. */
+#define HEX_DUMP (1 << 0) /* The -x command line switch. */
+#define DISASS_DUMP (1 << 1) /* The -i command line switch. */
+#define DEBUG_DUMP (1 << 2) /* The -w command line switch. */
+#define STRING_DUMP (1 << 3) /* The -p command line switch. */
+
+typedef unsigned char dump_type;
+
+/* A linked list of the section names for which dumps were requested. */
struct dump_list_entry
{
char *name;
- int type;
+ dump_type type;
struct dump_list_entry *next;
};
static struct dump_list_entry *dump_sects_byname;
-/* A dynamic array of flags indicating for which sections a hex dump
- has been requested (via the -x switch) and/or a disassembly dump
- (via the -i switch). */
-char *cmdline_dump_sects = NULL;
-unsigned num_cmdline_dump_sects = 0;
+/* A dynamic array of flags indicating for which sections a dump
+ has been requested via command line switches. */
+static dump_type * cmdline_dump_sects = NULL;
+static unsigned int num_cmdline_dump_sects = 0;
/* A dynamic array of flags indicating for which sections a dump of
some kind has been requested. It is reset on a per-object file
basis and then initialised from the cmdline_dump_sects array,
the results of interpreting the -w switch, and the
dump_sects_byname list. */
-char *dump_sects = NULL;
-unsigned int num_dump_sects = 0;
+static dump_type * dump_sects = NULL;
+static unsigned int num_dump_sects = 0;
-#define HEX_DUMP (1 << 0)
-#define DISASS_DUMP (1 << 1)
-#define DEBUG_DUMP (1 << 2)
/* How to print a vma value. */
typedef enum print_mode
@@ -2745,9 +2750,10 @@ static struct option options[] =
{"arch-specific", no_argument, 0, 'A'},
{"version-info", no_argument, 0, 'V'},
{"use-dynamic", no_argument, 0, 'D'},
+ {"unwind", no_argument, 0, 'u'},
{"hex-dump", required_argument, 0, 'x'},
{"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP},
- {"unwind", no_argument, 0, 'u'},
+ {"string-dump", required_argument, 0, 'p'},
#ifdef SUPPORT_DISASSEMBLY
{"instruction-dump", required_argument, 0, 'i'},
#endif
@@ -2782,14 +2788,17 @@ usage (FILE *stream)
-V --version-info Display the version sections (if present)\n\
-A --arch-specific Display architecture specific information (if any).\n\
-D --use-dynamic Use the dynamic section info when displaying symbols\n\
- -x --hex-dump=<number> Dump the contents of section <number>\n\
+ -x --hex-dump=<number|name>\n\
+ Dump the contents of section <number|name> as bytes\n\
+ -p --string-dump=<number|name>\n\
+ Dump the contents of section <number|name> as strings\n\
-w[liaprmfFsoR] or\n\
--debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
Display the contents of DWARF2 debug sections\n"));
#ifdef SUPPORT_DISASSEMBLY
fprintf (stream, _("\
- -i --instruction-dump=<number>\n\
- Disassemble the contents of section <number>\n"));
+ -i --instruction-dump=<number|name>\n\
+ Disassemble the contents of section <number|name>\n"));
#endif
fprintf (stream, _("\
-I --histogram Display histogram of bucket list lengths\n\
@@ -2810,20 +2819,20 @@ usage (FILE *stream)
the first time. */
static void
-request_dump (unsigned int section, int type)
+request_dump_bynumber (unsigned int section, dump_type type)
{
if (section >= num_dump_sects)
{
- char *new_dump_sects;
+ dump_type *new_dump_sects;
- new_dump_sects = calloc (section + 1, 1);
+ new_dump_sects = calloc (section + 1, sizeof (* dump_sects));
if (new_dump_sects == NULL)
error (_("Out of memory allocating dump request table.\n"));
else
{
/* Copy current flag settings. */
- memcpy (new_dump_sects, dump_sects, num_dump_sects);
+ memcpy (new_dump_sects, dump_sects, num_dump_sects * sizeof (* dump_sects));
free (dump_sects);
@@ -2841,7 +2850,7 @@ request_dump (unsigned int section, int type)
/* Request a dump by section name. */
static void
-request_dump_byname (const char *section, int type)
+request_dump_byname (const char *section, dump_type type)
{
struct dump_list_entry *new_request;
@@ -2868,7 +2877,7 @@ parse_args (int argc, char **argv)
usage (stderr);
while ((c = getopt_long
- (argc, argv, "ersuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
+ (argc, argv, "ersuahnldSDAINtgw::x:i:vVWHp:", options, NULL)) != EOF)
{
char *cp;
int section;
@@ -2946,10 +2955,18 @@ parse_args (int argc, char **argv)
do_dump++;
section = strtoul (optarg, & cp, 0);
if (! *cp && section >= 0)
- request_dump (section, HEX_DUMP);
+ request_dump_bynumber (section, HEX_DUMP);
else
request_dump_byname (optarg, HEX_DUMP);
break;
+ case 'p':
+ do_dump++;
+ section = strtoul (optarg, & cp, 0);
+ if (! *cp && section >= 0)
+ request_dump_bynumber (section, STRING_DUMP);
+ else
+ request_dump_byname (optarg, STRING_DUMP);
+ break;
case 'w':
do_dump++;
if (optarg == 0)
@@ -3097,11 +3114,9 @@ parse_args (int argc, char **argv)
do_dump++;
section = strtoul (optarg, & cp, 0);
if (! *cp && section >= 0)
- {
- request_dump (section, DISASS_DUMP);
- break;
- }
- goto oops;
+ request_dump_bynumber (section, DISASS_DUMP);
+ else
+ request_dump_byname (optarg, DISASS_DUMP);
#endif
case 'v':
print_version (program_name);
@@ -3113,9 +3128,6 @@ parse_args (int argc, char **argv)
do_wide++;
break;
default:
-#ifdef SUPPORT_DISASSEMBLY
- oops:
-#endif
/* xgettext:c-format */
error (_("Invalid option '-%c'\n"), c);
/* Drop through. */
@@ -4182,14 +4194,14 @@ process_section_headers (FILE *file)
|| (do_debug_str && streq (name, "str"))
|| (do_debug_loc && streq (name, "loc"))
)
- request_dump (i, DEBUG_DUMP);
+ request_dump_bynumber (i, DEBUG_DUMP);
}
/* linkonce section to be combined with .debug_info at link time. */
else if ((do_debugging || do_debug_info)
&& const_strneq (name, ".gnu.linkonce.wi."))
- request_dump (i, DEBUG_DUMP);
+ request_dump_bynumber (i, DEBUG_DUMP);
else if (do_debug_frames && streq (name, ".eh_frame"))
- request_dump (i, DEBUG_DUMP);
+ request_dump_bynumber (i, DEBUG_DUMP);
}
if (! do_sections)
@@ -7670,7 +7682,84 @@ disassemble_section (Elf_Internal_Shdr *section, FILE *file)
#endif
static int
-dump_section (Elf_Internal_Shdr *section, FILE *file)
+dump_section_as_strings (Elf_Internal_Shdr *section, FILE *file)
+{
+ Elf_Internal_Shdr *relsec;
+ bfd_size_type num_bytes;
+ bfd_vma addr;
+ char *data;
+ char *end;
+ char *start;
+ char *name = SECTION_NAME (section);
+ bfd_boolean some_strings_shown;
+
+ num_bytes = section->sh_size;
+
+ if (num_bytes == 0 || section->sh_type == SHT_NOBITS)
+ {
+ printf (_("\nSection '%s' has no data to dump.\n"), name);
+ return 0;
+ }
+
+ addr = section->sh_addr;
+
+ start = get_data (NULL, file, section->sh_offset, 1, num_bytes,
+ _("section data"));
+ if (!start)
+ return 0;
+
+ printf (_("\nString dump of section '%s':\n"), name);
+
+ /* If the section being dumped has relocations against it the user might
+ be expecting these relocations to have been applied. Check for this
+ case and issue a warning message in order to avoid confusion.
+ FIXME: Maybe we ought to have an option that dumps a section with
+ relocs applied ? */
+ for (relsec = section_headers;
+ relsec < section_headers + elf_header.e_shnum;
+ ++relsec)
+ {
+ if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
+ || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
+ || SECTION_HEADER (relsec->sh_info) != section
+ || relsec->sh_size == 0
+ || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
+ continue;
+
+ printf (_(" Note: This section has relocations against it, but these have NOT been applied to this dump.\n"));
+ break;
+ }
+
+ data = start;
+ end = start + num_bytes;
+ some_strings_shown = FALSE;
+
+ while (data < end)
+ {
+ while (!ISPRINT (* data))
+ if (++ data >= end)
+ break;
+
+ if (data < end)
+ {
+ printf (" [%6zx] %s\n", data - start, data);
+ data += strlen (data);
+ some_strings_shown = TRUE;
+ }
+ }
+
+ if (! some_strings_shown)
+ printf (_(" No strings found in this section."));
+
+ free (start);
+
+ putchar ('\n');
+ return 1;
+}
+
+
+static int
+dump_section_as_bytes (Elf_Internal_Shdr *section, FILE *file)
{
Elf_Internal_Shdr *relsec;
bfd_size_type bytes;
@@ -8023,7 +8112,7 @@ initialise_dumps_byname (void)
for (i = 0, any = 0; i < elf_header.e_shnum; i++)
if (streq (SECTION_NAME (section_headers + i), cur->name))
{
- request_dump (i, cur->type);
+ request_dump_bynumber (i, cur->type);
any = 1;
}
@@ -8053,10 +8142,13 @@ process_section_contents (FILE *file)
disassemble_section (section, file);
#endif
if (dump_sects[i] & HEX_DUMP)
- dump_section (section, file);
+ dump_section_as_bytes (section, file);
if (dump_sects[i] & DEBUG_DUMP)
display_debug_section (section, file);
+
+ if (dump_sects[i] & STRING_DUMP)
+ dump_section_as_strings (section, file);
}
/* Check to see if the user requested a
@@ -9554,16 +9646,17 @@ process_object (char *file_name, FILE *file)
must make sure that the dump_sets array is zeroed out before each
object file is processed. */
if (num_dump_sects > num_cmdline_dump_sects)
- memset (dump_sects, 0, num_dump_sects);
+ memset (dump_sects, 0, num_dump_sects * sizeof (* dump_sects));
if (num_cmdline_dump_sects > 0)
{
if (num_dump_sects == 0)
/* A sneaky way of allocating the dump_sects array. */
- request_dump (num_cmdline_dump_sects, 0);
+ request_dump_bynumber (num_cmdline_dump_sects, 0);
assert (num_dump_sects >= num_cmdline_dump_sects);
- memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects);
+ memcpy (dump_sects, cmdline_dump_sects,
+ num_cmdline_dump_sects * sizeof (* dump_sects));
}
if (! process_file_header ())
@@ -9938,12 +10031,13 @@ main (int argc, char **argv)
if (num_dump_sects > 0)
{
/* Make a copy of the dump_sects array. */
- cmdline_dump_sects = malloc (num_dump_sects);
+ cmdline_dump_sects = malloc (num_dump_sects * sizeof (* dump_sects));
if (cmdline_dump_sects == NULL)
error (_("Out of memory allocating dump request table.\n"));
else
{
- memcpy (cmdline_dump_sects, dump_sects, num_dump_sects);
+ memcpy (cmdline_dump_sects, dump_sects,
+ num_dump_sects * sizeof (* dump_sects));
num_cmdline_dump_sects = num_dump_sects;
}
}
diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog
index c1fcd3c..82292aa 100644
--- a/binutils/testsuite/ChangeLog
+++ b/binutils/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2007-08-30 Nick Clifton <nickc@redhat.com>
+
+ * binutils-all/dumptest.s: New test file.
+ * binutils-all/readelf.exp: Add test of readelf's -p switch.
+
2007-08-28 Mark Shinwell <shinwell@codesourcery.com>
Joseph Myers <joseph@codesourcery.com>
diff --git a/binutils/testsuite/binutils-all/dumptest.s b/binutils/testsuite/binutils-all/dumptest.s
new file mode 100644
index 0000000..6335d22
--- /dev/null
+++ b/binutils/testsuite/binutils-all/dumptest.s
@@ -0,0 +1,2 @@
+ .data
+ .ascii "test_string"
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index d8ba1c0..52be1ee 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -21,6 +21,12 @@
# Based on scripts written by Ian Lance Taylor <ian@cygnus.com>
# and Ken Raeburn <raeburn@cygnus.com>.
+# Exclude non-ELF targets.
+if ![is_elf_format] {
+ verbose "$READELF is only intended for ELF targets" 2
+ return
+}
+
# First some helpful procedures, then the tests themselves
# Return the contents of the filename given
@@ -203,10 +209,58 @@ proc readelf_wi_test {} {
}
-# Exclude non-ELF targets.
-if ![is_elf_format] {
- verbose "$READELF is only intended for ELF targets" 2
- return
+# Test readelf's dumping abilities.
+
+proc readelf_dump_test {} {
+ global READELF
+ global READELFFLAGS
+ global srcdir
+ global subdir
+
+ # Assemble the dump test file.
+ if {![binutils_assemble $srcdir/$subdir/dumptest.s tmpdir/dumptest.o]} then {
+ unresolved "readelf -p: failed to assemble dump test file"
+ return
+ }
+ # Download it.
+ set tempfile [remote_download host tmpdir/dumptest.o]
+
+ # Run "readelf -p.data" on it.
+ set got [remote_exec host "$READELF $READELFFLAGS -p.data $tempfile" "" "/dev/null" "readelf.out"]
+ set got [lindex $got 1]
+
+ # Upload the results.
+ set output [remote_upload host readelf.out]
+
+ # Check for something going wrong.
+ if ![string match "" $got] then {
+ fail "readelf -p: unexpected output"
+ send_log $got
+ send_log "\n"
+ return
+ }
+
+ # Search for strings that should be in the output.
+ set sought {
+ ".*test_string.*"
+ }
+
+ foreach looked_for $sought {
+ set lines [grep $output $looked_for]
+ if ![llength $lines] then {
+ fail "readelf -p: missing: $looked_for"
+ send_log readelf.out
+ return
+ }
+ }
+
+ file_on_host delete $tempfile
+ file_on_host delete $output
+
+ # All done.
+ pass "readelf -p"
+
+ # XXX FIXME: Add test of readelf -x here
}
if ![is_remote host] {
@@ -220,7 +274,7 @@ send_user "Version [binutil_version $READELF]"
# Assemble the test file.
if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
- perror "unresolved 1"
+ perror "could not assemble test file"
unresolved "readelf - failed to assemble"
return
}
@@ -241,3 +295,5 @@ readelf_test -s $tempfile readelf.ss {}
readelf_test -r $tempfile readelf.r {}
readelf_wi_test
+
+readelf_dump_test