Compiling Linux Kernel Module With A Custom Header - linux

I would like to compile a simple character device module depending on a custom header. The folder is thus organized,
+ mymod.c
| customized-header.h
| customized-header.c
| Makefile
In mymod.c, the header is thus used,
#include "customized-header.h"
In Makefile:
obj-m := mymod.o
mymod-objs := customized-header.o
KVERSION = $(shell uname -r)
PWD = $(shell pwd)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
Everything should work fine, the module gets compiled without problem, I can load the module through sudo insmod, but the module doesn't work properly. When I checked nm mymod.ko, there are a lot of vars and functions are missing. It looks as if it stopped after linking customized_header.o. If I remove this header and its function, say no header function calls from the module, it compiles perfectly with desired result.
Could you see what went wrong here?

The problem resides in the Makefile. Due to the link here, I changed it into
obj-m: mymodko.o
mymodko-obj: customized-header.o mymod.o
It now works fine. So the question was the naming of module object. We need to specify different names as in this case mymodko.o and mymod.o.

Related

GET WARNING: modpost: missing MODULE_LICENSE() when LKM is Compiled with Multiple Src files

I have a LKM named RtmNetlinkLKM.c and compiles and run fine. The moment I update its Makefile to compile with other src files, it starts giving warning:
WARNING: modpost: missing MODULE_LICENSE()
The following MODULE_LICENSE("GPL"); is already present in kernel module file.
Previous Makefile, module compiles fine
obj-m += RtmNetlinkLKM.o
all:
make -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
make -C /lib/modules/`uname -r`/build M=$(PWD) clean
updated Makefile, module now compiles with a warning
obj-m += RtmNetlinkLKM.o
RtmNetlinkLKM-objs += rt_kern.o gluethread/glthread.o << Added two more sources
all:
make -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
make -C /lib/modules/`uname -r`/build M=$(PWD) clean
rm -f rt_kern.o
rm -f gluethread/glthread.o
When compiled using second Makefile, it gives stated warning. When I add MODULE_LICENSE("GPL") in gluethread/glthread.c , warning goes away. I don't understand, why do I need to add "GPL" license in glthread.c when it is not a module but contain functions to be used by module (It is a linked list mini-library). Why doesn't it complain with other src file rt_kern.c in a similar way. I had never made any changes in original module file RtmNetlink.c throughout this process.
Thanks to #Gautham Kantharaju in link provided by #Tsyvarev for solving my problem. While compiling multiple source files into a single module, the main reason for the warning seems to be, ".. it is not possible to have the module name and the source name to be the same."
If anyone else has the same question, I think following Makefile should solve the issue.
# give your module a different Name
obj-m += newModuleName.o
newModuleName-objs += RtmNetlinkLKM.o rt_kern.o gluethread/glthread.o
all:
make -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
make -C /lib/modules/`uname -r`/build M=$(PWD) clean

header and c files not included in build linux kernel

For a lpc3250 board, we had to developer a Linux kernel module to control the PWM output. I've created a 'helper' module which contains methodes like PMW1_ENABLE which set the correct bit at 1.
Unfortunately I run into problems when I create multiple .c and .h files. When I put all the code in just 1 file, the solution works fine. When I split it nicely in additional .c and .h files, something weird is happening. Even just printk statements do not show up on the console.
Most weird part, during cross compiling, no errors are shown so it looks like the binary is ok but it isn't.
Does this sound familiair? Could it be an issue with my makefile?
ARCH := arm
CROSS_COMPILE := /usr/local/xtools/arm-unknown-linux-uclibcgnueabi/bin/arm-linux-
CC= $(CROSS_COMPILE)gcc
obj-m := pwmdriver.o
pwmdriver-objs := pwmhelper.o pwmdriver.o
KDIR := /home/student/felabs/sysdev/tinysystem/linux-2.6.34
WORKINGDIRFIXED := /home/student/PRT/5_AssigPWM
export
all:
$(MAKE) -C $(KDIR) M=$(WORKINGDIRFIXED) modules
clean:
$(MAKE) -C $(KDIR) M=$(WORKINGDIRFIXED) clean

How to rename a kernel module name without renaming the .ko passed to insmod?

I need to rename a kernel module (the name that get displayed with lsmod) of an already existing driver without changing the name of the source file.
e.g.
# insmod xxx.ko
<<module loads successfully>>
# lsmod
Module Size Used by Tainted: P
xxx 191527 0
#
I want to rename xxx to yyy.
Now I know that changing the name of the driver source file (when it involves a single file) changes the name of the module.
But I don't want to change the name of a source file.
Rename your obj-m in Makefile and set dependency of obj-m to original module.
For example, I have file hello.c that contain all of my source code. But I want module to be mynewname.
Here is whole Makefile that does this:
obj-m := mynewname.o
mynewname-objs := hello.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
I set obj-m to mynewname.o and make mynewname.o dependant on hello.o. After invoking make you'll get mynewname.ko.

Makefile variable substitution apparently not done even though := is used in declaration

I have a main kernel module with which other kernel modules communicate. I have structured the modules like this (conceptually):
main module/
|
\drivers/
|
|\driver1
|\driver2
\driver3
Since these are kernel modules, I need to compile them like this:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
However, since the Makefile of drivers can be called from previous directories, I need to do the $(shell pwd) before calling the other make (linux's make). So the Makefile now looks like this:
CURRENT_DIR := $(shell pwd)
.PHONY: all
all:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) modules
So far it is fine and it works perfectly. The problem is this: I have a file that the drivers need to include, so I have to give the include path to make. I first tried
EXTRA_CFLAGS += -I../..
and immediately understood why it doesn't work (relative path would be to /lib/module/... not to current directory). So I changed it to:
MAIN_MODULE_HOME := $(CURRENT_DIR)/../..
EXTRA_CFLAGS += -I$(MAIN_MODULE_HOME)
Oddly enough, this doesn't work! If I write
EXTRA_CFLAGS += -Ipath/I/get/from/pwd/../..
manually, it compiles! Can someone explain what I am doing wrong? Before calling make, I echoed $(CURRENT_DIR) and $(MAIN_MODULE_HOME) and the variables are meaningful.
I know that EXTRA_CFLAGS is not immediately evaluated, but since CURRENT_DIR and MAIN_MODULE_HOME are declared with := I don't understand how things are getting messed up.
(If anyone can phrase the question title better, please do!)
You should pass EXTRA_CFLAGS to make like this:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) \
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" modules
Update:
The content of driver1/Makefile is read twice: first - when you run make inside driver1 directory, second - by Kbuild system.
First, CURRENT_DIR := $(shell pwd) is evaluated to something like /home/users/.../main module/drivers/driver1. Second, Kbuild evaluates CURRENT_DIR := $(shell pwd) to something like /usr/src/linux-headers-2.6.32-33-generic/
That situation described in LDD3, ch2, p24
The trick is to write your makefile as follows:
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
#endif
It most likely because of recursive flavor of EXTRA_CFLAGS, which gets actually expanded in a sub-make, which doesn't have an access to MAIN_MODULE_HOME referred from it.
First, try to export MAIN_MODULE_HOME:
export MAIN_MODULE_HOME
I would also tried to flatten EXTRA_CFLAGS before using it (however, I'm not sure whether this is a good practice for Kbuild):
EXTRA_CFLAGS := $(EXTRA_CFLAGS)

How to keep asm output from Linux kernel module build

I'm working on a Linux kernel module for a 2.6.x kernel and I need to view the assembly output, though it's currently being done as a temporary file an deleted afterwords. I'd like to have the assembly output mixed with my C source file so I can easily trace where my problem lies. This is for an ARMv6 core and apparently objdump doesn't support this architecture. I've included my makefile below.
ETREP=/xxSourceTreexx/
GNU_BIN=$(ETREP)/arm-none-linux-gnueabi/bin
CROSS_COMPILE := $(GNU_BIN)/arm-none-linux-gnueabi-
ARCH := arm
KDIR=$(ETREP)/linux-2.6.31/
MAKE= CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) make
obj-m += xxfile1xx.o
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
Objdump does support that architecture. Your executable will be called arm-none-linux-gnueabi-objdump
Assuming gcc and the gnu assembler a more readable output than objdump can be had. Tell the assembler to retain its intermediate code using flags to gcc:
-Wa,-alh=basename.s
And to get basename to be the actual source filename you need to tell make:
-Wa,-alh=$<.s
which will leave piles of foo.c.s files laying around your source directory. The big problem here is that the way gcc works it uses temporary files between code generation and assembly. I can't find a way to make gcc save its intermediates but the assembler is happy to stash a listing for you.
Getting that argument into the Makefile CFLAGS is left as an exercise for the reader (because I kinda hate "make" and hate "gnu info" even more.
To get an assembly language listing of my Linux kernel modules, I added the assembler switches to the kernel scripts/Makefile.build.
#cmd_cc_o_c = $(CC) $(c_flags) -c -o $(#D)/.tmp_$(#F) $<
cmd_cc_o_c = $(CC) $(c_flags) -c -Wa,-alh=$<.lst -o $(#D)/.tmp_$(#F) $<
You could try the flag "-save-temps" to gcc.
It works for me in my embedded project, I haven't tried it on kernel builds.
The proper way is likely to add target dependencies in your module makefile / Kbuild file:
always-m += basename.s
(As kbuild has the proper targets to generate the .s files)
If you are lazy as I am, this could look like:
MOD_NAME := some_module_name
myunits := file1 file2 file3 ... and many more... without .c extension
obj-m := $(MOD_NAME).o
$(MOD_NAME)-y := $(addsuffix .o,$(myunits))
# Comment/uncomment to generate assembly / preprocessor output
always-m += $(addsuffix .s,$(myunits)) $(MOD_NAME).mod.s
always-m += $(addsuffix .i,$(myunits)) $(MOD_NAME).mod.i
(2 bonuses here: assembly for the generated module meta-registration file, and the preprocessor output)

Resources