mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
x86: Check PT_GNU_PROPERTY early
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. Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
This commit is contained in:
parent
7e03e0de7e
commit
4753e92868
1 changed files with 80 additions and 40 deletions
|
@ -81,6 +81,60 @@ _dl_open_check (struct link_map *m)
|
||||||
#endif
|
#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))
|
static inline void __attribute__ ((unused))
|
||||||
_dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note,
|
_dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note,
|
||||||
const ElfW(Addr) size, const ElfW(Addr) align)
|
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;
|
last_type = type;
|
||||||
|
|
||||||
if (type == GNU_PROPERTY_X86_FEATURE_1_AND
|
int result = _dl_check_gnu_property (type, datasz, ptr,
|
||||||
|| type == GNU_PROPERTY_X86_ISA_1_NEEDED
|
&feature_1_and,
|
||||||
|| type == GNU_PROPERTY_1_NEEDED)
|
&needed_1,
|
||||||
{
|
&isa_1_needed);
|
||||||
/* The sizes of types which we are searching for are
|
if (result == -1)
|
||||||
4 bytes. There is no point to continue if this
|
return; /* Skip this note. */
|
||||||
note is ill-formed. */
|
else if (result == 0)
|
||||||
if (datasz != 4)
|
break; /* Stop checking. */
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the next property item. */
|
/* Check the next property item. */
|
||||||
ptr += ALIGN_UP (datasz, sizeof (ElfW(Addr)));
|
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,
|
_dl_process_gnu_property (struct link_map *l, int fd, uint32_t type,
|
||||||
uint32_t datasz, void *data)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _DL_PROP_H */
|
#endif /* _DL_PROP_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue