parameter of module_init() and module_exit() must not be a macro

Warlich, Christof christof.warlich at siemens.com
Thu Oct 15 05:48:53 EDT 2015


I'd just like to get some feedback on the following issue and if the patch that I'm suggesting would be appropriate to be considered for upstream submission:

While writing a driver template, I just came across an issue with the module_init() and module_exit() macros: They don't work properly when the parameter being passed to them is a macro itself. Here is a minimal example that shows the issue:

$ cat test.c
#include <linux/module.h>
#define DRIVER_INIT test_init
static int __init DRIVER_INIT(void)
{
	return 0;
}
//module_init(test_init); // This works, ...
module_init(DRIVER_INIT); // ... but this doesn't.

Building the module gives the following errors:

$ make -C /lib/modules/$(uname -r)/build MODULES=test M=$(pwd) modules
make: Entering directory `/usr/src/linux-headers-3.13.0-65-generic'
  CC [M]  /home/adwach13/tmp/module/tst.o
In file included from /usr/src/linux-headers-3.13.0-65-generic/arch/x86/include/asm/ptrace.h:63:0,
                 from /usr/src/linux-headers-3.13.0-65-generic/arch/x86/include/asm/alternative.h:8,
                 from /usr/src/linux-headers-3.13.0-65-generic/arch/x86/include/asm/bitops.h:16,
                 from include/linux/bitops.h:36,
                 from include/linux/kernel.h:10,
                 from include/linux/cache.h:4,
                 from include/linux/time.h:4,
                 from include/linux/stat.h:18,
                 from include/linux/module.h:10,
                 from /home/adwach13/tmp/module/tst.c:1:
include/linux/init.h:298:6: error: 'init_module' aliased to undefined symbol 'DRIVER_INIT'
  int init_module(void) __attribute__((alias(#initfn)));
      ^
/home/adwach13/tmp/module/tst.c:8:1: note: in expansion of macro 'module_init'
 module_init(DRIVER_INIT);
 ^
make[1]: *** [/home/adwach13/tmp/module/tst.o] Error 1
make: *** [_module_/home/adwach13/tmp/module] Error 2
make: Leaving directory `/usr/src/linux-headers-3.13.0-65-generic'

The reason for this behavior is because macro stringification is not done properly in the module_init() and module_exit() macro definitions in include/linux/init.h. But a fix would be easy:

$ diff -Nau /usr/src/linux-headers-3.13.0-65-generic/include/linux/init.h.orig  /usr/src/linux-headers-3.13.0-65-generic/include/linux/init.h
--- /usr/src/linux-headers-3.13.0-65-generic/include/linux/init.h.orig  2015-10-15 11:40:36.300458826 +0200
+++ /usr/src/linux-headers-3.13.0-65-generic/include/linux/init.h       2015-10-15 11:42:05.370985262 +0200
@@ -291,17 +291,20 @@
 
 #define security_initcall(fn)          module_init(fn)
 
+#define _STRINGIFY(x) #x
+#define STRINGIFY(x) _STRINGIFY(x)
+
 /* Each module must use one module_init(). */
 #define module_init(initfn)                                    \
        static inline initcall_t __inittest(void)               \
        { return initfn; }                                      \
-       int init_module(void) __attribute__((alias(#initfn)));
+       int init_module(void) __attribute__((alias(STRINGIFY(initfn))));
 
 /* This is only required if you want to be unloadable. */
 #define module_exit(exitfn)                                    \
        static inline exitcall_t __exittest(void)               \
        { return exitfn; }                                      \
-       void cleanup_module(void) __attribute__((alias(#exitfn)));
+       void cleanup_module(void) __attribute__((alias(STRINGIFY(exitfn))));
 
 #define __setup_param(str, unique_id, fn)      /* nothing */
 #define __setup(str, func)                     /* nothing */

What do you think: Is this patch worth to be suggested? Or is the current behavior intended?




More information about the Kernelnewbies mailing list