So I'm trying to debug a program that takes user input through the terminal. I'm using the GNU Debugger (gdb) to do so. When I reach the point where the program is waiting for user input it no longer allows me to control gdb and instead forces me to give input to the program.
The difficulty is, I want to debug the program at this exact point, but before there is any input given. So how do I switch between giving input to the program and controlling gdb? I've tried googling and searching through the manual for gdb but can't seem to find anything on switching between input to the program and input to gdb.
When I reach the point where the program is waiting for user input it no longer allows me to control gdb and instead forces me to give input to the program.
If you hit Control-C at that point, the inferior (being debugged) program should get interrupted, you should get a (gdb) prompt, and you should be able to control GDB all you want.
Once you are done, use continue GDB command to go back and resume the inferior reading its input.
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".
LLDB command jump lets me resume program execution at a different position from where it has stopped, but it seems to be restricted to addresses inside the current function:
(lldb) jump CLI.cpp:15
error: CLI.cpp:15 is outside the current function.
I'm curious about that, since this restriction is not documented in lldb's help, and the syntax jump <file>:<line> somehow indicates that one could use arbitrary entry points:
(lldb) help jump
('_regexp-jump') Set the program counter to a new address. Expects 'raw'
input (see 'help raw-input'.)
Syntax:
_regexp-jump <line>
_regexp-jump +<line-offset> | -<line-offset>
_regexp-jump <file>:<line>
_regexp-jump *<addr>
'jump' is an abbreviation for '_regexp-jump'
I'm aware that resuming in a different frame/stack may bring the program into an inconsistent state with "wonderful" side effects.
How can I jump to lines outside the current function in lldb (ignoring possible side effects)?
jump is a wrapper command that packages up some common uses of the underlying thread jump into a compact form. That's what all the _regex- commands are in lldb. Do:
(lldb) help command regex
if you want more details on this regex commands, and of course
(lldb) help thread jump
for everything you can do with that command.
The wrapper doesn't have an affordance to allow jumping outside the current function because that is definitely NOT a safe operation, so the default is to assume you made a mistake in typing the line or file name...
The underlying command does have a --force option that allows you to move the pc out of the current function.
I recently set up my system for kernel debug using qemu+gdb. At present, I can set breakpoints at, for example, __do_page_fault() and trace the call via gdb (with win command). Now I want the following task: A simple C program having a "hello world" printfstatement. Trace the call sequence starting from the userspace down to the write() system call ( or anything in the kernel space that is invoked during the execution of that particular userspace program). I want to learn how userspace program traps into system call w.r.t Linux kernel specifically.
Now my doubt is where to set the breakpoint? We have kernel code as well as the C code of the program. How to go about this situation ? Please give us an explanation with example.
Thank You !
The most easiest way in my opinion is to separate this into two pieces.
Place breakpoint in guest kernel using host gdb.
Place breakpoint in user code before trap instruction, using in-guest target gdb, when hit - print stack using target (in-qemu) gdb. You will get user space stack trace.
Continue execution in guest gdb
In-kernel breakpoint (we have set it at stage 1) will be hit in host gdb. Print kernel stack trace.
P.S.
If your kernel will continuously hit breakpoint (f.e. write syscall is definitely used widely), you can use a conditional breakpoint to hit a breakpoint only with a certain parameters passed.
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
Here I searched that:
Trap Flag (T) – This flag is used for on-chip debugging. Setting trap
flag puts the microprocessor into single step mode for debugging. In
single stepping, the microprocessor executes a instruction and enters
into single step ISR.
If trap flag is set (1), the CPU automatically generates an internal
interrupt after each instruction, allowing a program to be inspected
as it executes instruction by instruction.
If trap flag is reset (0), no function is performed.
https://en.wikipedia.org/wiki/Trap_flag
Now I am coding on emu-8086. As explained, TF must be set in order to debugger work.
Should I set a TF always myself or it is set automatically?
If I somehow set a TF to 0, will the whole computer systems debuggers work or just emu-8086 wont debug?
I've never used emu8086 but by looking at some screenshot of it and judging by its name it's probably an emulator - this means it is not running the code natively.
Each instruction is changing the state of a virtual 8086 CPU (represented as a data structure in memory) and not the state of your real CPU.
With this emulation, emu8086 doesn't need to rely on the TF flag to single-step your program, it just needs to stop after one step of emulation and wait for you to hit another button.
This is also why you can find a thing such as "Step back".
If you were wondering what would happen if a debugged program (and not an emulated one) sets the TF flag then the answer is that it depends on the debugger.
The correct behaviour is the one where the debuggee receives the exceptions but this is hard to handle correctly (since the debugger itself uses the TF flag).
Some debugger just don't care and swallow the exception (i.e. they don't forward it to the program under debug) assuming that a well written program doesn't need to use the TF flag.
Unfortunately malwares routinely use a set of anti-debug technique including setting the TF and checking it back/waiting for exceptions to detect the presence of a debugger.
A truly transparent debugger has to handle the RFLAGS register carefully.
When debugging with breakpoints the TF is not set while the program is executing, so there is nothing to worry about.
However when single stepping the TF is set during the next instruction, this is problematic during a pushfd/q and the debugger must explicitly handle that case to avoid detection.
If the debuggee sets the TF the debugger must pass the debug exception to the program - under current OS the TF won't last more than an instruction because the OS will catch the exception,
trasnform it in a signal and dispatch it to the program while clearing the TF. So the debugger can simply do a check before stepping into a popfd/q instruction.
Where the TF doesn't get cleared by the OS the debugger must effectively emulate RFLAGS with a copy.
The debugger sets TF according to what it needs to do. The code being debugged should not modify TF.