常用的Linux调试方法:
工具 描述 debugfs文件系统 提供了 procfs, sysfs, debugfs以及 relayfs 来与用户空间进行数据交互, 尤其是 debugfs, 这是内核开发者们实现的专门用来调试的文件系统接口. 其他的工具或者接口, 多数都依赖于 debugfs printk 强大的输出系统, 没有什么逻辑上的bug是用PRINT解决不了的 ftrace以及其前端工具trace-cmd等 内核提供了 ftrace 工具来实现检查点, 事件等的检测, 这一框架依赖于 debugfs, 他在 debugfs 中的 tracing 子系统中为用户提供了丰富的操作接口, 我们可以通过该系统对内核实现检测和分析. 功能虽然强大, 但是其操作并不是很简单, 因此使用者们为实现了 trace-cmd 等前端工具, 简化了 ftrace 的使用.
objdump 用法: 1 objdump -D a.out > a.dump
常用参数: -d:将代码段反汇编 -D:表示对全部文件进行反汇编 -S:将代码段反汇编的同时,将反汇编代码和源代码交替显示
,编译时需要给出-g,即需要调试信息。 -C:将C++符号名逆向解析。 -l:反汇编代码中插入源代码的文件名和行号。 -j section:仅反汇编指定的section。可以有多个-j参数来选择多个section。 $mips-linux-gnu-objdump -d vmlinux > a.s
addr2line 一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具
1 2 =====>$mips-linux-gnu-addr2line -e out/target/product/xxxxx/symbols/system/lib/libdvm.so 23452 /work/android-4.3-fpga/dalvik/vm/mterp/out/InterpAsm-mips.S:1335
23452 –> 异常PC
mips-linux-gnu-addr2line -e vmlinux 0x802354c0
汇编定位 在函数中添加空指令,确认该代码段反汇编后的具体位置.
1 2 3 4 5 6 7 8 asm __volatile__("ssnop\n\t"); asm __volatile__("ssnop\n\t"); for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (JSAMPLE) i; asm __volatile__("ssnop\n\t"); asm __volatile__("ssnop\n\t");
ftrace ftrace 是内建于 Linux 内核的跟踪工具,从 2.6.27 开始加入主流内核。使用 ftrace 可以调试或者分析内核中发生的事情。ftrace 提供了不同的跟踪器,以用于不同的场合,比如跟踪内核函数调用、对上下文切换进行跟踪、查看中断被关闭的时长、跟踪内核态中的延迟以及性能问题等
Documentation/trace/ftrace.txt
kernel配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Symbol: FTRACE [=y] Type : boolean Prompt: Tracers Location: -> Kernel hacking Defined at kernel/trace/Kconfig:135 Depends on: TRACING_SUPPORT [=y] --- Tracers -*- Kernel Function Tracer [*] Kernel Function Graph Tracer [*] Interrupts-off Latency Tracer [*] Preemption-off Latency Tracer [*] Scheduling Latency Tracer -*- Create a snapshot trace buffer -*- Allow snapshot to swap per CPU Branch Profiling (No branch profiling) ---> [*] Trace max stack [*] Support for tracing block IO actions [*] enable/disable function tracing dynamically [ ] Kernel function profiler [ ] Perform a startup test on ftrace < > Ring buffer benchmark stress tester [ ] Ring buffer startup self test
Use 1 # mount -t debugfs none /mnt/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # cd /mnt/tracing/ # ls README set_event available_events set_ftrace_filter available_filter_functions set_ftrace_notrace available_tracers set_ftrace_pid buffer_size_kb set_graph_function buffer_total_size_kb snapshot current_tracer stack_max_size dyn_ftrace_total_info stack_trace enabled_functions stack_trace_filter events trace free_buffer trace_clock instances trace_marker max_graph_depth trace_options options trace_pipe per_cpu tracing_cpumask printk_formats tracing_max_latency saved_cmdlines tracing_on saved_tgids tracing_thresh
available_tracers 记录了当前编译进内核的跟踪器的列表
available_tracers - list of configured tracers for current_tracer
1 2 # cat available_tracersblk function_graph wakeup_rt wakeup preemptirqsoff preemptoff irqsoff function nop
current_tracer 用于设置或显示当前使用的跟踪器; 使用echo
将跟踪器名字写入该文件可以切换到不同的跟踪器。系统启动后,其缺省值为nop
,即不做任何跟踪操作。在执行完一段跟踪任务后,可以通过向该文件写入nop
来重置跟踪器。
1 # echo wakeup > current_tracer
trace 文件提供了查看获取到的跟踪信息的接口。
通过 cat 等命令查看该文件以查看跟踪到的内核活动记录,也可以将其内容保存为记录文件以备后续查看。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # cat trace# tracer: wakeup # # -------------------------------------------------------------------- # latency: 624 us, # ----------------- # | task: ksdioirqd/mmc1-155 (uid:0 nice :0 policy:1 rt_prio:1) # ----------------- # # / _-----=> irqs-off # | / _----=> need-resched # || / _---=> hardirq/softirq # ||| / _--=> preempt-depth # |||| / delay # cmd pid ||||| time | caller # \ / ||||| \ | / <idle>-0 0dNh4 4us+: 0:120:R + [000] 155: 98:R ksdioirqd/mmc1 <idle>-0 0dNh4 12us+: 0 <idle>-0 0dNh4 17us+: task_woken_rt <-ttwu_do_wakeup <idle>-0 0dNh4 21us+: _raw_spin_unlock <-try_to_wake_up <idle>-0 0dNh4 24us+: sub_preempt_count <-_raw_spin_unlock <idle>-0 0dNh3 28us+: _raw_spin_unlock_irqrestore <-try_to_wake_up ....
使用 内核中断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # echo 0 > tracing_on# echo > trace# echo nop > current_tracer# echo irq > set_event# echo 1 > tracing_on# cat trace_pipe sh-100 [000] d.h3 1333.894909: irq_handler_entry: irq=58 name=uart1 sh-100 [000] d.h3 1333.894931: irq_handler_exit: irq=58 ret=handled <idle>-0 [000] d.h2 1333.902444: irq_handler_entry: irq=34 name=jz-timerirq # cat trace# tracer: nop # # # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU # | | | |||| | | sh-100 [000] d.h3 1342.498892: irq_handler_exit: irq=58 ret=handled <idle>-0 [000] d.h2 1342.673707: irq_handler_entry: irq=34 name=jz-timerirq <idle>-0 [000] d.h2 1342.673717: irq_handler_exit: irq=34 ret=handled
参考 Linux内核调试的方式以及工具集锦