[PATCH v5] objcopy: add option to specify custom prefix for symbol of binary input

Alon Bar-Lev alon.barlev@gmail.com
Mon Oct 27 13:53:48 GMT 2025


When using --input-target=binary, objcopy currently derives symbol names
from a mangled version of the input file name.  This approach can lead to
unpredictable results, as the generated symbols depend on the file path and
working directory.

This patch introduces a new option:

  --binary-symbol-prefix <prefix> Use <prefix> as the base symbol name for
                                    the input file (default: derived from
                                    file name)

It allows specifying an explicit symbol prefix, while preserving the existing
behavior as a fallback.

Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
---
 bfd/bfd-in2.h                               | 15 +++++++++
 bfd/bfd.c                                   | 15 +++++++++
 bfd/binary.c                                | 18 +++++++---
 binutils/doc/binutils.texi                  | 15 +++++++++
 binutils/objcopy.c                          | 24 +++++++++----
 binutils/testsuite/binutils-all/objcopy.exp | 37 +++++++++++++++++++++
 6 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 5e7c6ddf1ee..7ceecda1d8c 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1949,6 +1949,9 @@ struct bfd
   /* The filename the application opened the BFD with.  */
   const char *filename;
 
+  /* The symbol name for the file or NULL.  */
+  const char *binary_symbol_prefix;
+
   /* A pointer to the target jump table.  */
   const struct bfd_target *xvec;
 
@@ -2293,6 +2296,18 @@ bfd_get_filename (const bfd *abfd)
   return abfd->filename;
 }
 
+static inline const char *
+bfd_get_binary_symbol_prefix (const bfd *abfd)
+{
+  return abfd->binary_symbol_prefix;
+}
+
+static inline void
+bfd_set_binary_symbol_prefix (bfd *abfd, const char * const val)
+{
+  abfd->binary_symbol_prefix = val;
+}
+
 static inline bool
 bfd_get_cacheable (const bfd *abfd)
 {
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 858ab5ce017..417a4225be2 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -105,6 +105,9 @@ CODE_FRAGMENT
 .  {* The filename the application opened the BFD with.  *}
 .  const char *filename;
 .
+.  {* The symbol name for the file or NULL.  *}
+.  const char *binary_symbol_prefix;
+.
 .  {* A pointer to the target jump table.  *}
 .  const struct bfd_target *xvec;
 .
@@ -452,6 +455,18 @@ EXTERNAL
 .  return abfd->filename;
 .}
 .
+.static inline const char *
+.bfd_get_binary_symbol_prefix (const bfd *abfd)
+.{
+.  return abfd->binary_symbol_prefix;
+.}
+.
+.static inline void
+.bfd_set_binary_symbol_prefix (bfd *abfd, const char * const val)
+.{
+.  abfd->binary_symbol_prefix = val;
+.}
+.
 .static inline bool
 .bfd_get_cacheable (const bfd *abfd)
 .{
diff --git a/bfd/binary.c b/bfd/binary.c
index 7fe47b590de..7d5ac46ed7e 100644
--- a/bfd/binary.c
+++ b/bfd/binary.c
@@ -122,18 +122,28 @@ static char *
 mangle_name (bfd *abfd, char *suffix)
 {
   bfd_size_type size;
+  const char *prefix;
+  const char *prefix_amend = "";
   char *buf;
   char *p;
 
-  size = (strlen (bfd_get_filename (abfd))
-	  + strlen (suffix)
-	  + sizeof "_binary__");
+  prefix = bfd_get_binary_symbol_prefix (abfd);
+  if (prefix == NULL)
+    {
+      prefix = "_binary_";
+      prefix_amend = bfd_get_filename (abfd);
+    }
+
+  size = strlen (prefix)
+	 + strlen (prefix_amend)
+	 + strlen (suffix)
+	 + 2;
 
   buf = (char *) bfd_alloc (abfd, size);
   if (buf == NULL)
     return "";
 
-  sprintf (buf, "_binary_%s_%s", bfd_get_filename (abfd), suffix);
+  sprintf (buf, "%s%s_%s", prefix, prefix_amend, suffix);
 
   /* Change any non-alphanumeric characters to underscores.  */
   for (p = buf; *p; p++)
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 89425b8a15b..c0a09a373f9 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -1315,6 +1315,7 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}]
         [@option{--keep-global-symbols=}@var{filename}]
         [@option{--localize-symbols=}@var{filename}]
         [@option{--weaken-symbols=}@var{filename}]
+        [@option{--binary-symbol-prefix}@var{string}]
         [@option{--add-symbol} @var{name}=[@var{section}:]@var{value}[,@var{flags}]]
         [@option{--alt-machine-code=}@var{index}]
         [@option{--prefix-symbols=}@var{string}]
@@ -1554,6 +1555,20 @@ given more than once.  Note - unique symbols are not converted.
 @itemx --weaken-symbol=@var{symbolname}
 Make symbol @var{symbolname} weak. This option may be given more than once.
 
+@item --binary-symbol-prefix=@var{string}
+When used with @option{--input-target=binary}, sets @var{string} as the
+base name for the symbols generated for the input file.  These symbols are:
+
+@example
+@var{string}_start
+@var{string}_end
+@var{string}_size
+@end example
+
+By default, the binary input handler derives the prefix symbol name from a
+mangled version of the input file name and _binary prefix.  This option
+allows specifying it explicitly.
+
 @item --globalize-symbol=@var{symbolname}
 Give symbol @var{symbolname} global scoping so that it is visible
 outside of the file in which it is defined.  This option may be given
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 9373b75d6ed..6613af01bab 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -334,6 +334,7 @@ enum command_line_switch
   OPTION_HEAP,
   OPTION_IMAGE_BASE,
   OPTION_IMPURE,
+  OPTION_INPUT_SYMBOL,
   OPTION_INTERLEAVE_WIDTH,
   OPTION_KEEPGLOBAL_SYMBOLS,
   OPTION_KEEP_FILE_SYMBOLS,
@@ -465,6 +466,7 @@ static struct option copy_options[] =
   {"info", no_argument, 0, OPTION_FORMATS_INFO},
   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
   {"input-target", required_argument, 0, 'I'},
+  {"binary-symbol-prefix", required_argument, 0, OPTION_INPUT_SYMBOL},
   {"interleave", optional_argument, 0, 'i'},
   {"interleave-width", required_argument, 0, OPTION_INTERLEAVE_WIDTH},
   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
@@ -678,6 +680,9 @@ copy_usage (FILE *stream, int exit_status)
      --globalize-symbols <file>    --globalize-symbol for all in <file>\n\
      --keep-global-symbols <file>  -G for all symbols listed in <file>\n\
      --weaken-symbols <file>       -W for all symbols listed in <file>\n\
+     --binary-symbol-prefix <prefix>\n\
+                                    Use <prefix> as the base symbol name for the input file\n\
+                                     (default: derived from file name)\n\
      --add-symbol <name>=[<section>:]<value>[,<flags>]  Add a symbol\n\
      --alt-machine-code <index>    Use the target's <index>'th alternative machine\n\
      --writable-text               Mark the output text as writable\n\
@@ -3858,9 +3863,10 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
 /* The top-level control.  */
 
 static void
-copy_file (const char *input_filename, const char *output_filename, int ofd,
-	   struct stat *in_stat, const char *input_target,
-	   const char *output_target, const bfd_arch_info_type *input_arch)
+copy_file (const char *input_filename, const char *binary_symbol_prefix,
+	   const char *output_filename, int ofd, struct stat *in_stat,
+	   const char *input_target, const char *output_target,
+	   const bfd_arch_info_type *input_arch)
 {
   bfd *ibfd;
   char **obj_matching;
@@ -3891,6 +3897,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
       status = 1;
       return;
     }
+  bfd_set_binary_symbol_prefix(ibfd, binary_symbol_prefix);
 
   switch (do_debug_sections)
     {
@@ -5093,7 +5100,7 @@ strip_main (int argc, char *argv[])
 	}
 
       status = 0;
-      copy_file (argv[i], tmpname, tmpfd, &statbuf, input_target,
+      copy_file (argv[i], NULL, tmpname, tmpfd, &statbuf, input_target,
 		 output_target, NULL);
       if (status == 0)
 	{
@@ -5341,6 +5348,7 @@ static int
 copy_main (int argc, char *argv[])
 {
   char *input_filename = NULL;
+  char *binary_symbol_prefix = NULL;
   char *output_filename = NULL;
   char *tmpname;
   char *input_target = NULL;
@@ -5395,6 +5403,10 @@ copy_main (int argc, char *argv[])
 	  input_target = optarg;
 	  break;
 
+	case OPTION_INPUT_SYMBOL:
+	  binary_symbol_prefix = optarg;
+	  break;
+
 	case 'O':
 	case 'd':		/* "destination" - 'O' is preferred */
 	  output_target = optarg;
@@ -6197,8 +6209,8 @@ copy_main (int argc, char *argv[])
 	     input_filename, strerror (errno));
     }
 
-  copy_file (input_filename, tmpname, tmpfd, &statbuf, input_target,
-	     output_target, input_arch);
+  copy_file (input_filename, binary_symbol_prefix, tmpname, tmpfd, &statbuf,
+	     input_target, output_target, input_arch);
   if (status == 0)
     {
       const char *oname = output_filename ? output_filename : input_filename;
diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp
index b11b17e012c..fc589b84e1e 100644
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -1602,3 +1602,40 @@ proc objcopy_tek2bin {} {
 }
 
 objcopy_tek2bin
+
+# Test input symbol
+
+proc input_symbol {name file args symbol} {
+    global OBJCOPY
+    global NM
+    global NMFLAGS
+
+    set test "input symbol ($name)"
+
+    # detect a valid target, take the first supported
+    set target [lindex [split [binutils_run $OBJCOPY "--info"] \n] 1]
+
+    set out tmpdir/input_symbol.o
+    set got [binutils_run $OBJCOPY "-I binary -O $target $args $file $out"]
+
+    set expected [list "${symbol}_end" "${symbol}_size" "${symbol}_start"]
+
+    set exec_output [binutils_run $NM "-a $NMFLAGS $out"]
+    set exec_output [prune_warnings $exec_output]
+    set actual {}
+    while {[regexp {^[0-9a-fA-F]+?[ ]+[TtDdA] ([0-9a-zA-Z_]+)[\r\n]+(.*)$} ${exec_output} all s rest]} {
+	set actual [concat $actual $s]
+	set exec_output $rest
+    }
+
+    if {[lsort $expected] ne [lsort $actual]} {
+	send_log "expected: $expected, actual: $actual\n"
+	fail $test
+	return
+    }
+
+    pass $test
+}
+
+input_symbol implicit $srcdir/$subdir/version.s "" _binary_[regsub -all {[^0-9a-zA-Z]} $srcdir/$subdir/version.s _]
+input_symbol explicit $srcdir/$subdir/version.s "--binary-symbol-prefix symbol1" symbol1
-- 
2.43.0



More information about the Binutils mailing list