Random Kernel Debugging Tips

3 minute read

All-zero address shown when do cat /proc/modules

echo 0 > /proc/sys/kernel/kptr_restrict
# or with sysctl
sysctl kernel.kptr_restrict=0

e.g.

# cat /proc/modules
pstore 53248 0 - Live 0x0000000000000000
# sysctl kernel.kptr_restrict=0
# cat /proc/modules
pstore 53248 0 - Live 0xffffff9001c60000

Find kernel module load address

# cat /sys/module/pstore/sections/.text
0xffffff9001c60000
# cat /proc/modules
pstore 53248 0 - Live 0xffffff9001c60000

There are some other interesting stuff under directory sections:

# ls -a /sys/module/pstore/sections
.                         .init.text         .text
..                        .init_array        .text.exit
.bss                      .note.Linux        .text.ftrace_trampoline
.data                     .note.gnu.build-id .text.startup
.data..ro_after_init      .plt               __bug_table
.eh_frame                 .rodata            __kcrctab_gpl
.exit.text                .rodata.str        __ksymtab_gpl
.fini_array               .rodata.str1.8     __ksymtab_strings
.gnu.linkonce.this_module .strtab            __mcount_loc
.init.plt                 .symtab            __param

Pointer address not printed with format %p in printk

[    5.610054] dwc_otg 3f980000.usb: base=(____ptrval____)
[    6.193829] vchiq: vchiq_init_state: slot_zero = (____ptrval____), is_master = 0

Use %px instead, refer to printk-formats for more details.

Frequently used tools

gdb list command
aarch64-linux-gnu-addr2line -fe option
aarch64-linux-gnu-objdump -dS option

add initcall_debug to kernel command line parameter to see init sequence

[    0.051827] calling  cpu_stop_init+0x0/0x218 @ 1
[    0.055580] initcall cpu_stop_init+0x0/0x218 returned 0 after 2929 usecs
[    0.055704] calling  init_events+0x0/0x16c @ 1
[    0.055881] initcall init_events+0x0/0x16c returned 0 after 0 usecs
[    0.056004] calling  init_trace_printk+0x0/0x24 @ 1
[    0.056139] initcall init_trace_printk+0x0/0x24 returned 0 after 0 usecs
[    0.056390] calling  event_trace_enable_again+0x0/0xfc @ 1
[    0.056531] initcall event_trace_enable_again+0x0/0xfc returned 0 after 0 usecs
[    0.056663] calling  jump_label_init_module+0x0/0x28 @ 1
[    0.056806] initcall jump_label_init_module+0x0/0x28 returned 0 after 0 usecs
[    0.056939] calling  its_pmsi_init+0x0/0x200 @ 1
[    0.057727] initcall its_pmsi_init+0x0/0x200 returned 0 after 976 usecs
[    0.057858] calling  rand_initialize+0x0/0x268 @ 1
[    0.060564] initcall rand_initialize+0x0/0x268 returned 0 after 1953 usecs

You can sort the duration with below command to see which part cost time most:

dmesg -s 128000 | grep "initcall" | sed "s/\(.*\)after\(.*\)/\2 \1/g" | sort -n

This is how it looks like after sorting (omitting some lines):

 1 usecs [    6.478152] initcall statistic_mt_init+0x0/0x28 returned 0
 1 usecs [    6.479240] initcall u32_mt_init+0x0/0x28 returned 0
 1 usecs [    6.675807] initcall max_swapfiles_check+0x0/0x20 returned 0
 2 usecs [    6.454905] initcall nf_nat_amanda_init+0x0/0x74 returned 0
 2 usecs [    6.455861] initcall nf_nat_tftp_init+0x0/0x74 returned 0
 ... ...
 32472 usecs [    8.578399] initcall genpd_debug_init+0x0/0x1f0 returned 0
 51804 usecs [    8.644049] initcall regulatory_init_db+0x0/0x418 returned 0
 78080 usecs [    6.589763] initcall inet6_init+0x0/0x658 returned 0
 1803565 usecs [    8.543766] initcall deferred_probe_initcall+0x0/0x118 returned 0
 18538866 usecs [   27.639963] initcall init_kgdboc+0x0/0x78 returned 0

What does those characters mean in system.map or /proc/kallsyms

System.map is a look-up table between kernel symbols and addresses, these characters between addresses and symbols are symbol types:

ffffff900a1c819c t trace_event_define_fields_task_rename
ffffff900a1c82a4 t coredump_filter_setup
ffffff900a1c82f0 W arch_task_cache_init
ffffff900a1c830c T fork_init
ffffff900a1c856c T proc_caches_init
ffffff900a1c86d0 t register_warn_debugfs
ffffff900a1c8710 t oops_setup
ffffff900a1a6844 r _note_54
ffffff900a26b704 W vmemmap_populate_print_last
ffffff900a28045c R __alt_instructions
ffffff900a2a8ab8 R __alt_instructions_end

Most commonly seen types are:

A for absolute
B or b for uninitialized data section (called BSS)
D or d for initialized data section
G or g for initialized data section for small objects (global)
i for sections specific to DLLs
N for debugging symbol
p for stack unwind section
R or r for read only data section
S or s for uninitialized data section for small objects
T or t for text (code) section
U for undefined
V or v for weak object
W or w for weak objects which have not been tagged so
- for stabs symbol in an a.out object file
? for "symbol type unknown"

What does those numbers mean in /proc/sys/kernel/printk

# cat /proc/sys/kernel/printk
7	4	1	7

The four values define printk log levels for:

console_loglevel messages with a higher priority than this will be printed to the console
default_message_loglevel messages without an explicit priority will be printed with this priority
minimum_console_loglevel minimum (highest) value to which console_loglevel can be set
default_console_loglevel default value for console_loglevel

The console_loglevel can be changed with echo or dmesg with -n option:

echo 1 > /proc/sys/kernel/printk
dmesg -n1

References