bfd: Close the file descriptor if there is no archive fd
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 26 Jul 2021 12:59:55 +0000 (05:59 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 28 Jul 2021 13:01:32 +0000 (06:01 -0700)
Close the file descriptor if there is no archive plugin file descriptor
to avoid running out of file descriptors on thin archives with many
archive members.

bfd/

PR ld/28138
* plugin.c (bfd_plugin_close_file_descriptor): Close the file
descriptor there is no archive plugin file descriptor.

ld/

PR ld/28138
* testsuite/ld-plugin/lto.exp: Run ld/28138 tests.
* testsuite/ld-plugin/pr28138.c: New file.
* testsuite/ld-plugin/pr28138-1.c: Likewise.
* testsuite/ld-plugin/pr28138-2.c: Likewise.
* testsuite/ld-plugin/pr28138-3.c: Likewise.
* testsuite/ld-plugin/pr28138-4.c: Likewise.
* testsuite/ld-plugin/pr28138-5.c: Likewise.
* testsuite/ld-plugin/pr28138-6.c: Likewise.
* testsuite/ld-plugin/pr28138-7.c: Likewise.

bfd/plugin.c
ld/testsuite/ld-plugin/lto.exp
ld/testsuite/ld-plugin/pr28138-1.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr28138-2.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr28138-3.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr28138-4.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr28138-5.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr28138-6.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr28138-7.c [new file with mode: 0644]
ld/testsuite/ld-plugin/pr28138.c [new file with mode: 0644]

index 6cfa2b6647041772a3492f996c01f93c3ba19aa0..3bab8febe88209a35f9d0369f0d1a36981433dab 100644 (file)
@@ -291,6 +291,14 @@ bfd_plugin_close_file_descriptor (bfd *abfd, int fd)
             && !bfd_is_thin_archive (abfd->my_archive))
        abfd = abfd->my_archive;
 
+      /* Close the file descriptor if there is no archive plugin file
+        descriptor.  */
+      if (abfd->archive_plugin_fd == -1)
+       {
+         close (fd);
+         return;
+       }
+
       abfd->archive_plugin_fd_open_count--;
       /* Dup the archive plugin file descriptor for later use, which
         will be closed by _bfd_archive_close_and_cleanup.  */
index def69e43ab3060907a02fbc0df7b0f929daa0e8d..63be062032b1031f5a0404705c16dcd9590feb7c 100644 (file)
@@ -930,4 +930,34 @@ if { [check_lto_fat_available] } {
     }
 }
 
+run_cc_link_tests [list \
+    [list \
+       "Build pr28138.a" \
+       "-T" "" \
+       {pr28138-1.c pr28138-2.c pr28138-3.c pr28138-4.c pr28138-5.c \
+        pr28138-6.c pr28138-7.c} {} "pr28138.a" \
+    ] \
+    [list \
+       "Build pr28138.o" \
+       "" "" \
+       {pr28138.c} {} \
+    ] \
+]
+
+set exec_output [run_host_cmd "sh" \
+                             "-c \"ulimit -n 20; \
+                             $CC -Btmpdir/ld -o tmpdir/pr28138 \
+                             tmpdir/pr28138.o tmpdir/pr28138.a\""]
+set exec_output [prune_warnings $exec_output]
+if [string match "" $exec_output] then {
+    set exec_output [run_host_cmd "tmpdir/pr28138" ""]
+    if [string match "PASS" $exec_output] then {
+       pass "PR ld/28138"
+    } else {
+       fail "PR ld/28138"
+    }
+} else {
+    fail "PR ld/28138"
+}
+
 restore_notify
diff --git a/ld/testsuite/ld-plugin/pr28138-1.c b/ld/testsuite/ld-plugin/pr28138-1.c
new file mode 100644 (file)
index 0000000..51d119e
--- /dev/null
@@ -0,0 +1,6 @@
+extern int a0(void);
+int
+a1(void)
+{
+  return 1 + a0();
+}
diff --git a/ld/testsuite/ld-plugin/pr28138-2.c b/ld/testsuite/ld-plugin/pr28138-2.c
new file mode 100644 (file)
index 0000000..1120cd7
--- /dev/null
@@ -0,0 +1,6 @@
+extern int a1(void);
+int
+a2(void)
+{
+  return 1 + a1();
+}
diff --git a/ld/testsuite/ld-plugin/pr28138-3.c b/ld/testsuite/ld-plugin/pr28138-3.c
new file mode 100644 (file)
index 0000000..ec46494
--- /dev/null
@@ -0,0 +1,6 @@
+extern int a2(void);
+int
+a3(void)
+{
+  return 1 + a2();
+}
diff --git a/ld/testsuite/ld-plugin/pr28138-4.c b/ld/testsuite/ld-plugin/pr28138-4.c
new file mode 100644 (file)
index 0000000..475701b
--- /dev/null
@@ -0,0 +1,6 @@
+extern int a3(void);
+int
+a4(void)
+{
+  return 1 + a3();
+}
diff --git a/ld/testsuite/ld-plugin/pr28138-5.c b/ld/testsuite/ld-plugin/pr28138-5.c
new file mode 100644 (file)
index 0000000..e24f86c
--- /dev/null
@@ -0,0 +1,6 @@
+extern int a4(void);
+int
+a5(void)
+{
+  return 1 + a4();
+}
diff --git a/ld/testsuite/ld-plugin/pr28138-6.c b/ld/testsuite/ld-plugin/pr28138-6.c
new file mode 100644 (file)
index 0000000..b5b938b
--- /dev/null
@@ -0,0 +1,6 @@
+extern int a5(void);
+int
+a6(void)
+{
+  return 1 + a5();
+}
diff --git a/ld/testsuite/ld-plugin/pr28138-7.c b/ld/testsuite/ld-plugin/pr28138-7.c
new file mode 100644 (file)
index 0000000..4ef75bf
--- /dev/null
@@ -0,0 +1,6 @@
+extern int a6(void);
+int
+a7(void)
+{
+  return 1 + a6();
+}
diff --git a/ld/testsuite/ld-plugin/pr28138.c b/ld/testsuite/ld-plugin/pr28138.c
new file mode 100644 (file)
index 0000000..68252c9
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+extern int a7(void);
+
+int
+a0(void)
+{
+  return 0;
+}
+
+int
+main()
+{
+  if (a7() == 7)
+    {
+      printf ("PASS\n");
+      return 0;
+    }
+  return 1;
+}