lldb command if statement - if-statement

Hi I need to write a lldb breakpoint command that evaluates a value and prints out a value.
In gdb I could do it like this:
if ($value==2)
printf "Value is 2\n"
end
But in lldb the 'if-statement' is invalid it seems:
failed with error: 'if' is not a valid command.
error: Unrecognized command 'if'.
Can anyone tell me how to write this comparison inside my breakpoint command? Thanks!

You can use the expression parser to achieve this effect in some cases, and you can use the lldb Python interpreter for whatever complex work you want to do in response to a breakpoint hit. Given the fairly deep level of Python support, we felt if you don't know Python, you time would be better spent learning a little bit of that so you could really script lldb, rather than learning whatever little micro-language we would come up with.
Anyway, so using the interpreter, you could for instance do:
expr if ($value == 2) { (int) printf("Value is 2\n"); }
And using the python interpreter you can write a callback like:
def myCallback (frame, breakpoint_location, dict):
value = frame.FindValue("$value", lldb.eValueTypeConstResult)
if (value.unsigned == 10):
print "Value is 10"
put that in a file called myModule.py, do:
(lldb) command script import myModule.py
and then assign the command to your breakpoint with:
(lldb) breakpoint command add -F myModule.myCallback <BREAKPOINT_NUMBER>
That python example was a little more complex than normal because you were looking up lldb's equivalent of gdb's "convenience variable". If you were looking up a local, you could use frame.FindVariable.
More details on this at:
http://lldb.llvm.org/python-reference.html

Related

calling gdb print from python script

I have a python gdb script that finds a pointer to some important value.
I want to call gdb print command to have this value assigned to value history for future references in other debug commands.
How to do it?
I know that I can define python function that will return this value - but I really want gdb command for backward compatibility with old gdb scripts.
Generate python string and call gdb.execute
tmpVal = long(pointer)
tmpStr = "print (Xxxx *)0x{:x}".format(tmpVal)
gdb.execute(tmpStr)

How to execute commands conditionally in gdbinit functions

I have a gdb function, defined in gdbinit file:
define myfunc
set $retval = SOMEHOW_RET_VALUE_OF shell my-shell-command
if $retval == 0
load my-output
else
echo command not succeeded, not doing anything.\n
end
end
How can I get my-shell-func return status and use it to control loading new binary output?
There are two ways to do this.
The simplest way is to use gdb's built-in Python scripting capability. For a case like the above, you could write a new convenience function that does what you like. A convenience function is appropriate here because it can be used directly in an expression.
To write a convenience function, look through the docs for gdb.Function.
Then you would use it like:
set $retval = $_shellcommand("shell command")
If you'd rather not dive into Python, there is still a way; although it is somewhat more painful.
For a simple shell command, the idea would be to write the exit status of the shell command to a gdb script file, which you then source:
(gdb) shell false; echo "set \$retval = $?" > /tmp/q
(gdb) source /tmp/q
(gdb) print $retval
$1 = 1
This gets somewhat hairier if you want more than just the exit status, or if you want to use output from gdb commands in the computation.

How to evaluate an expression to be used for a gdb monitor command?

Inside a scripted gdb session I want to use monitor <cmd> where cmd should contain the address of a symbol. For example:
monitor foobar &myVariable
should become to:
monitor foobar 0x00004711
Because the remote side cannot evaluate the expression. Whatever I tried, the string "&myVariable" gets sent instead of the address.
I played around with convenience variables and stuff, but this is the only workaround I found:
# write the command into a file and execute this file
# didn't find a direct way to include the address into the monitor command
set logging overwrite on
set logging on command.tmp
printf "monitor foobar 0x%08x\n", &myVariable
set logging off
source command.tmp
Any ideas to solve this in a more elegant way?
The simplest way to do this is to use the gdb eval command, which was introduced for exactly this purpose. It works a bit like printf:
(gdb) eval "monitor foobar %p", &myVariable
(I didn't actually try this, so caution.)
If your gdb doesn't have eval, then it is on the old side. I would suggest upgrading.
If you can't upgrade, then you can also script this using Python.
If your gdb doesn't have Python, then it is either very old (upgrade!) or compiled without Python support (recompile!).
If you can't manage to get either of these features, then I am afraid the "write out a script and source it" approach is all that is left.

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.

Print `errno` name instead of value in GDB

I wonder if there is any way to print errno symbolic name instead of just a number in GDB. For example, instead of
errno = 13
I would like to see something like
EACCES
Assuming you have a recent GDB with embedded Python, you can use the Python interpreter to do what you want.
The following (untested) code should be about right:
(gdb) python import errno
(gdb) python print errno.errorcode[13]
You should be able to define a python command, e.g. perrno, that will cut down on typing. Documentation here.