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翻譯的算法:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM