简体   繁体   中英

Build .ko file from .c file using GCC command line

As a learning exercise, I'm trying to build a kernel object file from ac file which would only do printk("hello, world") when loaded with modprobe. My kernel version is 4.15.

So let's say I have this example code:

int printk(const char *fmt, ...);

struct platform_device;

struct platform_driver {
    int (*probe)(struct platform_device *);
    int (*remove)(struct platform_device *);
};

static struct platform_driver my_driver = {
    .probe = my_driver_probe,
    .remove = my_driver_remove
};

module_platform_driver(my_driver);

static int my_driver_probe(struct platform_device *pdev) {
        printk("my driver loaded\n");
    return 0;
}

static int my_driver_remove(struct platform_device *pdev) {
        printk("my driver removed\n");
    return 0;
}

How do I compile it using gcc to create a valid my_driver.ko file that can be loaded with modprobe ?

I'm trying to build a kernel object file from ac file which would only do printk("hello, world")

A short google search for such module resulted for me in the following examples: https://github.com/maK-/SimplestLKM https://github.com/moutoum/linux-kernel-module-hello-world https://github.com/ichergui/hello-world https://github.com/carloscdias/hello-world-linux-module .

How do I compile it using gcc to create a valid my_driver.ko file that can be loaded with modprobe?

The first project has the following source for a hello world module saved in hello.c :

#include<linux/init.h>
#include<linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("maK");

static int hello_init(void){
    printk(KERN_ALERT "Hello world!\n");
    return 0;
}

static void hello_exit(void){
    printk(KERN_ALERT "Goodbye cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

The following is a transcript of a session with compiling the first project with V=1 :

$ git clone https://github.com/maK-/SimplestLKM
Cloning into 'SimplestLKM'...
remote: Enumerating objects: 15, done.
remote: Total 15 (delta 0), reused 0 (delta 0), pack-reused 15
Receiving objects: 100% (15/15), 13.47 KiB | 431.00 KiB/s, done.
Resolving deltas: 100% (4/4), done.
$ cd SimplestLKM/
$ make V=1
make -C /lib/modules/5.10.72-1-lts/build M=/dev/shm/.1000.home.tmp.dir/SimplestLKM modules
make[1]: Entering directory '/usr/lib/modules/5.10.72-1-lts/build'
test -e include/generated/autoconf.h -a -e include/config/auto.conf || (        \
echo >&2;                           \
echo >&2 "  ERROR: Kernel configuration is invalid.";       \
echo >&2 "         include/generated/autoconf.h or include/config/auto.conf are missing.";\
echo >&2 "         Run 'make oldconfig && make prepare' on kernel src to fix it.";  \
echo >&2 ;                          \
/bin/false)
make -f ./scripts/Makefile.build obj=/dev/shm/.1000.home.tmp.dir/SimplestLKM \
single-build= \
need-builtin=1 need-modorder=1
  gcc -Wp,-MMD,/dev/shm/.1000.home.tmp.dir/SimplestLKM/.hello.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -fmacro-prefix-map=./= -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -fcf-protection=none -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 -fno-allow-store-data-races -Wframe-larger-than=2048 -fstack-protector-strong -Wimplicit-fallthrough -Wno-unused-but-set-variable -Wno-unused-const-variable -g -gdwarf-4 -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -Wno-zero-length-bounds -Wno-array-bounds -Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wno-packed-not-aligned -fplugin=./scripts/gcc-plugins/structleak_plugin.so -fplugin-arg-structleak_plugin-byref-all -DSTRUCTLEAK_PLUGIN  -DMODULE  -DKBUILD_BASENAME='"hello"' -DKBUILD_MODNAME='"hello"' -c -o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.c
   ./tools/objtool/objtool orc generate  --module --no-fp --retpoline --uaccess /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.o
  { echo  /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.o;  echo; } > /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.mod
  {   echo /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.ko; :; } | awk '!x[$0]++' - > /dev/shm/.1000.home.tmp.dir/SimplestLKM/modules.order
make -f ./scripts/Makefile.modpost
  sed 's/ko$/o/' /dev/shm/.1000.home.tmp.dir/SimplestLKM/modules.order | scripts/mod/modpost  -a   -o /dev/shm/.1000.home.tmp.dir/SimplestLKM/Module.symvers -e -i Module.symvers  -N -T -
make -f ./scripts/Makefile.modfinal
  gcc -Wp,-MMD,/dev/shm/.1000.home.tmp.dir/SimplestLKM/.hello.mod.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -fmacro-prefix-map=./= -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -fcf-protection=none -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 -fno-allow-store-data-races -Wframe-larger-than=2048 -fstack-protector-strong -Wimplicit-fallthrough -Wno-unused-but-set-variable -Wno-unused-const-variable -g -gdwarf-4 -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -Wno-zero-length-bounds -Wno-array-bounds -Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wno-packed-not-aligned -fplugin=./scripts/gcc-plugins/structleak_plugin.so -fplugin-arg-structleak_plugin-byref-all -DSTRUCTLEAK_PLUGIN  -DMODULE  -DKBUILD_BASENAME='"hello.mod"' -DKBUILD_MODNAME='"hello"' -c -o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.mod.o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.mod.c
  ld -r -m elf_x86_64 --build-id=sha1  -T scripts/module.lds -o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.ko /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.mod.o;  true
make[1]: Leaving directory '/usr/lib/modules/5.10.72-1-lts/build'

From that we know that we also need the generated hello.mod.c. The content for this module as generated by modpost program is as follows:

#include <linux/module.h>
#define INCLUDE_VERMAGIC
#include <linux/build-salt.h>
#include <linux/vermagic.h>
#include <linux/compiler.h>

BUILD_SALT;

MODULE_INFO(vermagic, VERMAGIC_STRING);
MODULE_INFO(name, KBUILD_MODNAME);

__visible struct module __this_module
__section(".gnu.linkonce.this_module") = {
    .name = KBUILD_MODNAME,
    .init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
    .exit = cleanup_module,
#endif
    .arch = MODULE_ARCH_INIT,
};

#ifdef CONFIG_RETPOLINE
MODULE_INFO(retpoline, "Y");
#endif

MODULE_INFO(depends, "");


MODULE_INFO(srcversion, "C7C2D304485DDC1C93263AE");

With both files in place, we can compile them with gcc, first to hello.o and hello.mod.o and then combine with ld . So these are the compiler flags needed to compile the module on my system :

( cd /usr/lib/modules/5.10.72-1-lts/build/ && gcc -nostdinc -isystem /usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -fmacro-prefix-map=./= -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -fcf-protection=none -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 -fno-allow-store-data-races -Wframe-larger-than=2048 -fstack-protector-strong -Wimplicit-fallthrough -Wno-unused-but-set-variable -Wno-unused-const-variable -g -gdwarf-4 -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -Wno-zero-length-bounds -Wno-array-bounds -Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wno-packed-not-aligned -fplugin=./scripts/gcc-plugins/structleak_plugin.so -fplugin-arg-structleak_plugin-byref-all -DSTRUCTLEAK_PLUGIN  -DMODULE  -DKBUILD_BASENAME='"hello"' -DKBUILD_MODNAME='"hello"' -c -o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.c )

( cd /usr/lib/modules/5.10.72-1-lts/build/ && gcc -nostdinc -isystem /usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -fmacro-prefix-map=./= -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -fcf-protection=none -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 -fno-allow-store-data-races -Wframe-larger-than=2048 -fstack-protector-strong -Wimplicit-fallthrough -Wno-unused-but-set-variable -Wno-unused-const-variable -g -gdwarf-4 -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -Wno-zero-length-bounds -Wno-array-bounds -Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wno-packed-not-aligned -fplugin=./scripts/gcc-plugins/structleak_plugin.so -fplugin-arg-structleak_plugin-byref-all -DSTRUCTLEAK_PLUGIN  -DMODULE  -DKBUILD_BASENAME='"hello"' -DKBUILD_MODNAME='"hello"' -c -o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.mod.o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.mod.c )

( cd /usr/lib/modules/5.10.72-1-lts/build/ && ld -r -m elf_x86_64 --build-id=sha1  -T scripts/module.lds -o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.ko /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.o /dev/shm/.1000.home.tmp.dir/SimplestLKM/hello.mod.o )

After that we can insmod hello.ko and have hello world printed with CRIT in dmesg.

what are the compiler flags to use in order to do it.

In the same fashion as presented above, you can find out what options are passed to the compiler on your system .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM