• arm 架构下内核打印的 oops 信息中的 Code 字段解析


    arm 架构下内核打印的 oops 信息中的 Code 字段解析

    问题描述

    在定位某个内核 oops 问题中,对 arm 架构 oops 信息中的 Code 字段输出信息的内容不太明白,查看内核 Documentation 文档得到如下信息:

    “Code” 之后的十六进制字节可能(在某些架构上)有一些当前指令之前的指令以及
    当前指令和之后的指令

    上述解释并不容易理解,于是阅读了下代码并编写了一个内核模块进行验证,在本文中记录一下。

    4.19.87 内核源码中 arm64 架构的 trap 代码

    static void __dump_instr(const char *lvl, struct pt_regs *regs)
    {
            unsigned long addr = instruction_pointer(regs);
            char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
            int i;
    
            for (i = -4; i < 1; i++) {
                    unsigned int val, bad;
    
                    bad = get_user(val, &((u32 *)addr)[i]);
    
                    if (!bad)
                            p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val);
                    else {
                            p += sprintf(p, "bad PC value");
                            break;
                    }
            }
            printk("%sCode: %s\n", lvl, str);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    此代码首先访问 pt_regs 结构,从中拿到 pc 指向的地址 addr,然后获取此地址前 4 个指令的值,最后打印的内容为 addr 指向地址的指令值。

    编写内核模块验证

    测试模块代码如下:

    #include 
    #include 
    
    static uint64_t *vaddr = (uint64_t *)0x61b8cba6;
    
    static int __init my_init(void)
    {
      printk("*vaddr is %llu\n", *vaddr);
    
      printk(KERN_INFO "Hello from Hello Module\\n");
      return 0;
    }
    
    static void __exit my_exit(void)
    {
      *vaddr = 0xdeadbeefdeadbeef;
      printk(KERN_INFO "Bye from Hello Module\\n");
    }
    
    module_init(my_init);
    module_exit(my_exit);
    
    MODULE_DESCRIPTION("Sample Hello World Module");
    MODULE_LICENSE("GPL");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    加载此模块时触发的内核 oops 部分信息如下:

    [ 9304.644233][ 0] [<ffffffbffc1e6010>] my_init+0x10/0x40 [test]
    [ 9304.649964][ 0] [<ffffffc000082988>] do_one_initcall+0xc8/0x1a8
    [ 9304.655869][ 0] [<ffffffc000155e78>] do_init_module+0x5c/0x1b4
    [ 9304.661687][ 0] [<ffffffc00010c830>] load_module+0x1a48/0x212c
    [ 9304.667504][ 0] [<ffffffc00010d160>] SyS_finit_module+0xac/0xd4
    [ 9304.673408][ 0] [<ffffffc000085c70>] el0_svc_naked+0x24/0x28
    [ 9304.679052][ 0] Code: d29974c1 f2ac3701 a9bf7bfd 910003fd (f9400021)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    相关代码反汇编信息如下:

    0000000000000000 :
       0:   d29974c1        mov     x1, #0xcba6                     // #52134
       4:   f2ac3701        movk    x1, #0x61b8, lsl #16
       8:   a9bf7bfd        stp     x29, x30, [sp,#-16]!
       c:   910003fd        mov     x29, sp
      10:   f9400021        ldr     x1, [x1]
      14:   580000e0        ldr     x0, 30 
      18:   94000000        bl      0 
      1c:   580000e0        ldr     x0, 38 
      20:   94000000        bl      0 
      24:   52800000        mov     w0, #0x0                        // #0
      28:   a8c17bfd        ldp     x29, x30, [sp],#16
      2c:   d65f03c0        ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    内核堆栈打印,crash 发生在 my_init+0x10 偏移处,此处的代码如下:

    10: f9400021 ldr x1, [x1]

    可以看到,指令的内容为 f9400021,正对应内核 oops 中 Code 打印括号内的值。Code 中的其它打印的指令内容,对应如下几个指令:

       0:   d29974c1        mov     x1, #0xcba6                     // #52134
       4:   f2ac3701        movk    x1, #0x61b8, lsl #16
       8:   a9bf7bfd        stp     x29, x30, [sp,#-16]!
       c:   910003fd        mov     x29, sp
    
    • 1
    • 2
    • 3
    • 4

    与上文的分析一致,说明分析正确。

  • 相关阅读:
    【Android】ADB无线连接Android设备
    软件测试--selenium安装使用
    PHP房屋租售信息管理系统可以用wamp、phpstudy运行定制开发mysql数据库BS模式
    Flink:企业向实时化、智能化大数据计算转型的利器
    jmeter JDBC Request参数化
    智慧公厕整体解决方案,厕所革命实施方案的范本
    OSG安装教程
    在 Python 中,函数是第一类对象
    安徽京准-NTP网络授时服务器助力助力甘南州公共资源交易
    mysql第三次作业
  • 原文地址:https://blog.csdn.net/Longyu_wlz/article/details/125955397