zoukankan      html  css  js  c++  java
  • 应用异常定位:通过记录maps更加准确定位问题点

    关键词:coredump、maps、objdump、gdb等等。

    最近遇到一个应用异常问题定位(Floating point exception/SIGFPE),说明是一个算术运算异常。

    这种问题通常也比较简单:通过ulimit -c打开coredump;SIGFPE会触发coredump;然后gdb分析coredump文件即可。

    这里的目的是记录一下过程,以及过程中做的一些优化点。主要就是增加了记录maps,更准确定位问题点。

    1. 设置coredump

    将coredump文件输出到/tmp目录下:

    echo "/tmp/core-%e-%p" > /proc/sys/kernel/core_pattern

    打开coredump选项:

    ulimit -c unlimited

    在系统遇到异常之后,就可能在/tmp/core-<comm>-<pid>文件。

    2. 程序中记录maps信息

    coredump文件中的backtrace能精确到函数,然后给一个发生问题的确切地址。

    但是这个地址是在进程中的虚拟地址,这个地址和可执行文件的对应关系,需要maps来确定。

    所以如果在程序开始记录自身的maps信息,能更有效定位问题。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/prctl.h>
    
    #define SELF_MAPS "/proc/self/maps"
    void dump_self_maps(void)
    {
        FILE *self_fd, *output_fd;
        char buf[1024], output_name[32], process_name[16];
    
        memset(buf, 0x0, sizeof(buf));
        memset(output_name, 0x0, sizeof(output_name));
    
        prctl(PR_GET_NAME, process_name);
    
        snprintf(output_name, sizeof(output_name), "/tmp/maps_%s_%d.txt", process_name, getpid());
        self_fd=fopen(SELF_MAPS,"r");
        if(self_fd==NULL)
        {
            perror("open file");
            exit(0);
        }
    
        output_fd=fopen(output_name,"w");
        if(output_fd==NULL)
        {
            perror("open file");
            exit(0);
        }
    
        while(fgets(buf,sizeof(buf),self_fd)!=NULL)
        {
            fputs(buf,output_fd);
            //printf("%s", buf);
        }
    
        fclose(output_fd);
        fclose(self_fd);
    }
    
    void main(void)
    {
        dump_self_maps();
    }

    就会生成/tmp/maps-<comm>-<pid>.txt文件,通过pid可以和core文件匹配上。

    3. 定位实例

    定位过程如下记录。

    3.1 执行程序

    执行程序后发现如下异常:

    Floating point exception

    这个信息说明收到了信号SIGFPE,是一种算术运算错误。

    3.2 查看coredump文件

    sudo gdb <bin> <core>

    然后查看backtrace信息:

    从#2可以看出是div0错误,然后最接近的是#3,说明问题出在IFMS_USBHostSend()中。

    但是在IFMS_USBHostSend()函数哪里呢?

    3.3 结合maps查看最直接问题点

    如果想看到更直接的问题点,就需要通过maps信息来确定。

    首先看地址0xb6bb4a12,看其落在maps的那个区域:

    可以看出这个地址在libusb230.so中,然后计算偏移量:

    0xb6bb4a12 - 0xb6bb0000 = 0x4a12

    所以最直接问题点在libusb230.so文件的0x4a12处。

    通过objdump -d <bin/lib>,然后找到地址0x4a12:

    通过反汇编结果可以看出问题点在__aeabi_uidivmod()函数。结合代码就不难发现问底根源了。 

  • 相关阅读:
    学习进度10
    阅读笔记07
    构建之法阅读笔记06
    学习进度09
    构建之法阅读笔记05
    团队项目个人每日总结(4.27)
    学习进度08
    构建之法阅读笔记04
    写好一份技术简历很重要
    技术人员的发展之路
  • 原文地址:https://www.cnblogs.com/arnoldlu/p/12125780.html
Copyright © 2011-2022 走看看