• Tutorials
  • U-Boot Debugging Tips: Mapping Crash Addresses Back to Source Code

    Views175

    When developing or porting U-Boot to a new board, it is common to encounter boot failures that provide only a cryptic error message and a memory address.

    For example, while bringing up an AM57xx-based board, you may encounter:

     1initcall sequence 7ffdb800 failed at call 0x8080bd78 (err=-1)
     2### ERROR ### Please RESET the board ###
    

    At first glance, this message does not reveal much. However, the reported address contains enough information to identify the exact function responsible for the failure.

    This article demonstrates how to trace such addresses back to the corresponding source code using addr2line and nm.

    #Understanding the Error

    The key part of the message is:

     10x8080bd78
    

    This is the address of the function that returned an error during U-Boot initialization.

    The goal is to determine which source file and line correspond to this address.

    #Using addr2line

    The fastest way to identify the location is:

     1${CROSS_COMPILE}addr2line -e u-boot -f -p 0x8080bd78
    

    Example output:

     1omap_gpio_probe at drivers/gpio/omap_gpio.c:312
    

    This immediately identifies the function and source line involved in the failure.

    #If the Address Does Not Resolve

    Sometimes the reported address is a runtime address and must be converted into an offset relative to CONFIG_TEXT_BASE.

    For example:

     1Runtime Address : 0x8080bd78
     2CONFIG_TEXT_BASE: 0x80800000
     3Offset          : 0x0000bd78
    

    Then run:

     1${CROSS_COMPILE}addr2line -e u-boot -f -p 0xbd78
    

    #Using nm to Find the Function

    Another useful tool is nm, which lists all symbols in the U-Boot image.

     1${CROSS_COMPILE}nm -n u-boot | less
    

    Example:

     18080bc40 T omap_gpio_probe
     28080be20 T omap_gpio_direction_input
    

    Since the failing address:

     10x8080bd78
    

    falls between these symbols, the crash occurred inside:

     1omap_gpio_probe()
    

    This is often enough to identify the subsystem responsible for the failure.

    You can also search for a specific address:

     1${CROSS_COMPILE}nm -n u-boot | grep -i omap_gpio
    

    #Using objdump for Detailed Analysis

    If additional investigation is required, disassemble the relevant section:

     1${CROSS_COMPILE}objdump -d u-boot > u-boot.dis
    

    Search for the failing address:

     1grep -A20 -B20 8080bd78 u-boot.dis
    

    This allows you to identify the exact instruction being executed.

    #Adding Debug Prints

    Once the function is known, add debug statements around the suspected code:

     1printf("DEBUG: entering omap_gpio_probe\n");
     2
     3ret = gpio_request_by_name(dev, "gpios", 0, &desc, 0);, &desc, 0););
     4printf("DEBUG: gpio_request_by_name ret=%d\n", ret);
    

    Rebuild U-Boot and observe the last message printed before the failure.

    #Verifying the Device Tree

    Many initialization failures are caused by missing or incorrect Device Tree properties.

    Always inspect the final generated DTB:

     1dtc -I dtb -O dts -o u-boot.dts u-boot.dtb
    

    Locate the node involved in the failure:

     1grep -A20 gpio@4804c000 u-boot.dts
    

    For an AM57xx GPIO controller, verify that required properties are present:

     1gpio1: gpio@4804c000 {
     2    compatible = "ti,omap4-gpio";
     3    reg = <0x4804c000 0x1000>;
     4    gpio-controller;
     5    #gpio-cells = <2>;
     6    ti,ngpio = <32>;
     7    status = "okay";
     8};
    

    Missing properties frequently lead to probe failures during the initcall phase.

    #Enable Additional Debugging

    To obtain more detailed information during boot, enable:

     1CONFIG_LOG=y
     2CONFIG_LOG_MAX_LEVEL=7
     3CONFIG_DEBUG_UART=y
     4CONFIG_DEBUG_UART_ANNOUNCE=y
     5CONFIG_DM_DEBUG=y
    

    These options provide valuable insight into driver initialization and Device Model probing.

    #Recommended Workflow

    Whenever U-Boot reports a failure at a specific address:

     1initcall sequence ... failed at call 0xXXXXXXXX
    

    follow these steps:

    1. Resolve the address:
     1${CROSS_COMPILE}addr2line -e u-boot -f -p 0xXXXXXXXX
    
    1. Find the surrounding symbols:
     1${CROSS_COMPILE}nm -n u-boot
    
    1. Optionally inspect the assembly:
     1${CROSS_COMPILE}objdump -d u-boot
    
    1. Add debug prints inside the identified function.

    2. Verify the generated Device Tree.

    3. Rebuild and repeat until the failing statement is identified.

    #Conclusion

    If you get stuck during U-Boot development or board porting, learning how to translate crash addresses back into source code is one of the most effective debugging techniques available. Tools such as addr2line, nm, and objdump allow you to quickly pinpoint the exact function involved, significantly reducing the time required to diagnose and fix boot-time issues.

    profile image of Martin Mitkov

    Martin Mitkov

    Martin is a founder and CEO of Mitkov Systems GmbH.

    More posts from Martin Mitkov