gdb - perform a command n times - gdb

I am using the gdb debugger to run a program that has a loop in it (let's sat of 10).
When I get to the loop, I don't want to go into it. I know I can make a second breakpoint after the loop and than do c (continue). But I also remember there is a possibility to do something like n 10 (next 10 times). n 10 doesn't work (gdb doesn't say I've done something wrong, but it doesn't do what I am expecting).
Is it possible to run a command n times?

To perform any gdb command N times, the easiest way is:
(gdb) python [gdb.execute('YOUR_COMMAND') for x in range(N)]
It can be very helpful for your custom gdb commands (see gdb define)
For example,
(gdb) python [gdb.execute('next') for x in range(10)]
(gdb) python [gdb.execute('step') for x in range(5)]

Do you know the command until?
Try use it to go until line X.
Example:
(gdb) until 123
or
(gdb) u 123
(gdb) help until
Execute until the program reaches a source line
greater than the current or a specified location (same args as break
command) within the current frame.

GDB Python API
You can run a command n times with the GDB Python API if someone really needs it:
class RepeatCmd(gdb.Command):
"""
Repeat a command n times:
repeat-cmd <n> <cmd>
"""
def __init__(self):
super().__init__(
'repeat-cmd',
gdb.COMMAND_NONE,
gdb.COMPLETE_NONE,
False
)
def invoke(self, arg, from_tty):
args = gdb.string_to_argv(arg)
n = int(args[0])
cmd = ' '.join(args[1:])
for i in range(n):
gdb.execute(cmd)
RepeatCmd()
GitHub upstream.
For the use case, you may also be interested in continue <n>.

Related

Repeating Command in LLDB

How can I repeatedly run a command in LLDB for debugging C++ code?
For example, when I set a breakpoint inside a loop and want to continue for 10 iterations before stopping, I am currently typing continue ten times manually to do this. Is there a better way?
As an example, let's say I have this code block:
int i = 0;
while (true) {
// Increment i
i++;
}
If I set a breakpoint on the line with the comment, I could keep using the command continue to go through one iteration of the loop and go back to that line. However, if I wanted to skip over 10 iterations (i.e. use the command continue 10 times), how would I do that?
lldb tends to use options where gdb would use a command argument. That makes it easier to have a bunch of different ways to condition a particular command without having to come up with ad hoc mini-syntaxes for each command.
Anyway, so in lldb you would do:
(lldb) c -i 10
You can see this in help:
(lldb) help continue
Continue execution of all threads in the current process.
Syntax: continue <cmd-options>
Command Options Usage:
continue [-i <unsigned-integer>]
-i <unsigned-integer> ( --ignore-count <unsigned-integer> )
Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread.
'continue' is an abbreviation for 'process continue'
Note also that you can do the same thing just by setting the ignore count in the breakpoint you just hit: break modify -i 10 <BKPTNO>.
Just add a conditional breakpoint. In gdb it's like this
break ... if cond
Set a breakpoint with condition cond; evaluate the expression cond each time the breakpoint is reached, and stop only if the value is nonzero--that is, if cond evaluates as true. `...' stands for one of the possible arguments described above (or no argument) specifying where to break. See section Break conditions, for more information on breakpoint conditions.
https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_28.html
For example if i is currently 0 and you want to break on line 10 then use
break 10 if i >= 10
Just increase the condition value based no the current value of i
I don't know lldb but according the the mapping list break foo if strcmp(y,"hello") == 0 in gdb can be done as the following in lldb
(lldb) breakpoint set --name foo --condition '(int)strcmp(y,"hello") == 0'
(lldb) br s -n foo -c '(int)strcmp(y,"hello") == 0'
If there's no loop counter you can just declare a debug variable yourself
expr unsigned int $foo = 1
breakpoint set --name foo --condition '++$foo >= 10'

breakpoint at end of a function

I am trying to log the input and output of a function via gdb script. below is a sample script.
set logging on
b func2
commands
silent
bt 1
continue
end
b func1
commands
silent
bt 1
set logging off
continue
end
It works fine and breakpoints at the specified functions, prints the backtrace and continues.
is there a way to automatically set a breakpoint just before the called function returns to the calling function, so that I can just print output variables via gdb just after this "new" breakpoint.
This will greatly simplify my debug, and help understand the function behavior for different calls in the code.
Any help is highly appreciated.
Thanks a lot in advance !
I have looked into this and cannot find a way to do this with normal GDB breakpoints.
It is possible to implement using the GDB Python extensions API.
source-ing a file with the following content (source FILENAME) from with GDB will allow one to issue the command break-return which will place a temporary break-point at every 'return' in the current file (this is overkill but works). Once any one of the breakpoints is hit they are all deleted.
import gdb
class _ReturnBreakpoint(gdb.Breakpoint):
def stop(self):
for breakpoint in self._siblings:
if breakpoint.number != self.number:
gdb.execute(f"d {breakpoint.number}")
return True
class _BreakReturn(gdb.Command):
def __init__(self):
super(_BreakReturn, self).__init__("break-return", gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
function_name = gdb.selected_frame().name()
source_file = gdb.selected_frame().find_sal().symtab.filename
breakpoints = []
with open(source_file) as o:
for zero_based_index, line in enumerate(o.readlines()):
if not 'return ' in line:
continue
breakpoint = _ReturnBreakpoint(line=zero_based_index+1, temporary=True)
breakpoints.append(breakpoint)
for breakpoint in breakpoints:
breakpoint._siblings = breakpoints
_BreakReturn() # register the command with GDB
Taken from https://github.com/jbcoe/GDB-extensions/blob/master/extensions/break-return.py
Patches are welcome.

gdb rbreak and commands (or dprintf behavior)?

Taking the example from http://shanekirk.com/2017/08/gdb-tips-and-tricks-2-setting-breakpoints-with-regular-expressions/ - when I use rbreak, I get something like:
(gdb) rb TestFixture.h:.
Breakpoint 1 at 0x4008b6: file TestFixture.h, line 5.
void TestFixture::setUp();
Breakpoint 2 at 0x4008d4: file TestFixture.h, line 6.
void TestFixture::tearDown();
Breakpoint 3 at 0x4008f2: file TestFixture.h, line 7.
void TestFixture::testA();
Breakpoint 4 at 0x400910: file TestFixture.h, line 8.
void TestFixture::testB();
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004008b6 in TestFixture::setUp() at TestFixture.h:5
2 breakpoint keep y 0x00000000004008d4 in TestFixture::tearDown() at TestFixture.h:6
3 breakpoint keep y 0x00000000004008f2 in TestFixture::testA() at TestFixture.h:7
4 breakpoint keep y 0x0000000000400910 in TestFixture::testB() at TestFixture.h:8
Now, what I want is basically a dprintf-like behavior: once one of this breakpoints is hit, I just want the function name printed out, and then continue (basically, a function call trace)
However, the way I understand gdb - in order to do that, I would issue a rbreak [regex] first, then I get a bunch of breakpoints, then for each and every one of those I'd had to type manually:
commands [number-of-breakpoint]
print "[name of function]"
continue
end
... which quickly becomes a chore, especially if you end up with a lot more breakpoints than the 4 in the above example (say hundreds).
Now, it would be rather cool, if I could use something like "regex dprintf", or rdprintf, as in:
rdprintf TestFixture.h:., "%s\n", $__breakname__
... but as far as I know, there is no such command...
Or, if after issuing a rbreak TestFixture.h:., I could target the commands for those breakpoints as:
commands 1-4
print $__breakname__
continue
end
... but again, I think this does not exist either...
So is there a way to use gdb to provide this kind of a function call trace printout - without me manually typing the names of breakpoints and their commands, similar to how rbreak allows you to set multiple breakpoints with one command?
EDIT: just found List of all function calls made in an application - record function-call-history /ilc might be interesting, but there doesn't seem to be a way to limit the scope of what functions to trace, say with a regex...
Ok, via the link above, found https://stackoverflow.com/a/39124320/277826 - turns out, you can issue command for multiple breakpoints, as found by rbreak; and to print the name of the function, just use backtrace 1:
(gdb) command 1-36
Type commands for breakpoint(s) 1-36, one per line.
End with a line saying just "end".
>silent
>bt 1
>continue
>end
(gdb) r
... or with python, printing the frame at bt 0 and its parent's frame name:
command 1-36
silent
python print("{} <- {}".format( gdb.execute("bt 0", False, True).strip(), gdb.newest_frame().older().name() ))
continue
end
... or even better, python printing bt 0 function name and args, and parent name:
command 1-36
silent
python nf = gdb.newest_frame(); nfb = nf.block()
python nfargs = [ "{}={}".format(sym, nf.read_var(sym, nfb)) for sym in nfb if sym.is_argument ]
python print("#0 {}({}) <- {}".format(nf.name(), ",".join(nfargs), nf.older().name() ))
continue
end
... which would print something like:
#0 Searcher::FlagFromCmd(this=0x7fffffffaed8,cmd=808) <- FindLiveStrip::GrabToggles
#0 Searcher::FlagFromCmd(this=0x7fffffffaed8,cmd=807) <- FindLiveStrip::ToggleChanged
... and this seems to work fine; though if there are other options, I'd love to know about them.

How can I use GDB to get the length of an instruction?

The problem I am trying to solve is that I want to dynamically compute the length of an instruction given its address (from within GDB) and set that length as the value of a variable. The challenge is that I don't want any extraneous output printed to the console (e.g. disassembled instructions, etc.).
My normal approach to this is to do x/2i ADDR, then subtract the two addresses. I would like to achieve the same thing automatically; however, I don't want anything printed to the console. If I could disable console output then I would be able to do this by doing x/2i ADDR, followed by $_ - ADDR.
I have not found a way to disable the output of a command in GDB. If you know such a way then please tell me! However, I have discovered interpreter-exec and GDB/MI. A quick test shows that doing x/2i works on GDB/MI, and the value of $_ computed by the MI interpreter is shared with the console interpreter. Unfortunately, this approach also spits out a lot of output.
Does anyone know a way to either calculate the length of an instruction without displaying anything, or how to disable the output of interpreter-exec, thus allowing me to achieve my goal? Thank you.
I'll give an arguably cleaner and more extensible solution that's not really shorter. It implements $instn_length() as a new GDB convenience function.
Save this to instn-length.py
import gdb
def instn_length(addr_expr):
t = gdb.execute('x/2i ' + addr_expr, to_string=True)
return long(gdb.parse_and_eval('$_')) - long(gdb.parse_and_eval(addr_expr))
class InstnLength(gdb.Function):
def __init__(self):
super(InstnLength, self).__init__('instn_length')
def invoke(self, addr):
return instn_length(str(long(addr)))
InstnLength()
Then run
$ gdb -q -x instn-length.py /bin/true
Reading symbols from /usr/bin/true...Reading symbols from /usr/lib/debug/usr/bin/true.debug...done.
done.
(gdb) start
Temporary breakpoint 1 at 0x4014c0: file true.c, line 59.
Starting program: /usr/bin/true
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffde28) at true.c:59
59 if (argc == 2)
(gdb) p $instn_length($pc)
$1 = 3
(gdb) disassemble /r $pc, $pc + 4
Dump of assembler code from 0x4014c0 to 0x4014c4:
An alternative implementation of instn_length() is to use the gdb.Architecture.disassemble() method in GDB 7.6+:
def instn_length(addr_expr):
addr = long(gdb.parse_and_eval(addr_expr))
arch = gdb.selected_frame().architecture()
return arch.disassemble(addr)[0]['length']
I have found a suitable solution; however, shorter solutions would be preferred. This solution sets a logging file to /dev/null, sets to to be overridden if it exists, and then redirects the console output to the log file temporarily.
define get-in-length
set logging file /dev/null
set logging overwrite on
set logging redirect on
set logging on
x/2i $arg0
set logging off
set logging redirect off
set logging overwrite off
set $_in_length = ((unsigned long) $_) - ((unsigned long) $arg0)
end
This solution was heavily inspired by another question's answer: How to get my program name in GDB when writting a "define" script?.

Using less as gdb pager

I noticed that in GDB, when issuing commands with long output like info variables, the output is displayed one page at time, pressing enter to go down and q to quit.
Is it possible to replace the default pager with another one, such as less, so that I can navigate up and down, quitting, searching, etc?
Is it possible to replace the default pager with another one
No: GDB doesn't call into external program to display the output, it simply pauses the output every screenfull (and you can make it not pause by set height 0).
In addtion to running inside emacs, you could also use screen or tmux (learning them will generally help you in a lot of other situations), or ask GDB to log output (set logging on) and then search in gdb.txt with any $PAGER you want.
Starting with version 9.1, GDB has a pipe command, so you can send a command's output to the pager of your choice. From the documentation:
pipe [command] | shell_command
Executes command and sends its output to shell_command. Note that no space is needed around |. If no command is provided, the last command executed is repeated.
run gdb inside of emacs and you should be able to use emacs' paging commands.
run emacs
type M-x gdb return (M stands for meta - alt key or option on Macs)
The Emacs message bar will now display the message:
Run gdb (like this): gdb
More information is available here: http://tedlab.mit.edu/~dr/gdbintro.html
HTH
you can put the following user-defined commands in ~/.gdbinit, then
% cat ~/.gdbinit
python import os
define less1
python os.popen("less","w").write(gdb.execute("$arg0",to_string=True))
end
define less2
python os.popen("less","w").write(gdb.execute("$arg0 $arg1",to_string=True))
end
...
% gdb
(gdb) less2 info var
...
(gdb) less1 disass
...
It is a bit old thread, but I think it is worth to add. #yichun gave a very nice idea here, but to be more practical it can be extended to any number of arguments:
define less
python import os
python os.popen("less","w").write(gdb.execute(' '.join(["$arg{0}".format(i) for i in range(0, argc)]), to_string=True))
end
Then it can also woth adding exceptions handling and waiting for processes to terminate to avoid keyboard glitches and we have something like that:
% cat ~/.gdbinit
define less
python argc = $argc
python
import os
f = None
try:
f = os.popen("less","w")
f.write(gdb.execute(' '.join(["$arg{0}".format(i) for i in range(0, argc)]), to_string=True))
except Exception as e:
if f:
f.write(str(e))
else:
print (str(e))
finally:
if f:
f.close()
end
end
In gdb 8.1.1 this code in .gdbinit adds the required functionality:
python
import os
class Less(gdb.Command):
def __init__(self):
super().__init__("less", gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
def invoke(self, argstr, from_tty):
with os.popen("less","w") as pipe:
try:
pipe.write(gdb.execute(argstr, to_string=True))
except Exception as e:
pipe.write(str(e))
Less()
end
Usage
(gdb) less info breakpoints
(gdb) less backtrace
Information: Commands In Python.