I'm currently debugging the linux kernel and it's properly set up with kgdb.
I set a breakpoint to a function I am trying to debug, and the break occurs once I run my program which needs this kernel function to do something, this is wanted. But whenever I try to step through the code with "n" or "si", I always immediately land in arch/x86/include/asm/apic.h, which then runs some interrupt handling code and timers. I'm aware of the kernel being heavily parallelized so it has to move into some other code while being executed, but is it possible to step through the function more comfortably?
What I want to achieve:
before:
-> line A
line B
after:
line A
-> line B
What I have right now:
before:
-> line A
line B
after:
line A
... jumps into way different code here
I think it's hard. Let's think if the interrupts are all aborted, then how can you put your order by keybord or mouse?
Related
Normally if you set a gdb breakpoint and the the program hits that point, gdb stops execution entirely and lets the user examine and poke around before continuing.
I want the option to be notified of the breakpoint traversal, but not halt execution.
I know I could simply go to the code and add a print statement, but this is annoying especially debugging libraries outside my code which I am not building myself.
Again, I'm already using GDB and want to use 'breakpoints' but just get some sort of notification of when and how many times a line is traversed without halting the whole program's execution. Is this possible?
I want the option to be notified of the breakpoint traversal, but not halt execution.
(gdb) break foo.c:123
(gdb) commands $bpnum
continue
end
This attaches a command to the breakpoint. GDB will print that a breakpoint is hit, then run the attached command, which will continue execution.
You could also print some variables before continuing, or even continue only if some condition is true, and stop otherwise. E.g. "continue if x > 100, but stop if it's not".
I don't understand why CALL function in this code doesn't work:
#include<stdio.h>
void main() {
__asm {
jmp L1
L2:
mov eax, 8
ret
L1:
call L2
}
}
If i debug the code step by step, the line 'call L1' is not processed, and program directly skips to the end. What is wrong? I'm working on VisualStudio2015 with Intel 32-bit registers.
The problem
You've stumbled on the difference between step over F10 and step into F11.
When you use (the default) step over, call appears to be ignored.
You need to step into the code and then the debugger will behave as you'd expect.
Step over
The way this works with step over is that the debugger sets a breakpoint on the next instruction, halts there and moves the breakpoint to the next instruction again.
Step over knows about (conditional) jumps and accounts for that, but disregards (steps over) call statements; it interprets a call as a jump to another subroutine and 'assumes' you want to stay within the current context.
These automatic breakpoints are ephemeral, unlike manual breakpoints which persist until you cancel them.
Step into
Step into does the same, but also sets a breakpoint at every call destination; in effect leading you deep into the woods traversing every subroutine.
Step out
If you've stepped too deep 'into' a subroutine Visual Studio allows you to step out using ShiftF11; this will take you back to the next instruction after the originating call.
Some other debuggers name this feature "run until return".
Debugging high level code
When the debugger is handling higher language source code (e.g. C) it keeps a list of target addresses for every line of source code. It will plan its breakpoints per line of source code.
Other than the fact that every line of high level code translates to zero or more lines of assembly it works the same as stepping through raw assembly code.
I am currently writing a debugger for a script virtual machine.
The compiler for the scripts generates debug information, such as function entry points, variable scopes, names, instruction to line mappings, etc.
However, and have run into an issue with step-over.
Right now, I have the following:
1. Look up the current IP
2. Get the source line from that
3. Get the next (valid) source line
4. Get the IP where the next valid source line starts
5. Set a temporary breakpoint at that instruction
or: if the next source line no longer belongs to the same function, set the temp breakpoint at the next valid source line after return address.
So far this works well. However, I seem to be having problems with jumps.
For example, take the following code:
n = 5; // Line A
if(n == 5) // Line B
{
foo(); // Line C
}
else
{
bar(); // Line D
--n;
}
Given this code, if I'm on line B and choose to step-over, the IP determined for the breakpoint will be on line C. If, however, the conditional jump evaluates to false, it should be placed on line D. Because of this, the step-over wouldn't halt at the expected location (or rather, it wouldn't halt at all).
There seems to be little information on debugger implementation of this specific issue out there. However, I found this. While this is for a native debugger on Windows, the theory still holds true.
It seems though that the author has not considered this issue, either, in section "Implementing Step-Over" as he says:
1. The UI-threads calls CDebuggerCore::ResumeDebugging with EResumeFlag set to StepOver.
This tells the debugger thread (having the debugger-loop) to put IBP on next line.
2. The debugger-thread locates next executable line and address (0x41141e), it places an IBP on that location.
3. It calls then ContinueDebugEvent, which tells the OS to continue running debuggee.
4. The BP is now hit, it passes through EXCEPTION_BREAKPOINT and reaches at EXCEPTION_SINGLE_STEP. Both these steps are same, including instruction reversal, EIP reduction etc.
5. It again calls HaltDebugging, which in turn, awaits user input.
Again:
The debugger-thread locates next executable line and address (0x41141e), it places an IBP on that location.
This statement does not seem to hold true in cases where jumps are involved, though.
Has anyone encountered this problem before? If so, do you have any tips on how to tackle this?
Since this thread comes in Google first when searching for "debugger implement step over". I'll share my experiences regarding the x86 architecture.
You start first by implementing step into: This is basically single stepping on the instructions and checking whether the line corresponding to the current EIP changes. (You use either the DIA SDK or the read the dwarf debug data to find out the current line for an EIP).
In the case of step over: before single stepping to the next instruction, you'll need to check if the current instruction is a CALL instuction. If it's a CALL instruction then put a temporary breakpoint on the instruction following it and continue execution till the execution stops (then remove it). In this case you effectively stepped over function calls literally in the assembly level and so in the source too.
No need to manage stack frames (unless you'll need to deal with single line recursive functions). This analogy can be applied to other architectures as well.
Ok, so since this seems to be a bit of black magic, in this particular case the most intelligent thing was to enumerate the instruction where the next line starts (or the instruction stream ends + 1), and then run that many instructions before halting again.
The only gotcha was that I have to keep track of the stack frame in case CALL is executed; those instructions should run without counting in case of step-over.
I've tried to set breakpoint on every function that makes any sense but program exit before reaching any of those. Is there a way to make program run in step-by-step mode from the start so I can see what's going on?
I'm trying to debug /usr/bin/id if it's important (we have custom plugin for it and it's misbehaved)
P.S. Start command doesn't work for me here(it should be a comment, but I don't have enough rep for it)
Get the program entry point address and insert a breakpoint at that address.
One way to do this is to do info files which gives you for example "Entry point: 0x4045a4". Then do "break *0x4045a4". After run-ning program, it will immediately stop.
From here on you can use single stepping instructions (like step or stepi) to proceed.
You did not tell what system you are trying to debug. If code is in read-only memory you may need to use hardware breakpoints (hbreak) if they are supported by that system.
Use start command
The ‘start’ command does the equivalent of setting a temporary breakpoint at the beginning of the main procedure and then invoking the ‘run’ command.
e.g.
a program with debug info main, and usage like this: main arg1 arg2
gdb main
(gdb) start arg1 arg2
Use starti. Unlike start this stops at the actual first instruction, not at main().
You can type record full right after running the program. This will record all instructions and make them possible for replaying/going back.
For main function, you'd need to type this before reaching the breakpoint so you can set an earlier one by break _start -> _start is a function always called before the standard main function. (apparently applies only to the gcc compiler or similar)
Then continue to main breakpoint and do reverse-stepi to go exactly one instruction back
For more info about recording look here: link
(I'm coding a debugger. But my doubt is also from the point of view of a debugger user)
Many debuggers in many languages (GDB, Eclipse) implement a STEP_OVER command that permits to execute one statement at a time; the difference with STEP_INTO is that it does not perform the stepping down in stack (i.e., called functions), which is often a good thing.
10 : y = f1(x);
11 : z = y + 1;
Now, suppose I step over line 10 above, but a breakpoint is hit inside function f1 (perhaps several levels deep in the call stack). It's not clear what should happen when I resume: should the debugger pause at line 11 (effectively "completing the step over" command)? Or should it forget about it? I believe most (all?) debuggers do the later. Is that the standard/expected behaviour? I myself have found this a little frustrating. Is there a way (in some debugger) to resume execution from the inside breakpoint to the outside stepped-over statement? Or is there some way to do a step-over-ignoring breakpoints?
WinDbg does the latter, and I believe this is standard behavior. If you are worried about a different breakpoint occurring during a step-over command, you could always manually set a breakpoint on line 11 and continue running until line 11 is hit. Alternatively, you could temporarily disable the other breakpoints, but note that the debugger still may break for other reasons as well (such as raising an exception), depending on its configuration.