lldb 调试 linux下 .net Core 总结及开源扩展 yinuo
相信很多朋友在跟隨微軟.net core 從windows平臺遷移至linux平臺的過程中遇到很多別扭的地方,這里我只聊聊 運行時 調試的那些事兒。
首先從工具上來講Windows上的windbg肯定是運行時的首選調試工具(因為有對應版本的SOS.dll),在linux平臺運行時調試需要切換到lldb (Only lldb is supported by the SOS plugin. gdb can be used to debug the coreclr code but with no SOS support.)
調試器的原理和功能基本一樣,但細節到某個功能的命令自然會有區別,尤其是熟練了其中1個的命令之后(比如之前在看匯編的時候是Intel格式,現在要適用AT&T格式)…
這里先總結一些個人常用的命令在 windbg下和lldb下的對比:
非托管命令:
| 列出當前模塊 | image list | lmf |
| 當前線程 | thread list | ~ |
| 當前線程棧回溯 | thread backtrace | kp |
| 所有線程棧回溯 | thread backtrace all | ~* kp |
| 切換線程 | thread select 2 | ~2s kp |
| 查看寄存器 | re r | r |
| 查看內存(8字節) | memory read –size 8 –format x <address> | dq <address> |
LLDB同GDB的命令對比:https://lldb.llvm.org/lldb-gdb.html
托管命令:
這里先介紹下自己寫的開源lldb調試.net Core擴展模塊?Yinuo
在使用lldb調試linux .net Core程序的過程中,有很多不適應的地方,比如遍歷并查看所有線程的托管棧回溯 在windbg下可以~*e !clrstack?在lldb里雖然有bt all和clrstack?但是卻只能手動切換單個線程再回溯,沒有辦法結合到一起,還有一個原因是lldb內命令輸出的內容顏色統一,不太好區分重點關注的點,比如線程回溯比較關注方法名,托管對象轉儲比較關注內部對象地址等等,lldb的好處是支持python或者c++接口,可以通過接口方式寫lldb的擴展來輔助我們調試過程,提高調試效率。
下面介紹下調試擴展 Yinuo 的加載過程:
以下的軟件環境 CentOS7(x64),lldb-3.6.0,python-2.7.5
首先git下載模塊?git clone https://github.com/espider/yinuo
目錄沒有要求,但要記得,因為加載模塊的時候要知道在哪。啟動lldb 并附加被調試的進程?(lldb) attach -p PID
加載Yinuo調試模塊?(lldb) command script import ~/yinuo/ynlldb.py?之前git下來的目錄里的python文件
成功加載ynlldb.py后可以?help?看下當前注冊進來的命令,都以 yn_ 為前綴,加載模塊的時候會判斷當前的.net Core版本號,并自動加載對應版本的調試插件libsosplugin.so
接下來介紹下當前注冊進lldb的輔助調試命令
yn_heap_dump
查看當前托管堆信息命令,以色塊和色塊的比例直觀的感受 Gen 0,1,2 LOH 在同一個堆內的比例 以及其實際大小(這里的比例按托管堆的地址空間計算,并沒有排除Free的和Gen0沒有使用的地址空間,由于比例可能相去甚遠所以有可能看不到某個堆的色塊)
yn_object_dump
轉儲托管對象,可以根據類型的方法表、類型名、對象地址 進行批量或者單個轉儲,同時計算對象(按方法表或類型的話針對每1個單獨對象)所屬托管堆的位置Gen 0,1,2,LOH,并統計4類堆內的數量。
支持選項和參數–methodtable/-m?轉儲此方法表的所有對象,后跟方法表地址;
–type/-t?轉儲此類型名的所有對象,后跟類型名(同方法表選項互斥 2選1);
–offset/-o?轉儲對象的同時是否深入轉儲其內部偏移對象,后跟該對象的偏移量(目前只支持1級內部偏移)
–address/-a?轉儲單個對象,后跟對象地址
–dumpobj/-d?是否轉儲對象,默認為True,如果不轉儲則只返回對象地址;
–gen/-g?是否顯示對象所在的堆Gen0,1,2,LOH,默認True;
例如想要查看 類型Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Frame`1[[Microsoft.AspNetCore.Hosting.Internal.HostingApplication+Context, Microsoft.AspNetCore.Hosting]] 方法表地址?00007ff8711df620?可以這樣寫轉儲命令:
這里會對輸出內容做下顏色處理,比如我們比較關心其內部成員的Value這列,如果是地址的話會顯示成黃色,方便調試時候的快速定位。
如果想要轉儲某個對象可以這樣寫,根據對象地址:
發現對象內的某個成員比較感興趣,例如 剛剛的對象內偏移?0xe0?位置是?RawTarget
想對其進行偏移轉儲 可以這樣寫:
yn_thread_clrstack
顯示某個線程或者所有線程的托管棧回溯,不指定選項?–thread/-t?的話默認顯示當前線程的托管棧回溯,?-t?跟線程index可以回溯指定線程,或者 跟?all,來批量顯示所有線程的托管棧回溯,參數?-a?可選(此為SOS命令clrstack可選參數)
這里也對輸出的內容做了顏色處理,比如IP指令指針列和CallSite是我們比較關注的,這里分別用黃色和綠色標注。
yn_thread_pe
顯示某個線程或者所有線程托管異常,選項同 yn_thread_clrstack 一樣
yn_transfer
此命令只用于轉移執行其他lldb命令,因為yinuo項目調試的時候會在當前目錄生成一個log文件(ynlldb.log)會把所有執行的yinuo命令及輸出寫入日志便于以后的查詢,使用例如:yn_transfer dumpheap -stat?會執行?dumpheap -stat?并把結果輸出到終端和日志文件里。Yinuo?項目 License 采用 BSD,大家有興趣可以自己調整或者聯系我共同維護,實現自己的調試命令比較簡單,git項目內的 commandlist 目錄,所有自動注冊的調試命令都在這里以,自命名.py文件即可,內容例子及說明如下:
#!/usr/bin/python # coding:utf-8 import lldb import commandlist.ynbase as yn from util.colorstyle import * from util.exportcontent import * """這里把自定義類型注冊進來等待加載的時候自動注冊""" def register_lldb_commands(): return [ YNTransfer() ] """自定義類型繼承自yn.YNCommand即可""" class YNTransfer(yn.YNCommand): """ transfer lldb command and exe it for log """ def __init__(self): pass """這個是注冊到lldb里的命令名字""" def name(self): # register function name in lldb return 'yn_transfer' """如果有選項的話在這里定義,基于python argparse模塊實現的 """ def options(self): return [ ] """描述信息""" def description(self): return 'Transfer lldb command for log,e.g. arguments: dumpheap -stat' """這里是實際命令的具體實現了""" def run(self, options, arguments): target = lldb.debugger.GetSelectedTarget() if target: if arguments: YNTransfer.handle_command(arguments) else: export_content(' ? ?no arguments in yn_transfer.') else: export_content(' ? ?no target in current debugger.') def handle_command(args): (ci, result) = yn.run_log_command( " " + (" ".join(args) if len(args) > 0 else '')) success = result.Succeeded() if success: output = result.GetOutput() contents = output.strip() lines = contents.splitlines(False) for i in range(len(lines)): export_content(' ? ?%s' % lines[i]) else: export_content( ' ? ?error="%s"' % use_style_level( important_level['high2'], result.GetError())) export_content( ' ? ?%s ? ' % use_style_level( important_level['low2'], '-------------')) |
參考文檔:
https://github.com/dotnet/coreclr/blob/master/Documentation/building/debugging-instructions.md
https://lldb.llvm.org/python-reference.html
https://github.com/llvm-mirror/lldb
https://github.com/facebook/chisel
相關文章:?
快速搭建本地 .NET Core 運行時調試環境
原文地址:https://espider.github.io/NET-Core/lldb-dotnet-core-python/
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的lldb 调试 linux下 .net Core 总结及开源扩展 yinuo的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET Core快速入门教程 1、开篇
- 下一篇: Visual Studio Code: