linking error while trying to add print_stack_trace

537 Views Asked by At

I am getting a error that looks like a linking problem, after adding a call to "print_stack_trace" in one of the exception handlers inside my embedded Linux kernel code.

Details are as below:

  1. My objective & context: I am trying to debug an "imprecise external abort" memory fault during my kernel's boot-up on my A9 board. I am getting the imprecise abort error as below:

    [    1.248680] Unhandled fault: imprecise external abort (0x406) at 0xc397ffec
    

My objective is to try and gather more details of the stack and registers when this abort is occurring. Once the abort occurs, I noted that it is getting directed to a handler called asmlinkage void __exception do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs).

I have called dump_stack() inside this function, which gives me the following stack and register data:

[    1.245755] CPU: 0 PID: 240 Comm: hotplug Not tainted 3.14.26-ts-armv7l #3
[    1.245845] [<c0011fe0>] (unwind_backtrace) from [<c0010934>] (show_stack+0x10/0x14)
[    1.245869] [<c0010934>] (show_stack) from [<c00083c0>] (do_DataAbort+0x40/0x9c)
[    1.245906] [<c00083c0>] (do_DataAbort) from [<c0277f74>] (__dabt_usr+0x34/0x40)
[    1.245919] Exception stack(0xc397ffb0 to 0xc397fff8)
[    1.245935] ffa0:                                     00000000 00000000 00000000 00000000
[    1.245952] ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    1.245969] ffe0: 00000000 be95fe80 00000000 b6f98eec 00000010 ffffffff
[    1.245985] Unhandled fault: imprecise external abort (0x406) at 0xc397ffec

I can note from the above data that address ffec corresponds to b6f98eec. I have no idea what value is this that causes the abort. I ran a nm and objdump against my Linux image (vmlinux file) and could not trace this to any symbol address. Now, I am trying to call save_stack_trace() and print_stack_trace() from inside the same handler, to obtain more details about this abort.

  1. Changes I have done: I added save_stack_trace() and print_stack_trace() as follows: At the top of the file, I have the following: Header file inclusions =>

    #include<linux/stacktrace.h>
    #include<asm/stacktrace.h>
    
    #ifdef CONFIG_STACKTRACE
    static unsigned long stack_entries[32];
    
    static struct stack_trace my_trace = {
        .nr_entries = 0,
        .entries = &stack_entries[0],
        .max_entries = 32,
        .skip = 0
    };
    #endif
    

Inside the function do_DataAbort, I have added the following code:

#ifdef CONFIG_STACKTRACE
    save_stack_trace(&my_trace);
    printk(KERN_ALERT "calling print_stack \n");
    print_stack_trace(&my_trace, 32);
#endif

At the top of the header file include/Linux/stacktrace.h, I have tried to define CONFIG_STACKTRACE.

#define CONFIG_STACKTRACE
  1. My observation and problem: When I compile this code, I am getting an error that looks like a linker error:

    arch/arm/mm/built-in.o: In function 'do_DataAbort':
    :(.exception.text+0x58): undefined reference to 'print_stack_trace'
    make[1]: *** [vmlinux] Error 1
    

Request your help to resolve this. Please let me know if any information is required.

2

There are 2 best solutions below

0
On

Never define CONFIG_* macros manually:

// DO NOT DO THAT!
#define CONFIG_STACKTRACE

They are intended to be set (or not set) during kernel's configuration (make menuconfig, make defconfig or other *config targets) and to be stored into .config file.

A configuration parameter may depends on target machine(architecture) or other parameters, without which functionality, defined by given parameter, will not work correctly (or even will not compile, like in your case).


If you need some configuration parameter to be set, one way could be set it via make menuconfig:

  1. Press key /, a dialog Search Configuration Parameter will appear.
  2. Write the name of the configuration parameter (case insensitive, CONFIG_ prefix is not required). E.g., enter stacktrace. Press OK.
  3. In the search ouput find exact name of your parameter: Symbol: STACKTRACE.
  4. Current value of the parameter will be given in []. If it is [=y] or [=m], then the symbol is already defined in the kernel. If it is [=n], then check, how to set given symbol.
  5. Symbols, which can be set by the user, have Prompt: line, which describes location of the symbol in the menu. Note, that symbol is shown in the menu only when expression under Dependens on: is saticfied. E.g., STACKTRACE symbol can be set only when STACKTRACE_SUPPORT symbol is set. Value of dependent symbols is already shown in the expression.
  6. Symbols, which have no Prompt: line, cannot be set by the user and can only be set automatically: in the arch-specific way, or being selected (Selected by:) by other symbols. On x86 symbol STACKTRACE_SUPPORT is set, arm also defines this symbol.
  7. If any of configuration has been changed, kernel needs to be rebuilt.
0
On

You should not just add a #define CONFIG_STACKTRACE. You have to enable this functionality in your kernel config instead. This will ensure the needed functionality is built into your kernel.