[DTrace-devel] [PATCH 2/2] Missing symbols for loadable modules when reading /proc/kallmodsyms
eugene.loh at oracle.com
eugene.loh at oracle.com
Tue Oct 5 14:20:19 PDT 2021
From: Eugene Loh <eugene.loh at oracle.com>
As DTv2 (DTrace on BPF) development started, the patch
"dtrace: handle .init.scratch section in /proc/kallmodsyms" was applied,
but different versions were applied to DTv1 and DTv2: 81c6542 and f5c1f088,
respectively. The patch applied to DTv2 was wrong. In particular, once
dt_modsym_update() starts reading symbols for loadable modules, it sets
kernel_flag=-1. If there is no .init.scratch section, the code will
forever think it is nonetheless in such a section and ignore all symbols.
Hence, symbols for loadable modules are never read.
Fix dt_modsym_update(), specifically more in line with DTv1. Importantly,
- handle .init.scratch first
- make kernel_flag an unsigned int
- signal the beginning of loadable modules by
setting only one bit of kernel_flag, not all of them
Thanks to Rajan Shanmugavelu for reporting this problem.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
libdtrace/dt_module.c | 59 ++++++++++++++------------
test/unittest/aggs/tst.aggmod_full2.sh | 6 +--
test/unittest/consumer/tst.symbols.c | 6 +--
3 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/libdtrace/dt_module.c b/libdtrace/dt_module.c
index aaf125b8..fdc0886d 100644
--- a/libdtrace/dt_module.c
+++ b/libdtrace/dt_module.c
@@ -1066,6 +1066,27 @@ dt_kern_module_find_ctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
}
}
+/*
+ * We will use kernel_flag to track which symbols we are reading.
+ *
+ * /proc/kallmodsyms starts with kernel (and built-in-module) symbols.
+ *
+ * The last kernel address is expected to have the name "_end",
+ * but there might also be a symbol "__brk_limit" with that address.
+ * Set the KERNEL_FLAG_KERNEL_END flag while these addresses are read.
+ *
+ * Otherwise, symbols in /proc/kallmodsyms will normally belong to
+ * loadable modules. Set the KERNEL_FLAG_LOADABLE flag once these
+ * symbols are reached.
+ *
+ * Another odd case is the .init.scratch section introduced by e1bfa87
+ * ("x86/mm: Create a workarea in the kernel for SME early encryption"),
+ * which appears in 5.2-rc6. We ignore this section by setting the
+ * KERNEL_FLAG_INIT_SCRATCH flag.
+ */
+#define KERNEL_FLAG_KERNEL_END 1
+#define KERNEL_FLAG_LOADABLE 2
+#define KERNEL_FLAG_INIT_SCRATCH 4
/*
* Update our module cache. For each line, create or
* populate the dt_module_t for this module (if necessary), extend its address
@@ -1078,7 +1099,7 @@ dt_kern_module_find_ctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
static int
dt_modsym_update(dtrace_hdl_t *dtp, const char *line, int flag)
{
- static int kernel_flag = 1;
+ static uint_t kernel_flag = 0;
static dt_module_t *last_dmp = NULL;
static int last_sym_text = -1;
@@ -1132,29 +1153,7 @@ dt_modsym_update(dtrace_hdl_t *dtp, const char *line, int flag)
return 0;
/*
- * The file starts with kernel (and built-in-module) symbols.
- * The last kernel address is expected to have the name "_end".
- * (There might also be a symbol "__brk_limit" with that address.)
- * Thereafter, symbols will belong to loadable modules.
- *
- * kernel_flag==+1 means normal kernel (and built-in-module) symbols
- * kernel_flag==-1 means loadable-module symbols
- * kernel_flag==0 is an odd in-between case for the section markers
- * (they signal the imminent end of the kernel section)
- */
-
- if ((strcmp(sym_name, "_end") == 0) ||
- (strcmp(sym_name, "__brk_limit") == 0))
- kernel_flag = 0;
- else if (kernel_flag == 0)
- kernel_flag = -1;
-
-#define KERNEL_FLAG_INIT_SCRATCH 0x80
- /*
- * Another odd case is the .init.scratch section introduced by e1bfa87
- * ("x86/mm: Create a workarea in the kernel for SME early encryption"),
- * which appears in 5.2-rc6. We ignore this section by setting the
- * KERNEL_FLAG_INIT_SCRATCH flag in kernel_flag.
+ * Skip over the .init.scratch section.
*/
if (strcmp(sym_name, "__init_scratch_begin") == 0) {
kernel_flag |= KERNEL_FLAG_INIT_SCRATCH;
@@ -1165,7 +1164,12 @@ dt_modsym_update(dtrace_hdl_t *dtp, const char *line, int flag)
} else if (kernel_flag & KERNEL_FLAG_INIT_SCRATCH) {
return 0;
}
-#undef KERNEL_FLAG_INIT_SCRATCH
+
+ if ((strcmp(sym_name, "_end") == 0) ||
+ (strcmp(sym_name, "__brk_limit") == 0))
+ kernel_flag |= KERNEL_FLAG_KERNEL_END;
+ else if (kernel_flag & KERNEL_FLAG_KERNEL_END)
+ kernel_flag = KERNEL_FLAG_LOADABLE;
/*
* Special case: rename the 'ctf' module to 'shared_ctf': the
@@ -1247,7 +1251,7 @@ dt_modsym_update(dtrace_hdl_t *dtp, const char *line, int flag)
if (sym_size == 0)
return 0;
- if (kernel_flag >= 0) {
+ if ((kernel_flag & KERNEL_FLAG_LOADABLE) == 0) {
/*
* The kernel and built-in modules are in address order.
*/
@@ -1299,6 +1303,9 @@ dt_modsym_update(dtrace_hdl_t *dtp, const char *line, int flag)
return 0;
}
+#undef KERNEL_FLAG_KERNEL_END
+#undef KERNEL_FLAG_LOADABLE
+#undef KERNEL_FLAG_INIT_SCRATCH
/*
* Unload all the loaded modules and then refresh the module cache with the
diff --git a/test/unittest/aggs/tst.aggmod_full2.sh b/test/unittest/aggs/tst.aggmod_full2.sh
index 30642310..6baea432 100755
--- a/test/unittest/aggs/tst.aggmod_full2.sh
+++ b/test/unittest/aggs/tst.aggmod_full2.sh
@@ -1,7 +1,7 @@
#!/bin/bash
#
# Oracle Linux DTrace.
-# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.
#
@@ -56,7 +56,7 @@ int main(int argc, char **argv) {
char *line = NULL;
size_t line_n = 0;
FILE *fd;
- int kernel_flag = 0;
+ unsigned int kernel_flag = 0;
if ((fd = fopen("/proc/kallmodsyms", "r")) == NULL) return 1;
while ((getline(&line, &line_n, fd)) > 0) {
@@ -77,7 +77,7 @@ int main(int argc, char **argv) {
/* see dt_module.c dt_modsym_update() */
if (type == 'a' || type == 'A')
continue;
-#define KERNEL_FLAG_INIT_SCRATCH 0x80
+#define KERNEL_FLAG_INIT_SCRATCH 4
if (strcmp(symname, "__init_scratch_begin") == 0) {
kernel_flag |= KERNEL_FLAG_INIT_SCRATCH;
continue;
diff --git a/test/unittest/consumer/tst.symbols.c b/test/unittest/consumer/tst.symbols.c
index d1ece5c7..f6d8d5da 100644
--- a/test/unittest/consumer/tst.symbols.c
+++ b/test/unittest/consumer/tst.symbols.c
@@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
-/* @@xfail: dtv2 */
/*
* Check mappings between symbol names and addresses using /proc/kallmodsyms.
@@ -53,7 +52,8 @@ int read_symbols() {
char *line = NULL;
size_t line_n = 0;
FILE *fd;
- int n_skip = 0, n_absolute = 0, kernel_flag = 0;
+ int n_skip = 0, n_absolute = 0;
+ unsigned int kernel_flag = 0;
printf("read_symbols():\n");
if ((fd = fopen("/proc/kallmodsyms", "r")) == NULL) return 1;
@@ -96,7 +96,7 @@ int read_symbols() {
if (symbols[nsymbols].type == 'a' ||
symbols[nsymbols].type == 'A')
continue;
-#define KERNEL_FLAG_INIT_SCRATCH 0x80
+#define KERNEL_FLAG_INIT_SCRATCH 4
if (strcmp(symname, "__init_scratch_begin") == 0) {
kernel_flag |= KERNEL_FLAG_INIT_SCRATCH;
continue;
--
2.18.4
More information about the DTrace-devel
mailing list