This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 3/3] binutils: read from stdin if input file is -
- From: Ahmad Fatoum <ahmad at a3f dot at>
- To: binutils at sourceware dot org
- Cc: Ahmad Fatoum <ahmad at a3f dot at>
- Date: Sun, 25 Feb 2018 02:23:08 +0100
- Subject: [PATCH 3/3] binutils: read from stdin if input file is -
- Authentication-results: sourceware.org; auth=none
- References: <20180225012308.47820-1-ahmad@a3f.at>
This changes the behavior of:
dlltool, nlmconv, nm, objcopy, objdump and size
Opening files named - now requires prefixing ./ or similar.
---
binutils/NEWS | 3 ++
binutils/dlltool.c | 9 ++++-
binutils/doc/binutils.texi | 36 +++++++++++-------
binutils/nlmconv.c | 5 ++-
binutils/nm.c | 14 +++++--
binutils/objcopy.c | 38 +++++++++++++++----
binutils/objdump.c | 10 ++++-
binutils/size.c | 10 ++++-
binutils/testsuite/binutils-all/nm.exp | 57 +++++++++++++++++------------
binutils/testsuite/binutils-all/objcopy.exp | 13 ++++++-
binutils/testsuite/binutils-all/objdump.exp | 8 +++-
binutils/testsuite/binutils-all/size.exp | 45 ++++++++++++++---------
binutils/testsuite/config/default.exp | 4 +-
binutils/testsuite/lib/utils-lib.exp | 5 ++-
14 files changed, 176 insertions(+), 81 deletions(-)
diff --git a/binutils/NEWS b/binutils/NEWS
index c0fa05f25e..eb9abc18f1 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Add ability to read from standard input if input file is `-' in dlltool,
+ nlmconv, nm, objcopy, objdump and size.
+
Changes in 2.30:
* Add --debug-dump=links option to readelf and --dwarf=links option to objdump
diff --git a/binutils/dlltool.c b/binutils/dlltool.c
index 189907a0b0..37d244e0e7 100644
--- a/binutils/dlltool.c
+++ b/binutils/dlltool.c
@@ -1679,7 +1679,14 @@ scan_open_obj_file (bfd *abfd)
static void
scan_obj_file (const char *filename)
{
- bfd * f = bfd_openr (filename, 0);
+ bfd *f;
+ const char *filename_bfd = filename;
+ if (strcmp (filename_bfd, "-") == 0)
+ {
+ filename_bfd = NULL;
+ filename = "<stdin>";
+ }
+ f = bfd_openr (filename_bfd, 0);
if (!f)
/* xgettext:c-format */
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index caf7f9d37d..dc4b72bdc3 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -776,8 +776,9 @@ nm [@option{-A}|@option{-o}|@option{--print-file-name}] [@option{-a}|@option{--d
@c man begin DESCRIPTION nm
@sc{gnu} @command{nm} lists the symbols from object files @var{objfile}@dots{}.
-If no object files are listed as arguments, @command{nm} assumes the file
-@file{a.out}.
+If an @var{objfile} is a single dash (`-'), @command{nm} reads from the
+standard input. If no object files are listed as arguments, @command{nm}
+assumes the file @file{a.out}.
For each symbol, @command{nm} shows:
@@ -1248,9 +1249,11 @@ same endianness or which have no endianness (e.g., @samp{srec}).
@item @var{infile}
@itemx @var{outfile}
The input and output files, respectively.
+If @var{infile} is a single dash (`-'), @command{objcopy} reads from the
+standard input.
If you do not specify @var{outfile}, @command{objcopy} creates a
temporary file and destructively renames the result with
-the name of @var{infile}.
+the name of @var{infile}, unless @var{infile} is `-'.
@item -I @var{bfdname}
@itemx --input-target=@var{bfdname}
@@ -2107,9 +2110,10 @@ information is mostly useful to programmers who are working on the
compilation tools, as opposed to programmers who just want their
program to compile and work.
-@var{objfile}@dots{} are the object files to be examined. When you
-specify archives, @command{objdump} shows information on each of the member
-object files.
+@var{objfile}@dots{} are the object files to be examined. If an @var{objfile}
+is a single dash (`-'), @command{objdump} reads from the standard input.
+When you specify archives, @command{objdump} shows information on each of the
+member object files.
@c man end
@@ -2836,8 +2840,9 @@ size [@option{-A}|@option{-B}|@option{--format=}@var{compatibility}]
The @sc{gnu} @command{size} utility lists the section sizes---and the total
size---for each of the object or archive files @var{objfile} in its
-argument list. By default, one line of output is generated for each
-object file or each module in an archive.
+argument list. If an @var{objfile} is a single dash (`-'), @command{size}
+reads from the standard input. By default, one line of output is generated
+for each object file or each module in an archive.
@var{objfile}@dots{} are the object files to be examined.
If none are specified, the file @code{a.out} will be used.
@@ -3734,11 +3739,12 @@ nlmconv [@option{-I} @var{bfdname}|@option{--input-target=}@var{bfdname}]
@command{nlmconv} converts the relocatable @samp{i386} object file
@var{infile} into the NetWare Loadable Module @var{outfile}, optionally
-reading @var{headerfile} for NLM header information. For instructions
-on writing the NLM command file language used in header files, see the
-@samp{linkers} section, @samp{NLMLINK} in particular, of the @cite{NLM
-Development and Tools Overview}, which is part of the NLM Software
-Developer's Kit (``NLM SDK''), available from Novell, Inc.
+reading @var{headerfile} for NLM header information. If @var{infile} is
+a single dash (`-'), @command{nlmconv} reads from the standard input.
+For instructions on writing the NLM command file language used in header
+files, see the @samp{linkers} section, @samp{NLMLINK} in particular,
+of the @cite{NLM Development and Tools Overview}, which is part of the
+NLM Software Developer's Kit (``NLM SDK''), available from Novell, Inc.
@command{nlmconv} uses the @sc{gnu} Binary File Descriptor library to read
@var{infile};
@ifclear man
@@ -4214,7 +4220,9 @@ dlltool [@option{-d}|@option{--input-def} @var{def-file-name}]
@command{dlltool} reads its inputs, which can come from the @option{-d} and
@option{-b} options as well as object files specified on the command
-line. It then processes these inputs and if the @option{-e} option has
+line. If the @var{object-file} is a single dash (`-'), @command{dlltool}
+reads from the standard input.
+It then processes these inputs and if the @option{-e} option has
been specified it creates a exports file. If the @option{-l} option
has been specified it creates a library file and if the @option{-z} option
has been specified it creates a def file. Any or all of the @option{-e},
diff --git a/binutils/nlmconv.c b/binutils/nlmconv.c
index 68941f80d0..ad9f04d1dd 100644
--- a/binutils/nlmconv.c
+++ b/binutils/nlmconv.c
@@ -199,6 +199,7 @@ main (int argc, char **argv)
int len;
char *modname;
char **matching;
+ bfd_boolean read_stdin = FALSE;
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
setlocale (LC_MESSAGES, "");
@@ -261,6 +262,8 @@ main (int argc, char **argv)
{
input_file = argv[optind];
++optind;
+ if (strcmp (input_file, "-") == 0)
+ read_stdin = TRUE;
if (optind < argc)
{
output_file = argv[optind];
@@ -329,7 +332,7 @@ main (int argc, char **argv)
show_usage (stderr, 1);
}
- inbfd = bfd_openr (input_file, input_format);
+ inbfd = bfd_openr (read_stdin ? NULL : input_file, input_format);
if (inbfd == NULL)
bfd_fatal (input_file);
diff --git a/binutils/nm.c b/binutils/nm.c
index 696eb7817e..77739a42f7 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -1299,11 +1299,19 @@ display_file (char *filename)
bfd_boolean retval = TRUE;
bfd *file;
char **matching;
+ const char *filename_bfd = filename;
- if (get_file_size (filename) < 1)
- return FALSE;
+ if (strcmp (filename_bfd, "-") == 0)
+ {
+ filename_bfd= NULL;
+ filename = "<stdin>";
+ }
+ else if (get_file_size (filename) < 1)
+ {
+ return FALSE;
+ }
- file = bfd_openr (filename, target ? target : plugin_target);
+ file = bfd_openr (filename_bfd, target ? target : plugin_target);
if (file == NULL)
{
bfd_nonfatal (filename);
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 8cdf27a87e..a7e5405646 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -3420,9 +3420,15 @@ copy_file (const char *input_filename, const char *output_filename,
bfd *ibfd;
char **obj_matching;
char **core_matching;
- off_t size = get_file_size (input_filename);
+ off_t size;
+ const char *filename_bfd = input_filename;
- if (size < 1)
+ if (strcmp (filename_bfd, "-") == 0)
+ {
+ filename_bfd = NULL;
+ input_filename = "<stdin>";
+ }
+ else if ((size = get_file_size (input_filename)) < 1)
{
if (size == 0)
non_fatal (_("error: the input file '%s' is empty"),
@@ -3433,7 +3439,7 @@ copy_file (const char *input_filename, const char *output_filename,
/* To allow us to do "strip *" without dying on the first
non-object file, failures are nonfatal. */
- ibfd = bfd_openr (input_filename, input_target);
+ ibfd = bfd_openr (filename_bfd, input_target);
if (ibfd == NULL)
{
bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
@@ -4685,6 +4691,7 @@ copy_main (int argc, char *argv[])
bfd_boolean show_version = FALSE;
bfd_boolean change_warn = TRUE;
bfd_boolean formats_info = FALSE;
+ bfd_boolean read_stdin = FALSE;
int c;
struct stat statbuf;
const bfd_arch_info_type *input_arch = NULL;
@@ -5393,6 +5400,8 @@ copy_main (int argc, char *argv[])
copy_usage (stderr, 1);
input_filename = argv[optind];
+ if (strcmp (input_filename, "-") == 0)
+ read_stdin = TRUE;
if (optind + 1 < argc)
output_filename = argv[optind + 1];
@@ -5459,9 +5468,13 @@ copy_main (int argc, char *argv[])
}
if (preserve_dates)
- if (stat (input_filename, & statbuf) < 0)
- fatal (_("warning: could not locate '%s'. System error message: %s"),
- input_filename, strerror (errno));
+ {
+ if (read_stdin)
+ fatal (_("warning: can't preserve date of input: <stdin>"));
+ if (stat (input_filename, & statbuf) < 0)
+ fatal (_("warning: could not locate '%s'. System error message: %s"),
+ input_filename, strerror (errno));
+ }
/* If there is no destination file, or the source and destination files
are the same, then create a temp and rename the result into the input. */
@@ -5481,8 +5494,17 @@ copy_main (int argc, char *argv[])
if (preserve_dates)
set_times (tmpname, &statbuf);
if (tmpname != output_filename)
- status = (smart_rename (tmpname, input_filename,
- preserve_dates) != 0);
+ {
+ if (read_stdin)
+ {
+ /* Might be nifty to dump the object to stdout if no destination file was
+ * specified. This requires ensuring nothing else writes to stdout though */
+ unlink_if_ordinary (tmpname);
+ fatal (_("error: source file <stdin> can't be reused as destination file"));
+ }
+
+ status = (smart_rename (tmpname, input_filename, preserve_dates) != 0);
+ }
}
else
unlink_if_ordinary (tmpname);
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 37a9f0d2e1..f3797e420b 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -3758,14 +3758,20 @@ static void
display_file (char *filename, char *target, bfd_boolean last_file)
{
bfd *file;
+ const char *filename_bfd = filename;
- if (get_file_size (filename) < 1)
+ if (strcmp (filename_bfd, "-") == 0)
+ {
+ filename_bfd = NULL;
+ filename = "<stdin>";
+ }
+ else if (get_file_size (filename) < 1)
{
exit_status = 1;
return;
}
- file = bfd_openr (filename, target);
+ file = bfd_openr (filename_bfd, target);
if (file == NULL)
{
nonfatal (filename);
diff --git a/binutils/size.c b/binutils/size.c
index 47f14fce33..82080d8bee 100644
--- a/binutils/size.c
+++ b/binutils/size.c
@@ -385,14 +385,20 @@ static void
display_file (char *filename)
{
bfd *file;
+ const char *filename_bfd = filename;
- if (get_file_size (filename) < 1)
+ if (strcmp (filename_bfd, "-") == 0)
+ {
+ filename_bfd = NULL;
+ filename = "<stdin>";
+ }
+ else if (get_file_size (filename) < 1)
{
return_code = 1;
return;
}
- file = bfd_openr (filename, target);
+ file = bfd_openr (filename_bfd, target);
if (file == NULL)
{
bfd_nonfatal (filename);
diff --git a/binutils/testsuite/binutils-all/nm.exp b/binutils/testsuite/binutils-all/nm.exp
index f8779c18f6..9c465acbf0 100644
--- a/binutils/testsuite/binutils-all/nm.exp
+++ b/binutils/testsuite/binutils-all/nm.exp
@@ -29,6 +29,35 @@ if ![is_remote host] {
send_user "Version [binutil_version $NM]"
+proc test_nm { testfile args } {
+ global NM
+ global NMFLAGS
+
+ set got [binutils_run $NM "$NMFLAGS $testfile" $args]
+
+ if [info exists vars] then { unset vars }
+ while {[regexp "(\[a-zA-Z\]) (\[a-z_\]*_symbol)(.*)" $got all type symbol rest]} {
+ set vars($symbol) $type
+ set got $rest
+ }
+
+ if {![info exists vars(text_symbol)] \
+ || $vars(text_symbol) != "T" \
+ || ![info exists vars(data_symbol)] \
+ || $vars(data_symbol) != "D" \
+ || ![info exists vars(common_symbol)] \
+ || $vars(common_symbol) != "C" \
+ || ![info exists vars(external_symbol)] \
+ || $vars(external_symbol) != "U" \
+ || ![info exists vars(static_text_symbol)] \
+ || $vars(static_text_symbol) != "t" \
+ || ![info exists vars(static_data_symbol)] \
+ || $vars(static_data_symbol) != "d"} {
+ fail "nm (no arguments) $testfile"
+ } else {
+ pass "nm (no arguments) $testfile"
+ }
+}
if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
fail "nm (assembling)"
@@ -41,6 +70,10 @@ if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
}
# Test nm with no arguments.
+ test_nm $tempfile
+
+ # Test nm with no arguments, but reading from stdin
+ test_nm "-" $tempfile
# This test does not work correctly on ECOFF targets, because ECOFF
# stores most symbols twice, which messes up the nm output.
@@ -52,30 +85,6 @@ if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
# does not enter static symbols in the symbol table.
setup_xfail "*-*-aix*"
- set got [binutils_run $NM "$NMFLAGS $tempfile"]
-
- if [info exists vars] then { unset vars }
- while {[regexp "(\[a-zA-Z\]) (\[a-z_\]*_symbol)(.*)" $got all type symbol rest]} {
- set vars($symbol) $type
- set got $rest
- }
-
- if {![info exists vars(text_symbol)] \
- || $vars(text_symbol) != "T" \
- || ![info exists vars(data_symbol)] \
- || $vars(data_symbol) != "D" \
- || ![info exists vars(common_symbol)] \
- || $vars(common_symbol) != "C" \
- || ![info exists vars(external_symbol)] \
- || $vars(external_symbol) != "U" \
- || ![info exists vars(static_text_symbol)] \
- || $vars(static_text_symbol) != "t" \
- || ![info exists vars(static_data_symbol)] \
- || $vars(static_data_symbol) != "d"} {
- fail "nm (no arguments)"
- } else {
- pass "nm (no arguments)"
- }
# Test nm -g
diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp
index f4a7692cdf..27dbf96e3e 100644
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -38,7 +38,7 @@ if ![is_remote host] {
# Test that objcopy does not modify a file when copying it.
-proc objcopy_test {testname srcfile} {
+proc objcopy_test {testname srcfile args} {
global OBJCOPY
global OBJCOPYFLAGS
global srcdir
@@ -46,13 +46,21 @@ proc objcopy_test {testname srcfile} {
global tempfile
global copyfile
+ if { [llength $args] == 0 } {
+ set objcopyfile "$tempfile"
+ set stdin ""
+ } else {
+ set objcopyfile "-"
+ set stdin "$tempfile"
+ }
+
if {![binutils_assemble $srcdir/$subdir/${srcfile} $tempfile]} then {
unresolved "objcopy ($testname)"
remote_file host delete $tempfile
return
}
- set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS $tempfile ${copyfile}.o"]
+ set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS $objcopyfile ${copyfile}.o" $stdin]
if ![string equal "" $got] then {
fail "objcopy ($testname)"
@@ -106,6 +114,7 @@ proc objcopy_test {testname srcfile} {
}
objcopy_test "simple copy" bintest.s
+objcopy_test "simple copy from stdin" bintest.s "use stdin"
if { [file exists $tempfile] } {
# Test reversing bytes in a section.
diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp
index f006d64f10..bf1b0d3391 100644
--- a/binutils/testsuite/binutils-all/objdump.exp
+++ b/binutils/testsuite/binutils-all/objdump.exp
@@ -93,12 +93,12 @@ if { ![istarget "alpha-*-*"] || [is_elf_format] } then {
# Test objdump -f
-proc test_objdump_f { testfile dumpfile } {
+proc test_objdump_f { testfile dumpfile args} {
global OBJDUMP
global OBJDUMPFLAGS
global cpus_regex
- set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $testfile"]
+ set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $testfile" $args]
set want "$dumpfile:\[ \]*file format.*architecture:\[ \]*${cpus_regex}.*HAS_RELOC.*HAS_SYMS"
@@ -114,6 +114,10 @@ if { [ remote_file host exists $testarchive ] } then {
test_objdump_f $testarchive bintest2.o
}
+# Test objdump -f -
+
+test_objdump_f "-" "<stdin>" $testfile
+
# Test objdump -h
proc test_objdump_h { testfile dumpfile } {
diff --git a/binutils/testsuite/binutils-all/size.exp b/binutils/testsuite/binutils-all/size.exp
index 185872d341..00d1646601 100644
--- a/binutils/testsuite/binutils-all/size.exp
+++ b/binutils/testsuite/binutils-all/size.exp
@@ -29,25 +29,18 @@ if ![is_remote host] {
send_user "Version [binutil_version $SIZE]"
+set dec "\[0-9\]+"
+set hex "\[0-9a-fA-F\]+"
-if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
- fail "size (assembling)"
-} else {
+proc test_size { testfile displayfile args} {
+ global SIZE
+ global SIZEFLAGS
+ global dec
+ global hex
- if [is_remote host] {
- set testfile [remote_download host tmpdir/bintest.o]
- } else {
- set testfile tmpdir/bintest.o
- }
-
- set dec "\[0-9\]+"
- set hex "\[0-9a-fA-F\]+"
-
- # Test size with no arguments
-
- set got [binutils_run $SIZE "$SIZEFLAGS $testfile"]
+ set got [binutils_run $SIZE "$SIZEFLAGS $testfile" $args]
- set want "($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($hex)\[ \]+${testfile}"
+ set want "($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($hex)\[ \]+${displayfile}"
if ![regexp $want $got all text data bss dtot hextot] then {
fail "size (no arguments)"
@@ -56,11 +49,27 @@ if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
# The z80-coff port defaults to a "binary" like output
# file format which does not include a data section.
setup_xfail "z80-*-coff"
- fail "size (no arguments)"
+ fail "size (no arguments) $displayfile"
} else {
- pass "size (no arguments)"
+ pass "size (no arguments) $displayfile"
}
}
+}
+
+if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
+ fail "size (assembling)"
+} else {
+ if [is_remote host] {
+ set testfile [remote_download host tmpdir/bintest.o]
+ } else {
+ set testfile tmpdir/bintest.o
+ }
+
+ # Test size with no arguments
+ test_size $testfile $testfile
+
+ # Test size with no arguments, but reading from stdin
+ test_size "-" "<stdin>" $testfile
# Test size -A
diff --git a/binutils/testsuite/config/default.exp b/binutils/testsuite/config/default.exp
index c5acd46e8f..fbde02fafd 100644
--- a/binutils/testsuite/config/default.exp
+++ b/binutils/testsuite/config/default.exp
@@ -114,8 +114,8 @@ if {[file isfile tmpdir/gas/as[exe_ext]]} then {
# sets binutils_run_failed if the program does not exist
# sets binutils_run_status to the exit status of the program
#
-proc binutils_run { prog progargs } {
- default_binutils_run $prog $progargs
+proc binutils_run { prog progargs args } {
+ default_binutils_run $prog $progargs {*}$args
}
#
diff --git a/binutils/testsuite/lib/utils-lib.exp b/binutils/testsuite/lib/utils-lib.exp
index cb1211204e..63ba9b5e70 100644
--- a/binutils/testsuite/lib/utils-lib.exp
+++ b/binutils/testsuite/lib/utils-lib.exp
@@ -53,7 +53,7 @@ proc binutil_version { prog } {
# sets binutils_run_failed if the program does not exist
# sets binutils_run_status to the exit status of the program
#
-proc default_binutils_run { prog progargs } {
+proc default_binutils_run { prog progargs args } {
global binutils_run_failed
global binutils_run_status
global host_triplet
@@ -87,7 +87,8 @@ proc default_binutils_run { prog progargs } {
# shell otherwise.
regsub -all "\\$" "$progargs" "\\$" progargs
- set state [remote_exec host $prog $progargs]
+ set state [remote_exec host $prog $progargs {*}$args]
+
set binutils_run_status [lindex $state 0]
set exec_output [prune_warnings [lindex $state 1]]
if {![string match "" $exec_output]} then {
--
2.16.1