[英]Why the breakpoints set in STL are "skipped/ignored" while using LLDB?
我的目標是:我想進入 STL istream
的某些代碼行。 所以我使用自定義構建的“LIBC++13”和“Debug”構建類型(我使用的命令顯示在底部),這樣(我認為)我可以獲得 STL 的完全可調試版本,並且能夠逐步進入我想要的一切。 但我有一個問題。
這是我的istream
斷點設置, BREAKPOINT A(Line 1447)
並希望進入Line 310
:
// -*- C++ -*-
//===--------------------------- istream ----------------------------------===//
// ..................(other).....................
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is,
basic_string<_CharT, _Traits, _Allocator>& __str)
{
ios_base::iostate __state = ios_base::goodbit;
typename basic_istream<_CharT, _Traits>::sentry __sen(__is); // BREAKPOINT A (Line 1447)
if (__sen) // Line 1448
{
// ...
}
// ..................(other).....................
template <class _CharT, class _Traits>
basic_istream<_CharT, _Traits>::sentry::sentry(basic_istream<_CharT, _Traits>& __is,
bool __noskipws)
: __ok_(false)
{
if (__is.good()) // Want To Step Into Here (Line 310)
{
// ...
}
和程序:
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream ifs{"testdata.txt"};
string tmp{};
ifs >> tmp;
}
我的問題是:使用 GDB,當我停在"BREAKPOINT A"時,我可以進入"Line 310" 。 但是對於 LLDB,當我停在"BREAKPOINT A"時,我無法進入"Line 310" ,嘗試進入會導致執行停止在"Line 1448" ,這只是跳過了"Line 310" 。 那是為什么? 而且,無論是使用 LLDB 還是 GBD,我都無法在"Line 310"明確設置斷點。 不知道我的情況發生了什么。
LIBC++13是通過命令構建的:(使用Building Libcxx Guides中的示例, /usr/local/myllvm
是我的安裝位置))
cmake -G Ninja -S llvm -B build \
-DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" \
-DCMAKE_BUILD_TYPE="Debug" \
-DCMAKE_INSTALL_PREFIX="/usr/local/myllvm" \
-DCMAKE_CXX_COMPILER="clang++"
程序使用推薦的選項編譯:
clang++ -nostdinc++ -nostdlib++ \
-isystem /usr/local/myllvm/include/c++/v1 \
-L /usr/local/myllvm/lib \
-Wl,-rpath,/usr/local/myllvm/lib \
-lc++ -g -O0 test1.cpp
默認情況下,lldb 以與沒有調試信息的函數相同的方式處理std:::
命名空間中的函數,並自動退出而不是在 function 中停止。
對於大多數用戶而言,您擁有內聯 stl 函數的源信息這一事實與其說是對這些函數感興趣,不如說是實現的意外。 並踏入 STL function 機構是破壞性的,沒有幫助。
此行為由 lldb 設置 target.process.thread.step target.process.thread.step-avoid-regex
控制 - 如果 lldb 步入與此正則表達式匹配的 function,則 lldb 將再次自動退出。 默認值為:
(lldb) settings show target.process.thread.step-avoid-regexp
target.process.thread.step-avoid-regexp (regex) = ^std::
如果您確實需要進入 STL 函數,只需運行:
(lldb) settings clear target.process.thread.step-avoid-regexp
然后 lldb 將停止在您擁有源信息的 stl 函數中。
感謝@Jim Ingham關於我的問題的第一個地址。
除了解決了我大部分問題的@Jim Ingham's Answer之外,我還將添加一些補充信息以解決我的部分問題。
- 為什么無論是使用 LLDB 還是 GBD,我們都無法在“第 310 行”顯式設置斷點。
簡短的原因:我們可以直接在“第 1447 行”設置斷點是因為該行駐留在istream
header 文件中(即INSTALL_DIR/include/c++/v1/istream
),而“第 310 行”沒有而是駐留在原始istream
中源文件(即BUILD_DIR/include/c++/v1/istream
)。
實際發生的一切都與可調試的可執行 object 文件提供的源信息有關,盡管看起來,這兩行應該在同一個源文件中,但由於其生成的 DWARF 部分包含這兩行的不同信息而被分開:
########### Using "llvm-dwarfdump" tool
########### Output by: llvm-dwarfdump a.out
...
# This relates to "Line 310"
0x00003a4a: DW_TAG_class_type
DW_AT_name ("sentry")
DW_AT_declaration (true)
...
# This relates to "Line 1448"
0x00004ae4: DW_TAG_variable
DW_AT_location (DW_OP_fbreg -24)
DW_AT_name ("__sen")
DW_AT_decl_file ("/usr/local/myllvm/include/c++/v1/istream")
DW_AT_decl_line (1448)
DW_AT_type (0x00003a4a "sentry")
...
根據DWARF 2 Standard , DW_AT_declaration (true)
意味着相應的 class 類型在其他地方定義,因此,我們不能設置斷點,除非調試器已經進入與該類定義相關的指令。 ( TODO:仍然不知道調試器如何動態找到它)
反之,我們可以在需要符號__sen
的行設置斷點,它之所以起作用,是因為編譯器已經為它生成了完全可調試的信息,即DW_AT_decl_file
對應“源文件”, DW_AT_decl_line
對應“源文件行號”等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.