This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[DWARF] Tracking uninitialized variables


Hello!

It is certainly true that debugging an optimized code is an inherently
difficult task. Though, I wonder if the compiler could make such
debugging experience slightly less surprising.

Consider the following example:

    1 extern void bar(int *i1, int *i2, int *i3);
    2
    3 int __attribute__((noinline)) foo(int i1, int i2) {
    4   int a, b, c;
    5   a = i1 << i2;
    6   b = (i1 + i2) * i1;
    7   c = (b + i1);
    8   bar(&a, &b, &c);
    9 }
   10
   11 int main() {
   12   foo(42, 12);
   13 }

Let's compile it:

   $ gcc-trunk tst.c -g -fvar-tracking-uninit -O2

After hitting a breakpoint at line 8 (the last line of the function
foo) I have some random (and very confusing) values displayed in gdb
for all three variables a, b and c. This is because GCC allocates
these three variables on the stack (their addresses are taken) and
creates for them DWARF entries like this:

   <2><a8>: Abbrev Number: 8 (DW_TAG_variable)
      <a9>   DW_AT_name        : a
      <ab>   DW_AT_decl_file   : 1
      <ac>   DW_AT_decl_line   : 4
      <ad>   DW_AT_type        : <0x64>
      <b1>   DW_AT_location    : 2 byte block: 91 64 (DW_OP_fbreg: -28)

That is, actual values for variables are supposed to reside in fixed
stack slots throughout the whole function. But in fact, by the time
the breakpoint is hit none of the values is stored on the stack (the
last line of the function, evaluation of the first argument for the
call):

   Dump of assembler code for function foo:
      0x00000000004004c0 <+0>:     mov    %esi,%ecx
      0x00000000004004c2 <+2>:     add    %edi,%esi
      0x00000000004004c4 <+4>:     sub    $0x18,%rsp
      0x00000000004004c8 <+8>:     imul   %edi,%esi
      0x00000000004004cb <+11>:    mov    %edi,%eax
   => 0x00000000004004cd <+13>:    lea    0xc(%rsp),%rdx
      0x00000000004004d2 <+18>:    shl    %cl,%eax
      0x00000000004004d4 <+20>:    mov    %eax,0x4(%rsp)
      0x00000000004004d8 <+24>:    mov    %esi,0x8(%rsp)
      0x00000000004004dc <+28>:    add    %edi,%esi
      0x00000000004004de <+30>:    lea    0x4(%rsp),%rdi
      0x00000000004004e3 <+35>:    mov    %esi,0xc(%rsp)
      0x00000000004004e7 <+39>:    lea    0x8(%rsp),%rsi
      0x00000000004004ec <+44>:    callq  0x4004f6 <bar>
      0x00000000004004f1 <+49>:    add    $0x18,%rsp
      0x00000000004004f5 <+53>:    retq
   End of assembler dump.

By contrast, If I didn't take addresses of these variables, they would
be <optimized out> until we can determine their correct values. I
believe that such behavior is much better than displaying wrong values
for variables. Also, GCC seems to be able to produce DW_OP_GNU_uninit
operations to mark uninitialized variables (when -fvar-tracking-uninit
is used) but I've never seen it in generated debug info.

At first glance the problem seems to have something to do with the
fact that there's no gimple_debug/BIND and debug_insn/var_location
instructions for such stack variables in internal representation.
There are only statements like this:

   gimple_assign <lshift_expr, a.0_3, i1_1(D), i2_2(D), NULL>
   # .MEM_5 = VDEF <.MEM_4(D)>
   gimple_assign <ssa_name, a, a.0_3, NULL, NULL>

and *no* BIND statement like gimple_debug BIND <a, a.0_3>

Furthermore, in dwarf2out.c there are a lot of calls to
mem_loc_descriptor where var_init_status is unconditionally set to
VAR_INIT_STATUS_INITIALIZED. And it looks like currently all values
in memory are considered to be initialized by default. And only in
few places NOTE_VAR_LOCATION_STATUS is taken into account (anyway,
there's no such notes for variables a, b, c in this case).

So, here are my questions:
1) Wouldn't it be nice if GCC marked such stack variables either as
   uninitialized (with DW_OP_GNU_uninit) or as <optimized out>?
2) Is it feasible to implement such tracking for variables?
3) What exactly is GCC supposed to track with -fvar-tracking-uninit
   option?


Thanks,
Nikolai


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]