144f612406
Downstream only and disabled by default.
161 lines
5.1 KiB
Diff
161 lines
5.1 KiB
Diff
From 4323e979bd1745e10ae29667c290bff7f74d38e4 Mon Sep 17 00:00:00 2001
|
|
From: "H.J. Lu" <hjl.tools@gmail.com>
|
|
Date: Thu, 13 Jan 2022 14:45:46 -0800
|
|
Subject: [PATCH v2 09/15] 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.
|
|
---
|
|
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 87702df040..ca07b83701 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 */
|
|
--
|
|
2.40.1
|
|
|