[PATCH] objcopy: add option to specify custom symbol name for binary input

Alon Bar-Lev alon.barlev@gmail.com
Sat Oct 25 00:37:44 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:

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

It allows specifying an explicit symbol name, 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                                |  7 ++-
 binutils/doc/binutils.texi                  | 15 ++++++
 binutils/objcopy.c                          | 23 ++++++---
 binutils/testsuite/binutils-all/objcopy.exp | 56 +++++++++++++++++++++
 6 files changed, 124 insertions(+), 7 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 5e7c6ddf1ee..313d0b66def 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 *filename_symbol;
+
   /* 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_filename_symbol (const bfd *abfd)
+{
+  return abfd->filename_symbol;
+}
+
+static inline void
+bfd_set_filename_symbol (bfd *abfd, const char * const val)
+{
+  abfd->filename_symbol = val;
+}
+
 static inline bool
 bfd_get_cacheable (const bfd *abfd)
 {
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 858ab5ce017..8a00113a147 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 *filename_symbol;
+.
 .  {* 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_filename_symbol (const bfd *abfd)
+.{
+.  return abfd->filename_symbol;
+.}
+.
+.static inline void
+.bfd_set_filename_symbol (bfd *abfd, const char * const val)
+.{
+.  abfd->filename_symbol = val;
+.}
+.
 .static inline bool
 .bfd_get_cacheable (const bfd *abfd)
 .{
diff --git a/bfd/binary.c b/bfd/binary.c
index 7fe47b590de..ec88f6ae71b 100644
--- a/bfd/binary.c
+++ b/bfd/binary.c
@@ -122,6 +122,7 @@ static char *
 mangle_name (bfd *abfd, char *suffix)
 {
   bfd_size_type size;
+  const char *symbol;
   char *buf;
   char *p;
 
@@ -133,7 +134,11 @@ mangle_name (bfd *abfd, char *suffix)
   if (buf == NULL)
     return "";
 
-  sprintf (buf, "_binary_%s_%s", bfd_get_filename (abfd), suffix);
+  symbol = bfd_get_filename_symbol (abfd);
+  if (symbol == NULL)
+    symbol = bfd_get_filename (abfd);
+
+  sprintf (buf, "_binary_%s_%s", symbol, 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..5af914399a3 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{--input-symbol}@var{symbolname}]
         [@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 --input-symbol=@var{symbolname}
+When used with @option{--input-target=binary}, sets @var{symbolname} as the
+base name for the symbols generated for the input file.  These symbols are:
+
+@example
+_binary_@var{symbolname}_start
+_binary_@var{symbolname}_end
+_binary_@var{symbolname}_size
+@end example
+
+By default, the binary input handler derives the base symbol name from a
+mangled version of the input file name.  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..3b912563c71 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'},
+  {"input-symbol", 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,8 @@ 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\
+     --input-symbol <name>         Use <name> 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 +3862,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 *input_symbol,
+	   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 +3896,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
       status = 1;
       return;
     }
+  bfd_set_filename_symbol(ibfd, input_symbol);
 
   switch (do_debug_sections)
     {
@@ -5093,7 +5099,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 +5347,7 @@ static int
 copy_main (int argc, char *argv[])
 {
   char *input_filename = NULL;
+  char *input_symbol = NULL;
   char *output_filename = NULL;
   char *tmpname;
   char *input_target = NULL;
@@ -5395,6 +5402,10 @@ copy_main (int argc, char *argv[])
 	  input_target = optarg;
 	  break;
 
+	case OPTION_INPUT_SYMBOL:
+	  input_symbol = optarg;
+	  break;
+
 	case 'O':
 	case 'd':		/* "destination" - 'O' is preferred */
 	  output_target = optarg;
@@ -6197,8 +6208,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, input_symbol, 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..d30fb199aca 100644
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -1602,3 +1602,59 @@ proc objcopy_tek2bin {} {
 }
 
 objcopy_tek2bin
+
+# Test input symbol default behavior
+
+proc input_symbol_default { } {
+    global OBJCOPY
+    global NM
+    global NMFLAGS
+    global srcdir
+    global subdir
+
+    set test "input symbol (default)"
+
+    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} $srcdir/$subdir/version.s $out"]
+
+    set exec_output [binutils_run $NM "-a $NMFLAGS $out"]
+    set exec_output [prune_warnings $exec_output]
+    if ![string match "*binary_*_version_s_*" $exec_output] {
+	fail $test
+	return
+    }
+
+    pass $test
+}
+
+input_symbol_default
+
+# Test explicit input symbol
+
+proc input_symbol_explicit { } {
+    global OBJCOPY
+    global NM
+    global NMFLAGS
+    global srcdir
+    global subdir
+
+    set test "input symbol (explicit)"
+
+    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} --input-symbol symbol1 $srcdir/$subdir/version.s $out"]
+
+    set exec_output [binutils_run $NM "-a $NMFLAGS $out"]
+    set exec_output [prune_warnings $exec_output]
+    if ![string match "*binary_*_symbol1_*" $exec_output] {
+	fail $test
+	return
+    }
+
+    pass $test
+}
+
+input_symbol_explicit
-- 
2.43.0



More information about the Binutils mailing list