objective-c에서 함수 cal은 objc_msgSend로 변환됩니다. 예 :lldb에서 objc_msgSend 함수를 단계적으로 실행하는 방법은 무엇입니까?
[foo doSomething:@"keke"]
은
objc_msgSend(foo, "doSomething:", @"keke")
lldb에서 디버깅하는 동안 어떻게 foo.doSomething:
에 직접 스텝 수로 변환된다?
objective-c에서 함수 cal은 objc_msgSend로 변환됩니다. 예 :lldb에서 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
파이썬 스크립트를 작성하여 lldb에로드하십시오. thread step-scripted gotouser.GotoUser
을 실행하십시오.
임무가 완료되었습니다.
전체 소스 코드 : https://github.com/Jichao/lldb-scripts/blob/master/gotouser.py
버전은 lldb에 내장 : https://github.com/Jichao/lldb
파이썬 스레드 계획을 사용하여 영리입니다! 그러나 ObjC 메시지에 대해서는이 작업을 수행하지 않아도됩니다. lldb는 objc_msgSend &이 ObjC 메시지의 디스패치 함수임을 알고 있습니다. 따라서 step in
이 objc_msgSend에서 끝나면 lldb는 전달 된 객체/선택기 쌍에서 메소드 구현을 파악하고 거기에 중단 점을 설정하고 계속합니다. 예를 들어
:
(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
그래서이 경우에는 실제 메시지 수신기에서 정지의 단계. 그것이 당신을 위해 일어난 일이 아니라면, 무엇인가는 객체/선택자 -> 구현 룩업을하는 lldb 부분을 속일 수 있습니다. 그 이유를 알아 내려면 코드에 대해 더 알아야 할 것입니다.
소스 코드가 있기 때문에 – Jichao
아, 그렇습니다, 그것은 독립적 인 문제입니다. 기본적으로 lldb는 디버그 정보가없는 함수에 "step-in"이 도착해도 멈추지 않지만 대신 다시 단계를 밟습니다. 이 동작을 제어하는 "step"명령 플래그가 있습니다 :'--step-in-avoids-no-debug' 또는 줄여서'-a'. 이 값을 false로 설정하면 디버그 정보의 유무에 관계없이 step in은 타겟 메소드에서 멈출 것이다. 또한 일반적인 설정 인'target.process.thread.step-in-avoid-nodebug'가 있습니다. ('settings set'을 사용하여) 설정하면이 행동을 당신의 취향에 맞게 세계적으로 제어 할 수 있습니다. –