aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/x86
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2023-12-07 13:05:39 -0800
committerH.J. Lu <hjl.tools@gmail.com>2023-12-11 11:05:46 -0800
commit4753e9286858a61d5fbe8742d48d8c9166143354 (patch)
treef50fd83ef6348da899f909c1ca1ff699f1a261c2 /sysdeps/x86
parent7e03e0de7e7c2de975b5c5e18f5a4b0c75816674 (diff)
downloadglibc-4753e9286858a61d5fbe8742d48d8c9166143354.zip
glibc-4753e9286858a61d5fbe8742d48d8c9166143354.tar.gz
glibc-4753e9286858a61d5fbe8742d48d8c9166143354.tar.bz2
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>
Diffstat (limited to 'sysdeps/x86')
-rw-r--r--sysdeps/x86/dl-prop.h120
1 files changed, 80 insertions, 40 deletions
diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
index b2836f3..d2c53c2 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;
}
#endif /* _DL_PROP_H */