[PATCH v2] elf: Avoid possible duplicated local symbol names

H.J. Lu hjl.tools@gmail.com
Wed May 5 22:11:29 GMT 2021


On Wed, May 5, 2021 at 2:36 PM Fangrui Song <i@maskray.me> wrote:
>
> On 2021-05-05, H.J. Lu via Binutils wrote:
> >On Wed, May 5, 2021 at 11:31 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >>
> >> 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;
> >
> >> This scheme doesn't work.
> >>
> >
> >This one works.
> >
> >--
> >H.J.
>
> I don't read the implementation.
>
> If bar.2.1 already exists, can the implementation correctly rename bar.2 (to bar.2.2) ?

Is this what you have in mind?

[hjl@gnu-cfl-2 pr27825-2]$ cat pr27825a.s
.text
.globl _start
_start:
bar.2:
.nop
[hjl@gnu-cfl-2 pr27825-2]$ cat pr27825b.s
.text
bar.2:
.nop
[hjl@gnu-cfl-2 pr27825-2]$ cat pr27825c.s
.text
bar.1.1:
bar.2.1:
.nop
[hjl@gnu-cfl-2 pr27825-2]$ make
as   -o pr27825a.o pr27825a.s
as   -o pr27825b.o pr27825b.s
as   -o pr27825c.o pr27825c.s
./ld --emit-relocs -z unique-symbol -e _start -o x pr27825a.o
pr27825b.o pr27825c.o
./nm x
0000000000401002 t bar.1.1
0000000000401000 t bar.2
0000000000401001 t bar.2.1
0000000000401002 t bar.2.1.1
0000000000402000 B __bss_start
0000000000402000 D _edata
0000000000402000 B _end
0000000000401000 T _start
[hjl@gnu-cfl-2 pr27825-2]$


-- 
H.J.


More information about the Binutils mailing list