[PATCH] elf: Avoid conflicts with local symbol names of "XXX.COUNT"
H.J. Lu
hjl.tools@gmail.com
Wed May 5 15:48:55 GMT 2021
When appending ".COUNT" to duplicated local symbol names of "XXX",
increment COUNT if there is an existing local symbol name of "XXX.COUNT".
bfd/
PR ld/27825
* elflink.c (elf_link_output_symstrtab): Avoid conflicts with
local symbol names of "XXX.COUNT".
ld/
PR ld/27825
* testsuite/ld-elf/pr27825.d: New file.
* testsuite/ld-elf/pr27825a.s: Likewise.
* testsuite/ld-elf/pr27825b.s: Likewise.
---
bfd/elflink.c | 31 ++++++++++++++++++++++++++++---
ld/testsuite/ld-elf/pr27825.d | 18 ++++++++++++++++++
ld/testsuite/ld-elf/pr27825a.s | 7 +++++++
ld/testsuite/ld-elf/pr27825b.s | 5 +++++
4 files changed, 58 insertions(+), 3 deletions(-)
create mode 100644 ld/testsuite/ld-elf/pr27825.d
create mode 100644 ld/testsuite/ld-elf/pr27825a.s
create mode 100644 ld/testsuite/ld-elf/pr27825b.s
diff --git a/bfd/elflink.c b/bfd/elflink.c
index cb38a025349..ac46585f0ab 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -9845,22 +9845,47 @@ elf_link_output_symstrtab (void *finf,
/* Append ".COUNT" to duplicated local symbols. */
size_t count_len;
size_t base_len = lh->size;
- char buf[30];
- sprintf (buf, "%lx", lh->count);
+ char buf[20];
+ if (snprintf (buf, sizeof (buf), "%lx", lh->count)
+ >= (int) sizeof (buf))
+ return 0;
if (!base_len)
{
base_len = strlen (name);
lh->size = base_len;
}
count_len = strlen (buf);
+ /* NB: Allocate the extra suffix buffer for possible
+ change. */
versioned_name = bfd_alloc (flinfo->output_bfd,
- base_len + count_len + 2);
+ base_len + sizeof (buf)
+ + 2);
if (versioned_name == NULL)
return 0;
memcpy (versioned_name, name, base_len);
versioned_name[base_len] = '.';
memcpy (versioned_name + base_len + 1, buf,
count_len + 1);
+ do
+ {
+ /* Avoid conflicts with local symbol names of
+ "XXX.COUNT". */
+ struct local_hash_entry *lvh
+ = (struct local_hash_entry *) bfd_hash_lookup
+ (&flinfo->local_hash_table, versioned_name,
+ false, false);
+ if (lvh == NULL)
+ break;
+ lh->count++;
+ if (snprintf (buf, sizeof (buf), "%lx",
+ lh->count) >= (int) sizeof (buf))
+ return 0;
+ count_len = strlen (buf);
+ /* NB: Use the existing suffix buffer. */
+ memcpy (versioned_name + base_len + 1, buf,
+ count_len + 1);
+ }
+ while (1);
}
lh->count++;
break;
diff --git a/ld/testsuite/ld-elf/pr27825.d b/ld/testsuite/ld-elf/pr27825.d
new file mode 100644
index 00000000000..da9832be850
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr27825.d
@@ -0,0 +1,18 @@
+#source: pr27825a.s
+#source: pr27825b.s
+#ld: -e _start --emit-relocs -z unique-symbol
+#nm: --defined-only
+
+#...
+[0-9a-f]+ t bar
+#...
+[0-9a-f]+ t bar.1
+#...
+[0-9a-f]+ t bar.1.1
+#...
+[0-9a-f]+ t bar.2
+#...
+[0-9a-f]+ t bar.2.1
+#...
+[0-9a-f]+ t bar.3
+#pass
diff --git a/ld/testsuite/ld-elf/pr27825a.s b/ld/testsuite/ld-elf/pr27825a.s
new file mode 100644
index 00000000000..e6940e17430
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr27825a.s
@@ -0,0 +1,7 @@
+ .text
+ .globl _start
+_start:
+bar:
+bar.1:
+bar.2:
+ .nop
diff --git a/ld/testsuite/ld-elf/pr27825b.s b/ld/testsuite/ld-elf/pr27825b.s
new file mode 100644
index 00000000000..2128e802d4b
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr27825b.s
@@ -0,0 +1,5 @@
+ .text
+bar:
+bar.1:
+bar.2:
+ .nop
--
2.31.1
More information about the Binutils
mailing list