簡體   English   中英

為什么在使用 LLDB 時 STL 中設置的斷點被“跳過/忽略”?

[英]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"明確設置斷點。 不知道我的情況發生了什么。

所以我的問題是:為什么 LLDB 會跳過/忽略 STL 中的某些代碼行? (在我的情況下,即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之外,我還將添加一些補充信息以解決我的部分問題。


  1. 為什么無論是使用 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 StandardDW_AT_declaration (true)意味着相應的 class 類型在其他地方定義,因此,我們不能設置斷點,除非調試器已經進入與該類定義相關的指令。 TODO:仍然不知道調試器如何動態找到它

反之,我們可以在需要符號__sen的行設置斷點,它之所以起作用,是因為編譯器已經為它生成了完全可調試的信息,即DW_AT_decl_file對應“源文件”, DW_AT_decl_line對應“源文件行號”等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM