3

I'm trying to build a static -helper- library of pure C code (no standards c headers) and then link it with a kernel module in compile time in the Makefile, but I can't seem to get it working.

Let's say I have a library which is just this header file utils.h:

#ifndef __UTILS__
#define __UTILS__

int initialize(int value);
void increment(void);
int get(void);

#endif // __UTILS__

and it's implementation utils.c:

#include "utils.h"

int g_value;

int initialize(int value) {
  g_value = value;
  return 0;
}

void increment(void) {
  g_value++;
}

int get(void) {
  return g_value;
}

and I'm using this Makefile to build the library out of it:

BIN_DIR := .

# Specify extensions of files to delete when cleaning
CLEANEXTS   = o a

# Specify the target file and the install directory
OUTPUTFILE  = libutils.a
INSTALLDIR  = ../

# Default target
.PHONY: all
all: $(OUTPUTFILE)

# Build libutils.a from uilts.o
$(OUTPUTFILE): utils.o
    ar cr $@ $^
    ranlib $@

# No rule to build utils.o from .c 
# files is required; this is handled by make's database of
# implicit rules

.PHONY: install
install:
    mkdir -p $(INSTALLDIR)
    cp -p $(OUTPUTFILE) $(INSTALLDIR)

.PHONY: clean 
clean:
    for file in $(CLEANEXTS); do rm -f *.$$file; done

# Indicate dependencies of .c files on .h files
utils.o: utils.h

I run make all to build the library and I get libutils.a and utils.o files.

Then I have a simple kernel module which uses the utils library mymodule_main.c

#include <linux/kernel.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");

#include "utils/utils.h"

int init_module(void) {
  int i;
  initialize(1);
  for(i = 0; i < 10; ++i) {
    increment();
  }
  return 0;
}

void cleanup_module(void)
{
  pr_info("value=%d\n", get());
}

and the Makefile for it:

NAME        := mymodule
target      := $(shell uname -r)
KERNEL_DIR  ?= /lib/modules/$(target)/build

obj-m       := $(NAME).o
$(NAME)-y   := mymodule_main.o libutils.a

all:
    make -C $(KERNEL_DIR) M=$(shell pwd)
clean:
    make -C $(KERNEL_DIR) M=$(shell pwd) clean

Now when I try to build this kernel module make all I get these errors:

ERROR: "initialize" [/home/mosa/dev/mymodule.ko] undefined!
ERROR: "get" [/home/mosa/dev/mymodule.ko] undefined!
ERROR: "increment" [/home/mosa/dev/mymodule.ko] undefined!

I then tried using the utils.o file instead of the libutils.a and updated the Makefile for the kernel module accordingly, I got these warnings:

WARNING: "g_value" [/home/mosa/dev/mymodule] is COMMON symbol
WARNING: could not find /home/mosa/dev/.utils.o.cmd for /home/mosa/dev/utils.o

and if I tried to insmod the resulting kernel module I get this error in the logs: mymodule: please compile with -fno-common

I tried adding ccflags-y += -fno-common to the Makefile and still same error.

I've read that it's possible to do this but I can't get it to work.

What I'm trying to do here is to not distribute the utils source code, just the kernel module code along with the headers of the utils and the library object file. How can I go with this?

Mohamed Osama
  • 43
  • 1
  • 6
  • That last makefile delegates the work to another makefile we can't see. Have you tried making a local copy of the other makefile, and stripping the whole problem down to a [minimal complete example](https://stackoverflow.com/help/minimal-reproducible-example)? – Beta Dec 09 '20 at 13:15
  • Use the standard way to build modules. many modules have two or more file to be linked. Kernel build system is complex. Main Makefile will execute an other make (which will include other paths), so your example cannot work, you are in the wrong process. – Giacomo Catenazzi Dec 09 '20 at 13:39
  • Try to search SO for the answer. I have seen in the past couple of years two or three questions like this. It's possible to achieve. Usual issue is how to form a *Makefile*. Look for *how to link static object to a kernel module* type of questions. – 0andriy Dec 12 '20 at 21:01
  • @Beta I think the other Makefile is part of the Kbuild in the kernel. – Mohamed Osama Dec 16 '20 at 13:03
  • @GiacomoCatenazzi Can you provide a link that can guide me to what I'm trying to achieve? – Mohamed Osama Dec 16 '20 at 13:04
  • @0andriy I looked on all the possible stackoverflow questions and answers about this subject, and none of them worked for me. – Mohamed Osama Dec 16 '20 at 13:04
  • @MohamedOsama: Check in kernel source, the different drivers (drivers, not subsystems). You see the files to configure and to build modules. Some drivers have extra `*.o` files, and some uses also other libraries (shared on many files). I prefer real example than documentation (which was also included in Documentation directory in kernel – Giacomo Catenazzi Dec 16 '20 at 14:25
  • @GiacomoCatenazzi Cool, will check the kernel source and let you know if I found anything. – Mohamed Osama Dec 21 '20 at 23:44

1 Answers1

-1

Kernel modules can only be reached via syscalls or sysfs or ioctl,.... You can not link userspace code to kernel, cf. How to Link static or shared library to Kernel Module?

ralf htp
  • 9,149
  • 4
  • 22
  • 34
  • 1
    It seems you didn't get what OP asks for. – 0andriy Dec 12 '20 at 20:59
  • i think you mean the `_shipped` mechanism with that you link binary blobs into kernel modules like in https://www.kernel.org/doc/html/latest/kbuild/modules.html#binary-blobs and also chapter 3.2 of this link, however i do not think this is asked for here – ralf htp Dec 13 '20 at 09:21
  • @ralfhtp I'm a little confused here. What I'm trying to do is, compile some portion of my code (which does not rely on any userspace APIs) into a static library (binray blob?) that I can then include in the Makefile of my actual kernel module to resolve the dependencies/symbols I'm using in the kernel module's code. If that makes any sense. – Mohamed Osama Dec 16 '20 at 13:00
  • As far as i know this is only possibly if your library does not depend on anything else (no dependence on external symbols), i.e. other libraries. This independence of anything would make your library a binary blob. This includes that your library is not allowed to depend on libc ,... If your library has other userspace dependencies it is not possible like said in https://stackoverflow.com/questions/20487512/how-to-link-static-or-shared-library-to-kernel-module and https://stackoverflow.com/questions/31928255/linking-shared-library-in-linux-kernel – ralf htp Dec 16 '20 at 13:28
  • @ralfhtp Yeah, I'm trying to create a library that doesn't depend on anything. Do you happen to know how to write a Makefile that achieves this? The above Makefile's don't work. – Mohamed Osama Dec 21 '20 at 23:46
  • Yes see https://www.kernel.org/doc/Documentation/kbuild/modules.txt chapter 2, 3, 3.1, 3.2 kbuild files are 'makefiles' the kernel uses they are separate from userspace makefiles but you can combine kbuild files and makefiles – ralf htp Dec 22 '20 at 09:18