Tuesday, January 4, 2022

[SOLVED] GDB can't load kernel symbol correctly with KASLR enabled

Issue

With KASLR enabled there will be an offset between symbol file and actual symbol location.

% cat /proc/kallsyms| grep '\<jiffies_64\>'
ffffffff86805000 D jiffies_64
% objdump -t /usr/lib/debug/boot/vmlinux-4.13.0-1-amd64 | grep '\<jiffies_64\>'
ffffffff81c05000 g     O .data  0000000000000008 jiffies_64

Find the .text section location, so I can load the symbol file correctly:

% cat /proc/kallsyms | grep '\<_text\>'
ffffffff85c00000 T _text

But even if I loaded the symbol file at correction location:

% sudo gdb -c /proc/kcore
GNU gdb (Debian 8.0-1) 8.0
(gdb) add-symbol-file /usr/lib/debug/boot/vmlinux-4.13.0-1-amd64 0xffffffff85c00000
add symbol table from file "/usr/lib/debug/boot/vmlinux-4.13.0-1-amd64" at
    .text_addr = 0xffffffff85c00000
(y or n) y
Reading symbols from /usr/lib/debug/boot/vmlinux-4.13.0-1-amd64...done.

GDB still giving the wrong symbol location:

(gdb) p &jiffies_64
$1 = (u64 *) 0xffffffff81c05000 <jiffies_64>

How do I force GDB to load the symbol at correct location ?


Solution

First, notice the second field in the line of jiffies_64 symbol.

# grep -w jiffies_64 /proc/kallsyms 
ffffffffbb005000 D jiffies_64

The second field is the symbol type (see nm(1)). In this case, D means that the jiffies_64 symbol is located at the data segment.

You have loaded your vmlinux file and only specified the address of the text segment, but since jiffies_64 is not in the text segment but in the data segment, it didn't help you.

So first you need to find the start address of your kernel's data segment, which is the address of the _sdata symbol in /proc/kallsyms.

# grep -w _sdata /proc/kallsyms
ffffffffbb000000 D _sdata

Then you need to load your vmlinux file with the start address of the kernel's data segment.

# gdb -q -c /proc/kcore
(gdb) add-symbol-file /usr/lib/debug/boot/vmlinux-4.12.14-122.37-default.debug -s .data 0xffffffffbb000000
add symbol table from file "/usr/lib/debug/boot/vmlinux-4.12.14-122.37-default.debug" at
        .data_addr = 0xffffffffbb000000
(y or n) y
Reading symbols from /usr/lib/debug/boot/vmlinux-4.12.14-122.37-default.debug...
(gdb) p &jiffies_64
$1 = (u64 *) 0xffffffffbb005000 <jiffies_64>

And - voila, now the address of jiffies_64 is 0xffffffffbb0050000, which is exactly what you see in /proc/kallsyms.



Answered By - aviro