• addr2line快速定位进程异常位置


    一、addr2line简介

    1、addr2line可以通过解析地址来定位异常发生在哪个文件,哪个函数,哪一行;不过只对编译时带-g参数的进程或者库文件有效,因此想使用addr2line定义进程发生crash时的位置,需要在编译时带上-g参数编译。

    2、可以通过addr2line --h指令查看addr2line各参数的说明:

     

    这里用的最多的参数是

    -e:指定需要转换地址的可执行文件名(默认文件是a.out)

    -f:显示函数名

    二、简单示例

    • 代码

    #include
    void print_crash(void)
    {
            char* s = "hello world!";
            *s = 'H';
    }
    int main()
    {
            print_crash();
            return 0;
    }
     

    •  编译

     

    • 执行dmesg指令,可以看到最后几行报错的信息 

     [2513891.249108] test_has_g[50957]: segfault at 4005a4 ip 00000000004004fd sp 00007ffc1c2e27e0 error 7 in test_has_g[400000+1000]
    [2513899.702424] test_no_g[51013]: segfault at 4005a4 ip 00000000004004fd sp 00007fff6425a8d0 error 7 in test_no_g[400000+1000]

    从报错的地址来看,编译时带-g跟不带-g报的地址都是00000000004004fd,这现象说明在程序正常运行的项目中可以不带-g来编译模块,当出现问题时再加上带-g参数来编译模块,然后用addr2line工具分析带-g参数编译出来的文件,因为带-g参数编译出来的文件比不带-g参数编译出来的文件大很多,所以在机器运行中的文件要不带-g参数编译。

    • 通过addr2line来查看进程test_no_g跟test_has_g异常的位置

     

     从addr2line -e  test_has_g 00000000004004fd -f跟addr2line -e  test_no_g 00000000004004fd -f 

     的执行结果可以看出,不带-g参数编译的test_no_g定位不到异常的位置,打印信息是??:?;带-g参数编译的进程test_has_g可以定位到异常的位置是test.c:5;就是test.c文件中的第5行出错,第5行代码是*s = 'H';这里报错是因为程序被装载时,系统把“hello world” 连同其它的字符串和const型数据放入到内存的只读区。执行时,一个变量s被设为指向该字符串的位置,当再试图向该位置写时,就会产生段错误。简单理解就是*s只可以读,不可以写。

    三、Android中的示例

    1、在Android.bp或者Android.mk添加-g跟strip信息,不然使用addr2line定位不到异常位置

    • Android.bp中添加
    1. cflags: ["-g"],
    2. cppflags: ["-g"],
    3. strip: {
    4. none:true
    5. },
    • Android.mk中添加 
    1. LOCAL_CFLAGS += -g
    2. LOCAL_CPPFLAGS += -g
    3. LOCAL_STRIP_MODULE :=false

     2、在墓碑tombstone_00文件中找到报错的地址及对应文件,这里报文的文件是/system/lib64/libandroid_servers.so,地址是0000000000037918。

    #04 pc 0000000000037918  /system/lib64/libandroid_servers.so (android::server::BroadcastRadio::BroadcastRadioService::nativeOpenTuner(_JNIEnv*, _jobject*, long, int, _jobject*, bool, _jobject*)+1520)

    这里是收音机服务异常导致system_server进程崩掉,通过addr2line工具定位到具体出错的位置。

    3、addr2line定位出错位置

    在Android.bp或者Android.mk添加-g跟strip信息后,重新编译frameworks/base/services目录得到新的/system/lib64/libandroid_servers.so库文件,然后对该库文件进行如下操作:

    •  addr2line -e out/target/product/spm8666p1_64_car/system/lib64/libandroid_servers.so 0000000000037918 -f

    定位到异常的位置是:
    frameworks/base/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp:276

     

     

     

  • 相关阅读:
    最新的Cesium和Three的整合方法(附完整代码)
    canal安装与客户端使用
    三维图形学课程笔记,3D建模与游戏开发方向(unity3d,c4d,3dsmax, maya的对比与联系)
    centos更换yum源
    一个SpringBoot问题就干趴下了?我却凭着这份PDF文档吊打面试官(Spring Boot知识点+详解)
    一文学会Spring,Spring最简单的入门教程(万字好文)
    JAVA‘无效目标发行版 17’的解决方案
    如何更好的选择服务器硬盘?
    基于mysql关系型数据库实现分布式锁以及存在的问题
    kali安装docker(亲测有效)
  • 原文地址:https://blog.csdn.net/u013357557/article/details/127784910