forked from rpms/glibc
144f612406
Downstream only and disabled by default.
512 lines
16 KiB
Diff
512 lines
16 KiB
Diff
From 8431e78b2df0ee194ac0bbd5a5136e89765444c4 Mon Sep 17 00:00:00 2001
|
|
From: "H.J. Lu" <hjl.tools@gmail.com>
|
|
Date: Fri, 24 Mar 2023 13:20:06 -0700
|
|
Subject: [PATCH v2 10/15] x86: Modularize sysdeps/x86/dl-cet.c
|
|
|
|
Improve readability and make maintenance easier for dl-feature.c by
|
|
modularizing sysdeps/x86/dl-cet.c:
|
|
1. Support processors with:
|
|
a. Only IBT. Or
|
|
b. Only SHSTK. Or
|
|
c. Both IBT and SHSTK.
|
|
2. Lock CET features only if IBT or SHSTK are enabled and are not
|
|
enabled permissively.
|
|
---
|
|
sysdeps/x86/dl-cet.c | 456 ++++++++++++++++++++++++++-----------------
|
|
1 file changed, 280 insertions(+), 176 deletions(-)
|
|
|
|
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
|
|
index 60ea1cb558..67c51ee8c2 100644
|
|
--- a/sysdeps/x86/dl-cet.c
|
|
+++ b/sysdeps/x86/dl-cet.c
|
|
@@ -32,206 +32,310 @@
|
|
# error GNU_PROPERTY_X86_FEATURE_1_SHSTK != X86_FEATURE_1_SHSTK
|
|
#endif
|
|
|
|
-/* Check if object M is compatible with CET. */
|
|
+struct dl_cet_info
|
|
+{
|
|
+ const char *program;
|
|
+
|
|
+ /* Check how IBT and SHSTK should be enabled. */
|
|
+ enum dl_x86_cet_control enable_ibt_type;
|
|
+ enum dl_x86_cet_control enable_shstk_type;
|
|
+
|
|
+ /* If IBT and SHSTK were previously enabled. */
|
|
+ unsigned int feature_1_enabled;
|
|
+
|
|
+ /* If IBT and SHSTK should be enabled. */
|
|
+ unsigned int enable_feature_1;
|
|
+
|
|
+ /* If there are any legacy shared object. */
|
|
+ unsigned int feature_1_legacy;
|
|
+
|
|
+ /* Which shared object is the first legacy shared object. */
|
|
+ unsigned int feature_1_legacy_ibt;
|
|
+ unsigned int feature_1_legacy_shstk;
|
|
+};
|
|
+
|
|
+/* Check if the object M and its dependencies are legacy object. */
|
|
|
|
static void
|
|
-dl_cet_check (struct link_map *m, const char *program)
|
|
+dl_check_legacy_object (struct link_map *m,
|
|
+ struct dl_cet_info *info)
|
|
{
|
|
- /* Check how IBT should be enabled. */
|
|
- enum dl_x86_cet_control enable_ibt_type
|
|
- = GL(dl_x86_feature_control).ibt;
|
|
- /* Check how SHSTK should be enabled. */
|
|
- enum dl_x86_cet_control enable_shstk_type
|
|
- = GL(dl_x86_feature_control).shstk;
|
|
-
|
|
- /* No legacy object check if both IBT and SHSTK are always on. */
|
|
- if (enable_ibt_type == cet_always_on
|
|
- && enable_shstk_type == cet_always_on)
|
|
+ unsigned int i;
|
|
+ struct link_map *l = NULL;
|
|
+
|
|
+ i = m->l_searchlist.r_nlist;
|
|
+ while (i-- > 0)
|
|
{
|
|
- THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
|
|
- return;
|
|
- }
|
|
+ /* Check each shared object to see if IBT and SHSTK are enabled. */
|
|
+ l = m->l_initfini[i];
|
|
|
|
- /* Check if IBT is enabled by kernel. */
|
|
- bool ibt_enabled
|
|
- = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0;
|
|
- /* Check if SHSTK is enabled by kernel. */
|
|
- bool shstk_enabled
|
|
- = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0;
|
|
+ if (l->l_init_called)
|
|
+ continue;
|
|
|
|
- if (ibt_enabled || shstk_enabled)
|
|
- {
|
|
- struct link_map *l = NULL;
|
|
- unsigned int ibt_legacy = 0, shstk_legacy = 0;
|
|
- bool found_ibt_legacy = false, found_shstk_legacy = false;
|
|
-
|
|
- /* Check if IBT and SHSTK are enabled in object. */
|
|
- bool enable_ibt = (ibt_enabled
|
|
- && enable_ibt_type != cet_always_off);
|
|
- bool enable_shstk = (shstk_enabled
|
|
- && enable_shstk_type != cet_always_off);
|
|
- if (program)
|
|
+#ifdef SHARED
|
|
+ /* Skip check for ld.so since it has the features enabled. The
|
|
+ features will be disabled later if they are not enabled in
|
|
+ executable. */
|
|
+ if (l == &GL(dl_rtld_map)
|
|
+ || l->l_real == &GL(dl_rtld_map)
|
|
+ || (info->program != NULL && l == m))
|
|
+ continue;
|
|
+#endif
|
|
+
|
|
+ /* IBT and SHSTK set only if enabled in executable and all DSOs.
|
|
+ NB: cet_always_on is handled outside of the loop. */
|
|
+ info->enable_feature_1 &= ((l->l_x86_feature_1_and
|
|
+ & (GNU_PROPERTY_X86_FEATURE_1_IBT
|
|
+ | GNU_PROPERTY_X86_FEATURE_1_SHSTK))
|
|
+ | ~(GNU_PROPERTY_X86_FEATURE_1_IBT
|
|
+ | GNU_PROPERTY_X86_FEATURE_1_SHSTK));
|
|
+ if ((info->feature_1_legacy
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) == 0
|
|
+ && ((info->enable_feature_1
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT)
|
|
+ != (info->feature_1_enabled
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT)))
|
|
{
|
|
- /* Enable IBT and SHSTK only if they are enabled in executable.
|
|
- NB: IBT and SHSTK may be disabled by environment variable:
|
|
-
|
|
- GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
|
|
- */
|
|
- enable_ibt &= (CPU_FEATURE_USABLE (IBT)
|
|
- && (enable_ibt_type == cet_always_on
|
|
- || (m->l_x86_feature_1_and
|
|
- & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0));
|
|
- enable_shstk &= (CPU_FEATURE_USABLE (SHSTK)
|
|
- && (enable_shstk_type == cet_always_on
|
|
- || (m->l_x86_feature_1_and
|
|
- & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0));
|
|
+ info->feature_1_legacy_ibt = i;
|
|
+ info->feature_1_legacy |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
}
|
|
|
|
- /* ld.so is CET-enabled by kernel. But shared objects may not
|
|
- support IBT nor SHSTK. */
|
|
- if (enable_ibt || enable_shstk)
|
|
- {
|
|
- unsigned int i;
|
|
+ if ((info->feature_1_legacy
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK) == 0
|
|
+ && ((info->enable_feature_1
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
|
+ != (info->feature_1_enabled
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK)))
|
|
+ {
|
|
+ info->feature_1_legacy_shstk = i;
|
|
+ info->feature_1_legacy |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
+ }
|
|
+ }
|
|
|
|
- i = m->l_searchlist.r_nlist;
|
|
- while (i-- > 0)
|
|
- {
|
|
- /* Check each shared object to see if IBT and SHSTK are
|
|
- enabled. */
|
|
- l = m->l_initfini[i];
|
|
+ /* Handle cet_always_on. */
|
|
+ if ((info->feature_1_enabled
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0
|
|
+ && info->enable_ibt_type == cet_always_on)
|
|
+ {
|
|
+ info->feature_1_legacy &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
+ info->enable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
+ }
|
|
|
|
- if (l->l_init_called)
|
|
- continue;
|
|
+ if ((info->feature_1_enabled
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0
|
|
+ && info->enable_shstk_type == cet_always_on)
|
|
+ {
|
|
+ info->feature_1_legacy &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
+ info->enable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
+ }
|
|
+}
|
|
|
|
#ifdef SHARED
|
|
- /* Skip CET check for ld.so since ld.so is CET-enabled.
|
|
- CET will be disabled later if CET isn't enabled in
|
|
- executable. */
|
|
- if (l == &GL(dl_rtld_map)
|
|
- || l->l_real == &GL(dl_rtld_map)
|
|
- || (program && l == m))
|
|
- continue;
|
|
+/* Enable IBT and SHSTK only if they are enabled in executable. Set
|
|
+ feature bits properly at the start of the program. */
|
|
+
|
|
+static void
|
|
+dl_cet_check_startup (struct link_map *m, struct dl_cet_info *info)
|
|
+{
|
|
+ /* NB: IBT and SHSTK may be disabled by environment variable:
|
|
+
|
|
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK.
|
|
+ */
|
|
+ if (CPU_FEATURE_USABLE (IBT))
|
|
+ {
|
|
+ if (info->enable_ibt_type == cet_always_on)
|
|
+ info->enable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
+ else
|
|
+ info->enable_feature_1 &= ((m->l_x86_feature_1_and
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT)
|
|
+ | ~GNU_PROPERTY_X86_FEATURE_1_IBT);
|
|
+ }
|
|
+ else
|
|
+ info->enable_feature_1 &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
+
|
|
+ if (CPU_FEATURE_USABLE (SHSTK))
|
|
+ {
|
|
+ if (info->enable_shstk_type == cet_always_on)
|
|
+ info->enable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
+ else
|
|
+ info->enable_feature_1 &= ((m->l_x86_feature_1_and
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
|
+ | ~GNU_PROPERTY_X86_FEATURE_1_SHSTK);
|
|
+ }
|
|
+ else
|
|
+ info->enable_feature_1 &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
+
|
|
+ if (info->enable_feature_1 != 0)
|
|
+ dl_check_legacy_object (m, info);
|
|
+
|
|
+ unsigned int disable_feature_1
|
|
+ = info->enable_feature_1 ^ info->feature_1_enabled;
|
|
+ if (disable_feature_1 != 0)
|
|
+ {
|
|
+ /* Disable features in the kernel because of legacy objects or
|
|
+ cet_always_off. */
|
|
+ if (dl_cet_disable_cet (disable_feature_1) != 0)
|
|
+ _dl_fatal_printf ("%s: can't disable x86 Features\n",
|
|
+ info->program);
|
|
+
|
|
+ /* Clear the disabled bits. Sync dl_x86_feature_1 and
|
|
+ info->feature_1_enabled with info->enable_feature_1. */
|
|
+ info->feature_1_enabled = info->enable_feature_1;
|
|
+ GL(dl_x86_feature_1) = info->enable_feature_1;
|
|
+ }
|
|
+
|
|
+ if (HAS_CPU_FEATURE (IBT) || HAS_CPU_FEATURE (SHSTK))
|
|
+ {
|
|
+ /* Lock CET features only if IBT or SHSTK are enabled and are not
|
|
+ enabled permissively. */
|
|
+ unsigned int feature_1_lock = 0;
|
|
+
|
|
+ if (((info->feature_1_enabled & GNU_PROPERTY_X86_FEATURE_1_IBT)
|
|
+ != 0)
|
|
+ && info->enable_ibt_type != cet_permissive)
|
|
+ feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
+
|
|
+ if (((info->feature_1_enabled & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
|
|
+ != 0)
|
|
+ && info->enable_shstk_type != cet_permissive)
|
|
+ feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
+
|
|
+ if (feature_1_lock != 0
|
|
+ && dl_cet_lock_cet () != 0)
|
|
+ _dl_fatal_printf ("%s: can't lock CET\n", info->program);
|
|
+ }
|
|
+
|
|
+ THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
|
|
+}
|
|
#endif
|
|
|
|
- /* IBT is enabled only if it is enabled in executable as
|
|
- well as all shared objects. */
|
|
- enable_ibt &= (enable_ibt_type == cet_always_on
|
|
- || (l->l_x86_feature_1_and
|
|
- & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0);
|
|
- if (!found_ibt_legacy && enable_ibt != ibt_enabled)
|
|
- {
|
|
- found_ibt_legacy = true;
|
|
- ibt_legacy = i;
|
|
- }
|
|
-
|
|
- /* SHSTK is enabled only if it is enabled in executable as
|
|
- well as all shared objects. */
|
|
- enable_shstk &= (enable_shstk_type == cet_always_on
|
|
- || (l->l_x86_feature_1_and
|
|
- & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0);
|
|
- if (enable_shstk != shstk_enabled)
|
|
- {
|
|
- found_shstk_legacy = true;
|
|
- shstk_legacy = i;
|
|
- }
|
|
- }
|
|
- }
|
|
+/* Check feature bits when dlopening the shared object M. */
|
|
+
|
|
+static void
|
|
+dl_cet_check_dlopen (struct link_map *m, struct dl_cet_info *info)
|
|
+{
|
|
+ /* Check if there are any legacy objects loaded. */
|
|
+ if (info->enable_feature_1 != 0)
|
|
+ {
|
|
+ dl_check_legacy_object (m, info);
|
|
|
|
- bool cet_feature_changed = false;
|
|
+ /* Skip if there are no legacy shared objects loaded. */
|
|
+ if (info->feature_1_legacy == 0)
|
|
+ return;
|
|
+ }
|
|
|
|
- if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled)
|
|
- {
|
|
- if (!program)
|
|
- {
|
|
- if (enable_ibt_type != cet_permissive)
|
|
- {
|
|
- /* When IBT is enabled, we cannot dlopen a shared
|
|
- object without IBT. */
|
|
- if (found_ibt_legacy)
|
|
- _dl_signal_error (0,
|
|
- m->l_initfini[ibt_legacy]->l_name,
|
|
- "dlopen",
|
|
- N_("rebuild shared object with IBT support enabled"));
|
|
- }
|
|
-
|
|
- if (enable_shstk_type != cet_permissive)
|
|
- {
|
|
- /* When SHSTK is enabled, we cannot dlopen a shared
|
|
- object without SHSTK. */
|
|
- if (found_shstk_legacy)
|
|
- _dl_signal_error (0,
|
|
- m->l_initfini[shstk_legacy]->l_name,
|
|
- "dlopen",
|
|
- N_("rebuild shared object with SHSTK support enabled"));
|
|
- }
|
|
-
|
|
- if (enable_ibt_type != cet_permissive
|
|
- && enable_shstk_type != cet_permissive)
|
|
- return;
|
|
- }
|
|
-
|
|
- /* Disable IBT and/or SHSTK if they are enabled by kernel, but
|
|
- disabled in executable or shared objects. */
|
|
- unsigned int cet_feature = 0;
|
|
-
|
|
- if (!enable_ibt)
|
|
- cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
- if (!enable_shstk)
|
|
- cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
-
|
|
- int res = dl_cet_disable_cet (cet_feature);
|
|
- if (res != 0)
|
|
- {
|
|
- if (program)
|
|
- _dl_fatal_printf ("%s: can't disable CET\n", program);
|
|
- else
|
|
- {
|
|
- if (found_ibt_legacy)
|
|
- l = m->l_initfini[ibt_legacy];
|
|
- else
|
|
- l = m->l_initfini[shstk_legacy];
|
|
- _dl_signal_error (-res, l->l_name, "dlopen",
|
|
- N_("can't disable CET"));
|
|
- }
|
|
- }
|
|
-
|
|
- /* Clear the disabled bits in dl_x86_feature_1. */
|
|
- GL(dl_x86_feature_1) &= ~cet_feature;
|
|
-
|
|
- cet_feature_changed = true;
|
|
- }
|
|
+ unsigned int disable_feature_1 = 0;
|
|
+ unsigned int legacy_obj = 0;
|
|
+ const char *msg = NULL;
|
|
|
|
-#ifdef SHARED
|
|
- if (program && (ibt_enabled || shstk_enabled))
|
|
+ if ((info->feature_1_enabled
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0
|
|
+ && (info->feature_1_legacy
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0)
|
|
+ {
|
|
+ if (info->enable_ibt_type != cet_permissive)
|
|
{
|
|
- if ((!ibt_enabled
|
|
- || enable_ibt_type != cet_permissive)
|
|
- && (!shstk_enabled
|
|
- || enable_shstk_type != cet_permissive))
|
|
- {
|
|
- /* Lock CET if IBT or SHSTK is enabled in executable unless
|
|
- IBT or SHSTK is enabled permissively. */
|
|
- int res = dl_cet_lock_cet ();
|
|
- if (res != 0)
|
|
- _dl_fatal_printf ("%s: can't lock CET\n", program);
|
|
- }
|
|
-
|
|
- /* Set feature_1 if IBT or SHSTK is enabled in executable. */
|
|
- cet_feature_changed = true;
|
|
+ legacy_obj = info->feature_1_legacy_ibt;
|
|
+ msg = N_("rebuild shared object with IBT support enabled");
|
|
}
|
|
-#endif
|
|
+ else
|
|
+ disable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
+ }
|
|
|
|
- if (cet_feature_changed)
|
|
+ /* Check the next feature only if there is no error. */
|
|
+ if (msg == NULL
|
|
+ && (info->feature_1_enabled
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0
|
|
+ && (info->feature_1_legacy
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0)
|
|
+ {
|
|
+ if (info->enable_shstk_type != cet_permissive)
|
|
{
|
|
- unsigned int feature_1 = 0;
|
|
- if (enable_ibt)
|
|
- feature_1 |= GNU_PROPERTY_X86_FEATURE_1_IBT;
|
|
- if (enable_shstk)
|
|
- feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
- struct pthread *self = THREAD_SELF;
|
|
- THREAD_SETMEM (self, header.feature_1, feature_1);
|
|
+ legacy_obj = info->feature_1_legacy_shstk;
|
|
+ msg = N_("rebuild shared object with SHSTK support enabled");
|
|
}
|
|
+ else
|
|
+ disable_feature_1 |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
|
|
+ }
|
|
+
|
|
+ /* If there is an error, long jump back to the caller. */
|
|
+ if (msg != NULL)
|
|
+ _dl_signal_error (0, m->l_initfini[legacy_obj]->l_name, "dlopen",
|
|
+ msg);
|
|
+
|
|
+ if (disable_feature_1 != 0)
|
|
+ {
|
|
+ int res = dl_cet_disable_cet (disable_feature_1);
|
|
+ if (res)
|
|
+ {
|
|
+ if ((disable_feature_1
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0)
|
|
+ msg = N_("can't disable IBT");
|
|
+ else
|
|
+ msg = N_("can't disable SHSTK");
|
|
+ /* Long jump back to the caller on error. */
|
|
+ _dl_signal_error (-res, m->l_initfini[legacy_obj]->l_name,
|
|
+ "dlopen", msg);
|
|
+ }
|
|
+
|
|
+ /* Clear the disabled bits in dl_x86_feature_1. */
|
|
+ GL(dl_x86_feature_1) &= ~disable_feature_1;
|
|
+
|
|
+ THREAD_SETMEM (THREAD_SELF, header.feature_1,
|
|
+ GL(dl_x86_feature_1));
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+dl_cet_check (struct link_map *m, const char *program)
|
|
+{
|
|
+ struct dl_cet_info info;
|
|
+
|
|
+ /* Check how IBT and SHSTK should be enabled. */
|
|
+ info.enable_ibt_type = GL(dl_x86_feature_control).ibt;
|
|
+ info.enable_shstk_type = GL(dl_x86_feature_control).shstk;
|
|
+
|
|
+ info.feature_1_enabled = GL(dl_x86_feature_1);
|
|
+
|
|
+ /* No legacy object check if IBT and SHSTK are always on. */
|
|
+ if (info.enable_ibt_type == cet_always_on
|
|
+ && info.enable_shstk_type == cet_always_on)
|
|
+ {
|
|
+#ifdef SHARED
|
|
+ /* Set it only during startup. */
|
|
+ if (program != NULL)
|
|
+ THREAD_SETMEM (THREAD_SELF, header.feature_1,
|
|
+ info.feature_1_enabled);
|
|
+#endif
|
|
+ return;
|
|
}
|
|
+
|
|
+ /* Check if IBT and SHSTK were enabled by kernel. */
|
|
+ if (info.feature_1_enabled == 0)
|
|
+ return;
|
|
+
|
|
+ info.program = program;
|
|
+
|
|
+ /* Check which features should be enabled. */
|
|
+ info.enable_feature_1 = 0;
|
|
+ if (info.enable_ibt_type != cet_always_off)
|
|
+ info.enable_feature_1 |= (info.feature_1_enabled
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_IBT);
|
|
+ if (info.enable_shstk_type != cet_always_off)
|
|
+ info.enable_feature_1 |= (info.feature_1_enabled
|
|
+ & GNU_PROPERTY_X86_FEATURE_1_SHSTK);
|
|
+
|
|
+ /* Start with no legacy objects. */
|
|
+ info.feature_1_legacy = 0;
|
|
+ info.feature_1_legacy_ibt = 0;
|
|
+ info.feature_1_legacy_shstk = 0;
|
|
+
|
|
+#ifdef SHARED
|
|
+ if (program)
|
|
+ dl_cet_check_startup (m, &info);
|
|
+ else
|
|
+#endif
|
|
+ dl_cet_check_dlopen (m, &info);
|
|
}
|
|
|
|
void
|
|
--
|
|
2.40.1
|
|
|