• dwarf格式解析


    debug_line中包含的是地址和源文件行之间的关系

    我今天想搞清楚的是文件的C代码和汇编代码之间的关系:

    对这块之前一直是迷迷糊糊的,发现这个问题已经严重影响到bug的定位了.

    之前感觉C和汇编不能一一对应起来,但是太模糊了! 什么叫做不能一一对应,到底是C能对应到某一部分的汇编,还是汇编能对应到某一部分的C,能不能说得清楚一些?

    希望看到的一种现象是: 能够从dwarf中看到, 说这部分汇编代码就是对应的C语言中的第几行到第几行!~

    addr2line的貌似可以解答我的疑惑.

    addr2line输入一个虚拟地址,然后addr2line会根据这个地址报告我说这个地址对应的虚拟地址是多少

    [疑惑: 对于inline的函数会怎么处理呢?]

    具体用法:

    an accurate picture of the source program

    x29在arm64中是栈帧寄存器

    发现栈帧中根本就没有!

    arm64的ret指令是会改变寄存器的

    b和ret,跳转指令会改变寄存器,ret指令也会改变寄存器. 但是改变的都是x30寄存器吧? 还包括状态寄存器!

    可能CPU会

    arm64的处理规范是:caller把所有的变量给准备好,按照x0到x7的方式准备好[],如果超过8个参数,会把参数放到堆栈中去,那个一个栈帧到底是指什么?

    下面这段代码用来考察arm64的栈帧:(该代码很简单,但是包含了传参的复杂场景,包括形参多于8个,此时会涉及到寄存器不够用的情况.并且涉及到返回值很大)

    stp x29,x30,[sp, 0x8]!
    先修改寄存器的值, 再做
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    struct big{
        char buf[64];
        int i;
    };
    int func(int a, int b, int c, int d, int e,  
            int f, int g, int h, int i, int j) {
        return a+b+c+d+e+f+g+h+i+j;
    }
    struct big funb() {
        struct big big_buf;
        big_buf.i = func(1,2,3,4,5,6,7,8,9,10);
        return big_buf;
    }
    int funa(int a)
    {
        return a+1;
    }
    int fun(int a)
    {
        int b, c;
        b = a+2;
        c = funa(1);
        return a+b+c;
    }
    int main()
    {
        int i;
        struct big big_buf;
        big_buf = funb();
        i = big_buf.i;
        return fun(i);
    
    }   
    

     debug_line中的信息, 一脸蒙.这个段说是C与汇编的对应, 但是根本就没看出来呀!

    Raw dump of debug contents of section .debug_line:
    
      Offset:                      0x0
      长度:                      62
      DWARF 版本:                2
      Prologue Length:             29
      最小指令长度:              1
      “is_stmt”的初始值:       1
      Line Base:                   -5
      Line Range:                  14
      Opcode Base:                 13
    
     Opcodes:
      Opcode 1 has 0 args
      Opcode 2 has 1 args
      Opcode 3 has 1 args
      Opcode 4 has 1 args
      Opcode 5 has 1 args
      Opcode 6 has 0 args
      Opcode 7 has 0 args
      Opcode 8 has 0 args
      Opcode 9 has 1 args
      Opcode 10 has 0 args
      Opcode 11 has 0 args
      Opcode 12 has 1 args
     目录表为空。
    
     The File Name Table (offset 0x1c):
      条目  目录    时间    大小    名称
      1 0   0   0   test.c
    
     Line Number Statements:
      [0x00000027]  Extended opcode 2: set Address to 0x4004f6
      [0x00000032]  Special opcode 10: advance Address by 0 to 0x4004f6 and Line by 5 to 6
      [0x00000033]  Special opcode 104: advance Address by 7 to 0x4004fd and Line by 1 to 7
      [0x00000034]  Special opcode 90: advance Address by 6 to 0x400503 and Line by 1 to 8
      [0x00000035]  Special opcode 35: advance Address by 2 to 0x400505 and Line by 2 to 10
      [0x00000036]  Special opcode 161: advance Address by 11 to 0x400510 and Line by 2 to 12
      [0x00000037]  Special opcode 132: advance Address by 9 to 0x400519 and Line by 1 to 13
      [0x00000038]  Special opcode 188: advance Address by 13 to 0x400526 and Line by 1 to 14
      [0x00000039]  Special opcode 188: advance Address by 13 to 0x400533 and Line by 1 to 15
      [0x0000003a]  Special opcode 35: advance Address by 2 to 0x400535 and Line by 2 to 17
      [0x0000003b]  Special opcode 119: advance Address by 8 to 0x40053d and Line by 2 to 19
      [0x0000003c]  Special opcode 147: advance Address by 10 to 0x400547 and Line by 2 to 21
      [0x0000003d]  Advance PC by 2 to 0x400549
      [0x0000003f]  Extended opcode 1: 序列结束
    

     dwarf 只记录整个汇编代码中最关机的部分,

    什么是最关键的部分呢? 其实汇编代码大部分和C代码是无关的,比如说寄存器现场的保存, 变量的读取等, 都不是最核心的代码, 什么是最核心的代码?

    核心的代码是要能和C语言对应起来的代码! 想想dwarf的出现真是牛逼!

    因为dwarf能从另一个角度看C代码: 变量的声明与定义这个与我们平常定位问题是无关的, 所谓的汇编与C对应, 其实就是可执行代码!

    可执行代码包括:赋值与计算! 应该就这么两类了!(突然感觉层次好高~~~)

    那么这里就涉及到一个难题, 通常C代码的一行可能对应着汇编代码的多行,这个在dwarf中是怎么处理的?

    突然感觉dwarf做了一件很人工智能的事情, 意义不亚于谷歌翻译!

    从汇编到C语言代码段的翻译,不简单!

    如果类比成谷歌翻译, 那么就是概率性的问题了, dwarf翻译出来的结果也是概率性的吗?

    发现这样一个规律 debug_line中只针对这样几处C代码:

    1) 是计算的部分; 2)函数头函数尾 |||  也就是过滤掉了变量的声明的部分! 真是一个天大的发现

    可以好好研究一下dwarf翻译的算法:

  • 相关阅读:
    基于Linux OpenJDK Debian的发行版的JAVA_HOME环境变量的正确目标是什么?
    redhat linux卸载默认的openjdk与安装sun的jdk
    更换介质:请把标有…… DVD 的盘片插入驱动器“/media/cdrom/”再按回车键“ 解决方法
    mysql 导出表结构和表数据 mysqldump用法
    转怎么让VI支持中文显示
    debian 更换sh的默认链接为bash
    基于percona-monitoring-plugins实现Zabbix的MySQL多端口自动发现监控
    elasticsearch中client.transport.sniff的使用方法和注意事项
    网络大数据分析 -- 使用 ElasticSearch + LogStash + Kibana 来可视化网络流量
    Parsing Netflow using Kibana via Logstash to ElasticSearch
  • 原文地址:https://www.cnblogs.com/honpey/p/5990604.html
Copyright © 2020-2023  润新知