[PATCH] ld: Issue an error for recursively included linker script
H.J. Lu
hjl.tools@gmail.com
Sun Aug 10 13:24:09 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_script_list): New.
(opened_scripts): Likewise.
(ldfile_opened_script_list_free): Likewise.
(ldfile_try_open_bfd): After reading a linker script, clear the
opened linker script list and free its memory.
(ldfile_open_command_file_1): 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.a: New file.
* testsuite/ld-scripts/pr33265.d: Likewise.
* testsuite/ld-scripts/script.exp: Run pr33265.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
ld/ldfile.c | 45 ++++++++++++++++++++++++++++
ld/testsuite/ld-scripts/libpr33265.a | 1 +
ld/testsuite/ld-scripts/pr33265.d | 3 ++
ld/testsuite/ld-scripts/script.exp | 2 ++
4 files changed, 51 insertions(+)
create mode 100644 ld/testsuite/ld-scripts/libpr33265.a
create mode 100644 ld/testsuite/ld-scripts/pr33265.d
diff --git a/ld/ldfile.c b/ld/ldfile.c
index e642c7f6620..c4619c16f3f 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -75,6 +75,28 @@ typedef struct input_remap
static struct input_remap * input_remaps = NULL;
+struct opened_script_list
+{
+ struct opened_script_list *next;
+ const char *name;
+};
+
+/* The linked list of opened linker scripts in a linker script. */
+static struct opened_script_list *opened_scripts = NULL;
+
+/* Clear the opened linker script list and free its memory. */
+
+static void
+ldfile_opened_script_list_free (struct opened_script_list **root)
+{
+ struct opened_script_list *ent;
+ while ((ent = *root) != NULL)
+ {
+ *root = ent->next;
+ free (ent);
+ }
+}
+
void
ldfile_add_remap (const char * pattern, const char * renamed)
{
@@ -474,6 +496,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_opened_script_list_free (&opened_scripts);
+
if (skip)
{
if (command_line.warn_search_mismatch)
@@ -887,6 +914,7 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
FILE *ldlex_input_stack;
bool sysrooted;
struct script_name_list *script;
+ struct opened_script_list *opened_script;
size_t len;
/* PR 24576: Catch the case where the user has accidentally included
@@ -924,6 +952,23 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
lineno = 1;
saved_script_handle = ldlex_input_stack;
+
+ /* PR 33265: Catch the case where the user has accidentally included
+ the linker script recursively. */
+ for (opened_script = opened_scripts;
+ opened_script != NULL;
+ opened_script = opened_script->next)
+ if (strcmp (name, opened_script->name) == 0)
+ fatal (_("%P: error: linker script '%s' included recursively\n"),
+ name);
+
+ opened_script = xmalloc (sizeof (*opened_script));
+ /* Since ldfile_opened_script_list_free is called immediately after
+ the linker linker script is processed, only the pointer to string
+ is recorded. */
+ opened_script->name = name;
+ opened_script->next = opened_scripts;
+ opened_scripts = opened_script;
}
static void
diff --git a/ld/testsuite/ld-scripts/libpr33265.a b/ld/testsuite/ld-scripts/libpr33265.a
new file mode 100644
index 00000000000..c580ba6c713
--- /dev/null
+++ b/ld/testsuite/ld-scripts/libpr33265.a
@@ -0,0 +1 @@
+GROUP ( libpr33265.a )
diff --git a/ld/testsuite/ld-scripts/pr33265.d b/ld/testsuite/ld-scripts/pr33265.d
new file mode 100644
index 00000000000..761ba3bb1f3
--- /dev/null
+++ b/ld/testsuite/ld-scripts/pr33265.d
@@ -0,0 +1,3 @@
+#source: start.s
+#ld: -r --whole-archive -lpr33265
+#error: .*libpr33265.a' included recursively
diff --git a/ld/testsuite/ld-scripts/script.exp b/ld/testsuite/ld-scripts/script.exp
index 5206563f250..e5f4e1bf117 100644
--- a/ld/testsuite/ld-scripts/script.exp
+++ b/ld/testsuite/ld-scripts/script.exp
@@ -238,4 +238,6 @@ run_dump_test "segment-start" {{name (default)}}
run_dump_test "segment-start" {{name (overridden)} \
{ld -Ttext-segment=0x10000000}}
+run_dump_test "pr33265"
+
set LDFLAGS $old_LDFLAGS
--
2.50.1
More information about the Binutils
mailing list