Reputation: 65
I'm trying to compile kernel version 4.4 in Ubuntu 16.04 LTS. I added or modified some code to store the block number of the write block in the block I / O layer into the custom buffer.
I modified the codes [linux-kernel-location]/block/blk-core.c (original):
...
#include <custom/custom-buffer.h>
...
blk_qt_t submit_bio(int rw, struct bio *bio)
{
...
if(rw & WRITE)
{
unsigned long cntUnit = bio->bi_bdev->bd_super->s_blocks / bdev_logical_block_size(bio->bi_bdev);
unsigned long blk_no = bio->bi_iter.bi_sector / cntUnit;
count_vm_events(PGPGOUT, count);
custom_buf_write_blk_no(blk_no);
}
...
}
...
[linux-kernel-location]/block/Makefile (original):
...
obj-y += custom/
[linux-kernel-location]/block/Kconfig (original):
...
source "block/custom/Kconfig"
and created directories [linux-kernel-location]/include/custom, [linux-kernel-location]/block/custom. Then, I created files [linux-kernel-location]/include/custom/custom-buffer.h:
#ifndef _CUSTOM_BUFFER_H_
#define _CUSTOM_BUFFER_H_
extern int custom_buf_write_blk_no(unsigned long blk_no);
#endif
[linux-kernel-location]/block/custom/Makefile:
obj-y += custom-buffer.o
[linux-kernel-location]/block/custom/Kconfig:
config CUSTOM_BUFFER
tristate
depends on BLOCK
default y
[linux-kernel-location]/block/custom/custom-buffer.c(include definition of custom_buf_write_blk_no(unsigned long blk_no)
with EXPORT_SYMBOL
macro).
I typed make
command in shell at linux kernel location, and the following results were obtained:
...
LD init/built-in.o
block/built-in.o: In function `submit_bio':
[linux-kernel-location]/block/blk-core.c:2117: undefined reference to `custom_buf_write_blk_no'
block/built-in.o:(___ksymtab+custom_buf_write_blk_no+0x0): undefined reference to `custom_buf_write_blk_no'
Makefile:927: recipe for target 'vmlinux' failed
make: *** [vmlinux] Error 1
My guess is I need to fix the Makefile, how do I fix it?
Edit: I also know that this is happening because linker can not find the symbol in the linking process. But I don't know how to fix it in the Makefile that the Kbuild system applies to.
Solved by self: custom-buffer.c
has a wrong letter. I fixed it correctly so it was compiled well.
It's too hard to find typos...
Upvotes: 4
Views: 5426
Reputation: 1073
Yes, it is hard to find typos. But compiler tries to show us place where the typo been made.
I've tried to reproduce your issue to write an answer that may help others visiting this question.
First, what would have happened if you made a typo in your filename? Lets say custom/custom-buffe.c
Kernel build system will complain:
CHK include/generated/compile.h
make[2]: *** No rule to make target 'block/custom/custom-buffer.o', needed by 'block/custom/built-in.o'. Stop.
scripts/Makefile.build:403: recipe for target 'block/custom' failed
make[1]: *** [block/custom] Error 2
Makefile:943: recipe for target 'block' failed
make: *** [block] Error 2
So, it is clear that build rule is looking for file to create custom-buffer.o
, but it is missing. By default, it should have custom-buffer.c
.
From documentation:
The most simple kbuild makefile contains one line:
Example: obj-y += foo.o
This tells kbuild that there is one object in that directory, named foo.o. foo.o will be built from foo.c or foo.S.
It was not your case. So then I've made a typo in function definition (buff
vs buf
):
int custom_buff_write_blk_no(unsigned long blk_no) {
printk(KERN_INFO "WIP NUMBER %lu\n", blk_no);
return 0;
}
EXPORT_SYMBOL(custom_buff_write_blk_no);
And now, after building I have info from compiler:
LD init/built-in.o
block/built-in.o: In function `submit_bio':
(.text+0x8bb0): undefined reference to `custom_buf_write_blk_no'
Makefile:929: recipe for target 'vmlinux' failed
make: *** [vmlinux] Error 1
We can trace what exactly this LD step is doing by issuing make V=1
:
+ ld -m elf_x86_64 --build-id -o .tmp_vmlinux1 -T ./arch/x86/kernel/vmlinux.lds arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/head.o init/built-in.o --start-gr
oup usr/built-in.o arch/x86/built-in.o kernel/built-in.o certs/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o lib/lib.
a arch/x86/lib/lib.a lib/built-in.o arch/x86/lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o arch/x86/pci/built-in.o arch/x86/power/built-in.o arch/x86/video
/built-in.o arch/x86/ras/built-in.o net/built-in.o virt/built-in.o --end-group
block/built-in.o: In function `submit_bio':
(.text+0x8bb0): undefined reference to `custom_buf_write_blk_no'
First, we think that everything is correct, and our custom_buf_write_blk_no
symbol should be in file block/custom/build-in.o
. Here we don't see this file. But, Kbuild system merges all objects recursively to one build-in.o:
Kbuild compiles all the $(obj-y) files. It then calls "$(LD) -r" to merge these files into one built-in.o file. built-in.o is later linked into vmlinux by the parent Makefile.
So it should be in block/build-in.o
. To make sure we can trace it by investigating make V=1
output:
...
ld -m elf_x86_64 -r -o block/custom/built-in.o block/custom/custom-buffer.o
...
ld -m elf_x86_64 -r -o block/built-in.o block/bio.o block/elevator.o block/blk-core.o block/blk-tag.o block/blk-sysfs.o block/blk-flush.o block/blk-settings.o block/blk-ioc.o
block/blk-map.o block/blk-exec.o block/blk-merge.o block/blk-softirq.o block/blk-timeout.o block/blk-iopoll.o block/blk-lib.o block/blk-mq.o block/blk-mq-tag.o block/blk-mq-sysfs.o
block/blk-mq-cpu.o block/blk-mq-cpumap.o block/ioctl.o block/genhd.o block/scsi_ioctl.o block/partition-generic.o block/ioprio.o block/partitions/built-in.o block/bounce.o block/b
sg.o block/noop-iosched.o block/deadline-iosched.o block/cfq-iosched.o block/compat_ioctl.o block/custom/built-in.o
Indeed, there is our custom-buffer.o
. So why we have undefined reference? Well, we can investigate symbols that are in block/build-in.o
, by using objdump -t block/built-in.o | grep custom
:
0000000000000000 l d ___ksymtab+custom_buff_write_blk_no 0000000000000000 ___ksymtab+custom_buff_write_blk_no
0000000000000000 l df *ABS* 0000000000000000 custom-buffer.c
000000000000132e l O __ksymtab_strings 0000000000000019 __kstrtab_custom_buff_write_blk_no
0000000000000000 *UND* 0000000000000000 custom_buf_write_blk_no
0000000000000000 g O ___ksymtab+custom_buff_write_blk_no 0000000000000010 __ksymtab_custom_buff_write_blk_no
0000000000025ed0 g F .text 0000000000000017 custom_buff_write_blk_no
Now we see symbol custom_buff_write_blk_no
and compiler complains that he is looking for custom_buf_write_blk_no
.
Upvotes: 4