How do I quit from debugger without exiting my IRB session? - ruby-on-rails

This is a long standing source of frustration, but maybe there is something I'm missing. If i'm in the middle of debugging, and I want to exit the debugger and return to IRB or Rails Console, "quit" won't work as it will exit IRB. "finish" also seems to have the same effect as continue. Using "delete" to remove breakpoints and then trying "continue" or "finish" doesn't work.
Any ideas?

At least in byebug, you can do this:
eval return
Which has the net effect of evaluating a return statement from the current function. That works sometimes, depending on how the call stack looks.
Now while this doesn't remove the current breakpoint .... if you just want control back, this will do that in most cases, depending on how your code is structured.
It also is useful to do this when creating a debug entry in your code:
byebug unless $continue
So if all else fails in a debugging session, you can always run
$continue = true
c
Now this opens up a whole set of possibilities.

This SO question has a few good suggestions. It deals with specifically with debugging inside of loops. One great solution is to set the break point outside the loop, then from irb set it inside the loop and clear it manually when you want to.
Basically it comes down to putting a little bit of thought into where you set your breakpoints.
Other than that there doesn't appear to be anything else you can do.

Related

How to evaluate a statement in XCode debugger

So every other IDE I have ever used, if there is some statement in the code with a break point set, there is a way to evaluate that statement to see what it is returning, ie immediate windows in visual studio, or using watch menu. Is there anything somewhat equivalent in XCode, or some way to evaluate a statement within a section of code?
ex:
if (CGRectContainsPoint([FGO BoundingBox], touchLocation))
Is returning false, so I'd like to see what [FGO BoundingBox] is evaluating to, but I can't seem to figure anything out short of changing the code to store it in an intermediate variable. Assuming I have a break point on this line in XCode what is the easiest way to see what this statement will return?
You can try:
po [FGO BoundingBox]
or
po NSStringFromCGRect([FGO BoundingBox])
also check out
help expression
in the debugger.
Break on that line, then step in to the "BoundingBox" function and step to the end of it (or where it returns something) and you should see what it's returning.

iOS: LLDB multiline breakpoint commands don't work as expected

I'm trying to do something a little fancy here, but the docs suggest it should be possible. Maybe LLDB is still too new, but I'm getting a lot of debugger crashes / deadlocks and even when that doesn't happen it does't seem to work like I expected.
I'm trying to put together a debug wrapper around all selector calls, to extract the message call graph inside a certain chunk of code. (I could explain why if you really want to know, but it isn't really relevant to the debugger issue.)
I start out with an Xcode breakpoint on the line where I want to start tracking things (for bonus points, this is happening on a secondary thread, but before you ask, no, nothing on any other thread is doing any accesses to this object or anything in its property subgraph):
[myObject startProcessing];
The breakpoint triggers, and I run "bt", just to extract:
* thread #5: tid = 0x2203, 0x000277d2 .........
I then do something mildly evil: I put a breakpoint in objc_msgSend, right at the instruction where it calls out to the real object selector. objc_msgSend looks like:
libobjc.A.dylib`objc_msgSend:
...(instructions)...
0x37babfa4: bx r12
...(more instructions)...
(Actually there are two bx calls but let's keep things simple.) I run:
breakpoint set -a 0x37babfa4 -t 0x2203
(TID included because I'm having enough trouble tracking this one thread and I don't need irrelevant stuff interfering.)
Here's where the scripting comes in. The setup described above works exactly as I'd like it to. If I resume execution until the breakpoint triggers, 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 the objc_msgSend frame
steps by one instruction, advancing it into the object selector frame it was pointing at
displays relevant details (object type, selector called)
resumes execution
at which point I can keep pasting in those four commands over and over and copying the output until I hate myself.
If, on the other hand, I run:
breakpoint command add -s command
and paste in those exact same commands, everything breaks. It does not advance to the object selector frame. It doesn't show the frame details, or at least not the correct ones -- depending on various tweaks (see below), it may or may not show "objc_msgSend" as being the current function. It doesn't resume execution.
In this case, if I could get that example working, I'd be mostly happy. But for even more bonus points, I've also tried this with python, which I would prefer because it would allow for much more sophisticated 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
Again no good. Again depending on tiny details, this may or may not print something (usually objc_msgSend), but it never prints the correct thing. It never steps the instruction forward. It never resumes execution afterwards.
And again, the python version works fine if I do it by hand: if I wait till the breakpoint fires, then run "script" and enter those exact same lines, it works as expected. Some parts will even work in isolation, e.g. if I remove everything except the parts that get the process and call process.Continue() and trigger those automatically, that "works" (meaning I see the lldb prompt flashing rapidly as it suspends and resumes execution. Usually I regret this because it becomes unresponsive and crashes shortly after.)
So: Any ideas? Is the technology Not Ready Yet, or am I just missing some clever piece of the puzzle that will fix everything? Or should I give up entirely and just live with the fact that there are some parts of object internals that I will never understand?...
Breakpoint commands cannot resume execution and then get control back again, at least today. There are a lot of unresolved questions about what would happen if breakpoint 1 is running the process and then breakpoint 2 is hit. Besides the whole question of whether the code base can really handle nested breakpoints correctly (it was designed to...), what does it mean if breakpoint 2 decides execution should stop? Is breakpoint 1's state thrown away?
It seems a little esoteric to worry about a breakpoint hitting another breakpoint while stepping the inferior process but unless all the details have been worked out, it's easy for the user to shoot themselves in the foot. So for today, breakpoint commands can either stop when the breakpoint is hit or continue to run - but there isn't any ability to run a little bit and do more processing. I know this would be a really useful capability for certain tasks but there are a lot of gotchas that need to be thought out before it could be done.
For some cases, it is possible to handle it the other way around ... if you want to stop in function parser() only when it has been called by function lexer(), it is easy to put a breakpoint on lexer() with some a few python commands to go one stack frame up the stack and see what the calling function is. If it's not lexer(), continue. I don't think this will apply to what you're trying to do, though.

Jump to next line of *my code* in ruby-debug

In ruby-debug, the next command takes you to the next line of code to be executed, regardless of whether that line is in your own code, or in the rails framework, or in a gem.
Is there some way to force ruby-debug (1.9) to jump to the next line that it encounters in your code without stopping at all the other lines it must execute along the way?
Yes, there is.
You can use break linenum to manually set a breakpoint on an arbitrary line number (for instance the next one), and then type c to continue to the next breakpoint.
The documentation for ruby-debug breakpoints would probably help you a bit as well.

Why do conditional breakpoints slow my program down so much?

When I'm debugging something that goes wrong inside a loop, say on the 600th iteration, it can be a pain to have to break for every one. So I tried setting a conditional breakpoint, to only break if I = 600. That works, but now it takes almost a full minute to reach that point, where before it was almost instantaneous. What's going on, and is there any way to fix it?
When you hit a breakpoint, Windows stops the process and notifies the debugger. It has to switch contexts, evaluate the condition, decide that no, you don't want to be notified about it, restart the process and switch back. That can take a lot of processor cycles. If you're doing it in a tight loop, it'll take a couple orders of magnitude more processor cycles than one iteration of the loop takes.
If you're willing to mess with your code a little, there's a way to do conditional breakpoints without incurring all this overhead.
if <condition here> then
asm int 3 end;
This is a simple assembly instruction that manually sends a breakpoint notification to the OS. Now you can evaluate your condition inside the program, without switching contexts. Just make sure to take it out again when you're done with it. If an int 3 goes off inside a program that's not connected to a debugger, it'll raise an exception.
It slows it down because every time you reach that point, it has to check your condition.
What I tend to do is to temporarily create another variable like this (in C but should be doable in Delphi).
int xyzzynum = 600;
while (true) {
doSomething();
if (--xyzzynum == 0)
xyzzynum = xyzzynum;
}
then I put a non-conditional breakpoint on the "xyzzynum = xyzzynum;" line.
The program runs at full speed until it's been through the loop 600 times, because the debugger is just doing a normal breakpoint interrupt rather than checking conditions every time.
You can make the condition as complicated as you want.
Further to Mason's answer, you could make the int 3 assember only be compiled in if the program is built with the debug conditional defined:
{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
asm int 3 end;
{$endif}
So, when you are debugging in the ide, you have the debug conditional in the project options. When you build the final product for your customers (with your build script?), you wouldn't include that symbol, so it wont get compiled in.
I also included the $message compiler directive, so you will see a warning when you compile letting you know that the code is still there. If you do that everywhere you use int 3, you will then have a nice list of places which you can double click on to take you straight to the offending code.
N#
Mason's explanations are quite good.
His code could be made a bit more secure by testing that you run under the debugger:
if (DebugHook <> 0) and <your specific condition here> then
asm int 3 end;
This will not do anything when the application is running normally and will stop if it's running under the debugger (whether launched from the IDE or attached to the debugger).
And with boolean shortcut <your specific condition here> won't even be evaluated if you're not under the debugger.
Conditional breakpoints in any debugger (I'm just surmising here) require the process to flip back and forth every time between your program and the debugger every time the breakpoint is hit. This process is time consuming but I do not think there is anything you can do.
Normally condition breakpoints work by inserting the appropriate break instruction into the code and then checking for the conditions you have specified. It'll check at every iteration and it might well be that the way in which the check is implemented is responsible for the delay as it's unlikely that the debugger compiles and inserts the complete check and breakpoint code into the existing code.
A way that you might be able to accelerate this is if you put the condition followed by an op with no side effect into the code directly and break on that op. Just remember to remove the condition and the op when you're done.

Delphi: How to debug run until you get back to your source file?

If I run a program and an exception is raised I am asked if I want to continue or break.
If I choose break I can see where the exception is coming from but if the break is in a library or system file not one of my source files (Say the exception is in System.pas or Controls.pas) I need to manually step the execution forward using F8 until it returns to one of my files, so I can see what part of my code caused the exception.
This can take a long time.
I know I should be catching lower level exceptions in my code but in this instance it's not hitting one of my exception handlers.
Is there a way to say
run forward with execution until you get to file X or
until you get back into a project specific file.
I'm also interested out of general curiosity on how other compilers / IDEs handle this.
Apologies if I haven't made this as clear as a I should.
You can resolve this by using the Stack View window.
Open the Stack View window (CTRL+ALT+S).
Double click on the method in the stack view where you wish to insert a breakpoint.
The unit, containing the caller method opens and the cursor is positioned on the caller method.
Set your breakpoint.
There's an even simpler way than Lieven's suggestion. Follow the first 3 steps as he laid them out, but don't place a breakpoint.
The problem with placing a breakpoint is that you have to clear it afterwards or you'll end up getting dropped into the debugger every time you pass that line. If you only want to run to a certain line and then drop to the debugger once, put the cursor on that line (the insertion point, not the mouse cursor) and press F4 (Run to Cursor). It's like a one-time breakpoint.
There are several ways:
Use the "Next source line" function (Shift+F7)
Use the call stack and double-click on the function you need, add a breakpoint there and hit "Run" (F9).
Use the "Step out" (Shift+F8) function until you are back into your own code.

Resources