我的目標是:我想進入 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"明確設定斷點。不知道我的情況發生了什么。
所以我的問題是:為什么 STL 中的某些代碼行會被 LLDB 跳過/忽略?(在我的情況下,即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
uj5u.com熱心網友回復:
默認情況下,lldb 將std:::命名空間中的函式視為沒有除錯資訊的函式,并自動退出而不是在函式中停止。
對于大多數用戶而言,您擁有行內 stl 函式的源資訊這一事實更多的是實作的意外,而不是表示對這些函式感興趣;并且步入 STL 功能體是破壞性的并且沒有幫助。
此行為由 lldb 設定控制target.process.thread.step-avoid-regex- 如果 lldb 步入與此正則運算式匹配的函式,則 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 函式中。
uj5u.com熱心網友回復:
感謝@Jim Ingham關于我的問題的第一個地址。
除了解決了我大部分問題的@Jim Ingham's Answer 之外,我還將添加一些補充資訊以解決我的部分問題。
- 為什么無論是使用 LLDB 還是 GBD,我們都無法在“第 310 行”顯式設定斷點。
簡短的原因:我們可以直接在“第 1447 行”設定斷點是因為該行駐留在istream頭檔案中(即,INSTALL_DIR/include/c /v1/istream),而“第 310 行”沒有,而是駐留在原始istream源檔案中(即,BUILD_DIR/include/c /v1/istream)。
實際發生的一切都與可除錯的可執行目標檔案提供的源資訊有關,盡管看起來,應該在同一個源檔案中的這兩行是分開的,因為它生成的 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)這意味著相應的型別別在其他地方定義,因此,我們不能設定斷點,除非除錯器已經進入與該類定義相關的指令。(TODO:仍然不知道除錯器如何動態找到它)
反之,我們可以在需要符號的行設定斷點__sen,之所以有效,是因為編譯器已經為它生成了完全可除錯的資訊,即DW_AT_decl_file對應“Source File”, DW_AT_decl_line對應“Source File Line”號”等。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/405047.html
標籤:
上一篇:GDB在QEMU上的裸機開發中逐步執行特定內核的指令
下一篇:無法打開檔案以從C中讀取登錄資料
