Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In gdb my variable shows as <optimised out>, how can I find its value?

In gdb how can I discover the value of a variable which displays as optimized out? Presumably the value is being stored in a register, how can I find out which one? Given this simple program (copied from the website named below).

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int foo = rand();
    printf("foo is %d\n", foo++);
    return foo;
}

Compile with optimization.

gcc -O3 -g optimized.c
gdb a.out

Run GDB

(gdb) print foo
$1 = <optimized out>

What is going on? The variable foo must exist somewhere but how do I find its value or where it is stored?

I found a page which explains in detail how the DWARF debug information works for optimized code https://undo.io/resources/gdb-watchpoint/build-for-debug-in-gdb. Using the suggestions there I could eventually find the register assigned to foo but it's rather painful.

How can I get gdb to tell me which register to watch?

I tried compiling with -g3 but that didn't help.

I tried a few commands in gdb which also didn't help.

ptype foo
info locals
print &foo
like image 613
WorldGeek Avatar asked Nov 27 '19 13:11

WorldGeek


Video Answer


2 Answers

The variable foo must exist somewhere

There is no requirement that it should exist. C++ operates on the as-if principle. The program works as if the variable exists. If the compiler can get away with throwing your variable out of the window, while adhering to the as-if principle, expect it to do so eagerly. This is the very essence of optimisation. If you don't like it, don't use optimisation. For extra double strong protection, declare the variable of interest volatile.

how do I find its value or where it is stored

It does not have to be stored anywhere. In this case you can find its value by looking at the output of the program and/or examining its exit status. There is no general method to deternine which register an optimised-out variable gets assigned. There may or may not be such a register, depending on the exact details of your program. The value and the computation that leads to it might well be optimised away together with the storage. (Not in this case because the value is visible from the outside).

like image 56
n. 1.8e9-where's-my-share m. Avatar answered Oct 15 '22 07:10

n. 1.8e9-where's-my-share m.


The variable foo must exist somewhere

Not necessarily. The compiler may instead store some value derived from the variable (e.g. foo+1 or foo-23) if it's convenient.

In this particular case, since foo is being passed to printf, you can discover it in a register or on the stack if you know the calling convention for your particular platform.

but how do I find its value or where it is stored?

Debugging optimized code currently requires significant skill, knowledge of the ABI and the assembly instructions used.

The problem is that compilers rarely accurately track values through their in-register and in-memory locations for debugging purposes, because doing so is quite hard.

Debuggers also have to correctly interpret the debugging info which compilers produce, and that isn't an easy or bug-free process either.

GCC recently had a lot of improvement in that area. Using gcc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1) from Fedora 31 on Linux x86_64, I observe this:

(gdb) start
Temporary breakpoint 1 at 0x401050: file t.c, line 6.
Starting program: /tmp/a.out 
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.30-5.fc31.x86_64

Temporary breakpoint 1, main () at t.c:6
6       int foo = rand();
(gdb) n
7       printf("foo is %d\n", foo++);
(gdb) p foo
$1 = 1804289384
(gdb) p &foo
Can't take address of "foo" which isn't an lvalue.
(gdb) c
Continuing.
foo is 1804289383
[Inferior 1 (process 2696) exited with code 0150]
(gdb) q

Here you can see that gcc described the location of foo in a register (or some other location that isn't memory), and GDB was able to print almost the value of foo.

like image 42
Employed Russian Avatar answered Oct 15 '22 08:10

Employed Russian