如何跨过 lldb 中的 objc_msgSend 函数?
How to step over objc_msgSend function in lldb?
在objective-c中,函数cal被翻译成objc_msgSend。例如
[foo doSomething:@"keke"]
翻译成
objc_msgSend(foo, "doSomething:", @"keke")
在 lldb 中调试时如何直接进入 foo.doSomething:
?
lldb确实提供了可以控制步骤逻辑的线程计划。
class GotoUser:
def __init__ (self, thread_plan, dict):
self.start_time = time.time()
self.thread_plan = thread_plan
target = self.thread_plan.GetThread().GetProcess().GetTarget();
module = target.GetModuleAtIndex(0)
sbaddr = lldb.SBAddress(module.GetObjectFileHeaderAddress())
self.start_address = sbaddr.GetLoadAddress(target)
module = target.GetModuleAtIndex(1)
sbaddr = lldb.SBAddress(module.GetObjectFileHeaderAddress())
self.end_address = sbaddr.GetLoadAddress(target)
print "start addr: ", hex(self.start_address), " end addr: ", hex(self.end_address)
def explains_stop (self, event):
if self.thread_plan.GetThread().GetStopReason()== lldb.eStopReasonTrace:
return True
else:
return False
def should_stop (self, event):
cur_pc = self.thread_plan.GetThread().GetFrameAtIndex(0).GetPC()
if cur_pc >= self.start_address and cur_pc <= self.end_address:
self.thread_plan.SetPlanComplete(True)
print 'time used ', (time.time() - self.start_time)
return True
else:
return False
def should_step (self):
return True
创建一个python脚本,将其加载到lldb。
运行 thread step-scripted gotouser.GotoUser
.
任务完成。
完整源代码:
https://github.com/Jichao/lldb-scripts/blob/master/gotouser.py
lldb 内置的版本:
https://github.com/Jichao/lldb
使用Python线程计划很聪明!但是您不必为 ObjC 消息执行此操作。 lldb 知道 objc_msgSend 和其他一些是 ObjC 消息的调度函数。因此,如果 step in
结束于 objc_msgSend,lldb 将从传入的 object/selector 对中找出方法实现,在那里设置断点,然后继续。
例如:
(lldb) run
Process 55502 launched: '/private/tmp/trivial' (x86_64)
Process 55502 stopped
* thread #1: tid = 0x32619ba, function: main , stop reason = breakpoint 1.1
frame #0: 0x0000000100000f28 trivial`main at trivial.m:18
15 main()
16 {
17 Trivial *my_foo = [[Trivial alloc] init];
-> 18 [my_foo doSomething];
19 return 0;
20 }
(lldb) s
Process 55502 stopped
* thread #1: tid = 0x32619ba, function: -[Trivial doSomething] , stop reason = step in
frame #0: 0x0000000100000ed7 trivial`-[Trivial doSomething] at trivial.m:10
7 @implementation Trivial
8 - (void) doSomething
9 {
-> 10 NSLog(@"%@ called doSomething.", self);
11 }
12 @end
13
所以在这种情况下,步骤停止在实际的消息接收者处。如果这不是你正在发生的事情,很可能是某些东西在欺骗执行 object/selector -> 实现查找的 lldb 部分。我必须更多地了解您的代码才能弄清楚为什么会这样。
How could I step directly to foo.doSomething: while debugging in lldb?
似乎:不可能
解决方法:添加相关断点
- 你在这里:
-[foo doSomething:]
在objective-c中,函数cal被翻译成objc_msgSend。例如
[foo doSomething:@"keke"]
翻译成
objc_msgSend(foo, "doSomething:", @"keke")
在 lldb 中调试时如何直接进入 foo.doSomething:
?
lldb确实提供了可以控制步骤逻辑的线程计划。
class GotoUser:
def __init__ (self, thread_plan, dict):
self.start_time = time.time()
self.thread_plan = thread_plan
target = self.thread_plan.GetThread().GetProcess().GetTarget();
module = target.GetModuleAtIndex(0)
sbaddr = lldb.SBAddress(module.GetObjectFileHeaderAddress())
self.start_address = sbaddr.GetLoadAddress(target)
module = target.GetModuleAtIndex(1)
sbaddr = lldb.SBAddress(module.GetObjectFileHeaderAddress())
self.end_address = sbaddr.GetLoadAddress(target)
print "start addr: ", hex(self.start_address), " end addr: ", hex(self.end_address)
def explains_stop (self, event):
if self.thread_plan.GetThread().GetStopReason()== lldb.eStopReasonTrace:
return True
else:
return False
def should_stop (self, event):
cur_pc = self.thread_plan.GetThread().GetFrameAtIndex(0).GetPC()
if cur_pc >= self.start_address and cur_pc <= self.end_address:
self.thread_plan.SetPlanComplete(True)
print 'time used ', (time.time() - self.start_time)
return True
else:
return False
def should_step (self):
return True
创建一个python脚本,将其加载到lldb。
运行 thread step-scripted gotouser.GotoUser
.
任务完成。
完整源代码: https://github.com/Jichao/lldb-scripts/blob/master/gotouser.py
lldb 内置的版本: https://github.com/Jichao/lldb
使用Python线程计划很聪明!但是您不必为 ObjC 消息执行此操作。 lldb 知道 objc_msgSend 和其他一些是 ObjC 消息的调度函数。因此,如果 step in
结束于 objc_msgSend,lldb 将从传入的 object/selector 对中找出方法实现,在那里设置断点,然后继续。
例如:
(lldb) run
Process 55502 launched: '/private/tmp/trivial' (x86_64)
Process 55502 stopped
* thread #1: tid = 0x32619ba, function: main , stop reason = breakpoint 1.1
frame #0: 0x0000000100000f28 trivial`main at trivial.m:18
15 main()
16 {
17 Trivial *my_foo = [[Trivial alloc] init];
-> 18 [my_foo doSomething];
19 return 0;
20 }
(lldb) s
Process 55502 stopped
* thread #1: tid = 0x32619ba, function: -[Trivial doSomething] , stop reason = step in
frame #0: 0x0000000100000ed7 trivial`-[Trivial doSomething] at trivial.m:10
7 @implementation Trivial
8 - (void) doSomething
9 {
-> 10 NSLog(@"%@ called doSomething.", self);
11 }
12 @end
13
所以在这种情况下,步骤停止在实际的消息接收者处。如果这不是你正在发生的事情,很可能是某些东西在欺骗执行 object/selector -> 实现查找的 lldb 部分。我必须更多地了解您的代码才能弄清楚为什么会这样。
How could I step directly to foo.doSomething: while debugging in lldb?
似乎:不可能
解决方法:添加相关断点
- 你在这里:
-[foo doSomething:]
- 你在这里: