Temeraire
Temeraire

Reputation: 11

ERROR: "func" [drivers/bluetooth/hci_uart.ko] undefined

I have a large repository that I want to modify. The part I'm working on is basically a linux kernel with some modifications. The simplified file structure looks like this:

├── asm
│   ├── mytee.h
├── kernel
│   ├── mytee.S
├── drivers
│   ├── bluetooth
|   |   ├── hci_uart.h
|   |   ├── hci_h4.c
│   ├── video
|   |   ├── fbmem.c

mytee.h declares some functions which are implemented in mytee.S in the following way:

ENTRY(func)
// assembly code
ENDPROC(func)

If I want to use them in hci_h4.c, I get the following error: ERROR: "func" [drivers/bluetooth/hci_uart.ko] undefined! hci_uart.ko is the header file to hci_h4.c.

These functions are however already successfully used in fbmem.c and without my changes the whole repository compiles. So my guess is, something goes wrong during the linking process. The Code is compiled using Kbuild Makefiles and since it is quite large, it uses multiple layers of them.

The relevant lines of both makefiles look like this:

obj-$(CONFIG_FB)                  += fb.o
fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
                                     modedb.o fbcvt.o
fb-objs                           := $(fb-y)

What I have already tried:

Additional questions which might be relevant:

Unfortunately I'm relatively new to c and makefiles, so there might be some mechanics which I don't understand. I can provide additional Information if needed.

Upvotes: 0

Views: 151

Answers (1)

Temeraire
Temeraire

Reputation: 11

Thanks to @0andriy who pointed me in the right direction.

hci_uart.h gets compiled to a loadable module, you can see this in the .config file in the root directory. This means it can only call kernel functions if they are exported. You can see all of the exported functions in the file Module.symvers.

I think the correct way to export them is using EXPORT_SYMBOL(func) from export.h in the file which implements func. But I couldn't get it to work in assembly, in c it worked fine for me.

My solution was to rename mytee.S to myteeasm.S and add the file mytee.c with the following code:

#include <linux/module.h>
#include <asm/mytee.h>

EXPORT_SYMBOL(func);

and in the makefile change obj-$(CONFIG_MYTEE)+= mytee.o to obj-$(CONFIG_MYTEE)+= mytee.o myteeasm.o

Upvotes: 0

Related Questions