Skip to content

Commit

Permalink
lib/test_map_h: add new module to test map.h macros
Browse files Browse the repository at this point in the history
Build test_map_h.ko to validate MAP & MAP_LIST

To test include/linux/map.h, this adds lib/test_map_h.c and config
TEST_MAP_H to build test_map_h.ko.  It uses BUILD_BUG_DEBUG, so that
failures of the macro just break the build.

So this adds config TEST_MAP_H stanza into:
menu "Compile-time checks and compiler options",
and fixes endmenu comment to match.

avoid __i386__, __builtin_memcmp ??

do runtime tests at modprobe, including a purposeful failure and warn.

default m, to maximize robot coverage. builtin doesn't add anything more.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
  • Loading branch information
jimc committed Mar 25, 2023
1 parent 3c634f2 commit eb0de9b
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 1 deletion.
15 changes: 14 additions & 1 deletion lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,20 @@ config DEBUG_FORCE_WEAK_PER_CPU
To ensure that generic code follows the above rules, this
option forces all percpu variables to be defined as weak.

endmenu # "Compiler options"
config TEST_MAP_H
tristate "module to test include/linux/map.h"
depends on DYNAMIC_DEBUG_CORE
default m
help
Adding include/linux/map.h requires proof that it works.

This adds test_map_h.ko, with BUILD_BUG_ON/compile-time
tests for MAP_LIST(__stringify, ...). Other macro_fn()s
are deemed equivalent.

Default m to see more compilers/cpps via @robots

endmenu # "Compile-time checks and compiler options"

menu "Generic Kernel Debugging Instruments"

Expand Down
1 change: 1 addition & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
obj-$(CONFIG_TEST_REF_TRACKER) += test_ref_tracker.o
CFLAGS_test_fprobe.o += $(CC_FLAGS_FTRACE)
obj-$(CONFIG_FPROBE_SANITY_TEST) += test_fprobe.o
obj-$(CONFIG_TEST_MAP_H) += test_map_h.o
#
# CFLAGS for compiling floating point code inside the kernel. x86/Makefile turns
# off the generation of FPU/SSE* instructions for kernel proper but FPU_FLAGS
Expand Down
91 changes: 91 additions & 0 deletions lib/test_map_h.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* test include/linux/map.h macros: MAP_LIST & MAP
*
* Authors:
* Jim Cromie <jim.cromie@gmail.com>
*/

#include <linux/map.h>
#include <linux/module.h>

/* compile-time test MAP */
static int sum = MAP( +, 1, 2, 3);
static char* caten = MAP(__stringify, YES, NO, MAYBE);

/* client/user defines enum NAMES as source of truth */
enum client_categories { DRMx_CORE, DRMx_DRIVER, DRMx_KMS };

/* test MAP_LIST(__stringify, ...). others deemed equivalent */
#define DEFINE_SLIST_FROM_ENUM_VALS_(_vec_, ...) \
const char *_vec_##_names[] = { \
MAP_LIST(__stringify, ##__VA_ARGS__) }

static DEFINE_SLIST_FROM_ENUM_VALS_(debug_cats, DRMx_CORE, DRMx_DRIVER, DRMx_KMS);

#if defined(__i386__)
/* avoid a "__compiletime_assert_" error */
#define BUILD_BUG_STREQ(_var, ref) BUILD_BUG_ON(0)
#else
/* test w 2 exprs, for now */
#define BUILD_BUG_STREQ(_var, ref) do { \
BUILD_BUG_ON(__builtin_memcmp(_var, ref, sizeof(ref))); \
BUILD_BUG_ON(__builtin_memcmp(_var, ref, __builtin_strlen(ref))); \
} while (0)
#endif
#define BUILD_BUG_STREQ_VI(_vec_, idx, ref) \
BUILD_BUG_STREQ(_vec_##_names[idx], ref)

/* force compile, even if its not called */
static void __used MAPH_BUILD_BUG(void)
{
BUILD_BUG_ON(sum != 6);
BUILD_BUG_STREQ(caten, "YESNOMAYBE");

BUILD_BUG_STREQ_VI(debug_cats, 0, "DRMx_CORE");
BUILD_BUG_STREQ_VI(debug_cats, 1, "DRMx_DRIVER");
BUILD_BUG_STREQ_VI(debug_cats, 2, "DRMx_KMS");

#ifdef MAPH_FORCE_FAIL
/* either breaks compile */
BUILD_BUG_ON(sum != 8);
BUILD_BUG_STREQ(debug_cats, 1, "'not-in-map'");
#endif
}

#define rTEST_eq(_v_, _ref) \
({ \
if (strcmp(_v_, _ref)) { \
pr_warn("failed: %s eq %s\n", _v_, _ref); \
} else { \
pr_debug("ok: %s eq %s\n", _v_, _ref); \
} \
})
#define rTEST_eq_VI(_v_, _i, _ref) rTEST_eq(_v_##_names[_i], _ref)

static int __init test_maph_init(void)
{
pr_debug("init start\n");

MAPH_BUILD_BUG();

rTEST_eq(caten, "YESNOMAYBE");
rTEST_eq_VI(debug_cats, 0, "DRMx_CORE");
rTEST_eq_VI(debug_cats, 1, "DRMx_DRIVER");
rTEST_eq_VI(debug_cats, 2, "DRMx_KMS");

/* force fail and ignore */
rTEST_eq_VI(debug_cats, 1, "'not-in-map'");
return 0;
}

static void __exit test_maph_exit(void)
{
pr_debug("exited\n");
}

module_init(test_maph_init);
module_exit(test_maph_exit);

MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
MODULE_LICENSE("GPL");

0 comments on commit eb0de9b

Please sign in to comment.