[PATCH] ld: Issue an error for recursively included linker script
H.J. Lu
hjl.tools@gmail.com
Thu Aug 14 15:05:56 GMT 2025
When a linker script is included recursively by mistake, issue an error
instead of hang forever without outputting any error message.
PR ld/33265
* ldfile.c (opened_scripts): New.
(ldfile_try_open_bfd): After reading a linker script, clear the
opened linker script list and free its memory.
(ldfile_find_command_file): Issue a fatal error when the linker
script is included recursively. Add the linker script to the
linked list of opened linker scripts.
* testsuite/ld-scripts/libpr33265-1.a: New file.
* testsuite/ld-scripts/libpr33265-2.a: Likewise.
* testsuite/ld-scripts/pr33265-1.d: Likewise.
* testsuite/ld-scripts/pr33265-2.d: Likewise.
* testsuite/ld-scripts/script.exp: Run PR ld/33265 tests.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
ld/ldfile.c | 31 ++++++++++++++++++++++++--
ld/testsuite/ld-scripts/libpr33265-1.a | 1 +
ld/testsuite/ld-scripts/libpr33265-2.a | 1 +
ld/testsuite/ld-scripts/pr33265-1.d | 3 +++
ld/testsuite/ld-scripts/pr33265-2.d | 3 +++
ld/testsuite/ld-scripts/script.exp | 3 +++
6 files changed, 40 insertions(+), 2 deletions(-)
create mode 100644 ld/testsuite/ld-scripts/libpr33265-1.a
create mode 100644 ld/testsuite/ld-scripts/libpr33265-2.a
create mode 100644 ld/testsuite/ld-scripts/pr33265-1.d
create mode 100644 ld/testsuite/ld-scripts/pr33265-2.d
diff --git a/ld/ldfile.c b/ld/ldfile.c
index ce81fdc266f..98408788f45 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -76,6 +76,11 @@ typedef struct input_remap
static struct input_remap * input_remaps = NULL;
+/* The linked list of opened linker scripts in a linker script. */
+static struct script_name_list *opened_scripts = NULL;
+
+static void ldfile_script_free (struct script_name_list **);
+
void
ldfile_add_remap (const char * pattern, const char * renamed)
{
@@ -475,6 +480,11 @@ ldfile_try_open_bfd (const char *attempt,
ldfile_assumed_script = false;
fclose (yyin);
yyin = NULL;
+
+ /* After reading a linker script, clear the opened
+ linker script list and free its memory. */
+ ldfile_script_free (&opened_scripts);
+
if (skip)
{
if (command_line.warn_search_mismatch)
@@ -886,11 +896,12 @@ ldfile_find_command_file (const char *name,
*search_tail_ptr = NULL;
success:
- /* PR 24576: Catch the case where the user has accidentally included
- the same linker script twice. */
if (stat (filename, &sbuf1) == 0)
{
struct stat sbuf2;
+
+ /* PR 24576: Catch the case where the user has accidentally included
+ the same linker script twice. */
for (script = processed_scripts;
script != NULL;
script = script->next)
@@ -899,6 +910,16 @@ ldfile_find_command_file (const char *name,
&& SAME_INODE (sbuf1, sbuf2))
fatal (_("%P: error: linker script file '%s (%s)'"
" appears multiple times\n"), filename, script->name);
+
+ /* PR 33265: Catch the case where the user has accidentally included
+ the linker script recursively. */
+ for (script = opened_scripts;
+ script != NULL;
+ script = script->next)
+ if (stat (script->name, &sbuf2) == 0
+ && SAME_INODE (sbuf1, sbuf2))
+ fatal (_("%P: error: linker script '%s (%s)' included recursively\n"),
+ filename, script->name);
}
len = strlen (filename);
@@ -908,6 +929,12 @@ ldfile_find_command_file (const char *name,
memcpy (script->name, filename, len + 1);
processed_scripts = script;
+ script = xmalloc (sizeof (*script) + len);
+ script->next = opened_scripts;
+ script->open_how = open_how;
+ memcpy (script->name, name, len + 1);
+ opened_scripts = script;
+
free (path);
return result;
diff --git a/ld/testsuite/ld-scripts/libpr33265-1.a b/ld/testsuite/ld-scripts/libpr33265-1.a
new file mode 100644
index 00000000000..eab1008c0a8
--- /dev/null
+++ b/ld/testsuite/ld-scripts/libpr33265-1.a
@@ -0,0 +1 @@
+GROUP ( libpr33265-1.a )
diff --git a/ld/testsuite/ld-scripts/libpr33265-2.a b/ld/testsuite/ld-scripts/libpr33265-2.a
new file mode 100644
index 00000000000..10f4b91aa9e
--- /dev/null
+++ b/ld/testsuite/ld-scripts/libpr33265-2.a
@@ -0,0 +1 @@
+GROUP ( ./././././/libpr33265-2.a )
diff --git a/ld/testsuite/ld-scripts/pr33265-1.d b/ld/testsuite/ld-scripts/pr33265-1.d
new file mode 100644
index 00000000000..1d446a43efb
--- /dev/null
+++ b/ld/testsuite/ld-scripts/pr33265-1.d
@@ -0,0 +1,3 @@
+#source: start.s
+#ld: -r --whole-archive -lpr33265-1
+#error: .*libpr33265-1.a\)' included recursively
diff --git a/ld/testsuite/ld-scripts/pr33265-2.d b/ld/testsuite/ld-scripts/pr33265-2.d
new file mode 100644
index 00000000000..236417eda03
--- /dev/null
+++ b/ld/testsuite/ld-scripts/pr33265-2.d
@@ -0,0 +1,3 @@
+#source: start.s
+#ld: -r --whole-archive -lpr33265-2
+#error: .*libpr33265-2.a\)' included recursively
diff --git a/ld/testsuite/ld-scripts/script.exp b/ld/testsuite/ld-scripts/script.exp
index 0b37675ebe8..5e52179fdbf 100644
--- a/ld/testsuite/ld-scripts/script.exp
+++ b/ld/testsuite/ld-scripts/script.exp
@@ -240,4 +240,7 @@ run_dump_test "segment-start" {{name (default)}}
run_dump_test "segment-start" {{name (overridden)} \
{ld -Ttext-segment=0x10000000}}
+run_dump_test "pr33265-1"
+run_dump_test "pr33265-2"
+
set LDFLAGS $old_LDFLAGS
--
2.50.1
More information about the Binutils
mailing list