首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >实例演示 | 用Kdump分析内核奔溃原因

实例演示 | 用Kdump分析内核奔溃原因

作者头像
刘盼
发布于 2022-07-27 01:50:42
发布于 2022-07-27 01:50:42
4.2K00
代码可运行
举报
文章被收录于专栏:人人都是极客人人都是极客
运行总次数:0
代码可运行

本文主要介绍kdump服务和crash的使用,并结合一个简单的实例演示如何分析内核奔溃的原因。本文基于linux kernel 4.19, 体系结构为aarch64。

kdump概述

  1. kdump

kdump 是一种先进的基于 kexec 的内核崩溃转储机制,用来捕获kernel crash(内核崩溃)的时候产生的crash dump。当内核产生错误时,kdump会将内存导出为vmcore保存到磁盘。

  1. kdump流程

当系统崩溃时,kdump 使用 kexec 启动到第二个内核。第二个内核通常叫做捕获内核,以很小内存启动以捕获转储镜像。第一个内核启动时会保留一段内存给kdump用。

  1. kdump的配置
  • 系统启动时为crashkernel保留内存

可以在kernel command line中加入如下参数:crashkernel=size[@offset]。保留内存是否预留成功,可以通过cat /proc/meminfo查看。。

cat /proc/meminfo | grep Crash

  • 安装kexec-toools

yum install kexec-tools

kexec-tool推荐使用rpm方式安装,使用时需要和内核版本配套。

  • 启动kdump服务

systemctl start kdump.service // 启动kdump服务 service kdump status  // 查看kdump状态

  • 测试kdump是否可以正常dump

echo c > /proc/sysrq-trigger

如果没有问题,系统会自动重启,重启后可以看到在/var/crash/目录下生成了coredump文件。

qemu使用kdump

我们经常会使用qemu去启动虚拟机。qemu启动的内核发生错误也可以用kdump生成vmcore文件。

  1. 首先先将qemu的panic重启关闭,防止coredump的时候发生了reboot

echo 0 > /proc/sys/kernel/panic

  1. 触发kernel panic

echo c > /proc/sysrq-trigger

  1. kernel panic后,使得qemu进入monitor模式

ctrl + A, --->  c,   qemu进入monitor模式

  1. 进入monitor模式后,进行coredump

dump-guest-memory -z xxx-vmcore

如下图所示,成功在qemu 的kernel panic后,获得了coredump文件。

使用crash分析内核奔溃转储文件

在内核奔溃后,如果部署了kdump, 会在/var/crash目录中找到vmcore转储文件,vmcore文件可以配合crash工具进行分析。

crash的版本要和内核的版本保持一致, 比如上面成功dump了qemu arm64的coredump文件,就需要配套的arm64的crash工具进行分析,否则会报兼容性错误。

编译arm64 crash工具:

下载:https://github.com/crash-utility/crash/releases 编译安装: $ tar -xf crash-7.2.8.tar.gz $ cd crash-7.2.8/ $ make target=arm64

安装完成后,使用crash工具分析vmcore文件, vmlinux在编译内核时会在根目录下生成。

crash vmcore vmlinux

crash常用命令

  • bt: 查看函数调用栈
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> bt
PID: 1452   TASK: ffff80007b0f1a80  CPU: 1   COMMAND: "sh"
 #0 [ffff00000aeb3900] __delay at ffff000008af2528
 #1 [ffff00000aeb3930] __const_udelay at ffff000008af2488
 #2 [ffff00000aeb3940] panic at ffff0000080d7f04
 #3 [ffff00000aeb3a20] die at ffff00000808cb18
 #4 [ffff00000aeb3a60] die_kernel_fault at ffff00000809f7e8
 #5 [ffff00000aeb3a90] __do_kernel_fault at ffff00000809f07c
 #6 [ffff00000aeb3ac0] do_page_fault at ffff00000809f12c
 #7 [ffff00000aeb3b30] do_translation_fault at ffff00000809f574
 #8 [ffff00000aeb3b40] do_mem_abort at ffff000008081448
 #9 [ffff00000aeb3ca0] el1_ia at ffff00000808318c
     PC: ffff0000085dc0d0  [sysrq_handle_crash+32]
     LR: ffff0000085dc0bc  [sysrq_handle_crash+12]
     SP: ffff00000aeb3cb0  PSTATE: 40000005
    X29: ffff00000aeb3cb0  X28: ffff80007b0f1a80  X27: 0000000000000000
    X26: 0000000000000000  X25: 0000000056000000  X24: 0000000000000000
    X23: 0000000000000007  X22: ffff000009289000  X21: ffff000009289400
    X20: 0000000000000063  X19: ffff0000091a1000  X18: ffffffffffffffff
    X17: 0000000000000000  X16: 0000000000000000  X15: ffff0000091896c8
    X14: ffff0000892ed70f  X13: ffff0000092ed71d  X12: ffff0000091a1000
    X11: 0000000005f5e0ff  X10: ffff000009189940   X9: 00000000ffffffd0
     X8: ffff000008602b08   X7: 54203a2071527379   X6: 00000000000000d2
     X5: 0000000000000000   X4: 0000000000000000   X3: ffffffffffffffff
     X2: 2c501196acfc7700   X1: 0000000000000000   X0: 0000000000000001
#10 [ffff00000aeb3cb0] sysrq_handle_crash at ffff0000085dc0cc
#11 [ffff00000aeb3cc0] __handle_sysrq at ffff0000085dc6cc
#12 [ffff00000aeb3d00] write_sysrq_trigger at ffff0000085dcc60
#13 [ffff00000aeb3d20] proc_reg_write at ffff0000082ac7e4
#14 [ffff00000aeb3d40] __vfs_write at ffff00000823a9cc
#15 [ffff00000aeb3de0] vfs_write at ffff00000823ace0
#16 [ffff00000aeb3e20] ksys_write at ffff00000823afd4
#17 [ffff00000aeb3e70] __arm64_sys_write at ffff00000823b064
#18 [ffff00000aeb3e80] el0_svc_common at ffff000008094ef4
#19 [ffff00000aeb3eb0] el0_svc_handler at ffff000008094fa8
#20 [ffff00000aeb3ff0] el0_svc at ffff000008084044
     PC: 0000000000401a58   LR: 00000000004b2be4   SP: 0000ffffe68f8e10
    X29: 0000ffffe68f9500  X28: 0000ffffe68f9fba  X27: 000000000056f9c0
    X26: 00000000005ed000  X25: 0000000000000000  X24: 0000000000000020
    X23: 0000000011710110  X22: 00000000005ed000  X21: 0000000000000002
    X20: 0000000011710110  X19: 0000000000000001  X18: 0000000000000001
    X17: 0000000000000000  X16: 0000000000000000  X15: 0000000000000008
    X14: 0000000000000012  X13: 726567676972742d  X12: 0101010101010101
    X11: 0000005000564818  X10: 0101010101010101   X9: fffffffffffffff0
     X8: 0000000000000040   X7: 0000000011710120   X6: 0080808080808080
     X5: 0000000000000000   X4: 0000000000000063   X3: 0000000011710111
     X2: 0000000000000002   X1: 0000000011710110   X0: 0000000000000001
    ORIG_X0: 0000000000000001  SYSCALLNO: 40  PSTATE: 80000000
  • log: 查看内核dmesg日志
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> log
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x411fd070]
[    0.000000] Linux version 4.20.0-rc4-00007-gef78e5e (root@localhost.localdomain) (gcc version 7.3.1 20180425 [linaro-7.3-2018.05 revision d29120a424ecfbc167ef90065c0eeb7f91977701] (Linaro GCC 7.3-2018.05)) #3 SMP PREEMPT Wed Jan 15 07:52:10 PST 2020
[    0.000000] Machine model: linux,dummy-virt
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 32 MiB at 0x00000000be000000
[    0.000000] NUMA: No NUMA configuration found
[    0.000000] NUMA: Faking a node at [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] NUMA: NODE_DATA [mem 0xbdfea840-0xbdfebfff]
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] On node 0 totalpages: 524288
[    0.000000]   DMA32 zone: 8192 pages used for memmap
[    0.000000]   DMA32 zone: 0 pages reserved
[    0.000000]   DMA32 zone: 524288 pages, LIFO batch:63
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv0.2 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] random: get_random_bytes called from start_kernel+0xa8/0x418 with crng_init=0
[    0.000000] percpu: Embedded 23 pages/cpu @(____ptrval____) s55704 r8192 d30312 u94208
[    0.000000] pcpu-alloc: s55704 r8192 d30312 u94208 alloc=23*4096
[    0.000000] pcpu-alloc: [0] 0 [0] 1 
[    0.000000] Detected PIPT I-cache on CPU0
[    0.000000] CPU features: enabling workaround for ARM erratum 832075
[    0.000000] CPU features: enabling workaround for ARM erratum 834220
[    0.000000] CPU features: enabling workaround for EL2 vector hardening
[    0.000000] CPU features: detected: Kernel page table isolation (KPTI)
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 516096
[    0.000000] Policy zone: DMA32
[    0.000000] Kernel command line: rdinit=/linuxrc console=ttyAMA0
[    0.000000] Memory: 2009884K/2097152K available (10876K kernel code, 1414K rwdata, 5100K rodata, 1344K init, 380K bss, 54500K reserved, 32768K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
[    0.000000] rcu: Preemptible hierarchical RCU implementation.
[    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=2.
[    0.000000]  Tasks RCU enabled.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] GICv2m: range[mem 0x08020000-0x08020fff], SPI[80:143]
[    0.000000] arch_timer: cp15 timer(s) running at 62.50MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
  • struct: 查看数据结构
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> struct task_struct ffff0000085dc0d0 -x
struct task_struct {
  thread_info = {
    flags = 0xa8c17bfd39000020, 
    addr_limit = 0xd503201fd65f03c0, 
    preempt_count = 0xa9bf7bfd
  }, 
  state = 0x97ec827fd50342ff, 
  stack = 0xd65f03c0a8c17bfd, 
  usage = {
    counter = 0xa9bd7bfd
  }, 
  flags = 0x910003fd, 
  ptrace = 0xa90153f3, 
  wake_entry = {
    next = 0xaa0103f4911b2262
  }, 
  on_cpu = 0xf9400041, 
  cpu = 0xf90017a1, 
  wakee_flips = 0xd2800001, 
  wakee_flip_decay_ts = 0x37f8018097f909a2, 
  last_wakee = 0xf10bfc7ff94013a3, 
  recent_used_cpu = 0x54000228, 
  wake_cpu = 0xb0006561, 
  on_rq = 0x91018021, 
  prio = 0xf9401284, 
  static_prio = 0x52800000, 
  normal_prio = 0xb9404022, 
  rt_priority = 0x79000083, 
  sched_class = 0x911b2273b9004022, 
  se = {
    load = {
      weight = 0x940b05adf9400013, 
      inv_weight = 0x91012260
    }, 
    runnable_weight = 0x97edbddd91052260, 
    run_node = {
      __rb_parent_color = 0x940b05c5aa1403e0, 
      rb_right = 0x97f0ec85aa1303e0, 
      rb_left = 0xa8c27bfda94153f3
    }, 
    group_node = {
      next = 0xd503201fd65f03c0, 
      prev = 0x52800021a9bf7bfd
    }, 
    on_rq = 0x910003fd, 
    exec_start = 0xd280000097f251d0, 
    sum_exec_runtime = 0xa8c17bfd97ec8318, 
    vruntime = 0xd503201fd65f03c0, 
    prev_sum_exec_runtime = 0x910003fda9be7bfd, 
    nr_migrations = 0xd1012013f9000bf3, 
    statistics = {<No data fields>}, 
    depth = 0x39434660, 
    parent = 0x52800020f9000fb4, 
    cfs_rq = 0xb940ce7439034a60, 
    my_q = 0x52800023d5033f9f, 
    avg = {
      last_update_time = 0x940b0cf552800001, 
      load_sum = 0x52800003aa1303e0, 
      runnable_load_sum = 0x5280002152800c62, 
      util_sum = 0x940b0cf0, 

struct -o [struct] : 显示结构体中成员的偏移 struct [struct] [address] : 显示对应地址结构体的值 [struct] [address] :简化形式显示对应地址结构体的值 [struct] [address] -xo: 打印结构体定义和大小 [struct].member[address]: 显示某个成员的值

  • rd: 读取内存内容
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> rd ffff0000085dc0d0 32
ffff0000085dc0d0:  a8c17bfd39000020 d503201fd65f03c0    ..9.{...._.. ..
ffff0000085dc0e0:  910003fda9bf7bfd 97ec827fd50342ff   .{.......B......
ffff0000085dc0f0:  d65f03c0a8c17bfd 910003fda9bd7bfd   .{...._..{......
ffff0000085dc100:  b0005d73a90153f3 aa0103f4911b2262   .S..s]..b"......
ffff0000085dc110:  f90017a1f9400041 910083a2d2800001   A.@.............
ffff0000085dc120:  37f8018097f909a2 f10bfc7ff94013a3   .......7..@.....
ffff0000085dc130:  b000656154000228 f940128491018021   (..Tae..!.....@.
ffff0000085dc140:  b940402252800000 1100044279000083   ...R"@@....yB...
ffff0000085dc150:  911b2273b9004022 f9400261f94017a2   "@..s"....@.a.@.
ffff0000085dc160:  b50000c1ca010041 a8c37bfda94153f3   A........SA..{..
ffff0000085dc170:  128002a0d65f03c0 97ebee0b17fffff7   .._.............
ffff0000085dc180:  910003fda9be7bfd aa0003f4a90153f3   .{.......S......
ffff0000085dc190:  940b05adf9400013 97ec5fb991012260   ..@.....`"..._..
ffff0000085dc1a0:  97edbddd91052260 940b05c5aa1403e0   `"..............
ffff0000085dc1b0:  97f0ec85aa1303e0 a8c27bfda94153f3   .........SA..{..
ffff0000085dc1c0:  d503201fd65f03c0 52800021a9bf7bfd   .._.. ...{..!..R

rd [addr] [len]: 查看指定地址,长度为len的内存 rd -S [addr][len]: 尝试将地址转换为对应的符号 rd [addr] -e [addr] : 查看指定内存区域内容

  • dis: 进行返汇编,查看对应地址的代码逻辑
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> dis -r ffff0000085dc0d0
0xffff0000085dc0b0 <sysrq_handle_crash>:        stp     x29, x30, [sp,#-16]!
0xffff0000085dc0b4 <sysrq_handle_crash+4>:      mov     x29, sp
0xffff0000085dc0b8 <sysrq_handle_crash+8>:      bl      0xffff000008141a48 <__rcu_read_unlock>
0xffff0000085dc0bc <sysrq_handle_crash+12>:     adrp    x1, 0xffff0000092e9000 <xen_dummy_shared_info+984>
0xffff0000085dc0c0 <sysrq_handle_crash+16>:     mov     w0, #0x1                        // #1
0xffff0000085dc0c4 <sysrq_handle_crash+20>:     str     w0, [x1,#1448]
0xffff0000085dc0c8 <sysrq_handle_crash+24>:     dsb     st
0xffff0000085dc0cc <sysrq_handle_crash+28>:     mov     x1, #0x0                        // #0
0xffff0000085dc0d0 <sysrq_handle_crash+32>:     strb    w0, [x1]
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> dis -f ffff0000085dc0d0
0xffff0000085dc0d0 <sysrq_handle_crash+32>:     strb    w0, [x1]
0xffff0000085dc0d4 <sysrq_handle_crash+36>:     ldp     x29, x30, [sp],#16
0xffff0000085dc0d8 <sysrq_handle_crash+40>:     ret
  • ps: 查看线程状态
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> ps
   PID    PPID  CPU       TASK        ST  %MEM     VSZ    RSS  COMM
>     0      0   0  ffff000009192580  RU   0.0       0      0  [swapper/0]
      0      0   1  ffff80007bbc1a80  RU   0.0       0      0  [swapper/1]
      1      0   0  ffff80007bb68000  IN   0.0    2196     60  linuxrc
      2      0   0  ffff80007bb68d40  IN   0.0       0      0  [kthreadd]
      3      2   0  ffff80007bb69a80  ID   0.0       0      0  [rcu_gp]
      4      2   0  ffff80007bb6a7c0  ID   0.0       0      0  [rcu_par_gp]
      5      2   0  ffff80007bb6b500  ID   0.0       0      0  [kworker/0:0]
      6      2   0  ffff80007bb6c240  ID   0.0       0      0  [kworker/0:0H]
      7      2   0  ffff80007bb6cf80  ID   0.0       0      0  [kworker/u4:0]
      8      2   0  ffff80007bb6dcc0  ID   0.0       0      0  [mm_percpu_wq]
      9      2   0  ffff80007bb6ea00  IN   0.0       0      0  [ksoftirqd/0]
     10      2   0  ffff80007bbc0000  ID   0.0       0      0  [rcu_preempt]
     11      2   0  ffff80007bbc0d40  IN   0.0       0      0  [migration/0]
     12      2   0  ffff80007bbc27c0  IN   0.0       0      0  [cpuhp/0]
     13      2   1  ffff80007bbc3500  IN   0.0       0      0  [cpuhp/1]
     14      2   1  ffff80007bbc4240  IN   0.0       0      0  [migration/1]
     15      2   1  ffff80007bbc4f80  IN   0.0       0      0  [ksoftirqd/1]
     16      2   1  ffff80007bbc5cc0  ID   0.0       0      0  [kworker/1:0]
     17      2   1  ffff80007bbc6a00  ID   0.0       0      0  [kworker/1:0H]
     18      2   0  ffff80007bbd0000  IN   0.0       0      0  [kdevtmpfs]
     19      2   0  ffff80007bbd0d40  ID   0.0       0      0  [netns]
     20      2   0  ffff80007b040000  ID   0.0       0      0  [kworker/u4:1]
     21      2   1  ffff80007b040d40  IN   0.0       0      0  [rcu_tasks_kthre]
     42      2   1  ffff80007b0f3500  ID   0.0       0      0  [kworker/1:1]
     43      2   0  ffff80007b0f4240  ID   0.0       0      0  [kworker/0:1]
     49      2   1  ffff80007b0f4f80  ID   0.0       0      0  [kworker/u4:2]
     56      2   1  ffff80007b140000  IN   0.0       0      0  [kauditd]
    212      2   0  ffff80007b26ea00  ID   0.0       0      0  [kworker/u4:3]
    256      2   0  ffff80007b336a00  ID   0.0       0      0  [kworker/u4:4]
    471      2   1  ffff80007b2d6a00  IN   0.0       0      0  [oom_reaper]
    472      2   1  ffff80007b2d5cc0  ID   0.0       0      0  [writeback]
    474      2   0  ffff80007b330d40  IN   0.0       0      0  [kcompactd0]
    475      2   0  ffff80007b3327c0  IN   0.0       0      0  [ksmd]
    476      2   0  ffff80007b2d1a80  IN   0.0       0      0  [khugepaged]
    477      2   0  ffff80007b2d0000  ID   0.0       0      0  [crypto]
    478      2   1  ffff80007b2d0d40  ID   0.0       0      0  [kintegrityd]
    480      2   1  ffff80007b2d27c0  ID   0.0       0      0  [kblockd]
    501      2   1  ffff80007b2d3500  ID   0.0       0      0  [tpm_dev_wq]
    508      2   1  ffff80007b2d4240  ID   0.0       0      0  [ata_sff]
    541      2   0  ffff80007ac98000  ID   0.0       0      0  [edac-poller]
    551      2   1  ffff80007b044240  ID   0.0       0      0  [devfreq_wq]
    561      2   1  ffff80007b268000  IN   0.0       0      0  [watchdogd]
    647      2   0  ffff80007b268d40  ID   0.0       0      0  [rpciod]
    648      2   1  ffff80007b26c240  ID   0.0       0      0  [kworker/u5:0]
    649      2   0  ffff80007ad04f80  ID   0.0       0      0  [xprtiod]
    718      2   1  ffff80007bbd3500  IN   0.0       0      0  [kswapd0]
    815      2   1  ffff80007ad00000  ID   0.0       0      0  [nfsiod]
   1250      2   0  ffff80007b26dcc0  ID   0.0       0      0  [vfio-irqfd-clea]
>  1452      1   1  ffff80007b0f1a80  RU   0.0    2196     76  sh

ps -p [pid]: 显示进程父子关系 ps -t [pid]: 显示进程运行时间

  • kmem: 查看内核内存使用情况
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> kmem -i
                 PAGES        TOTAL      PERCENTAGE
    TOTAL MEM   511276         2 GB         ----
         FREE   506631       1.9 GB   99% of TOTAL MEM
         USED     4645      18.1 MB    0% of TOTAL MEM
       SHARED      353       1.4 MB    0% of TOTAL MEM
      BUFFERS        0            0    0% of TOTAL MEM
       CACHED      480       1.9 MB    0% of TOTAL MEM
         SLAB     1930       7.5 MB    0% of TOTAL MEM

   TOTAL HUGE        0            0         ----
    HUGE FREE        0            0    0% of TOTAL HUGE

   TOTAL SWAP        0            0         ----
    SWAP USED        0            0    0% of TOTAL SWAP
    SWAP FREE        0            0    0% of TOTAL SWAP

 COMMIT LIMIT   255638     998.6 MB         ----
    COMMITTED      479       1.9 MB    0% of TOTAL LIMIT
crash> 

kmem -i: 查看内存整体使用情况 kmem -s: 查看slab使用情况 kmem [addr]: 搜索地址所属的内存结构

  • 更多其它命令通过help查看

内核panic实例

内核访问空指针产生panic。

  1. 驱动制作

编写一个驱动,构造一个内核模块访问空指针的异常,演示如何使用crash分析内核奔溃的原因。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
include <linux/module.h>
#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/slab.h>

struct my_struct {
        unsigned long head;
        spinlock_t lock;
};
int *addr = 0; //null pointer
void panic_foo(struct my_struct *ms)
{
        int *p = addr;
        spin_lock(&ms->lock);
        if (ms->head == 10) {
                *p = 0xFFFF;
        } else if (ms->head = 0) {
                // do sth
        } else {
                // do sth
        }

        spin_unlock(&ms->lock);
}
int panic_kernel_init(void)
{
        struct my_struct *ms = kzalloc(sizeof(struct my_struct), GFP_KERNEL);
        spin_lock_init(&ms->lock);
        ms->head = 10;
        panic_foo(ms);

        return 0;
}
void panic_kernel_exit(void)
{
}
module_init(panic_kernel_init);
module_exit(panic_kernel_exit);
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
obj-m := panic-kernel.o
KERNEL_DIR := /home/linux

PWD := $(shell pwd)
all:
        make -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules

clean:
        rm *.o *.ko *.mod.c

.PHONY: clean

将编好的驱动打包进根文件系统, 启动后插入内核模块。

  1. panic 分析

内核的call trace如上图所示, 将对应的文件反汇编,找到问题出现对应的代码。

aarch64-linux-gnu-objdump -S panic-kernel.o > test.txt

截取部分反汇编如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Disassembly of section .text:

0000000000000000 <panic_foo>:

int *addr = 0; //null pointer


void panic_foo(struct my_struct *ms)
{
   0:   a9bd7bfd        stp     x29, x30, [sp, #-48]!
   4:   910003fd        mov     x29, sp
   8:   a90153f3        stp     x19, x20, [sp, #16]
   c:   aa0003f3        mov     x19, x0
        int *p = addr;
  10:   90000000        adrp    x0, 0 <panic_foo>
        raw_spin_lock_init(&(_lock)->rlock);            \
} while (0)

从汇编代码可以看出, panic_foo函数的参数(x0)最终保存在x19寄存器。我们现在想要知道出现问题时,代码走的是哪一个分支。

配合crash进行分析,先导入模块符号表:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> mod -S my_module
     MODULE       NAME           SIZE  OBJECT FILE
ffff000000ae2000  panic_kernel  16384  my_module/panic-kernel.o 

使用crash 查看出问题时结构体的值,确认函数走的是哪个分支。函数的参数是x19:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
crash> struct my_struct ffff8000fa4d9780
struct my_struct {
  head = 10, 
  lock = {
    {
      rlock = {
        raw_lock = {
          {
            val = {
              counter = 1
            }, 
            {
              locked = 1 '\001', 
              pending = 0 '\000'
            }, 
            {
              locked_pending = 1, 
              tail = 0
            }
          }
        }
      }
    }
  }
}

从打印的之来看,head成员的值为10, 可以确定代码走的是哪一个分支。

再结合之前的反汇编代码, 出错的位置在pc: panic_foo +0x54。pc保存的是栈顶指针,lr保存的是函数返回的地址(x30)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static __always_inline void spin_unlock(spinlock_t *lock)
{
        raw_spin_unlock(&lock->rlock);
  38:   aa1403e0        mov     x0, x20
  3c:   94000000        bl      0 <_raw_spin_unlock>
        } else {
                // do sth
        }

        spin_unlock(&ms->lock);
}
  40:   f94013f5        ldr     x21, [sp, #32]
  44:   a94153f3        ldp     x19, x20, [sp, #16]
  48:   a8c37bfd        ldp     x29, x30, [sp], #48
  4c:   d65f03c0        ret
                *p = 0xFFFF;
  50:   529fffe0        mov     w0, #0xffff                     // #65535
  54:   b90002a0        str     w0, [x21]
  58:   aa1403e0        mov     x0, x20
  5c:   94000000        bl      0 <_raw_spin_unlock>
}

偏移54的位置是把w0的值保存到x21, 而x21的地址是0。w0的值是mov w0, 0xffff直接赋值得来的。所以这里是将0xffff直接写到0地址导致的问题。

综上如上信息,结合实际的代码,最终找到问题的原因。

5T技术资源大放送!包括但不限于:C/C++,Arm, Linux,Android,人工智能单片机,树莓派,等等。在上面的【人人都是极客】公众号内回复「peter」,即可免费获取!!

记得点击分享、赞和在看,给我充点儿电吧

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 人人都是极客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
通过优启通制作U盘启动安装Windows系统「建议收藏」
通过优启通制作U盘启动安装Windows系统 (一)制作启动项,拷贝镜像(EASY U软件) 通过EASYU(优启通),制作启动盘,启动盘制作成功之后,在优启通主界面,模拟测试,选BIOS测试,若能进入,将win7的GHO镜像文件放入U盘.
全栈程序员站长
2022/09/07
8.9K0
通过优启通制作U盘启动安装Windows系统「建议收藏」
Win10加Ubuntu20.04双系统安装教程
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/163940.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/15
3.6K0
Linux通过U盘安装
1、CentOS 7.0 64位系统:CentOS-7.0-1406-x86_64-DVD.iso
用户5760343
2022/05/24
9.9K0
Linux通过U盘安装
安装win10+黑苹果双系统零基础教程
镜像链接迅雷资源https://mirrors.dtops.cc/iso/MacOS/daliansky_macos/macOS%20Catalina%2010.15.4%2819E287%29%20Installer%20for%20Clover%205109%20and%20WEPE%20Support%20UEFI%20and%20MBR.dmg
全栈程序员站长
2022/08/12
3.5K0
安装win10+黑苹果双系统零基础教程
win10如何添加linux开机引导,win10 linux 双系统怎么设置开机引导「建议收藏」
当然是下载Ubuntu了,我是在Ubuntu官网下载的原生版本,我下载的是Ubuntu最新版本15.04。没有选择国人修改过的kylin版本。kylin好不好我完全不懂,只是习惯性的觉得国人做系统不放心,就连修改下我都不放心。
全栈程序员站长
2022/09/15
7.9K0
手把手教你安装win10+Ubuntu16.04的双系统(全网最详细)
本系列为小白入门整个AI项目教程,主要涉及双系统的搭建,linux的使用,安装caffe-gpu版本,利用caffe实现目标检测,并移植模型到android移动端,也就是手机端进行目标检测,本篇为安装双系统的教程。
小小詹同学
2019/05/15
27.1K1
手把手教你安装win10+Ubuntu16.04的双系统(全网最详细)
U盘 PE系统制作教程(附pe系统启动方式+资源获取)
微 PE 工具箱 v2.2 是一款免费纯净、无捆绑软件、体积小巧、功能齐全的PE 系统,微PE工具箱 v2.2 由全新 Win10 内核打造,全面支持 NVMe盘,集成了实用的硬盘分区、数据恢复、系统安装和维护优化等一系列工具集。
软件小栈
2022/07/19
8.6K1
U盘 PE系统制作教程(附pe系统启动方式+资源获取)
Win7 U盘安装Ubuntu16.04 双系统详细教程
http://blog.sciencenet.cn/blog-3027933-956284.html
bear_fish
2018/09/19
7.8K0
Win7 U盘安装Ubuntu16.04 双系统详细教程
U盘pe(理论大白菜、优启通、微PE都可以) 装ESXI方案 (非通用UltraISO重做启动U盘),省U盘「建议收藏」
此文是我发的一篇的准备工作,因为ESXi 6.7刚发布的原因,很多同学等着升级,故而先写了出来。原文如下:
全栈程序员站长
2022/10/03
8.9K0
U盘pe(理论大白菜、优启通、微PE都可以) 装ESXI方案 (非通用UltraISO重做启动U盘),省U盘「建议收藏」
【安装教程】Win10与Ubuntu16.04双系统安装教程
实验室的项目的客户方是机场,所有程序必须在windows环境运行,但是为了学习深度学习中目标检测的RCNN系列算法,论文代码是caffe框架下,因此必须在Ubuntu16.04下安装caffe。为了兼顾两者,自己开始了双系统的安装之路。
AI那点小事
2020/04/20
4.9K0
【安装教程】Win10与Ubuntu16.04双系统安装教程
UEFI安装win10+manjaro双系统
微软官方 Windows 10 ISO 直接下载网页:https://www.microsoft.com/zh-cn/software-download/windows10ISO
全栈程序员站长
2022/09/07
4.8K0
UEFI安装win10+manjaro双系统
win10下装ubuntu双系统(免U盘)
最近决定在win10的基础上装一个ubuntu系统用来管理服务器。但是有一个问题,前段时间U盘不慎丢失,没有启动盘,又想装ubuntu双系统,该怎么办呢?基于以前装黑苹果的经历,决定用EasyBCD做引导的方式,试了试还可以,过程如下。
星尘的一个朋友
2020/11/25
16.1K1
win10下装ubuntu双系统(免U盘)
技术角 | Windows 10/7与Ubuntu 18.04双系统安装
最近需要学习深度学习的同时混一混Kaggle社区,所以部署Kaggle Docker以便环境上一致,因此需要安装Ubuntu以便环境的部署。因此需要在已有Windows 10的带有GPU台式机上安装双系统来部署,为了方便以后有使用需求,现简单总结下双系统的安装情况。
ZNing
2020/05/13
1.8K0
技术角 | Windows 10/7与Ubuntu 18.04双系统安装
windows系统下安装linux(ubuntu)双系统
windows系统下安装linux(ubuntu)双系统 原创程序员爱酸奶(QuellanAn) 最后发布于2018-03-09 13:41:13 阅读数 24907 收藏 展开 最近在找工作,很多面试要求上都写着熟悉linux系统,擅长shell编程,虽然在学校学过操作系统的课程,但是到现在出来工作,学的课程忘得也差不多了,并且那些linux命令不经常使用的话,还是很容易忘记的,以前也有一段时间想学学linux,但是一直没有狠下心来,总是在网站(实验楼https://www.shiyanlou.com/)上学习,但是那种其实很难坚持下来,在window系统上装过虚拟机,然后再虚拟机上装的ubuntu,但是相当于一个软件使用,使用起来是相当的卡,体验感太差,终于下定决心装一个linux系统了,不过感觉还是离不开windows系统,毕竟做java开发从学校到现在都是用window系统,怕一下子换了有点适应不过来,所以就装了一个双系统。 好了,废话不过说,直接开始,首先需要准备的东西: U盘(容量>8G)、UltraISO刻录软件、Ubuntu 镜像文件 1.U盘是做启动盘的,就像用老毛桃或大白菜把U盘制作成启动盘装window系统一样。最好3.0端口,比较快。 2.在电脑上下一个UltraISO软件,可以百度UltraISO(https://cn.ultraiso.net/xiazai.html 免费下载试用就可以了)第一个就可以。 3.ubuntu镜像文件,这个可以在官网上下载,我用的是ubuntu 15.10.你们可以选择自己想要的镜像文件就行网址:http://old-releases.ubuntu.com/releases/ (希望对你们有用)。
Python之道
2020/04/09
13.3K0
Window和Linux双系统安装历程
然后这单独分出来的 20g 就作为一个新的未分配的分区,到时就可以给 Linux 用。
星哥玩云
2022/07/18
9.1K0
Window和Linux双系统安装历程
[ 利器篇 ] - Microsoft Surface Pro 系列安装 Ubuntu 16.04 系统
Microsoft Surface Pro 系列一直是平板+PC中的强者,刷新了针对PC的看法。这次由于项目的需求搭建测试环境,需要使用Ubuntu 16.04 系统,在Surface Pro 7 安装Ubuntu 16.04 进行开发体验。
程序手艺人
2020/09/15
4K0
[ 利器篇 ] -  Microsoft Surface Pro 系列安装 Ubuntu 16.04 系统
Ubuntu系统制作U盘启动项以及针对U盘挂载后显示"只读系统"的解决措施
1)Linux系统制作U盘启动项 在公司的一台ubuntu机器上插入U盘,然后将机器上的一个ubuntu的iso镜像做成U盘启动。制作方法如下: 首先执行命令
洗尽了浮华
2018/10/11
3.1K0
Ubuntu系统制作U盘启动项以及针对U盘挂载后显示"只读系统"的解决措施
[735]利用UItraISO软碟通制作U盘启动盘安装Ubuntu16.04系统
第2,3可以不勾选:第2选项是默认.ISO文件都用软碟通打开,不经常使用软碟通没必要关联;第3选项会生产一个驱动器(空盘),类似于百度云盘的,不经常使用软碟通不建议勾选。
周小董
2020/01/13
3.8K0
[735]利用UItraISO软碟通制作U盘启动盘安装Ubuntu16.04系统
使用Ventoy引导安装系统,是时候告别格式化U盘时代了(Windows & Linux)
操作系统(Operating System,简称OS)是管理计算机硬件与软件资源的计算机程序。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入设备与输出设备、操作网络与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作界面。--- 参考百度百科
爱技术的小黄鸭
2023/06/15
2.6K0
使用Ventoy引导安装系统,是时候告别格式化U盘时代了(Windows & Linux)
win10下安装Ubuntu16.04双系统「建议收藏」
我们首先去Ubuntu的官网下载一个Ubuntu16.04的iso镜像文件。当然里面也有优麒麟,其实就是把Ubuntu16.04汉化了一下,个人推荐安装Ubuntu16.04 体验上可能好一些。
全栈程序员站长
2022/09/15
1.6K0
win10下安装Ubuntu16.04双系统「建议收藏」
推荐阅读
相关推荐
通过优启通制作U盘启动安装Windows系统「建议收藏」
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档