]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ar and foreign object files
authorAlan Modra <amodra@gmail.com>
Sun, 5 Jan 2025 11:14:06 +0000 (21:44 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 6 Jan 2025 03:39:32 +0000 (14:09 +1030)
ar is supposed to make archives containing any sort of file, and it
generally does that.  It also tries to make archives suited to target
object files stored.  Some targets have peculiar archives.

In one particular case we get into trouble trying to suit archives to
object files: where the target object file is recognised but that
target doesn't happen to support archives, and the default target has
a special archive format.  For example, we'll get failures on
rs6000-aix if trying to add tekhex objects to a new archive.  What
happens in that the tekhex object is recognised and its target vector
used to create an empty archive, ie. with _bfd_generic_mkarchive and
_bfd_write_archive_contents.  An attempt is then made to open the
newly created archive.  The tekhex target vector does not have a
check_format function to recognise generic archives, nor as it happens
do any of the xcoff or other targets built for rs6000-aix.

It seems to me the simplest fix is to not use any target vector to
create archives where that vector can't also recognise them.  That's
what this patch does, and to reinforce that I've removed target vector
support for creating empty archives from such targets.

bfd/
* i386msdos.c (i386_msdos_vec): Remove support for creating
empty archives.
* ihex.c (ihex_vec): Likewise.
* srec.c (srec_vec, symbolsrec_vec): Likewise.
* tekhex.c (tekhex_vec): Likewise.
* wasm-module.c (wasm_vec): Likewise.
* ptrace-core.c (core_ptrace_vec): Tidy.
* targets.c (bfd_target_supports_archives): New inline function.
* bfd-in2.h: Regenerate.
binutils/
* ar.c (open_inarch): Don't select a target from the first
object file that can't read archives.  Set output_filename
earlier.
* testsuite/binutils-all/ar.exp (thin_archive_with_nested):
Don't repeat --thin test using T.
(foreign_object): New test.
* testsuite/binutils-all/tek1.obj,
* testsuite/binutils-all/tek2.obj: New files.

12 files changed:
bfd/bfd-in2.h
bfd/i386msdos.c
bfd/ihex.c
bfd/ptrace-core.c
bfd/srec.c
bfd/targets.c
bfd/tekhex.c
bfd/wasm-module.c
binutils/ar.c
binutils/testsuite/binutils-all/ar.exp
binutils/testsuite/binutils-all/tek1.obj [new file with mode: 0644]
binutils/testsuite/binutils-all/tek2.obj [new file with mode: 0644]

index 511d2665ef5eb7d6f314243616b384c70b3da92f..3a5a6dd8a5f4bb1d7f941501c5697d2c6b1f780a 100644 (file)
@@ -8020,6 +8020,13 @@ bfd_keep_unused_section_symbols (const bfd *abfd)
   return abfd->xvec->keep_unused_section_symbols;
 }
 
+static inline bool
+bfd_target_supports_archives (const bfd *abfd)
+{
+  return (abfd->xvec->_bfd_check_format[bfd_archive]
+         != abfd->xvec->_bfd_check_format[bfd_unknown]);
+}
+
 bool bfd_set_default_target (const char *name);
 
 const bfd_target *bfd_find_target (const char *target_name, bfd *abfd);
index 6ac3dcf9a8cfe2fbc072b60cba204ccc040412ec..ba58f0feabcd06b9f6a7d7c564b6454d8dacc380 100644 (file)
@@ -295,13 +295,13 @@ const bfd_target i386_msdos_vec =
     {
       _bfd_bool_bfd_false_error,
       msdos_mkobject,
-      _bfd_generic_mkarchive,
+      _bfd_bool_bfd_false_error,
       _bfd_bool_bfd_false_error,
     },
     {                          /* bfd_write_contents */
       _bfd_bool_bfd_false_error,
       msdos_write_object_contents,
-      _bfd_write_archive_contents,
+      _bfd_bool_bfd_false_error,
       _bfd_bool_bfd_false_error,
     },
 
index ce958bf6f3335095c69c89606fdf278726937cbb..96559749b9125fe9cd365eb5e44cd03d4f62bdae 100644 (file)
@@ -997,13 +997,13 @@ const bfd_target ihex_vec =
   {
     _bfd_bool_bfd_false_error,
     ihex_mkobject,
-    _bfd_generic_mkarchive,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
   {                            /* bfd_write_contents.  */
     _bfd_bool_bfd_false_error,
     ihex_write_object_contents,
-    _bfd_write_archive_contents,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
 
index 54480eed5ef94fcbe5ded5ba9886f659e15165d3..1d44f9f5d021680e1b14440a7ef41fa420cd48ab 100644 (file)
@@ -194,12 +194,16 @@ const bfd_target core_ptrace_vec =
       ptrace_unix_core_file_p          /* a core file */
     },
     {                          /* bfd_set_format */
-      _bfd_bool_bfd_false_error, bfd_false,
-      _bfd_bool_bfd_false_error, bfd_false
+      _bfd_bool_bfd_false_error,
+      _bfd_bool_bfd_false_error,
+      _bfd_bool_bfd_false_error,
+      _bfd_bool_bfd_false_error,
     },
     {                          /* bfd_write_contents */
-      _bfd_bool_bfd_false_error, bfd_false,
-      _bfd_bool_bfd_false_error, bfd_false
+      _bfd_bool_bfd_false_error,
+      _bfd_bool_bfd_false_error,
+      _bfd_bool_bfd_false_error,
+      _bfd_bool_bfd_false_error,
     },
 
     BFD_JUMP_TABLE_GENERIC (_bfd_generic),
index cef87c3bea115fc190d016ef9f0bc6c44eac7968..e1d39e521fc7d9324672c719b966b32dddd645ab 100644 (file)
@@ -1307,13 +1307,13 @@ const bfd_target srec_vec =
   {
     _bfd_bool_bfd_false_error,
     srec_mkobject,
-    _bfd_generic_mkarchive,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
   {                            /* bfd_write_contents.  */
     _bfd_bool_bfd_false_error,
     srec_write_object_contents,
-    _bfd_write_archive_contents,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
 
@@ -1364,13 +1364,13 @@ const bfd_target symbolsrec_vec =
   {
     _bfd_bool_bfd_false_error,
     srec_mkobject,
-    _bfd_generic_mkarchive,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
   {                            /* bfd_write_contents.  */
     _bfd_bool_bfd_false_error,
     symbolsrec_write_object_contents,
-    _bfd_write_archive_contents,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
 
index a6848c805528df5d84694187dd4f809e0ef32faa..18f5782daf773fb5e484e747554f7118cb34e12c 100644 (file)
@@ -667,6 +667,13 @@ to find an alternative output format that is suitable.
 .  return abfd->xvec->keep_unused_section_symbols;
 .}
 .
+.static inline bool
+.bfd_target_supports_archives (const bfd *abfd)
+.{
+.  return (abfd->xvec->_bfd_check_format[bfd_archive]
+.         != abfd->xvec->_bfd_check_format[bfd_unknown]);
+.}
+.
 */
 
 /* All known xvecs (even those that don't compile on all systems).
index 1498b0a6b106409f0520bd787e580c30285affc3..01feeef8d4c49b1e5f9fd11128406a60db9479a0 100644 (file)
@@ -1012,13 +1012,13 @@ const bfd_target tekhex_vec =
   {
     _bfd_bool_bfd_false_error,
     tekhex_mkobject,
-    _bfd_generic_mkarchive,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
   {                            /* bfd_write_contents.  */
     _bfd_bool_bfd_false_error,
     tekhex_write_object_contents,
-    _bfd_write_archive_contents,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
 
index f3750860f1a9714e30c67397d7e03ffdbc05ab99..d5d186e07c8b71aae22741f25093a4f6841a6e13 100644 (file)
@@ -823,13 +823,13 @@ const bfd_target wasm_vec =
   {
     _bfd_bool_bfd_false_error,
     wasm_mkobject,
-    _bfd_generic_mkarchive,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
   {                            /* bfd_write_contents.  */
     _bfd_bool_bfd_false_error,
     wasm_write_object_contents,
-    _bfd_write_archive_contents,
+    _bfd_bool_bfd_false_error,
     _bfd_bool_bfd_false_error,
   },
 
index 3ad675c7bb4a2febe5a2788a645cb61f5c3e022c..40cad576b46c37da75872d0b9adfaa8db850d36b 100644 (file)
@@ -1006,12 +1006,16 @@ open_inarch (const char *archive_filename, const char *file)
          obj = bfd_openr (file, target);
          if (obj != NULL)
            {
-             if (bfd_check_format (obj, bfd_object))
+             if (bfd_check_format (obj, bfd_object)
+                 && bfd_target_supports_archives (obj))
                target = bfd_get_target (obj);
              (void) bfd_close (obj);
            }
        }
 
+      /* If we die creating a new archive, don't leave it around.  */
+      output_filename = xstrdup (archive_filename);
+
       /* Create an empty archive.  */
       arch = bfd_openw (archive_filename, target);
       if (arch == NULL
@@ -1020,9 +1024,6 @@ open_inarch (const char *archive_filename, const char *file)
        bfd_fatal (archive_filename);
       else if (!silent_create)
         non_fatal (_("creating %s"), archive_filename);
-
-      /* If we die creating a new archive, don't leave it around.  */
-      output_filename = xstrdup (archive_filename);
     }
 
   arch = bfd_openr (archive_filename, target);
index 8d346e4c6bd84310045a14f9bfb5542f255b18ac..d06fe90c8c5e20312ed547859c28138e302d251e 100644 (file)
@@ -309,13 +309,11 @@ proc thin_archive_with_nested { bfdtests } {
     if [is_remote host] {
        set archive artest.a
        set archive2 artest2.a
-       set archive3 artest3.a
        set objfile [remote_download host tmpdir/bintest.${obj}]
        remote_file host delete $archive
     } else {
        set archive tmpdir/artest.a
        set archive2 tmpdir/artest2.a
-       set archive3 tmpdir/artest3.a
        set objfile tmpdir/bintest.${obj}
     }
 
@@ -329,15 +327,7 @@ proc thin_archive_with_nested { bfdtests } {
 
     remote_file build delete tmpdir/artest2.a
 
-    set got [binutils_run $AR "rcT $archive2 ${archive}"]
-    if ![string match "" $got] {
-       fail $testname
-       return
-    }
-
-    remote_file build delete tmpdir/artest3.a
-
-    set got [binutils_run $AR "rc --thin $archive3 ${archive}"]
+    set got [binutils_run $AR "rc --thin $archive2 ${archive}"]
     if ![string match "" $got] {
        fail $testname
        return
@@ -357,13 +347,6 @@ proc thin_archive_with_nested { bfdtests } {
            fail "$testname ($bfdtest)"
            return
        }
-
-       set exec_output [binutils_run "$base_dir/$bfdtest" "$archive3"]
-       if ![string match "" $exec_output] {
-           verbose -log $exec_output
-           fail "$testname ($bfdtest)"
-           return
-       }
     }
 
     set got [binutils_run $NM "--print-armap $archive"]
@@ -994,6 +977,54 @@ __.LIBDEP*" $got] {
     pass $testname
 }
 
+# Test creation of an archive containing object files not of the same
+# format as the target object files.
+
+proc foreign_object { } {
+    global AR
+    global NM
+    global srcdir
+    global subdir
+
+    set testname "ar foreign object"
+
+    set object1 $srcdir/$subdir/tek1.obj
+    set object2 $srcdir/$subdir/tek2.obj
+    if [is_remote host] {
+       set archive artest.a
+       set object1 [remote_download host $object1]
+       set object2 [remote_download host $object2]
+       remote_file host delete $archive
+    } else {
+       set archive tmpdir/artest.a
+    }
+
+    remote_file build delete tmpdir/artest.a
+
+    set got [binutils_run $AR "rc $archive $object1 $object2"]
+    if ![string match {} $got] {
+       fail $testname
+       return
+    }
+
+    set got [binutils_run $NM $archive]
+    if ![string match {
+tek1.obj:
+*: no symbols
+
+tek2.obj:
+00000001 D _binary_x_end
+00000001 A _binary_x_size
+00000000 D _binary_x_start
+} $got] {
+       fail $testname
+       return
+    }
+
+    pass $testname
+}
+
+
 # Run the tests.
 
 # Only run the bfdtest checks if the programs exist.  Since these
@@ -1030,3 +1061,5 @@ test_add_dependencies
 if { [is_elf_format] && [supports_gnu_unique] } {
     unique_symbol
 }
+
+foreign_object
diff --git a/binutils/testsuite/binutils-all/tek1.obj b/binutils/testsuite/binutils-all/tek1.obj
new file mode 100644 (file)
index 0000000..7f828c5
--- /dev/null
@@ -0,0 +1,2 @@
+%47615103000000000000000000000000000000000000000000000000000000000000000
+%0781010
diff --git a/binutils/testsuite/binutils-all/tek2.obj b/binutils/testsuite/binutils-all/tek2.obj
new file mode 100644 (file)
index 0000000..da696d1
--- /dev/null
@@ -0,0 +1,6 @@
+%47615103000000000000000000000000000000000000000000000000000000000000000
+%103E95.data11011
+%1E3FB5.data4F_binary_x_start10
+%1C3735.data4D_binary_x_end11
+%1D3135*ABS*2E_binary_x_size11
+%0781010