[PATCH 09/17] x86: Check PT_GNU_PROPERTY early

Noah Goldstein goldstein.w.n@gmail.com
Wed Dec 6 23:57:28 GMT 2023


On Wed, Dec 6, 2023 at 11:20 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> The PT_GNU_PROPERTY segment is scanned before PT_NOTE.  For binaries
> with the PT_GNU_PROPERTY segment, we can check it to avoid scan of
> the PT_NOTE segment.
> ---
>  sysdeps/x86/dl-prop.h | 120 ++++++++++++++++++++++++++++--------------
>  1 file changed, 80 insertions(+), 40 deletions(-)
>
> diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
> index b2836f3009..d2c53c2182 100644
> --- a/sysdeps/x86/dl-prop.h
> +++ b/sysdeps/x86/dl-prop.h
> @@ -81,6 +81,60 @@ _dl_open_check (struct link_map *m)
>  #endif
>  }
>
> +/* Check the GNU property and return its value.  It returns:
> +   -1: Skip this note.
> +    0: Stop checking.
> +    1: Continue to check.
> + */
> +static inline int
> +_dl_check_gnu_property (unsigned int type, unsigned int datasz,
> +                       void *ptr, unsigned int *feature_1_and,
> +                       unsigned int *needed_1,
> +                       unsigned int *isa_1_needed)
> +{
> +  if (type == GNU_PROPERTY_X86_FEATURE_1_AND
> +      || type == GNU_PROPERTY_X86_ISA_1_NEEDED
> +      || type == GNU_PROPERTY_1_NEEDED)
> +    {
> +      /* The sizes of types which we are searching for are
> +        4 bytes.  There is no point to continue if this
> +        note is ill-formed.  */
> +      if (datasz != 4)
> +       return -1;
> +
> +      /* NB: Stop the scan only after seeing all types which
> +        we are searching for.  */
> +      _Static_assert (((GNU_PROPERTY_X86_ISA_1_NEEDED
> +                       > GNU_PROPERTY_X86_FEATURE_1_AND)
> +                      && (GNU_PROPERTY_X86_FEATURE_1_AND
> +                          > GNU_PROPERTY_1_NEEDED)),
> +                     "GNU_PROPERTY_X86_ISA_1_NEEDED > "
> +                     "GNU_PROPERTY_X86_FEATURE_1_AND && "
> +                     "GNU_PROPERTY_X86_FEATURE_1_AND > "
> +                     "GNU_PROPERTY_1_NEEDED");
> +      if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
> +       *feature_1_and = *(unsigned int *) ptr;
> +      else if (type == GNU_PROPERTY_1_NEEDED)
> +       *needed_1 = *(unsigned int *) ptr;
> +      else
> +       {
> +         *isa_1_needed = *(unsigned int *) ptr;
> +
> +         /* Keep searching for the next GNU property note
> +            generated by the older linker.  */
> +         return 0;
> +       }
> +    }
> +  else if (type > GNU_PROPERTY_X86_ISA_1_NEEDED)
> +    {
> +      /* Stop the scan since property type is in ascending
> +        order.  */
> +      return 0;
> +    }
> +
> +  return 1;
> +}
> +
>  static inline void __attribute__ ((unused))
>  _dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note,
>                            const ElfW(Addr) size, const ElfW(Addr) align)
> @@ -141,45 +195,14 @@ _dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note,
>
>               last_type = type;
>
> -             if (type == GNU_PROPERTY_X86_FEATURE_1_AND
> -                 || type == GNU_PROPERTY_X86_ISA_1_NEEDED
> -                 || type == GNU_PROPERTY_1_NEEDED)
> -               {
> -                 /* The sizes of types which we are searching for are
> -                    4 bytes.  There is no point to continue if this
> -                    note is ill-formed.  */
> -                 if (datasz != 4)
> -                   return;
> -
> -                 /* NB: Stop the scan only after seeing all types which
> -                    we are searching for.  */
> -                 _Static_assert (((GNU_PROPERTY_X86_ISA_1_NEEDED
> -                                   > GNU_PROPERTY_X86_FEATURE_1_AND)
> -                                  && (GNU_PROPERTY_X86_FEATURE_1_AND
> -                                      > GNU_PROPERTY_1_NEEDED)),
> -                                 "GNU_PROPERTY_X86_ISA_1_NEEDED > "
> -                                 "GNU_PROPERTY_X86_FEATURE_1_AND && "
> -                                 "GNU_PROPERTY_X86_FEATURE_1_AND > "
> -                                 "GNU_PROPERTY_1_NEEDED");
> -                 if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
> -                   feature_1_and = *(unsigned int *) ptr;
> -                 else if (type == GNU_PROPERTY_1_NEEDED)
> -                   needed_1 = *(unsigned int *) ptr;
> -                 else
> -                   {
> -                     isa_1_needed = *(unsigned int *) ptr;
> -
> -                     /* Keep searching for the next GNU property note
> -                        generated by the older linker.  */
> -                     break;
> -                   }
> -               }
> -             else if (type > GNU_PROPERTY_X86_ISA_1_NEEDED)
> -               {
> -                 /* Stop the scan since property type is in ascending
> -                    order.  */
> -                 break;
> -               }
> +             int result = _dl_check_gnu_property (type, datasz, ptr,
> +                                                  &feature_1_and,
> +                                                  &needed_1,
> +                                                  &isa_1_needed);
> +             if (result == -1)
> +               return;         /* Skip this note.  */
> +             else if (result == 0)
> +               break; /* Stop checking.  */
>
>               /* Check the next property item.  */
>               ptr += ALIGN_UP (datasz, sizeof (ElfW(Addr)));
> @@ -217,7 +240,24 @@ static inline int __attribute__ ((always_inline))
>  _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type,
>                           uint32_t datasz, void *data)
>  {
> -  return 0;
> +  /* This is called on each GNU property.  */
> +  unsigned int needed_1 = 0;
> +  unsigned int feature_1_and = 0;
> +  unsigned int isa_1_needed = 0;
> +  int result = _dl_check_gnu_property (type, datasz, data,
> +                                      &feature_1_and, &needed_1,
> +                                      &isa_1_needed);
> +  if (needed_1 != 0)
> +    l->l_1_needed = needed_1;
> +  if (isa_1_needed != 0)
> +    l->l_x86_isa_1_needed = isa_1_needed;
> +  if (feature_1_and != 0)
> +    l->l_x86_feature_1_and = feature_1_and;
> +  if ((needed_1 | isa_1_needed | feature_1_and) != 0)
> +    l->l_property = lc_property_valid;
> +  else if (l->l_property == lc_property_unknown)
> +    l->l_property = lc_property_none;
> +  return result <= 0 ? 0 : result;
These seems like a seperate change from the refactor mentioned in the
commit message?
>  }
>
>  #endif /* _DL_PROP_H */
> --
> 2.43.0
>


More information about the Libc-alpha mailing list