Print `errno` name instead of value in GDB - 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.

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)

lldb command 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

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.

How to get my program name in GDB when writting a "define" script?

I found it's very annoying to get the program name when defining a GDB script. I can't find any corresponding "info" command, and we can't use argv[0] either, because of multi-process/thread and frame-choosing.
So, what should I do?
If you are using a recent gdb (7 and above) you can play around with the Python support which is quite extensive (and probably where you want to go when defining gdb-scripts in general). I'm no expert at it but for a test-program /tmp/xyz I could use:
(gdb) python print gdb.current_progspace().filename
/tmp/xyz
See http://sourceware.org/gdb/current/onlinedocs/gdb/Python.html for more info on the Python support.
In "normal" gdb you could get the process name with "info proc" and "info target", but I guess you wanted it not just printed but being able to use it further in scripts? Don't know how to get the value out of the python runtime into a gdb variable other than the extremely ugly "using log files and sourcing it and hope for the best". This is how this could be done:
define set-program-name
set logging file tmp.gdb
set logging overwrite on
set logging redirect on
set logging on
python print "set $programname = \"%s\"" % gdb.current_progspace().filename
set logging off
set logging redirect off
set logging overwrite off
source tmp.gdb
end
and in your own function doing:
define your-own-func
set-program-name
printf "The program name is %s\n", $programname
end
I would suggest "going all in" on the python support, and scrap gdb-scripting. I believe it is worth the effort.