[PATCH] elf: Avoid conflicts with local symbol names of "XXX.COUNT"

H.J. Lu hjl.tools@gmail.com
Wed May 5 18:31:56 GMT 2021


On Wed, May 5, 2021 at 8:48 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> 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
>

This scheme doesn't work.

-- 
H.J.


More information about the Binutils mailing list