Skip to content

天楚锐齿

人工智能 云计算 大数据 物联网 IT 通信 嵌入式

天楚锐齿

  • 下载
  • 物联网
  • 云计算
  • 大数据
  • 人工智能
  • Linux&Android
  • 网络
  • 通信
  • 嵌入式
  • 杂七杂八

使用objdump、readelf和addr2line来定位coredump时的exception异常或kernel panic异常

2019-09-21

模拟用户层奔溃

发送ABORT信号量来创造一个coredump或tombstone文件:
# kill -6 822
# cat /data/tombstones/tombstone_00
*** Aborted
Register dump:
R0: fffffffc   R1: 00000000   R2: 00000002   R3: 00000000
R4: 00000000   R5: bede5c88   R6: 0002f5c8   R7: 000000a2
R8: 01ce8014   R9: 00000000   SL: 47728000   FP: 00000000
IP: 00000000   SP: bede5c58   LR: b6f798c0   PC: 478a7e64
CPSR: 800e0010
Trap: 00000000   Error: 00000000   OldMask: 00000000
Addr: 00000000
Backtrace:
/lib/libpthread.so.0(__nanosleep+0x44)[0x478a7e64]
/usr/bin/avinserver[0x10f64]
/lib/libc.so.6(__libc_start_main+0x114)[0x4776f8fc]
Memory map:
00008000-00027000 r-xp 00000000 103:00 1145      /usr/bin/avinserver
0002e000-00037000 rw-p 0001e000 103:00 1145      /usr/bin/avinserver
01ce8000-01d09000 rw-p 00000000 00:00 0          [heap]
47700000-47720000 r-xp 00000000 103:00 566       /lib/ld-2.20.so
47727000-47728000 r–p 0001f000 103:00 566       /lib/ld-2.20.so
47728000-47729000 rw-p 00020000 103:00 566       /lib/ld-2.20.so
47730000-4774d000 r-xp 00000000 103:00 597       /lib/libgcc_s.so.1
4774d000-47754000 —p 0001d000 103:00 597       /lib/libgcc_s.so.1
47754000-47755000 rw-p 0001c000 103:00 597       /lib/libgcc_s.so.1
47758000-47882000 r-xp 00000000 103:00 579       /lib/libc-2.20.so
47882000-4788a000 —p 0012a000 103:00 579       /lib/libc-2.20.so
4788a000-4788c000 r–p 0012a000 103:00 579       /lib/libc-2.20.so
4788c000-4788e000 rw-p 0012c000 103:00 579       /lib/libc-2.20.so
4788e000-47890000 rw-p 00000000 00:00 0
47898000-478ad000 r-xp 00000000 103:00 628       /lib/libpthread-2.20.so
478ad000-478b4000 —p 00015000 103:00 628       /lib/libpthread-2.20.so
478b4000-478b5000 r–p 00014000 103:00 628       /lib/libpthread-2.20.so
478b5000-478b6000 rw-p 00015000 103:00 628       /lib/libpthread-2.20.so
我们看Backtrace部分最后一个调用位置:
/lib/libpthread.so.0(__nanosleep+0x44)[0x478a7e64]
这里的0x478a7e64为运行时地址,该地址对应/lib/libpthread.so.0里面的__nanosleep()函数偏移0x44位置。
不管这个运行时地址,我们用编译主机的工具链来objdump或readelf来查找__nanosleep()函数的链接地址(注:链接地址和运行时地址是不一样的,内核会有一个重定位的功能,把链接地址挪到运行时地址。如果没有用调试模式编译来加入符号表,则可能没法定位,除非直接理解无符号的纯汇编):
$ ../build/tmp/sysroots/x86_64-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-readelf -s ../build/tmp/sysroots/ac8317/lib/libpthread-2.20.so |grep __nanosleep
   175: 0000fd00   136 FUNC    WEAK   DEFAULT   12 __nanosleep@@GLIBC_2.4
  1269: 0000fce0    28 FUNC    LOCAL  DEFAULT   12 __nanosleep_nocancel
  1590: 0000fd00   136 FUNC    WEAK   DEFAULT   12 __nanosleep
$ ../build/tmp/sysroots/x86_64-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-objdump -S ../build/tmp/sysroots/ac8317/lib/libpthread-2.20.so |grep -A 30 “<__nanosleep>”
0000fd00 <__nanosleep>:
    fd00:       e59fc080        ldr     ip, [pc, #128]  ; fd88 <__local_syscall_error+0x20>
    fd04:       e79fc00c        ldr     ip, [pc, ip]
    fd08:       e33c0000        teq     ip, #0
    fd0c:       e52d7004        push    {r7}            ; (str r7, [sp, #-4]!)
    fd10:       1a000005        bne     fd2c <__nanosleep+0x2c>
    fd14:       e3a070a2        mov     r7, #162        ; 0xa2
    fd18:       ef000000        svc     0x00000000
    fd1c:       e49d7004        pop     {r7}            ; (ldr r7, [sp], #4)
    fd20:       e3700a01        cmn     r0, #4096       ; 0x1000
    fd24:       312fff1e        bxcc    lr
    fd28:       ea00000e        b       fd68 <__local_syscall_error>
    fd2c:       e92d4003        push    {r0, r1, lr}
    fd30:       ebfffba4        bl      ebc8 <__pthread_enable_asynccancel>
    fd34:       e1a0c000        mov     ip, r0
    fd38:       e8bd0003        pop     {r0, r1}
    fd3c:       e3a070a2        mov     r7, #162        ; 0xa2
    fd40:       ef000000        svc     0x00000000
    fd44:       e1a07000        mov     r7, r0
    fd48:       e1a0000c        mov     r0, ip
    fd4c:       ebfffbcc        bl      ec84 <__pthread_disable_asynccancel>
    fd50:       e1a00007        mov     r0, r7
    fd54:       e49de004        pop     {lr}            ; (ldr lr, [sp], #4)
    fd58:       e49d7004        pop     {r7}            ; (ldr r7, [sp], #4)
    fd5c:       e3700a01        cmn     r0, #4096       ; 0x1000
        ret
    fd60:       312fff1e        bxcc    lr
    fd64:       eaffffff        b       fd68 <__local_syscall_error>
0000fd68 <__local_syscall_error>:
T_PSEUDO_END (SYSCALL_SYMBOL)
可以看到,__nanosleep()函数链接地址在0x0000fd00位置。把该链接地址加上tombstone里面的偏移0x44,即0x0000fd44为出错的位置。其实从objdump已经可以看出出错的是
    fd44:       e1a07000        mov     r7, r0
这一行。
根据0x0000fd44用addr2line来定位源代码的文件和行号:
$ ../build/tmp/sysroots/x86_64-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-addr2line -e ../build/tmp/sysroots/ac8317/lib/libpthread-2.20.so -a -f -p  0x0000fd44
0x0000fd44: $a at /extended/disk9/android19/maxshu/linux_compile/linux_alios_bm/sources/build/tmp/work/armv7a-vfp-neon-poky-linux-gnueabi/glibc/2.20-r0/git/nptl/../sysdeps/unix/syscall-template.S:81
可以看到是syscall-template.S的第81行。
打开该源文件看看:
76 #else
77
78 /* This is a “normal” system call stub: if there is an error,
79    it returns -1 and sets errno.  */
80
81 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
82         ret
83 T_PSEUDO_END (SYSCALL_SYMBOL)
84
85 #endif
可以看到是:
T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
这里出错的。
其实__nanosleep()看源代码,就是用syscall方式进入了内核态,从用户层跟不到了:
/* Pause execution for a number of nanoseconds.  */
int
__nanosleep (const struct timespec *requested_time,
             struct timespec *remaining)
{
  return SYSCALL_CANCEL (nanosleep, requested_time, remaining);
}
hidden_def (__nanosleep)
weak_alias (__nanosleep, nanosleep)
当然该例子因为是用信号量模拟的异常,所以这个退出其实也是正常的系统调用。

模拟内核奔溃

用中断来触发panic错误,导致内核奔溃,重启后会有coredump或上次内核错误的log:
# echo c > /proc/sysrq-trigger
‘Kernel Exception: sysrq_handle_crash+0x14/0x20’ ..collect DB
.[bt]: [<c0008524>] do_DataAbort+0x84/0x104
.[bt]: [<c0012718>] __dabt_svc+0x38/0x60
.[bt]: [<c024a650>] sysrq_handle_crash+0x14/0x20
.[bt]: [<c024acfc>] __handle_sysrq+0x88/0x124
我们看异常出现位置:
.[bt]: [<c024a650>] sysrq_handle_crash+0x14/0x20
这里的c024a650为运行时地址,该地址对应内核vmlinux.bin里面的sysrq_handle_crash()函数偏移0x14位置。
不管这个运行时地址,我们用编译主机的工具链来objdump或readelf来查找sysrq_handle_crash()函数的链接地址(注:链接地址和运行时地址是不一样的,内核会有一个重定位的功能,把链接地址挪到运行时地址):
$ ../build/tmp/sysroots/x86_64-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-readelf -s ../image-release/vmlinux.bin |grep sysrq_handle_crash
  6449: c0248b5c    32 FUNC    LOCAL  DEFAULT    2 sysrq_handle_crash
$ ../build/tmp/sysroots/x86_64-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-objdump -S ../image-release/vmlinux.bin |grep -A 30 “<sysrq_handle_crash>”
c0248b5c <sysrq_handle_crash>:
static void sysrq_handle_crash(int key)
{
        char *killer = NULL;
        panic_on_oops = 1;      /* force panic */
c0248b5c:       e59f2014        ldr     r2, [pc, #20]   ; c0248b78 <sysrq_handle_crash+0x1c>
c0248b60:       e3a03001        mov     r3, #1
c0248b64:       e5823000        str     r3, [r2]
        wmb();
c0248b68:       f57ff04e        dsb     st
        *killer = 1;
c0248b6c:       e3a02000        mov     r2, #0
c0248b70:       e5c23000        strb    r3, [r2]
c0248b74:       e12fff1e        bx      lr
c0248b78:       c08692f4        .word   0xc08692f4
可以看到,sysrq_handle_crash()函数链接地址在0xc0248b5c位置。把该链接地址加上panic里面的偏移0x14,即0xc0248b70为出错的位置。其实从objdump已经可以看出出错的是
c0248b70:       e5c23000        strb    r3, [r2]
这一行。
根据0xc0248b70用addr2line来定位源代码的文件和行号:
$ ../build/tmp/sysroots/x86_64-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-addr2line -e ../image-release/vmlinux.bin -a -f -p  0xc0248b70
0xc0248b70: sysrq_handle_crash at /extended/disk9/android19/maxshu/linux_compile/linux_alios_bm/atc_linux/kernel/kernel-3.18/drivers/tty/sysrq.c:141
可以看到是sysrq.c的第141行导致。
从该源文件可以看到是:
135 static void sysrq_handle_crash(int key)
136 {
137         char *killer = NULL;
138
139         panic_on_oops = 1;      /* force panic */
140         wmb();
141         *killer = 1;
142 }
这里出错的,其本质还是一个正常操作,用来模拟panic方式。
当然该例子因为是用中断模拟触发的panic异常,所以这里强制panic后退出。
2,404次阅读

Post navigation

前一篇:

使用objdump、readelf和addr2line来定位coredump时的exception异常或kernel panic异常

后一篇:

DBus总线-X11、Wayland等桌面环境下进程间IPC通信机制

发表评论 取消回复

邮箱地址不会被公开。 必填项已用*标注

个人介绍

需要么,有事情这里找联系方式:关于天楚锐齿

=== 美女同欣赏,好酒共品尝 ===

微信扫描二维码赞赏该文章:

扫描二维码分享该文章:

分类目录

  • Linux&Android (79)
  • Uncategorized (1)
  • 下载 (28)
  • 云计算 (37)
  • 人工智能 (8)
  • 大数据 (24)
  • 嵌入式 (34)
  • 杂七杂八 (34)
  • 物联网 (59)
  • 网络 (23)
  • 通信 (21)

文章归档

近期文章

  • 使用Python渲染OpenGL的.obj和.mtl文件
  • 用LVGL图形库绘制二维码
  • Android使用Messenger和SharedMemory实现跨app的海量数据传输
  • CAN信号的c语言解析代码
  • QT qml下DBus的使用例子

近期评论

  • 硕发表在《使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序》
  • maxshu发表在《使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序》
  • Ambition发表在《使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序》
  • Ambition发表在《使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序》
  • maxshu发表在《Android9下用ethernet 的Tether模式来做路由器功能》

阅读量

  • 使用Android的HIDL+AIDL方式编写从HAL层到APP层的程序 - 16,804次阅读
  • 卸载深信服Ingress、SecurityDesktop客户端 - 12,078次阅读
  • 车机技术之Android Automotive - 6,661次阅读
  • 车机技术之车规级Linux-Automotive Grade Linux(AGL) - 5,860次阅读
  • Linux策略路由及iptables mangle、ip rule、ip route关系及一种Network is unreachable错误 - 5,709次阅读
  • 在Android9下用ndk编译vSomeIP和CommonAPI以及使用例子 - 5,658次阅读
  • linux下的unbound DNS服务器设置详解 - 5,601次阅读
  • linux的tee命令导致ssh客户端下的shell卡住不动 - 4,998次阅读
  • 车机技术之360°全景影像(环视)系统 - 4,897次阅读
  • libwebp(处理webp图像)的安装和使用 - 4,749次阅读

功能

  • 文章RSS
  • 评论RSS

联系方式

地址
深圳市科技园

时间
周一至周五:  9:00~12:00,14:00~18:00
周六和周日:10:00~12:00

标签

android AT命令 centos Hadoop hdfs ip ipv6 kickstart linux mapreduce mini6410 modem OAuth openstack os python socket ssh uboot 内核 协议 安装 嵌入式 性能 报表 授权 操作系统 数据 数据库 月报 模型 汽车 测试 深信服 深度学习 源代码 神经网络 统计 编译 网络 脚本 虚拟机 调制解调器 车机 金融
© 2023 天楚锐齿