[ ] Linux |
/proc/version
. , , Android, Android Code Aurora, Cyanogen Android, , . , msm-3.0. , , . , , . 3.0.21, 3.0.8. , , 3.1, 3.0.x. /proc/config.gz
, , , , ( , , , ).arm-eabi-gcc
PATH, , :$ mkdir build
$ gunzip config.gz > build/.config # , , .config
$ make silentoldconfig prepare headers_install scripts ARCH=arm CROSS_COMPILE=arm-eabi- O=build KERNELRELEASE=`adb shell uname -r`
silentoldconfig
, , , . , .KERNELRELEASE
, , .Makefile
. hello.c
, :#include module.h> /* Needed by all modules */
#include kernel.h> /* Needed for KERN_INFO */
#include init.h> /* Needed for the macros */
static int __init hello_start(void)
{
printk(KERN_INFO "Hello world\n");
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "Goodbye world\n");
}
module_init(hello_start);
module_exit(hello_end);
Makefile
:obj-m = hello.o
hello.mod.c
, :MODULE_INFO(vermagic, VERMAGIC_STRING);
VERMAGIC_STRING
UTS_RELEASE
, include/generated/utsrelease.h
, . , git-. , KERNELRELEASE
. VERMAGIC_STRING
, dmesg
:hello: version magic '3.0.21-perf-ge728813-00399-gd5fa0c9' should be '3.0.8-perf'
struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = KBUILD_MODNAME,
.init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
.exit = cleanup_module,
#endif
.arch = MODULE_ARCH_INIT,
};
struct module
, include/linux/module.h
, :struct module
{
(...)
#ifdef CONFIG_UNUSED_SYMBOLS
(...)
#endif
(...)
/* Startup function. */
int (*init)(void);
(...)
#ifdef CONFIG_GENERIC_BUG
(...)
#endif
#ifdef CONFIG_KALLSYMS
(...)
#endif
(...)
(... plenty more ifdefs ...)
#ifdef CONFIG_MODULE_UNLOAD
(...)
/* Destruction function. */
void (*exit)(void);
(...)
#endif
(...)
}
init
, CONFIG_UNUSED_SYMBOLS
, . exit, CONFIG_GENERIC_BUG
, CONFIG_KALLSYMS
, CONFIG_SMP
, CONFIG_TRACEPOINTS
, CONFIG_JUMP_LABEL
, CONFIG_TRACING
, CONFIG_EVENT_TRACING
, CONFIG_FTRACE_MCOUNT_RECORD
CONFIG_MODULE_UNLOAD
. static const struct modversion_info ____versions[]
__used
__attribute__((section("__versions"))) = {
{ 0xsomehex, "module_layout" },
{ 0xsomehex, "__aeabi_unwind_cpp_pr0" },
{ 0xsomehex, "printk" },
};
Module.symvers
, . module_layout
, , struct module
, , , , , . , __aeabi_unwind_cpp_pr0
, , ABI ARM, printk
.printk
, , , , .hello: disagrees about version of symbol symbol_name
Module.symvers
, . bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
struct module *owner,
void *data),
void *data)
{
struct module *mod;
static const struct symsearch arr[] = {
{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,
NOT_GPL_ONLY, false },
{ __start___ksymtab_gpl, __stop___ksymtab_gpl,
__start___kcrctab_gpl,
GPL_ONLY, false },
{ __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future,
__start___kcrctab_gpl_future,
WILL_BE_GPL_ONLY, false },
#ifdef CONFIG_UNUSED_SYMBOLS
{ __start___ksymtab_unused, __stop___ksymtab_unused,
__start___kcrctab_unused,
NOT_GPL_ONLY, true },
{ __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl,
__start___kcrctab_unused_gpl,
GPL_ONLY, true },
#endif
};
if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))
return true;
(...)
struct symsearch {
const struct kernel_symbol *start, *stop;
const unsigned long *crcs;
enum {
NOT_GPL_ONLY,
GPL_ONLY,
WILL_BE_GPL_ONLY,
} licence;
bool unused;
};
each_symbol_section
( , CONFIG_UNUSED_SYMBOLS
) , , .integer
each_symbol_section
, , Module.symvers .zImage
), . , . zImage
, .dmesg
:$ adb shell dmesg | grep "\.init"
<5>[01-01 00:00:00.000] [0: swapper] .init : 0xc0008000 - 0xc0037000 ( 188 kB)
0xc0008000
.$ python extract-symvers.py -B 0xc0008000 kernel-filename > Module.symvers
Module.symvers
, , (, , arm-eabi-gcc
PATH
, ):$ cp /path/to/Module.symvers build/
$ make M=/path/to/module/source ARCH=arm CROSS_COMPILE=arm-eabi- O=build modules
$ adb shell
# insmod hello.ko
# dmesg | grep insmod
<6>[mm-dd hh:mm:ss.xxx] [id: insmod]Hello world
# lsmod
hello 586 0 - Live 0xbf008000 (P)
# rmmod hello
# dmesg | grep rmmod
<6>[mm-dd hh:mm:ss.xxx] [id: rmmod]Goodbye world