forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Kunit to check the longest symbol length #956
Draft
sergiocollado
wants to merge
1
commit into
Rust-for-Linux:rust
Choose a base branch
from
sergiocollado:kunit_check_longest_symbol
base: rust
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Test the longest symbol length. Execute with: | ||
* ./tools/testing/kunit/kunit.py run longest-symbol | ||
* --arch=x86_64 --kconfig_add CONFIG_KPROBES=y --kconfig_add CONFIG_MODULES=y | ||
*/ | ||
|
||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
|
||
#include <kunit/test.h> | ||
#include <linux/stringify.h> | ||
#include <linux/kprobes.h> | ||
#include <linux/kallsyms.h> | ||
|
||
#define DI(name) s##name##name | ||
#define DDI(name) DI(n##name##name) | ||
#define DDDI(name) DDI(n##name##name) | ||
#define DDDDI(name) DDDI(n##name##name) | ||
#define DDDDDI(name) DDDDI(n##name##name) | ||
|
||
#define PLUS1(name) __PASTE(name, e) | ||
|
||
/*Generate a symbol whose name length is 511 */ | ||
#define LONGEST_SYM_NAME DDDDDI(g1h2i3j4k5l6m7n) | ||
|
||
/*Generate a symbol whose name length is 512 */ | ||
#define LONGEST_SYM_NAME_PLUS1 PLUS1(LONGEST_SYM_NAME) | ||
|
||
noinline int LONGEST_SYM_NAME(void) | ||
{ | ||
return 424242; | ||
} | ||
|
||
noinline int LONGEST_SYM_NAME_PLUS1(void) | ||
{ | ||
return 434343; | ||
} | ||
|
||
_Static_assert(sizeof(__stringify(LONGEST_SYM_NAME)) == KSYM_NAME_LEN, | ||
"Incorrect symbol length found. Expected KSYM_NAME_LEN: " | ||
__stringify(KSYM_NAME) ", but found: " | ||
__stringify(sizeof(LONGEST_SYM_NAME))); | ||
|
||
static void test_longest_symbol(struct kunit *test) | ||
{ | ||
KUNIT_EXPECT_EQ(test, 424242, LONGEST_SYM_NAME()); | ||
}; | ||
|
||
static void test_longest_symbol_kallsyms(struct kunit *test) | ||
{ | ||
unsigned long (*kallsyms_lookup_name)(const char *name); | ||
static int (*longest_sym)(void); | ||
|
||
struct kprobe kp = { | ||
.symbol_name = "kallsyms_lookup_name", | ||
}; | ||
|
||
if (register_kprobe(&kp) < 0) { | ||
pr_info("%s: kprobe not registered\n", __func__); | ||
kunit_warn(test, "test_longest_symbol kallsyms: kprobe not registered\n"); | ||
KUNIT_ASSERT_TRUE(test, register_kprobe(&kp) < 0); | ||
KUNIT_FAIL(test, "test_longest_symbol kallsysms: kprobe not registered\n"); | ||
return; | ||
} | ||
|
||
kunit_warn(test, "test_longest_symbol kallsyms: kprobe registered\n"); | ||
kallsyms_lookup_name = (unsigned long (*)(const char *name))kp.addr; | ||
unregister_kprobe(&kp); | ||
|
||
longest_sym = | ||
(void *) kallsyms_lookup_name(__stringify(LONGEST_SYM_NAME)); | ||
KUNIT_EXPECT_EQ(test, 424242, longest_sym()); | ||
}; | ||
|
||
static void test_longest_symbol_plus1(struct kunit *test) | ||
{ | ||
KUNIT_EXPECT_EQ(test, 434343, LONGEST_SYM_NAME_PLUS1()); | ||
}; | ||
|
||
static void test_longest_symbol_plus1_kallsyms(struct kunit *test) | ||
{ | ||
unsigned long (*kallsyms_lookup_name)(const char *name); | ||
static int (*longest_sym_plus1)(void); | ||
|
||
struct kprobe kp = { | ||
.symbol_name = "kallsyms_lookup_name", | ||
}; | ||
|
||
if (register_kprobe(&kp) < 0) { | ||
pr_info("%s: kprobe not registered\n", __func__); | ||
KUNIT_ASSERT_TRUE(test, register_kprobe(&kp) < 0); | ||
KUNIT_FAIL(test, "test_longest_symbol kallsysms: kprobe not registered\n"); | ||
return; | ||
} | ||
|
||
kunit_warn(test, "test_longest_symbol_plus1 kallsyms: kprobe registered\n"); | ||
kallsyms_lookup_name = (unsigned long (*)(const char *name))kp.addr; | ||
unregister_kprobe(&kp); | ||
|
||
longest_sym_plus1 = | ||
(void *) kallsyms_lookup_name(__stringify(LONGEST_SYM_NAME_PLUS1)); | ||
KUNIT_EXPECT_EQ(test, NULL, longest_sym_plus1); | ||
}; | ||
|
||
static struct kunit_case longest_symbol_test_cases[] = { | ||
KUNIT_CASE(test_longest_symbol), | ||
KUNIT_CASE(test_longest_symbol_kallsyms), | ||
KUNIT_CASE(test_longest_symbol_plus1), | ||
KUNIT_CASE(test_longest_symbol_plus1_kallsyms), | ||
{} | ||
}; | ||
|
||
static struct kunit_suite longest_symbol_test_suite = { | ||
.name = "longest-symbol", | ||
.test_cases = longest_symbol_test_cases, | ||
}; | ||
kunit_test_suite(longest_symbol_test_suite); | ||
|
||
MODULE_LICENSE("GPL"); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't build as a module:
The easy thing to do would be to make this a
bool
option, but this is exactly the sort of thing we probably should test as a module, too (maybe that's why the longest+1 name is working: the compiler/linker are fine, but the module tools (e.g. modpost) aren't). Fixing it up to work as a module would lose us some of the simplicity of the KUnit port, though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting ... yes, that may be very well the reason for the longest+1 working. That is good, because I was feeling quite uneasy about it.
I will look into it and make it a module.
Thanks for pointing it out :) 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sulix I have updated the code, so now it actually compiles and can be executed as a module (as referenced here: https://www.kernel.org/doc/html/latest/dev-tools/kunit/running_tips.html#running-tests-as-modules ).
Incredible as it sounds, the test with the longest symbol +1, when executed as a module, passes. Is not clear to me why. I have to delve into this further.
running kunit.py:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have taken a look: the test passes unexpectedly because the symbol is simply
LONGEST_SYM_PLUS1
, not the expected one (very long).This is due to two issues:
A typo in
LONGEST_SYM_PLUS1
vs.LONGEST_SYM_NAME_PLUS1
.The preprocessor will concatenate before expanding. So you need one level of indirection more, e.g. with the
__PASTE
macro.With this, the expected symbol is generated:
You can play with it at https://godbolt.org/z/9ach7Wq63.
Hope that helps!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:) Great! thanks a lot for having a look and pointing out the issue! I will fix this 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My pleasure, and apologies for the delay!