[patch] Backtrace prints wrong argument value

Luis Machado luisgpm@linux.vnet.ibm.com
Wed Apr 25 19:13:00 GMT 2007


Hi Folks,

GDB sometimes acts in an unexpected way while showing backtrace argument
values in certain optimized binaries. I'll go through the example:

The code used to reproduce this follows:

unsigned * __attribute__((noinline))
start_sequence (unsigned * x, unsigned * y)
{
  return (unsigned *)0xdeadbeef;
};

unsigned __attribute__((noinline))
gen_movsd (unsigned * operand0, unsigned * operand1)
{
  return *start_sequence(operand0, operand1);
}

int main(void)
{
  unsigned x, y;

  x = 13;
  y = 14;
  return (int)gen_movsd (&x, &y);
}

Basically we have two functions, gen_movsd and start_sequence. Since the
argument values for those two functions are not really used, GCC
optimizes some of them.

Loading the binary on GDB, we step through the code until we reach the
"start_sequence" function. It shows the following frame info:

#0 - start_sequence (x=<value optimized out>, y=0xfffff9b1b34)

"x" was originally passed on R3, and it's now lost since the same
register was used for the return value (0xdeadbeef) of the
"start_sequence" function. This is OK.

If we call a backtrace on GDB, that's what we have:

#0 - start_sequence (x=<value optimized out>, y=0xfffff9b1b34)
#1 - gen_movsd (operand0=0xdeadbeef, operand1=0xfffff9b1b34)

Notice that on frame #1, "operand0" has a "0xdeadbeef" value, which
happens to be the return value from the "start_sequence" function from
frame #0. This is clearly incorrect.

Stepping a little bit further through the code until we exit from
"start_sequence" and fall back into "gen_movsd", we have the following
as the frame info:

#0 - gen_movsd (operand0=<value optimized out>, operand1=<value
optimized out>)

This last frame info is just correct, since both values aren't available
anymore.

What is causing this incorrect value to be printed on frame levels above
0 is an adjustment to the PC on the "frame_unwind_address_in_block"
function. The purpose of this adjustment to PC is to make it point to
the branch instruction rather than the instruction right after the
branch instruction ( this is achieved with a --pc decrement).

This breaks the code that finds the right DWARF expression in the
location lists for each argument due to an off-by-1 error. Thus, GDB
selects the incorrect DWARF expression and shows the wrong value on
backtrace.

This patch fixes the problem by adjusting the PC to prevent the off-by-1
problem, thus making GDB select the correct DWARF expression.

Another point is that the PC decrement operation on
"frame_unwind_address_in_block", as it is now,  doesn't make sense if
the branch instruction is longer than 1 byte. To make sure that PC
points to the branch instruction we must go back the length of the last
instruction executed. On ppc this length is fixed, but on other
architectures it is not.

Comments and suggestions are welcome.

Best regards,
Luis
-------------- next part --------------
A non-text attachment was scrubbed...
Name: wrong_backtrace_argument.diff
Type: text/x-patch
Size: 1292 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/gdb-patches/attachments/20070425/6313ce4e/attachment.bin>


More information about the Gdb-patches mailing list