In my limited experience with kernel program, my os is Ubuntu16.04,and use sudo apt-get install linux-headers-`uname -r` to install kernel header,and the kernel_hello.c file is
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("DUAL BSD/GPL")
MODULE_AUTHOR("YANQIN")
MODULE_DESCRIPTION("kernel module hello")
MODULE_VERSION("1.0")
static int hello_init(void)
{
printk(KERN_ALERT "hello_init() start\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "hello_exit() start\n");
}
module_init(hello_init);
module_exit(hello_exit);
and the Makefile is
KERNAL_DIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m := kernel_hello.o
default:
$(MAKE) -C $(KERNAL_DIR) M=$(PWD) modules
but the build result is like this
yq#ubuntu:~/kernelProgram$ make
make -C /lib/modules/4.10.0-28-generic/build M=/home/yq/kernelProgram modules
make[1]: Entering directory '/usr/src/linux-headers-4.10.0-28-generic'
CC [M] /home/yq/kernelProgram/kernel_hello.o
In file included from ./include/linux/module.h:18:0,
from /home/yq/kernelProgram/kernel_hello.c:2:
./include/linux/moduleparam.h:21:1: error: expected ‘,’ or ‘;’ before ‘static’
static const char __UNIQUE_ID(name)[] \
^
./include/linux/module.h:161:32: note: in expansion of macro ‘__MODULE_INFO’
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
^
/home/yq/kernelProgram/kernel_hello.c:6:1: note: in expansion of macro ‘MODULE_AUTHOR’
MODULE_AUTHOR("YANQIN")
^
In file included from /home/yq/kernelProgram/kernel_hello.c:2:0:
/home/yq/kernelProgram/kernel_hello.c: In function ‘__inittest’:
/home/yq/kernelProgram/kernel_hello.c:19:13: error: ‘hello_init’ undeclared (first use in this function)
module_init(hello_init);
^
./include/linux/module.h:131:11: note: in definition of macro ‘module_init’
{ return initfn; } \
^
/home/yq/kernelProgram/kernel_hello.c: At top level:
./include/linux/module.h:132:6: error: ‘init_module’ aliased to undefined symbol ‘hello_init’
int init_module(void) __attribute__((alias(#initfn)));
^
/home/yq/kernelProgram/kernel_hello.c:19:1: note: in expansion of macro
‘module_init’
module_init(hello_init);
^
scripts/Makefile.build:301: recipe for target
'/home/yq/kernelProgram/kernel_hello.o' failed
make[2]: *** [/home/yq/kernelProgram/kernel_hello.o] Error 1
Makefile:1524: recipe for target '_module_/home/yq/kernelProgram' failed
make[1]: *** [_module_/home/yq/kernelProgram] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.10.0-28-generic'
Makefile:7: recipe for target 'default' failed
make: *** [default] Error 2
i don't know why it saids the linux kernel header has error
Calls to MODULE_LICENSE and other MODULE_* macros, which setup information about the module, should be terminated with ; like common C instructions
Related
I'm working on a STM32MP1 target with yocto. In general I can compile a helloworld .ko file and load it into the kernel. But when I want to compile following:
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/types.h>
static struct platform_device *pdev;
static int __init fake_eth_add(void)
{
int inst_id = 0;
pdev = platform_device_alloc("fake-eth", inst_id);
platform_device_add(pdev);
pr_info("fake-eth added");
return 0;
}
static void __exit fake_eth_put(void)
{
pr_info("fake-fake removed");
platform_device_put(pdev);
}
module_init(fake_eth_add);
module_exit(fake_eth_put);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Madieu <john.madieu#gmail.com>");
I get following errors:
ERROR: modpost: "platform_device_put" [/home/rdm/ethtest/eth-ins.ko] undefined!
ERROR: modpost: "platform_device_add" [/home/rdm/ethtest/eth-ins.ko] undefined!
ERROR: modpost: "platform_device_alloc" [/home/rdm/ethtest/eth-ins.ko] undefined!
I check if the platform_device_alloc Symbol/Function is defined and it does:
root#txmp-1570:/lib/modules/5.7.1/source/kernel# grep -w platform_device_alloc /proc/kallsyms
c0547cfc T platform_device_alloc
Now I have learned that the symbols must be in the Module.symvers File tagged as EXPORT_SYMBOL_GPL. The symbols were not there, so I added them to the Module.symvers file:
0x00000000 platform_device_alloc vmlinux EXPORT_SYMBOL_GPL
0x00000000 platform_device_add vmlinux EXPORT_SYMBOL_GPL
0x00000000 platform_device_put vmlinux EXPORT_SYMBOL_GPL
Now the code compiles! But when I want to load it with insmod, then I get following error:
root#txmp-1570:/home/rdm/ethtest# insmod eth-ins.ko
insmod: ERROR: could not insert module eth-ins.ko: Unknown symbol in module
And the dmseg logs:
[ 2954.658383] eth_ins: Unknown symbol platform_device_put (err -2)
[ 2954.664194] eth_ins: Unknown symbol platform_device_add (err -2)
[ 2954.672737] eth_ins: Unknown symbol platform_device_alloc (err -2)
What am I missing? Why did I have to append the Module.symvers file by myself? Did I miss something regarding setting up the enviromnent for kernel driver development?
I want to compile an own minimalistic Linux Kernel with make tinyconfig and after doing all steps (like here:)
I get this error message:
arch/x86/kernel/apic/apic.c:2282:6: error: redefinition of ‘apic_id_disabled’
bool apic_id_disabled(unsigned int id)
^~~~~~~~~~~~~~~~
In file included from arch/x86/kernel/apic/apic.c:47:0:
./arch/x86/include/asm/apic.h:529:20: note: previous definition of ‘apic_id_disabled’ was here
static inline bool apic_id_disabled(unsigned int id) { return false; }
^~~~~~~~~~~~~~~~
scripts/Makefile.build:330: recipe for target 'arch/x86/kernel/apic/apic.o' failed
make[6]: *** [arch/x86/kernel/apic/apic.o] Error 1
scripts/Makefile.build:604: recipe for target 'arch/x86/kernel/apic' failed
make[5]: *** [arch/x86/kernel/apic] Error 2
scripts/Makefile.build:604: recipe for target 'arch/x86/kernel' failed
make[4]: *** [arch/x86/kernel] Error 2
Makefile:1077: recipe for target 'arch/x86' failed
make[3]: *** [arch/x86] Error 2
make[3]: Verzeichnis „/home/lukas/kernel/linux-source-4.15.0“ wird verlassen
debian/ruleset/targets/common.mk:295: recipe for target 'debian/stamp/build/kernel' failed
make[2]: *** [debian/stamp/build/kernel] Error 2
make[2]: Verzeichnis „/home/lukas/kernel/linux-source-4.15.0“ wird verlassen
debian/ruleset/common/targets.mk:242: recipe for target 'debian/stamp/do-build-arch' failed
make[1]: *** [debian/stamp/do-build-arch] Error 2
make[1]: Verzeichnis „/home/lukas/kernel/linux-source-4.15.0“ wird verlassen
dpkg-buildpackage: Fehler: debian/rules build Unterprozess gibt Abbruchstatus 2 zurück
debian/ruleset/targets/common.mk:401: recipe for target 'debian/stamp/build/buildpackage' failed
make: *** [debian/stamp/build/buildpackage] Error 2
Thank you in advance
#ifdef CONFIG_SMP
535 bool apic_id_is_primary_thread(unsigned int id);
536 bool apic_id_disabled(unsigned int id);
537 #else
538 static inline bool apic_id_is_primary_thread(unsigned int id) { return false; }
539 static inline bool apic_id_disabled(unsigned int id) { return false; }
540 #endif
actually you can see the conflict code in /arch/x86/include/asm/apic.h
from these code, enable SMP in your config is the easiest way to fix this problem.
PROCESS:
make menuconfig
-> Processor type and features
enable [Symmetric multi-processing support] there
then
make -j8 # will compile successfully now
I'm trying to compile and run a "Hello World" module from the book "Linux Device Drivers"
the program ~/ldd3/hello.c I'm trying to compile is:
/*
* $Id: hello.c,v 1.5 2004/10/26 03:32:21 corbet Exp $
*/
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
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);
And the Makefile is:
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
When I run make, the compilation seems ok:
root#deb:/home/deb/ldd3# make
make -C /lib/modules/4.14.86/build M=/home/deb/ldd3 modules
make[1]: Entering directory '/home/deb/src/linux-4.14.86'
Building modules, stage 2.
MODPOST 1 modules
make[1]: Leaving directory '/home/deb/src/linux-4.14.86'
But when I run :
root#deb:/home/deb/ldd3# insmod ./hello.ko
root#deb:/home/deb/ldd3#
the "Hello World" message doesnt get printed.
Nor do I get a message printed when I run
rmmod hello
Can you tell me why?
Thanks
In order to see kernel messages, you can use dmesg.
Alternatively, you can see the syslog tail var/log/syslog.
I am trying to debug a JNI C function by inserting log messages, but I can't get it to work. To start with I am just trying to modify the hello-jni example that comes with Android Studio. This is the modified code:
#include <string.h>
#include <jni.h>
#include <android/log.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a/NEON (hard-float)"
#else
#define ABI "armeabi-v7a/NEON"
#endif
#else
#if defined(__ARM_PCS_VFP)
#define ABI "armeabi-v7a (hard-float)"
#else
#define ABI "armeabi-v7a"
#endif
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__x86_64__)
#define ABI "x86_64"
#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */
#define ABI "mips64"
#elif defined(__mips__)
#define ABI "mips"
#elif defined(__aarch64__)
#define ABI "arm64-v8a"
#else
#define ABI "unknown"
#endif
__android_log_write(ANDROID_LOG_ERROR, "TEST_TAG", "Error here");
return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");
}
And this is my Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_LDFLAGS := -llog
include $(BUILD_SHARED_LIBRARY)
When I use the ndk-build script the libhello-jni.so files get built no problem. When I try to build the project in Android Studio I get the following gradle error message
Information:Gradle tasks [:app:assembleDebug]
:app:preBuild
:app:compileDebugNdk
C:\Android\projects\hello-jni\app\build\intermediates\ndk\debug\obj/local/arm64-v8a/objs/hello-jni/C_\Android\projects\hello-jni\app\src\main\jni\hello-jni.o: In function `Java_com_example_hellojni_HelloJni_stringFromJNI':
hello-jni.c:(.text.Java_com_example_hellojni_HelloJni_stringFromJNI+0x24): undefined reference to `__android_log_write'
Error:error: ld returned 1 exit status
make.exe: *** [C:\Android\projects\hello-jni\app\build\intermediates\ndk\debug\obj/local/arm64-v8a/libhello-jni.so] Error 1
Error:Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
C:\Android\android-ndk-r10c\ndk-build.cmd NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=C:\Android\projects\hello-jni\app\build\intermediates\ndk\debug\Android.mk APP_PLATFORM=android-19 NDK_OUT=C:\Android\projects\hello-jni\app\build\intermediates\ndk\debug\obj NDK_LIBS_OUT=C:\Android\projects\hello-jni\app\build\intermediates\ndk\debug\lib APP_ABI=all
Error Code:
2
Output:
C:\Android\projects\hello-jni\app\build\intermediates\ndk\debug\obj/local/arm64-v8a/objs/hello-jni/C_\Android\projects\hello-jni\app\src\main\jni\hello-jni.o: In function `Java_com_example_hellojni_HelloJni_stringFromJNI':
hello-jni.c:(.text.Java_com_example_hellojni_HelloJni_stringFromJNI+0x24): undefined reference to `__android_log_write'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [C:\Android\projects\hello-jni\app\build\intermediates\ndk\debug\obj/local/arm64-v8a/libhello-jni.so] Error 1
Information:BUILD FAILED
Information:Total time: 3.297 secs
Information:2 errors
Information:0 warnings
Information:See complete output in console
I've tried the suggestions given in this question, but I still get the same error: What is the Log API to call from an Android JNI program?
What am I doing wrong?
I'm using Android Studio 0.8.9 and NDK r10c.
I found an answer after a bit more searching.
If I build the .so files using the ndk-build script on the command line and add
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
into my build.gradle file so gradle doesn't try to build the .so files it all then works. Looks like a problem with Android Studio-Gradle-NDK integration?
I found the answer here https://stackoverflow.com/a/21111458/4182796
Ugly workaround is to remove function call and rebuild sources just add this after includes :
#if 1
#undef __android_log_print
#define __android_log_print(...) {}
#endif
Hello stackoverflowers :)
For the last several hours I've been trying to compile+load a multiple file module. The compilation emits a strange warning and the module fails to load. Here are the module, Makefile, compilation output and dmesg.
header:
// header.h
#ifndef _HEADER_H
#define _HEADER_H
void do_module_func(void);
void do_other_func(void);
#endif
'main' module file:
//mymodule.c
#include <linux/module.h>
#include <linux/kernel.h>
#include "header.h"
void do_module_func(void)
{
printk(KERN_INFO "module_func\n");
}
static int mymodule_init(void)
{
printk(KERN_INFO "Hello world\n");
do_other_func();
return 0;
}
module_init(mymodule_init);
static void mymodule_exit(void)
{
printk(KERN_INFO "Goodbye, cruel world\n");
}
module_exit(mymodule_exit);
MODULE_LICENSE("GPL")
other c file, which calls do_module_func() that sits in the 'main' module
//other_file.c
#include "header.h"
#include <linux/kernel.h>
void do_other_func(void)
{
printk(KERN_INFO "other_func\n");
do_module_func();
}
Makefile
//Makefile
obj-m := mymodule.o
mymodule-objs := other_file.o
CROSS:=arm-unknown-linux-gnueabi-
KERNEL:= ~/work/linux-davinci-2.6.38/
ARCH:=arm
PWD:=$(shell pwd)
all:
$(MAKE) CROSS_COMPILE=$(CROSS) ARCH=$(ARCH) -C $(KERNEL) M=$(PWD) modules
clean:
$(MAKE) CROSS_COMPILE=$(CROSS) ARCH=$(ARCH) -C $(KERNEL) M=$(PWD) clean
I'm cross compiling but I believe this shouldn't be a problem.
make output:
make CROSS_COMPILE....
make[1]: Entering directory .../linux-davinci-2.6.38
CC [M] .../other_file.o
LD [M] .../mymodule.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "do_module_func" [.../mymodule.o] undefined! <--- warning here
CC .../mymodule.mod.o
LD [M] .../mymodule.ko
make[1]: Leaving directory .../linux-davinci-2.6.38
insmod output:
can't insert 'mymodule.ko': unknown symbol in module, or unknown parameter
dmesg:
mymodule: Unknown symbol do_mdule_func (err 0)
Thus the module compiles with a (linkage?) warning and the module doesn't load.
Now, I see that in the make output there appears to be a linkage attempt after compiling other_file.c, but shouldn't there be a compilation of also mymodule.c before the linkage?
Thanks! :)
Turns out the problem was in the Makefile. The 'trick' is that you define in obj-m the module that will be compiled (into a .ko) and in the -objs you write all the source files.
Thus the definitions in this Makefile turn to:
obj-m := moduleko.o
moduleko-objs := other_file.o mymodule.o
and this is compiled into moduleko.ko.
This is because file_2 required file_1 symbol reference for building file_2 as LKM.
To overcome this, build file_1(LKM) and place the Module.symvers of file_1 in file_2 location. And build the file_2 again.
all:
$(MAKE) CROSS_COMPILE=$(CROSS) ARCH=$(ARCH) -C $(KERNEL) M=$(PWD) modules
instead try like this
$(MAKE) -C $(KERNEL) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS) M=$(PWD) /
this will run each file and links with object.hope this would solve your problem