国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

開發一個Linux調試器(八):堆棧展開

系統 Linux
有時你需要知道的最重要的信息是什么,你當前的程序狀態是如何到達那里的。有一個 backtrace 命令,它給你提供了程序當前的函數調用鏈。這篇文章將向你展示如何在 x86_64 上實現堆棧展開以生成這樣的回溯。

[[205544]]

有時你需要知道的最重要的信息是什么,你當前的程序狀態是如何到達那里的。有一個 backtrace 命令,它給你提供了程序當前的函數調用鏈。這篇文章將向你展示如何在 x86_64 上實現堆棧展開以生成這樣的回溯。

系列索引

這些鏈接將會隨著其他帖子的發布而上線。

  1. 準備環境
  2. 斷點
  3. 寄存器和內存
  4. ELF 和 DWARF
  5. 源碼和信號
  6. 源碼級逐步執行
  7. 源碼級斷點
  8. 堆棧展開
  9. 讀取變量
  10. 之后步驟

用下面的程序作為例子:

  1. void a() { 
  2.     //stopped here 
  3. void b() { 
  4.      a(); 
  5. void c() { 
  6.      a(); 
  7. int main() { 
  8.     b(); 
  9.     c(); 

如果調試器停在 //stopped here' 這行,那么有兩種方法可以達到:main->b->a或main->c->a`。如果我們用 LLDB 設置一個斷點,繼續執行并請求一個回溯,那么我們將得到以下內容:

  1. * frame #0: 0x00000000004004da a.out`a() + 4 at bt.cpp:3 
  2.   frame #1: 0x00000000004004e6 a.out`b() + 9 at bt.cpp:6 
  3.   frame #2: 0x00000000004004fe a.out`main + 9 at bt.cpp:14 
  4.   frame #3: 0x00007ffff7a2e830 libc.so.6`__libc_start_main + 240 at libc-start.c:291 
  5.   frame #4: 0x0000000000400409 a.out`_start + 41 

這說明我們目前在函數 a 中,a 從函數 b 中跳轉,b 從 main 中跳轉等等。***兩個幀是編譯器如何引導 main 函數的。

現在的問題是我們如何在 x86_64 上實現。最穩健的方法是解析 ELF 文件的 .eh_frame 部分,并解決如何從那里展開堆棧,但這會很痛苦。你可以使用 libunwind 或類似的來做,但這很無聊。相反,我們假設編譯器以某種方式設置了堆棧,我們將手動遍歷它。為了做到這一點,我們首先需要了解堆棧的布局。

  1.     High 
  2. |   ...   | 
  3. +---------+ 
  4. |  Arg 1  | 
  5. +---------+ 
  6. |  Arg 2  | 
  7. +---------+ 
  8. Return  | 
  9. +---------+ 
  10. |Saved EBP| 
  11. +---------+ 
  12. |  Var 1  | 
  13. +---------+ 
  14. |  Var 2  | 
  15. +---------+ 
  16. |   ...   | 
  17.     Low 

如你所見,***一個堆棧幀的幀指針存儲在當前堆棧幀的開始處,創建一個鏈接的指針列表。堆棧依據這個鏈表解開。我們可以通過查找 DWARF 信息中的返回地址來找出列表中下一幀的函數。一些編譯器將忽略跟蹤 EBP 的幀基址,因為這可以表示為 ESP 的偏移量,并可以釋放一個額外的寄存器。即使啟用了優化,傳遞 -fno-omit-frame-pointer 到 GCC 或 Clang 會強制它遵循我們依賴的約定。

我們將在 print_backtrace 函數中完成所有的工作:

  1. void debugger::print_backtrace() { 

首先要決定的是使用什么格式打印出幀信息。我用了一個 lambda 來推出這個方法:

  1. auto output_frame = [frame_number = 0] (auto&& func) mutable { 
  2.     std::cout << "frame #" << frame_number++ << ": 0x" << dwarf::at_low_pc(func) 
  3.               << ' ' << dwarf::at_name(func) << std::endl; 
  4. }; 

打印輸出的***幀是當前正在執行的幀。我們可以通過查找 DWARF 中的當前程序計數器來獲取此幀的信息:

  1. auto current_func = get_function_from_pc(get_pc()); 
  2.     output_frame(current_func); 

接下來我們需要獲取當前函數的幀指針和返回地址。幀指針存儲在 rbp 寄存器中,返回地址是從幀指針堆棧起的 8 字節。

  1. auto frame_pointer = get_register_value(m_pid, reg::rbp); 
  2. auto return_address = read_memory(frame_pointer+8); 

現在我們擁有了展開堆棧所需的所有信息。我只需要繼續展開,直到調試器*** main,但是當幀指針為 0x0 時,你也可以選擇停止,這些是你在調用 main 函數之前調用的函數。我們將從每幀抓取幀指針和返回地址,并打印出信息。

  1. while (dwarf::at_name(current_func) != "main") { 
  2.         current_func = get_function_from_pc(return_address); 
  3.         output_frame(current_func); 
  4.         frame_pointer = read_memory(frame_pointer); 
  5.         return_address = read_memory(frame_pointer+8); 
  6.     } 

就是這樣!以下是整個函數:

  1. void debugger::print_backtrace() { 
  2.     auto output_frame = [frame_number = 0] (auto&& func) mutable { 
  3.         std::cout << "frame #" << frame_number++ << ": 0x" << dwarf::at_low_pc(func) 
  4.                   << ' ' << dwarf::at_name(func) << std::endl; 
  5.     }; 
  6.     auto current_func = get_function_from_pc(get_pc()); 
  7.     output_frame(current_func); 
  8.     auto frame_pointer = get_register_value(m_pid, reg::rbp); 
  9.     auto return_address = read_memory(frame_pointer+8); 
  10.     while (dwarf::at_name(current_func) != "main") { 
  11.         current_func = get_function_from_pc(return_address); 
  12.         output_frame(current_func); 
  13.         frame_pointer = read_memory(frame_pointer); 
  14.         return_address = read_memory(frame_pointer+8); 
  15.     } 

添加命令

當然,我們必須向用戶公開這個命令。

  1. else if(is_prefix(command, "backtrace")) { 
  2.     print_backtrace(); 

測試

測試此功能的一個方法是通過編寫一個測試程序與一堆互相調用的小函數。設置幾個斷點,跳到代碼附近,并確保你的回溯是準確的。

我們已經從一個只能產生并附加到其他程序的程序走了很長的路。本系列的倒數第二篇文章將通過支持讀寫變量來完成調試器的實現。在此之前,你可以在這里找到這個帖子的代碼。 

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2017-06-28 14:21:22

Linux調試器斷點

2017-06-22 10:44:55

Linux調試器準備環境

2017-10-09 10:56:49

Linux調試器處理變量

2017-10-12 18:20:44

Linux調試器高級主題

2017-08-28 14:40:57

Linux調試器源碼和信號

2017-09-25 08:04:31

Linux調試器源碼級斷點

2017-07-25 10:30:32

Linux調試器Elves和dwarv

2017-07-05 14:37:07

Linux調試器寄存器和內存

2017-08-28 15:29:19

Linux調試器源碼級逐步執行

2024-03-13 08:00:00

Linux調試器應用程序

2017-04-19 21:35:38

Linux調試器工作原理

2011-08-25 16:34:27

Lua調試器

2010-03-01 11:06:52

Python 調試器

2020-03-16 10:05:13

EmacsGUDLinux

2009-12-14 10:57:34

Ruby調試器

2011-08-31 16:51:12

Lua調試器

2016-09-21 12:34:10

Chrome瀏覽器插件

2019-12-06 14:30:41

GNU調試器GDB修復代碼

2023-02-28 11:39:55

CMake腳本項目

2009-06-23 11:05:05

Mircosoft C
點贊
收藏

51CTO技術棧公眾號

日韩美女主播在线视频一区二区三区 | 韩国女主播成人在线| 性一交一乱一伧国产女士spa| 国产一区视频网站| 国产青青视频| 51久久夜色精品国产麻豆| 亚洲热av色在线播放| 91视频免费在线观看| 成人性色生活片免费看爆迷你毛片| 性一爱一乱一交一视频| 亚洲精品动漫久久久久| 中文字幕伦av一区二区邻居| 亚洲国产日韩美| 亚洲欧美日韩国产中文在线| 成人影音在线| 国产精品久久久久久久久借妻 | 国产在线不卡一卡二卡三卡四卡| 亚洲免费一级视频| 91精品国产麻豆| 国产一区不卡| 亚洲小视频在线播放| 欧美日韩精品在线| 国产电影一区| 日本不卡二区| 婷婷综合五月天| 福利一区视频| 日韩欧美精品一区二区| 午夜伦欧美伦电影理论片| 不卡精品视频| 91久久久在线| 亚洲天堂av一区| 91成人抖音| 欧美一区免费视频| 懂色aⅴ精品一区二区三区蜜月| 四虎视频在线精品免费网址| 日韩中文字幕一区| 欧美性生活久久| av一区二区在线播放| 漂亮人妻被中出中文字幕| 精品成人a区在线观看| 欧美成人午夜| 美乳中文字幕| 久久久爽爽爽美女图片| 高清不卡一区二区在线| www.综合网.com| 精品综合在线| 欧美色综合网站| 98精品久久久久久久| 1区不卡电影| 欧美极品少妇xxxxⅹ免费视频| 精品一二线国产| 欧美xxxx做受欧美88bbw| 精品国产二区在线| 欧美日韩日日夜夜| 亚洲第一精品影视| 国产中文字幕在线播放| 亚洲free性xxxx护士白浆| 亚洲第一主播视频| 欧美艳星介绍134位艳星| 老鸭窝av在线| 国产精品入口免费视| 一区二区在线看| 亚洲第一福利社区| 国产视频1区2区3区| 精品自拍视频在线观看| 91麻豆视频网站| 欧美aaa级| 男人的天堂99| 欧美激情欧美狂野欧美精品| 国产日韩精品一区| 欧美顶级毛片在线播放| 福利电影导航| 国产精品成人av性教育| 偷拍日韩校园综合在线| 这里只有精品在线| 日本暖暖在线视频| 欧美日韩精品一区| 精品免费一区二区三区| 久久99久国产精品黄毛片色诱| 青春草视频在线观看| 亚洲成人网上| 亚洲丝袜一区在线| 99久久精品免费| 日本高清久久| 性chinese极品按摩| 欧美性视频网站| 精品人伦一区二区三区蜜桃网站 | 色偷偷噜噜噜亚洲男人的天堂| 操欧美女人视频| 免费观看羞羞视频网站| 91手机视频在线观看| 欧美日韩一区不卡| 精品综合久久久久久8888| 四虎精品一区二区免费| av三级影院| 国产高清自拍一区| 精品久久久久一区| 99在线热播精品免费| 国产a久久精品一区二区三区| 午夜影院在线观看视频| 日韩精品久久一区| 欧美久久精品午夜青青大伊人| 亚洲女爱视频在线| 国产婷婷精品| 宅男噜噜噜66国产精品免费| 国产不卡视频| 国产专区一区二区三区| 中文字幕亚洲一区| 一区二区视频免费在线观看| 一区二区三区高清视频在线观看| 国产高清不卡| 天堂av在线网站| 国产精品高精视频免费| 色噜噜夜夜夜综合网| 激情综合一区二区三区| 久久亚洲国产精品尤物| 香蕉av在线| 视频一区二区精品| 色悠悠久久88| 国产精品天干天干在线综合| 99热这里只有成人精品国产| 91av久久| 手机看片福利盒子久久| 国产91在线高潮白浆在线观看 | 黄色av电影在线观看| 亚洲乱码日产精品bd在线观看| 久久精品精品电影网| 一区二区久久久久| 香蕉久久夜色精品国产| 四虎国产精品永久在线国在线| 国模私拍视频| 免费看污污视频| 欧美中文字幕在线观看| 这里只有精品视频在线观看| www.亚洲色图.com| 99久久www免费| 伪装者免费全集在线观看| 波多野结衣av一区二区全免费观看 | 国产尤物久久久| 最新真实国产在线视频| 日韩五码在线观看| 成人h猎奇视频网站| 亚洲第一网站免费视频| 1000精品久久久久久久久| 在线精品一区| 国语自产精品视频在线看抢先版结局| 色视频www在线播放国产| 欧美日韩国产综合在线| 九九热r在线视频精品| 欧美综合一区二区| 91麻豆福利精品推荐| 欧美一区视频| 最新国产一区| 韩国成人动漫| 1769视频在线播放免费观看| 成人午夜天堂| 妞干网视频在线观看| 欧美在线激情| 国产成人久久精品| 九九视频这里只有精品| 欧美本精品男人aⅴ天堂| 欧美色视频日本版| 久久av中文字幕| 国语对白做受69| 高清国产一区| 国内自拍中文字幕| 交视频在线观看国产| 欧美性受黑人性爽| 在线观看欧美一区| 日本午夜视频| 国产成人l区| 久久久蜜臀国产一区二区| 亚洲涩涩av| 性欧美videohd高精| 福利视频在线看| 在线观看免费视频高清游戏推荐| 日本一区免费看| 亚洲一区二区三区毛片| 久久91精品国产91久久跳| 久久影院视频免费| 亚洲精品自拍偷拍| 91麻豆国产精品| 日韩无套无码精品| 青春草免费在线视频| 伊人久久大香线蕉综合影院首页| hd国产人妖ts另类视频| 91国产视频在线| 国产精品日韩欧美大师| 黄色一级视频网站| 国产丝袜欧美中文另类| 轻点好疼好大好爽视频| 久久影院亚洲| 国内精品久久影院| 日日噜噜夜夜狠狠视频| 97se亚洲| 中文字幕一区二区三区不卡 | 亚洲国产精品综合| 青青国产在线| 欧美亚洲高清| 一区二区三区在线观看国产|