IOS: LLDB multi-line break commands do not work as expected

I am trying to do something small, but the documents suggest that this be possible. LLDB may still be too new, but I get a lot of crashes / deadlocks on the debugger, and even when that doesn't happen, it seems like it doesn't work as I expected.

I am trying to build a debugging shell around all selector calls in order to extract a message call graph inside a specific piece of code. (I could explain why if you really want to know, but this is not particularly relevant to the debugger problem.)

I start with the Xcode breakpoint at the line where I want to start tracking things (for bonus points, this happens in the secondary stream, but before you ask, no, nothing in any other stream makes any calls to this object or anything in its subgraph of properties):

[myObject startProcessing]; 

The breakpoint trigger, and I run "bt", just to retrieve:

 * thread #5: tid = 0x2203, 0x000277d2 ......... 

Then I do something a little evil: I put a breakpoint in objc_msgSend, right in the statement, where it calls the real object selector. objc_msgSend looks like this:

 libobjc.A.dylib`objc_msgSend: ...(instructions)... 0x37babfa4: bx r12 ...(more instructions)... 

(Actually, there are two calls to bx, but let everything be simplified). I run:

 breakpoint set -a 0x37babfa4 -t 0x2203 

(TID is enabled because I have enough trouble tracking this single thread, and I don’t need useless things to interfere.)

Here where the script comes. The setup described above works exactly as I would like. If I resume execution before the breakpoint is triggered, I can run:

 frame select 0 thread step-inst -m this-thread 5 frame info continue 

and the effect will be that the debugger:

  • moves to frame objc_msgSend
  • according to one instruction, moving it into the frame of the object selector, indicating
  • displays relevant data (object type, selector)
  • resumes execution

at this point, I can continue to paste these four commands over and over and copy the output until I hate myself.

If, on the other hand, I run:

 breakpoint command add -s command 

and insert the same commands, everything breaks. It does not advance to the object selection frame. It does not show frame details or, at least, not correct ones - depending on various settings (see below), it may or may not show "objc_msgSend" as the current function. It does not resume execution.

In this case, if I could get this example to work, I would be mostly happy. But for even more bonuses, I also tried this with python, which I would prefer, because it would allow much more complex logging:

 breakpoint command add -s python > thread = frame.GetThread() > thread.StepInstruction(1) > newFrame = thread.GetFrameAtIndex(0) > print " " * thread.GetNumFrames() + newFrame.GetFunctionName() > process = thread.GetProcess() > process.Continue() > DONE 

Nothing good again. Again, depending on the tiny details, it may or may not print something (usually objc_msgSend), but it never prints the right thing. He never executes a command ahead. It never resumes execution afterwards.

And again, the python version works fine if I do it manually: if I wait until a breakpoint is reached, run the "script" and enter the same lines, it works as expected. Some parts will work independently of each other, for example. if I delete everything except the parts that receive the process and invoke the process. Continue () and start them automatically, which β€œworks” (which means that the lldb request is blinking fast because it pauses and resumes execution. I usually regret it because it becomes unresponsive and crashes.)

So: Any ideas? Is the technology Not Ready Yet, or have I just missed some clever part of the puzzle that will fix everything? Or should I completely refuse and just live with the fact that there are some parts of objects that I will never understand? ...

+4
source share
1 answer

Interrupt commands cannot resume execution and then gain control again, at least today. There are many unresolved questions about what happens if breakpoint 1 executes this process and then breakpoint 2 is deleted. In addition, the whole question is whether the code base can really handle nested breakpoints correctly (it was developed for .. .) what does this mean if breakpoint 2 decides that execution should stop? Is breakpoint 1 out of state?

It seems a little esoteric to worry that the breakpoint will hit another breakpoint, performing the lower process, but if all the details are not developed, it’s easy for the user to shoot in the foot. Thus, today, breakpoint commands can stop when the breakpoint hits or continues to work, but there is no way to start a little and do more processing. I know that this will be a really useful opportunity for certain tasks, but there are many mistakes that need to be thought out before this could be done.

In some cases, you can handle it differently ... if you want to stop the parser() function only when it was called by the lexer() function, it's easy to put a breakpoint on lexer() with several python commands in order to move one stack onto the stack and see what the calling function is. If it is not lexer() , continue. I do not think this will apply to what you are trying to do.

+3
source

Source: https://habr.com/ru/post/1403759/


All Articles