GDB: Setting a convenience variable using an environment variable - gdb

I would like to do use a variable from my bash/ gdb environment and set it as a convenience variable in gdb.
(gdb) show environment
bar=1
(gdb) set $foo = (show environment bar)
(gdb) show convenience
foo=1
Of course, my second (gdb) command returns an error. I have looked quite a bit to see if something like this is possible. But perhaps I am looking in the wrong direction. Could anyone be of help?

You could do it using builtin Python, like so:
(gdb) py import os
(gdb) py gdb.set_convenience_variable("home", os.environ["HOME"])
(gdb) p $home
$1 = "/home/me"

Related

gdb eval "%s" replacement error

sorry about the title I tried hard to come up with something which would "describe" the issue. Sorry as well if the question has already been asked but I was not able to find something related.
So I was trying to use gdb convenience variable of type string with the eval function.
First, since I just started using gdb, I wanted to make sure I understand what's happening so I tried the following
(gdb) eval "!echo 5"
5
(gdb) eval "!echo 5+8"
5+8
(gdb) eval "!echo %d", 5
5
(gdb) eval "!echo %d", 5+8
13
(gdb) set $anumber = 12
(gdb) eval "!echo %d", $anumber
12
so far so good.
Then I tried this though and I cannot figure out why it's yelling at me for the last line.
(gdb) eval "!echo hello"
hello
(gdb) eval "!echo \"hello\""
hello
(gdb) eval "!echo 'hello'"
hello
(gdb) set $hellostr = "hello"
(gdb) eval "!echo %s", $hellostr
You can't do that without a process to debug.
Is there something I am missing?
If that might help, calling show version produce
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
This is just a bug in gdb. Currently gdb always tries to allocate the string in the inferior. However, this is not always truly necessary.

How to set a double variable in gdb with German locale?

I am debugging my c++ program with gdb. I am having difficulties to set a simple double variable because of the German locale.
gdb won't accept values with decimal point. Typed with German decimal point (comma), gdb ignores everything after the comma.
(gdb) p this->foodSupply
$1 = 1
(gdb) set this->foodSupply = 4.3
Ungültige Nummer »4.3«.
(gdb) p this->foodSupply
$1 = 1
(gdb) set this->foodSupply = 4,3
(gdb) p this->foodSupply
$3 = 4
I figured I can avoid the problem by running gdb with LC_ALL=EN gdb ....
But since it's not as easy when working out of my IDE, I want to know if there is another way.
How can a German user type a decimal point in gdb?
Have a look at this bug:
https://bugs.launchpad.net/ubuntu/+source/gdb/+bug/1341125
There it is maybe explained, why it does not work like you want it to.
You can try a workaround like
(gdb) set this->foodSupply = (double) 43/10
if your numbers are as simple as 4.3.

How can I use a variable name instead of addresses when debugging valgrind runs with gdb?

Let's say I'm debugging with valgrind and gdb by doing:
$ valgrind --vgdb-error=0 ./magic
...and then in a second terminal:
$ gdb ./magic
...
(gdb) target remote | /usr/lib/valgrind/../../bin/vgdb
If I want to examine the defined-ness of some memory, I can use:
(gdb) p &batman
$1 = (float *) 0xffeffe20c
(gdb) p sizeof(batman)
$2 = 4
(gdb) monitor get_vbits 0xffeffe20c 4
ffffffff
Using three commands to do one thing is kind of annoying, especially since I usually want to do this a few times for many different variables in the same stack frame. But if I try the obvious thing, I get:
(gdb) monitor get_vbits &batman sizeof(batman)
missing or malformed address
Is it possible to get gdb to evaluate &batman and sizeof(batman) on the same line as my monitor command?
But if I try the obvious thing, I get: missing or malformed address
This is from GDB doc (http://sourceware.org/gdb/onlinedocs/gdb/Connecting.html#index-monitor-1210) for the monitor cmd:
monitor cmd
This command allows you to send arbitrary commands
directly to the remote monitor. Since gdb doesn't care about the
commands it sends like this, this command is the way to extend gdb—you
can add new commands that only the external monitor will understand
and implement.
As you can see "gdb doesn't care about the commands it sends like this". It probably means that the command after monitor is not processed in any way and sent AS IS.
What you can do to evaluate your variable on the same line is to use user defined commands in gdb (http://sourceware.org/gdb/onlinedocs/gdb/Define.html). Define your own comand and use the eval gdb command to prepare your command with necessary values (http://sourceware.org/gdb/current/onlinedocs/gdb/Output.html#index-eval-1744):
define monitor_var
eval "monitor get_vbits %p %d", &$arg0, sizeof($arg0)
end
And then use it like this:
(gdb) monitor_var batman

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?.

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.