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'
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.
I know b and command can print things when breakpoint triggers. But in my program, there're lots of memcpy, I need to print the target length and source address when code goes there, which are register $r2 and $r1.
The memcpys are located at:
$my_module_base+0xaaa
$my_module_base+0xbbb
...
I tried to write a function that take the $my_module_base as argument and set these breakpoint automatically
define set_all_bp
set $module_base=$arg0
b *$module_base+0xaaa
command
echo Here is memcpy 1:\n
my_dump $r1 $r2
end
b *$module_base+0xbbb
command
echo Here is memcpy 2:\n
my_dump $r1 $r2
end
end
But it doesn't work, gdb says:
(gdb) source my_script
bp:8: Error in sourced command file:
This command cannot be used at the top level.
(gdb)
Any other way to do this?
How do I check the current line number that I'm stopped in when debugging with GDB? I would have thought this would be obvious (and maybe it is) but I don't see it on the GDB Cheat Sheet.
Some digging around revealed the following methods:
frame: This command was exactly what I was looking for. Output looked as follows:
(gdb) frame
#0 MyDialog::on_saveButton_clicked (this=0x72bf9e0) at src/ui/dialog/MyDialog.cxx:86
86 _item->save();
(gdb)
where or bt (same effect): This prints out the call stack, ending on the current line.
list *$pc: This doesn't tell you the exact line but it prints out the surrounding lines with the current line in the center.
x/i $eip
eip(rip) points to the next instruction
I want to see which parameter and return value to a function. I use gdb breakpoint command list (gdb command script) as follow:
int foo(int)
(gdb) break foo
(gdb) print $r0
(gdb) finish
(gdb) print $r0
(gdb) continue
(gdb) end
But it print only the parameter.
I got the reason from here GDB Breakpoint command lists
Any other commands in the command list, after a command that resumes execution, are ignored.
Any help is appreciated.
You need a second breakpoint at the end of the function if you want to associate commands there.