[PATCH v3] elf: Always append ".COUNT" to local symbols

Fangrui Song i@maskray.me
Thu May 6 01:27:37 GMT 2021


On 2021-05-05, H.J. Lu wrote:
>On Wed, May 5, 2021 at 3:11 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> 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?

Yes.

If foo cannot be used, try foo.1 foo.2 foo.3 ...
foo can itself be of the form bar.COUNT .

I guess the new code has handled the case.

(Personally I'd prefer zero-based numbering but one-based numbering
shouldn't hurt here.)

For the original FGKASLR (stalled?) request, the linker approach has a
drawback that the linker cannot change DW_AT_linkage_name in debug info,
so there may be a DW_AT_linkage_name / .symtab mismatch.

>> [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]$
>>
>
>Here is the v3 patch to always append ".COUNT" to local symbols
>to avoid potential conflicts with existing local symbol "XXX.COUNT".
>
>-- 
>H.J.




More information about the Binutils mailing list