Linux Kernel: Print Callee and Caller

Print the callback function name

If you cannot trace which function gets called when you call from core driver using function pointer, you can print function name using pf format specifier.
Linux maintains symbol table so based on function address, it can identify function name based on address pointed by function pointer.
e.g. Core driver calls hardware specific enable/disable functions:
core->ops->enable(). If you are not sure, which function is executed as a result of this call, you can print them using %pf or %pF:
pr_info("callee function name is: %pf,  core->ops->enable)
%pf prints without offset (e.g. foo) while %pF prints with offset (e.g. foo+0x00/0x80)
Reference: https://www.kernel.org/doc/Documentation/printk-formats.txt.
Thanks Bhargav(br13patel) for sharing this!

Print caller name

There are few ways to trace caller in Linux kernel.
  • Print stack backtrace
    • dump_stack();
      • To enable the dump_stack() function in the kernel config the following options must be set.
        1. Kernel hacking -> Kernel debugging
        2. Kernel hacking -> Verbose kernel error messages
    • WARN_ON(1);
  • Print caller name
    • pr_info(“caller function name is: %pf,  __builtin_return_address(0))
Advertisements

Device Tree Debugging

DTB-DTS conversion (Linux kernel)

  • Convert DTS file to DTB
  • ./scripts/dtc/dtc -I dts -O dtb -o .dtb .dts
  • Convert DTB file to DTS

  • ./scripts/dtc/dtc -I dtb -O dts -o .dts .dtb

 U-boot FDT commands

  • print fdt address
  • print $fdt_addr_r (or $fdt_addr)
  • Set FDT node property
  • fdt addr $fdt_addr
    fdt set /testnode testprop testvalue
  • remove FDT node property
  • fdt addr $fdt_addr
    fdt rm /testnode testprop
  • Remove DT node
  • fdt rm /testnode
  • List FDT nodes
  • fdt list                         /* All nodes */
    fdt list /cpus                   /* All nodes under cups node */
  • Create node
  • fdt mknode / testnode

References:

How to check Memory Leak in linux kernel

  • Compile kernel with
    CONFIG_DEBUG_KMEMLEAK=y
    #CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
    CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4096
    
  • Mount debugfs (if it is not mounted)
    mount -t debugfs nodev /sys/kernel/debug/
    
  • Check memory leaks
    # echo scan > /sys/kernel/debug/kmemleak
    # cat /sys/kernel/debug/kmemleak
    

Example Trace:

unreferenced object 0xffff88021481d600 (size 16):
comm “swapper/0”, pid 1, jiffies 4294667622 (age 9531.310s)
hex dump (first 16 bytes):
70 6e 70 20 30 30 3a 30 31 00 38 81 ff ff ff ff pnp 00:01.8…..
backtrace:
[<ffffffff811619cf>] create_object+0xff/0x2a0
[<ffffffff8189ba63>] kmemleak_alloc+0x23/0x40
[<ffffffff8115bf37>] kmem_cache_alloc_trace+0xb7/0x160
[<ffffffff81395fe9>] reserve_range+0x59/0xf0
[<ffffffff81396102>] system_pnp_probe+0x82/0x90
[<ffffffff81392447>] pnp_device_probe+0x67/0xd0
[<ffffffff814c2a7f>] driver_probe_device+0x13f/0x2a0
[<ffffffff814c2ea5>] __device_attach_driver+0x85/0xa0
[<ffffffff814c0fa7>] bus_for_each_drv+0x57/0x90
[<ffffffff814c28d0>] __device_attach+0xb0/0xf0
[<ffffffff814c2ece>] device_initial_probe+0xe/0x10
[<ffffffff814c1f85>] bus_probe_device+0x95/0xa0
[<ffffffff814c00ce>] device_add+0x36e/0x570
[<ffffffff814c0469>] device_register+0x19/0x20
[<ffffffff813913d6>] __pnp_add_device+0x96/0xe0
[<ffffffff8139145b>] pnp_add_device+0x3b/0x100

How to Change Linux Kernel dmesg buffer size

Printk is implemented by using a ring buffer in the kernel with a size of __LOG_BUF_LEN bytes where __LOG_BUF_LEN equals (1 << CONFIG_LOG_BUF_SHIFT).

dmesg buffer size can be changed using “CONFIG_LOG_BUF_SHIFT” Kconfig.

As per kernel source (4.1.0), default value of this config is 17 (i.e. 1 << 17 = 128KB). The range for this config is 12 to 21.

Addign  below line in defconfig sets

Note: If invalid value (out of range value) is set, default value is taken.

CONFIG_LOG_BUF_SHIFT can be changed from menuconfig or from defconfig as below:

CONFIG_LOG_BUF_SHIFT=21

Device Tree

An useful way to debug device tree is to set CONFIG_PROC_DEVICETREE kernel config in defconfig file. This will show device tree information in /proc file system.

After building kernel with CONFIG_PROC_DEVICETREE Kconfig set, boot the kernel with new boot.img and check below proc entry:

# cat /proc/device-tree

Kernel Dynamic Debugging Control

Dynamic debug is designed to allow you to dynamically enable/disable kernel code to obtain additional kernel information.  Currently, if CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() and print_hex_dump_debug()/print_hex_dump_bytes() calls can be dynamically enabled per-callsite.

The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a control file in the ‘debugfs’ filesystem. Thus, you must first mount the debugfs filesystem, in order to make use of this feature.

    • Mount debug fs (one time only)
      # mount -t debugfs debugfs /sys/kernel/debug
    • Enable Debug from a file
      # echo -n ‘file slim-msm-ngd.c +p’ > /sys/kernel/debug/dynamic_debug/control
    • Enable debug from a line
      # echo ‘file svcsock.c line 1603 +p’ > /sys/kernel/debug/dynamic_debug/control
    • Disable debug from a file
      # echo -n ‘file slim-msm-ngd.c -p’ > /sys/kernel/debug/dynamic_debug/control

original document can be found in kernel source tree:Documentation/dynamic-debug-howto.txt