Re: Kernel symbol table

Jan Kratochvil
2009-04-10T01:21:25Z

On Thu, 09 Apr 2009 22:36:40 +0200, Shrinand Javadekar wrote:
> If these are not loaded how can other (maybe even user written)
> modules link to them?

kernel uses /proc/kallsyms which are stored in ELF-incompatible kernel custom
format. You can get stripped ELF vmlinux file from vmlinuz by:

perl -e 'undef $/;$_=<>;print /(\x1f\x8b\x08.*$)/s;' <vmlinuz | gzip -d >vmlinux.bin

And there you can see these symbols by:

$ readelf -Wa vmlinux.bin
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 8] __ksymtab PROGBITS ffffffff81482660 682660 00bb10 00 A 0 0 16
[ 9] __ksymtab_gpl PROGBITS ffffffff8148e170 68e170 005420 00 A 0 0 16
[10] __ksymtab_unused PROGBITS ffffffff81493590 693590 000010 00 A 0 0 16
[11] __ksymtab_strings PROGBITS ffffffff814935a0 6935a0 01303a 00 A 0 0 1
$ objcopy -j __ksymtab -O binary vmlinux.bin vmlinux.bin-__ksymtab
$ objcopy -j __ksymtab_strings -O binary vmlinux.bin vmlinux.bin-__ksymtab_strings

You could write some script to extract this symbol information out of the
custom kernel __ksymtab* format into some readable format.

The better way would be to change Linux kernel to store its symbol information
in ELF format (such as common `.symtab' sections).

On Thu, 09 Apr 2009 20:59:54 +0200, Shrinand Javadekar wrote:
> 1. When I haven't built the kernel myself, I don't have the vmlinux file.

You should have debuginfo package for such kernel:
$ rpm -qlv kernel-debuginfo-2.6.28-3.fc10.x86_64 | grep vmlinux
-rwxr-xr-x 1 root root 86367610 Jan 13 17:07 /usr/lib/debug/lib/modules/2.6.28-3.fc10.x86_64/vmlinux

> 2. When I am remotely connected to a machine, I don't really have the
> vmlinux file with me.

You can reassemble the kernel symbol table from __ksymtab* as listed above by
some custom code. Or you can use the symbol table provided by the target
kernel itself as /proc/kallsyms. You can also use System.map file which is
usually more commonly available that the vmlinux file. For the latter two
source files you can use:

b=ffffffff81000000;sort </proc/kallsyms|perl -e 'print ".text\n";while (<>){($b,$s)=/^([0-9a-f]+) . (\S+)\s*$/s or next;next if $s{$s}++;$b=eval("0x$b-0x'$b'");next if $b<0 || $b>0x1000000 || $b{$b}++;printf "\t.org\t0x%x\n$s:\n",$b;}'|as -o /tmp/ker.o -;objcopy --adjust-vma=0x$b /tmp/ker.o

$ gdb /tmp/ker.o /proc/kcore
(gdb) disass printk
Dump of assembler code for function printk:
0xffffffff8132df6f <printk+0>: push %rbp
[...]
0xffffffff8132dfaf <printk+64>: nop
End of assembler dump.
(gdb)

Generating the symbol file /tmp/ker.o has some drawbacks:
* You cannot simply generate ABS symbols by `.equ' as GDB requires the symbol
to be SEC_CODE, therefore .text section relative.
* If you would generate such symbols by straight `.org' then:
* gas crashes on 64-bit overflow on the 0xffffffff... addresses.
* gas generates too big real zeroed .text section for the ker.o file.
* There are both address and symbol duplicates one could resolve better.
* 0xffffffff81000000 and 0x1000000 are x86_64 specific constants.

Regards,
Jan