lldb通过c ++ api未解析的断点
Posted
技术标签:
【中文标题】lldb通过c ++ api未解析的断点【英文标题】:lldb unresolved breakpoint via c++ api 【发布时间】:2017-01-30 22:09:24 【问题描述】:我有可执行模块 iCoreTest.exe,它是动态加载的库 IRTest.rs。我想通过 lldb c++ api 对其进行调试。
当我通过 lldb::SBTarget::Launch(..); 在 lldb 下创建 "iCoreTest.exe" 进程时,一切正常美好的。很好,我的意思是我可以设置断点BreakpointCreateByLocation
,当调试器停止它时,从SBListener.WaitForEvent();
获取事件
当我想附加到当前正在运行的进程时,问题就开始了。
创建目标并附加到进程
m_debugData->currentTarget=m_debugData>debugger.CreateTarget(executable.c_str());
m_debugData->currentProcess = m_debugData>currentTarget.AttachToProcessWithName(m_debugData->listener, processName.c_str(), false, error);
加载模块“IRTest.rs”
auto module = m_debugData->currentTarget.AddModule("IRTest.rs", "i386-pc-windows-msvc", nullptr);
之后 lldb 停止在 "ntdll.dll`DbgBreakPoint + 1"
我执行命令m_debugData->currentProcess.Continue();
所以,ICoreTest.exe 正在运行..
添加断点m_debugData->currentTarget.BreakpointCreateByLocation("IRTest.st", 58);
添加的断点未触发
在此之后,我使用以下代码打印现有断点:
void LLDBRunner::printBreakpoints()
for (int i = 0; i < m_debugData->currentTarget.GetNumBreakpoints(); i++)
auto bp = m_debugData->currentTarget.GetBreakpointAtIndex(i);
for (int j = 0; j < bp.GetNumLocations(); j++)
auto loc = bp.GetLocationAtIndex(j);
lldb::SBStream stream;
loc.GetDescription(stream, lldb::DescriptionLevel::eDescriptionLevelFull);
auto str = stream.GetData();
输出是:
1.1:其中 = IRTest.rs`Add + 421 at IRTest.st:58,地址 = IRTest.rs[0x10001525],未解决,命中数 = 0
这意味着我的断点未解决..为什么? :)
还有! 当我使用 lldb 命令行断点已解决,并且正在工作:
(lldb) attach -p 17448
Process 17448 stopped
* thread #1: tid = 0x0ae0, 0x77bc8d21 ntdll.dll`DbgBreakPoint + 1, stop reason = Exception 0x80000003 encountered at address 0x77bc8d20
frame #0: 0x77bc8d21 ntdll.dll`DbgBreakPoint + 1
ntdll.dll`DbgBreakPoint:
-> 0x77bc8d21 <+1>: retl
0x77bc8d22 <+2>: int3
0x77bc8d23 <+3>: int3
0x77bc8d24 <+4>: int3
Executable module set to "iCoreTest.exe".
Architecture set to: i386-pc-windows-msvc.
(lldb) b IRTest.st:58
Breakpoint 1: where = IRTest.rs`Add + 421 at IRTest.st:58, address = 0x07ca1525
(lldb) b
Current breakpoints:
1: file = 'IRTest.st', line = 58, exact_match = 0, locations = 1, resolved = 1, hit count = 0
1.1: where = IRTest.rs`Add + 421 at IRTest.st:58, address = 0x07ca1525, resolved, hit count = 0
(lldb) c
Process 17448 resuming
Process 17448 stopped
* thread #6: tid = 0x2560, 0x07ca1525 IRTest.rs`Add(X1=2, X2=42, X3=(RANGE = 1, MIN_SCALE = -4095, MAX_SCALE = 4095)) + 421 at IRTest.st:58, stop reason = breakpoint 1.1
frame #0: 0x07ca1525 IRTest.rs`Add(X1=2, X2=42, X3=(RANGE = 1, MIN_SCALE = -4095, MAX_SCALE = 4095)) + 421 at IRTest.st:58
55 i, j : INT;
56 END_VAR
57
-> 58 tmpInteg();
59
60
61
(lldb)
更新:
我写了一个简单的程序来重现错误
prog.cpp:
#include <cstdio>
void doSomething(void);
void doSomething(void)
int loop = 0;
loop += 1;
loop += 2;
loop += 3;
int main(void)`
printf("start \n");
while(1)
doSomething();
return 0;
编译它..
gcc prog.cpp -g -O0
当我试图设置断点时
m_debugData->currentTarget.BreakpointCreateByLocation("prog.cpp", 7);
我得到相同的结果
1.1: where = a.exe`doSomething() + 6 at prog.cpp:7, address = a.exe[0x00401356], unresolved, hit count = 0
我的小研究:
我比较了两个版本的 lldb 行为:
-
启动新进程(没问题)
附加到进程(损坏)
我发现在方法中
lldb::break_id_t
Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardware)
行..
load_addr = owner->GetAddress().GetOpcodeLoadAddress (&GetTarget());
在我附加到进程时返回版本中的 LLDB_INVALID_ADDRESS。
调用栈:
liblldb.dll!lldb_private::Process::CreateBreakpointSite(const std::shared_ptr<lldb_private::BreakpointLocation> & owner, bool use_hardware) Line 2094 C++
liblldb.dll!lldb_private::BreakpointLocation::ResolveBreakpointSite() Line 523 C++
liblldb.dll!lldb_private::BreakpointLocationList::AddLocation(const lldb_private::Address & addr, bool resolve_indirect_symbols, bool * new_location) Line 254 C++
liblldb.dll!lldb_private::Breakpoint::AddLocation(const lldb_private::Address & addr, bool * new_location) Line 102 C++
liblldb.dll!lldb_private::BreakpointResolver::AddLocation(lldb_private::Address loc_addr, bool * new_location) Line 214 C++
liblldb.dll!lldb_private::BreakpointResolver::SetSCMatchesByLine(lldb_private::SearchFilter & filter, lldb_private::SymbolContextList & sc_list, bool skip_prologue, const char * log_ident) Line 184 C++
liblldb.dll!lldb_private::BreakpointResolverFileLine::SearchCallback(lldb_private::SearchFilter & filter, lldb_private::SymbolContext & context, lldb_private::Address * addr, bool containing) Line 94 C++
liblldb.dll!lldb_private::SearchFilter::DoModuleIteration(const lldb_private::SymbolContext & context, lldb_private::Searcher & searcher) Line 190 C++
liblldb.dll!lldb_private::SearchFilter::Search(lldb_private::Searcher & searcher) Line 118 C++
liblldb.dll!lldb_private::BreakpointResolver::ResolveBreakpoint(lldb_private::SearchFilter & filter) Line 62 C++
liblldb.dll!lldb_private::Breakpoint::ResolveBreakpoint() Line 355 C++
liblldb.dll!lldb_private::Target::AddBreakpoint(std::shared_ptr<lldb_private::Breakpoint> bp_sp, bool internal) Line 695 C++
liblldb.dll!lldb_private::Target::CreateBreakpoint(std::shared_ptr<lldb_private::SearchFilter> & filter_sp, std::shared_ptr<lldb_private::BreakpointResolver> & resolver_sp, bool internal, bool request_hardware, bool resolve_indirect_symbols) Line 672 C++
liblldb.dll!lldb_private::Target::CreateBreakpoint(const lldb_private::FileSpecList * containingModules, const lldb_private::FileSpec & file, unsigned int line_no, unsigned __int64 offset, lldb_private::LazyBool check_inlines, lldb_private::LazyBool skip_prologue, bool internal, bool hardware, lldb_private::LazyBool move_to_nearest_code) Line 411 C++
liblldb.dll!lldb::SBTarget::BreakpointCreateByLocation(const lldb::SBFileSpec & sb_file_spec, unsigned int line, unsigned __int64 offset) Line 832 C++
liblldb.dll!lldb::SBTarget::BreakpointCreateByLocation(const lldb::SBFileSpec & sb_file_spec, unsigned int line) Line 803 C++
liblldb.dll!lldb::SBTarget::BreakpointCreateByLocation(const char * file, unsigned int line) Line 796 C++
ConsoleApplication1.exe!Debugger::LLDBRunner::setBreakpoint(std::basic_string<char,std::char_traits<char>,std::allocator<char> > file, unsigned int line) Line 204 C++
ConsoleApplication1.exe!main() Line 28 C++
更新 2:
我使用以下代码打印“a.exe”模块部分:
for (int i = 0; i < m_debugData->currentTarget.GetNumModules(); i++)
auto module = m_debugData->currentTarget.GetModuleAtIndex(i);
auto moduleName = module.GetFileSpec().GetFilename();
for (int j = 0; j < module.GetNumSections(); j++)
auto section = module.GetSectionAtIndex(j);
auto sectionName = section.GetName();
auto addr = section.GetLoadAddress(m_debugData->currentTarget);
auto isValid = LLDB_INVALID_ADDRESS != addr;
std::cout << "Module: " << moduleName << "; Section: " << sectionName << "; IsValid: " << isValid << std::endl;
输出是:
State changed unknown->stopped
Module: a.exe; Section: .text; IsValid: 0
Module: a.exe; Section: .data; IsValid: 0
Module: a.exe; Section: .rdata; IsValid: 0
Module: a.exe; Section: .eh_frame; IsValid: 0
Module: a.exe; Section: .bss; IsValid: 0
Module: a.exe; Section: .idata; IsValid: 0
Module: a.exe; Section: .CRT; IsValid: 0
Module: a.exe; Section: .tls; IsValid: 0
Module: a.exe; Section: .debug_aranges; IsValid: 0
Module: a.exe; Section: .debug_info; IsValid: 0
Module: a.exe; Section: .debug_abbrev; IsValid: 0
Module: a.exe; Section: .debug_line; IsValid: 0
Module: a.exe; Section: .debug_frame; IsValid: 0
【问题讨论】:
【参考方案1】:很难确定,但是python API和命令行api并不完全相同。在运行您请求的“实际”命令之前,它们都有自己的一组内部操作。在 Windows 上调试肯定不如在其他平台上那么成熟,部分原因是还没有很多人在使用它。我建议将此报告为 lldb 错误跟踪器上的错误。
与此同时,也许您可以尝试手动创建目标,并在附加到进程之前设置断点。我不知道这是否可行,但是在加载模块时动态解析断点,而不是在放下断点时立即解析断点是两个不同的代码路径,因此如果断点已经存在,它可能会起作用.
【讨论】:
“我建议将此作为 lldb 错误跟踪器上的错误报告”我向管理员发送创建帐户的请求。 “与此同时,也许您可以尝试手动创建目标,并在附加到进程之前设置断点”不,它没有帮助:)以上是关于lldb通过c ++ api未解析的断点的主要内容,如果未能解决你的问题,请参考以下文章