打印函数名
// 使用, 对于pF 废弃了
printk("%s: %ps\n", __func__, func);
// 内核函数位置:
// lib/vsprintf.c line:2214
/*
'[Ff]' %pf and %pF were obsoleted and later removed in favor of
* %ps and %pS. Be careful when re-using these specifiers.
*/
static noinline_for_stack
char *pointer(const char *fmt, char *buf, char *end, void *ptr,
struct printf_spec spec)
{
switch (*fmt) {
case 'S':
case 's':
ptr = dereference_symbol_descriptor(ptr);
/* fall through */
case 'B':
return symbol_string(buf, end, ptr, spec, fmt);
....
}
}
在内核文档 Documentation/core-api/printk-formats.rst
中查看
Symbols/Function Pointers
-------------------------
::
%pS versatile_init+0x0/0x110
%ps versatile_init
%pSR versatile_init+0x9/0x110
(with __builtin_extract_return_addr() translation)
%pB prev_fn_of_versatile_init+0x88/0x88
The ``S`` and ``s`` specifiers are used for printing a pointer in symbolic
format. They result in the symbol name with (S) or without (s)
offsets. If KALLSYMS are disabled then the symbol address is printed instead.
需要内核开启KALLSYMS
, 查看编译选项
cat /boot/config-`uname -r` | grep CONFIG_KALLSYMS
linux下自带的nm
分析工具,可以用来分析二进制文件、库文件、可执行文件中的符号表,返回二进制文件中各段的信息。
内核关闭随机化
cat /proc/sys/kernel/randomize_va_space
# 0: 关闭# 1: 半随机 # 2: 全随机
sudo sysctl -w kernel.randomize_va_space=0
其他方法
WARN_ON(condition)
在括号中的条件成立的时候,内核会抛出栈回溯,但是不会panic()
, 可以作为一个调试技巧, 了解函数的调用关系dump_stack()
函数,能够用来回溯打印调用栈信息。oops 时打印的栈回溯调用信息也是通过调用此函数来完成的backtrace()
获取当前线程的调用堆栈
#include<stdio.h>
#include<execinfo.h>
void func1(){}
int main()
{
void *func = func1; //注意这里必须转化为一个void *指针
backtrace_symbols_fd(&func, 1, 1);
return 0;
}
参考