Can't cross-compile simple kernel module - linux-kernel

I'm trying to compile following 'Hello World'.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("BOBR");
MODULE_DESCRIPTION("HELLO MODULE");
MODULE_VERSION("0.10");
static char *name = "user";
module_param(name, charp, S_IRUGO);
MODULE_PARM_DESC(name, "The name to display");
static int __init hello_init(void) {
printk(KERN_INFO "HEllo, %s!\n", name);
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_INFO "Goodbye, %s !\n", name);
}
module_init(hello_init);
module_exit(hello_exit);
My Makefile is
ifneq ($(KERNELRELEASE),)
include Kbuild
#KDIR ?= ../repos/linux
else
KDIR ?= /lib/modules/4.9.0-6-amd64/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
clean:
$(MAKE) -C $(KDIR) M=$$PWD clean
endif
I start make as: make ARCH=arm CROSS_COMPILE='ccache arm-eabi-' PATH=/opt/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin:$PATH
I compile on Debian 4.9.0-6-amd64. Target is arm32 4.16.18.
The problem is that I get a module for my host machine (I can insmod it), but the target kernel rejects it as invalid module.
When I try to change the linux path in the Makefile to the target kernel sources, the compilation fails with fatal error: asm/barrier.h: No such file or directory.

Related

"Unknown symbol" shown when 'insmod' module1 calls function declared in module2

I am newbee to linux kernel. Currently I want to have 2 module they can interact with each other. I've tried to call function2 from module2 in module1 by EXPORT_SYMBOL_GPL. When I 'insmod' module1 it tells me function2 is "unknown symbol" to module1. I did export function2 and add -DEXPORT_SYMTAB in Makefile. What else I miss? Any advice great appreciate.
Here's my hello samples
/* *************************************************************************************
* hello-1.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include "hello2.h"
static int __init init_module1(void)
{
printk(KERN_INFO "Hello world 1.\n");
function2();
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
static void __exit cleanup_module1(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
module_init(init_module1);
module_exit(cleanup_module1);
MODULE_DESCRIPTION("Hello1");
MODULE_LICENSE("GPL");
/* *************************************************************************************
* hello-2.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
static void function2 (void)
{
printk(KERN_INFO "Function called in hello2.\n");
}
EXPORT_SYMBOL_GPL(function2);
static int __init init_module2(void)
{
printk(KERN_INFO "Hello world 2.\n");
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
static void __exit cleanup_module2(void)
{
printk(KERN_INFO "Goodbye world 2.\n");
}
module_init(init_module2);
module_exit(cleanup_module2);
MODULE_DESCRIPTION("Hello2");
MODULE_LICENSE("GPL");
/* *************************************************************************************
* hello-2.h - The simplest kernel module header
*/
extern void function2 (void);
################################################
# Makefile for hello2
PWD := $(shell pwd)
KVERSION := $(shell uname -r)
KDIR := /lib/modules/$(shell uname -r)/build
KERNEL_DIR := /usr/src/linux-headers-$(KVERSION)/
INSTALL_PATH := /lib/modules/$(shell uname -r)/extra
EXTRA_CFLAGS = -DEXPORT_SYMTAB
MODULE_NAME = hello2
obj-m := hello2.o
#.PHONY: all clean insert
.PHONY: all clean
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
rm -rf *.o *.ko *.mod.* .c* .t*
insert:
$(MAKE) INSTALL_MOD_DIR=$(INSTALL_PATH) -C $(KDIR) M=$(PWD) modules_install
In hello-2.c you have:
static void function2 (void)
{
...
}
Please consider making it non-static:
void function2(void)
{
...
}
I found the solution from an old post:
insmod fails with "Unknown symbol in module" for a symbol defined in another module
Turns out 2 modules need to be built at the same time. I built they separately with 2 different Makefile.

Makefile pass define at compile time?

I am trying to pass a "define variable called DEBUG" at compile time for a kernel module.
i.e provide the same functionality as DEBUG does below, but in a Makefile for a kernel module.
gcc -o foo -DDEBUG=1 foo.c
Can anyone give me a hint on how this can be achieved?
The Makefile:
# name of the module to be built
TARGET ?= test_module
# How to pass this during compile time? (-D$(DEBUG) or something similar)
DEBUG ?= 1
#define sources
SRCS := src/hello.c
#extract required object files
OBJ_SRCS := $(SRCS:.c=.o)
#define path to include directory containing header files
INCLUDE_DIRS = -I$(src)/includes
ccflags-y := $(INCLUDE_DIRS)
#define the name of the module and the source files
obj-m += $(TARGET).o
$(TARGET)-y := $(OBJ_SRCS)
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
#echo "insert module:\n\t sudo insmod $(TARGET).ko"
#echo "remove module:\n\t sudo rmmod $(TARGET)"
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
I am using the module from link (with a small change in the init function, see the #if #endif statement)
hello.c:
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lakshmanan");
MODULE_DESCRIPTION("A Simple Hello World module");
static int __init hello_init(void)
{
#if (DEBUG == 1)
printk(KERN_INFO "DEBUG = 1\n")
#endif
printk(KERN_INFO "Hello world!\n");
return 0; // Non-zero return means that the module couldn't be loaded.
}
static void __exit hello_cleanup(void)
{
printk(KERN_INFO "Cleaning up module.\n");
}
module_init(hello_init);
module_exit(hello_cleanup);
I would like to see that dmesg poduces the following after
sudo insmod test_module.ko
DEBUG = 1
Hello world!
Solution:
ccflags-y := -DDEBUG=$(DEBUG)
Made the code below execute as intended
#if (DEBUG == 1)
printk(KERN_INFO "DEBUG = 1\n")
#endif
ccflags-y := -DDEBUG=$(DEBUG)
Made the code below execute as intended
#if (DEBUG == 1)
printk(KERN_INFO "DEBUG = 1\n")
#endif

Unknown symbol in module : printk_all_partitions

I have compiled this code:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/genhd.h> // declaration of printk_all_partitions()
MODULE_LICENSE("GPL");
int __init start (void) {
printk ("evaluating the module ") ;
printk_all_partitions();
printk (" module inserted .. ");
return 0 ;
}
void __exit x(void) {
printk ("module unloaded ..");
}
module_init(start);
module_exit (x);
MODULE_LICENSE("GPL");
makefile is:
EXTRA_CFLAGS += -Wall
obj-m += printk_all_partitions.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 I get
WARNING: "printk_all_partitions" [/root/c++/modulez/multiple_source_files/printk_plm/printk_all_partitions.ko] undefined!
egrep -w 'printk|printk_all_partitions' /proc/kallsyms :
ffffffff8162f135 T printk
ffffffff81ac7b46 T printk_all_partitions
Now the only difference between printk and printk_all_partitions is that printk_all_partitions does not exist in the Module.symvers
and printk is:
0x27e1a049 printk vmlinux EXPORT_SYMBOL
By the time i finished the writing I found out that a function must be EXPORT_SYMBOL-ed too in order for it to work
but if (somehow) Modules.symvers was deleted , and the kernel sources were not available, both printk and printk_all_partitions are begin with a "T", what other way to know is one is exported or not?
Normally this line
obj-m += printk_all_partitions.o
is the name of the module you're trying to create. In this case you're naming your module the same as an existing symbol, is this deliberate?

How to print linux kernel version number in kernel module

I'm a noob to linux kernel programming and thought I'd be able to find the answer for this (since it seems really simple) but haven't had any luck yet. I need to make a linux kernel module that prints the version number of the kernel. The assignment requires that implement a module which displays this kind of message when loaded:
"Hello Master. You are currently using Linux (version)", where (version) is the kernel version no.
How can I do this? I tried using uname (http://man7.org/linux/man-pages/man2/uname.2.html) but when I include sys/utsname.h, I get a fatal error upon compiling with my makefile
"Cannot open include file: 'sys/utsname.h': No such file or directory".
Here is my module
#undef __KERNEL__
#define __KERNEL__
#undef __MODULE__
#define __MODULE__
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <sys/utsname.h>
struct utsname unameData;
static int __init config_init(void)
{
uname(&unameData);
printk(KERN_INFO "Version number is %s\n", unameData.version);
return 0;
}
static void __exit config_exit(void)
{
printk(KERN_INFO "config_exit executed with success\n");
return;
}
module_init(config_init);
module_exit(config_exit);
MODULE_LICENSE("GPL");
Makefile
obj-m := config.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
Firstly, you need to use the correct headers and also the correct function utsname(). Following code work well for me.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/utsname.h>
static int __init my_init(void)
{
printk(KERN_INFO "Kernel version %s\n", utsname()->version);
printk(KERN_INFO "Kernel release %s\n", utsname()->release);
return 0;
}
static void __exit my_exit(void)
{
printk(KERN_INFO "exit module");
return;
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
dmesg output should looks something like this:
[ 1117.358451] Kernel version #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014
[ 1117.358457] Kernel release 3.13.0-37-generic

Simple Makefile for multi-files

all:
I have 2 files, module1.c and module2.c which contains functions needed by the third file, big_module.c. My Makefile complained of not finding functions defined in module1.c and module2.c. These functions are needed by big_module.c Could you please help me defining my Makefile so it would work?
module1.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
int module1 (struct file *filp, struct vm_area_struct *vma)
{ return 0; }
int __init init_module1 (void)
{ return 0; }
void __exit cleanup_module1 (void)
{ }
module2.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/io.h>
unsigned long virt_addr;
int module2(struct file * filp, struct vm_area_struct * vma)
{ return 0; }
int __init init_module2 (void)
{ return 0; }
void __exit cleanup_module2 (void) { }
big_module.c
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/vt_kern.h>
#include <linux/fs.h>
MODULE_DESCRIPTION("Example");
MODULE_AUTHOR("Your Name Here");
MODULE_LICENSE("GPL");
static int __init hello_init(void)
{
init_module1();
init_module2();
return 0;
}
static void __exit hello_cleanup(void)
{
cleanup_module1();
cleanup_module2();
}
module_init(hello_init);
module_exit(hello_cleanup);
Makefile:
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m += big_module.o
obj-m += module1.o
obj-m += module2.o
modules:
$(MAKE) -C $(KDIR) M=$(PWD) modules
Errors:
> uu#uu-VirtualBox:~/UCSC-Ext/LDDII/Assignment3/ASK$ sudo make
> make -C /lib/modules/3.10.0uu/build M=/home/uu/UCSC-Ext/LDDII/Assignment3/ASK modules
> make[1]: Entering directory `/usr/src/linux-3.10'
> CC [M] /home/uu/UCSC-Ext/LDDII/Assignment3/ASK/big_module.o
> /home/uu/UCSC-Ext/LDDII/Assignment3/ASK/big_module.c: In function ‘hello_init’:
> /home/uu/UCSC-Ext/LDDII/Assignment3/ASK/big_module.c:14:2: error: implicit declaration of function ‘init_module1’
> [-Werror=implicit-function-declaration]
> /home/uu/UCSC-Ext/LDDII/Assignment3/ASK/big_module.c:15:2: error: implicit declaration of function ‘init_module2’
> [-Werror=implicit-function-declaration]
> /home/uu/UCSC-Ext/LDDII/Assignment3/ASK/big_module.c: In function ‘hello_cleanup’:
> /home/uu/UCSC-Ext/LDDII/Assignment3/ASK/big_module.c:21:2: error: implicit declaration of function ‘cleanup_module1’
> [-Werror=implicit-function-declaration]
> /home/uu/UCSC-Ext/LDDII/Assignment3/ASK/big_module.c:22:2: error: implicit declaration of function ‘cleanup_module2’
> [-Werror=implicit-function-declaration]
> cc1: some warnings being treated as errors
> make[2]: *** [/home/uu/UCSC-Ext/LDDII/Assignment3/ASK/big_module.o] Error 1
> make[1]: *** [_module_/home/uu/UCSC-Ext/LDDII/Assignment3/ASK] Error 2
> make[1]: Leaving directory `/usr/src/linux-3.10'
> make: *** [modules] Error 2
all:
I found the solution to my question. It's in the Makefile which should look
like the following:
Makefile
=======================
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m := big_module.o
big_module-objs := module1.o module2.o
modules:
$(MAKE) -C $(KDIR) M=$(PWD) modules
=======================

Resources