在我的嵌入式 Linux 内核代码中的一个异常处理程序中添加对"print_stack_trace"的调用后,我收到一个看起来像链接问题的错误。
详情如下:
- 我
的目标和上下文:我正在尝试在A9板上启动内核期间调试"不精确的外部中止"内存错误。我收到不精确的中止错误,如下所示:
[ 1.248680] Unhandled fault: imprecise external abort (0x406) at 0xc397ffec
我的目标是尝试收集堆栈的更多详细信息,并在发生此中止时注册。一旦发生中止,我注意到它被定向到一个名为 asmlinkage void __exception do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
的处理程序。
我在这个函数中调用了dump_stack()
,它给了我以下堆栈和寄存器数据:
[ 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
我可以从上面的数据中注意到,地址 ffec 对应于b6f98eec
.我不知道这是什么值导致中止。我对我的 Linux 映像(vmlinux 文件(运行了nm
和objdump
,无法将其追溯到任何符号地址。现在,我正在尝试从同一处理程序内部调用save_stack_trace()
和print_stack_trace()
,以获取有关此中止的更多详细信息。
- 我
所做的更改:我添加了
save_stack_trace()
和print_stack_trace()
,如下所示:在文件的顶部,我有以下内容:头文件包含 =>#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
在函数do_DataAbort
中,我添加了以下代码:
#ifdef CONFIG_STACKTRACE
save_stack_trace(&my_trace);
printk(KERN_ALERT "calling print_stack n");
print_stack_trace(&my_trace, 32);
#endif
在头文件include/Linux/stacktrace.h
的顶部,我试图定义CONFIG_STACKTRACE
。
#define CONFIG_STACKTRACE
我的观察和问题:当我编译此代码时,我收到一个看起来像链接器错误的错误:
arch/arm/mm/built-in.o: In function 'do_DataAbort': :(.exception.text+0x58): undefined reference to 'print_stack_trace' make[1]: *** [vmlinux] Error 1
请求您帮助解决此问题。如果需要任何信息,请告诉我。
切勿手动定义CONFIG_*
宏:
// DO NOT DO THAT!
#define CONFIG_STACKTRACE
它们应该在内核的配置(make menuconfig
、make defconfig
或其他*config
目标(期间设置(或不设置(,并存储到.config
文件中。
配置参数可能取决于目标机器(架构(或其他参数,没有这些参数,由给定参数定义的功能将无法正常工作(甚至无法编译,就像您的情况一样(。
如果您需要设置一些配置参数,可以通过make menuconfig
- 按键
/
,将出现一个对话框Search Configuration Parameter
。 - 写入配置参数的名称(不区分大小写,
CONFIG_
前缀不是必需的(。 例如,输入stacktrace
。按OK
。 - 在搜索输出中,找到参数的确切名称:
Symbol: STACKTRACE
。 - 参数的当前值将以
[]
为单位给出。如果是[=y]
或[=m]
,则符号已经在内核中定义。如果是[=n]
,则检查如何设置给定的交易品种。 - 可由用户设置的符号具有
Prompt:
行,用于描述符号在菜单中的位置。请注意,仅当Dependens on:
下的表达式被满足时,该符号才会显示在菜单中。例如,只有在设置STACKTRACE_SUPPORT符号时才能设置堆栈跟踪符号。从属符号的值已显示在表达式中。 - 没有
Prompt:
线的符号不能由用户设置,只能自动设置:以特定于拱的方式,或被其他符号选择(Selected by:
(。在设置符号STACKTRACE_SUPPORTx86
,arm
也定义了此符号。 - 如果任何配置已更改,则需要重建内核。
你不应该只添加一个 #define CONFIG_STACKTRACE。您必须在内核配置中启用此功能。这将确保所需的功能内置到您的内核中。