Re: gdb problems with -O1 on x86_64 architecture.

Daniel Jacobowitz
2005-05-10T14:45:13Z

On Tue, May 10, 2005 at 03:33:31PM +0100, Tigran Aivazian wrote:
> Hi,
>
> I thought it is worth showing how it behaves on -O2 compiled binary as
> well:
>
> # gcc -g -Wall -O2 -fno-optimize-sibling-calls uvar.c -o uvar-O2
>
> (gdb) b kt_func3
> Breakpoint 1 at 0x4004e0: file uvar.c, line 11.
> (gdb) r
> Starting program: /root/mod/uvar-O2
>
> Breakpoint 1, kt_func3 (x1=0x11111133, x2=0x22222244, x3=0x33333355,
> x4=0x44444466, x5=0x55555577, x6=0x66666688,
> x7=0x77777799, x8=0x888888aa, x9=0x9566b560) at uvar.c:11
> 11 return (x1 + x2 + x3/2 + x4/4 + x5/5 + x6/6 + x7/7 + x8/8
> + x9/9);
> (gdb) bt
> #0 kt_func3 (x1=0x11111133, x2=0x22222244, x3=0x33333355, x4=0x44444466,
> x5=0x55555577, x6=0x66666688, x7=0x77777799,
> x8=0x888888aa, x9=0x9566b560) at uvar.c:11
> #1 0x00000000004005d3 in kt_func2 (x1=<value optimized out>, x2=<value
> optimized out>, x3=<value optimized out>,
> x4=<value optimized out>, x5=<value optimized out>, x6=<value
> optimized out>, x7=0x77777788, x8=0x88888899,
> x9=0x999999aa) at uvar.c:16
> #2 0x0000000000400623 in kt_func1 (x1=<value optimized out>, x2=<value
> optimized out>, x3=<value optimized out>,
> x4=<value optimized out>, x5=<value optimized out>, x6=<value
> optimized out>, x7=0x77777777, x8=0x88888888,
> x9=0x99999999) at uvar.c:22
> #3 0x000000000040067a in main (argc=<value optimized out>, argv=<value
> optimized out>) at uvar.c:30
>
> As you see, it claims that x1,x2,x3,x4,x5,x6 are optimized out and
> x7,x8,x9 are available and shows the correct values. This is for kt_func2
> and kt_func1 functions, but for kt_func3 it shows all values correctly
> except the last one --- x9 is garbage. But with -O0 it shows everything
> correctly.

GDB's doing the best it can. Let me give you a case-by-case. First
the top frame. We're at 0x4004e0; presumably because this function
does not appear to have a prologue. Debuginfo says:
x1 in reg5, but only for the first two instructions, then dead
x2 in reg4
x3 in reg1 until +0x14
x4 in reg2
...
x9 in reg3

Well, reg3 is %rbx and that's just not true.

4004e4: 53 push %rbx
4004f7: 8b 5c 24 20 mov 0x20(%rsp),%ebx

_NOW_ it's in rbx. The compiler didn't tell us that the variable came
in on the stack and then moved to %rbx, it said it was in %rbx the
whole time. This is a (very common) compiler bug; it's rare that a
compiler tracks incoming argument locations properly. I hope GCC does
someday.

How about for the next frame? Let's look at 0x00000000004005d3 in
kt_func2. Please take a look at the code for a moment.

400590: 48 83 ec 18 sub $0x18,%rsp
400594: 41 83 c1 11 add $0x11,%r9d
400598: 41 83 c0 11 add $0x11,%r8d
40059c: 8b 44 24 30 mov 0x30(%rsp),%eax
4005a0: 44 8b 54 24 28 mov 0x28(%rsp),%r10d
4005a5: 83 c1 11 add $0x11,%ecx
4005a8: 44 8b 5c 24 20 mov 0x20(%rsp),%r11d
4005ad: 83 c2 11 add $0x11,%edx
4005b0: 83 c6 11 add $0x11,%esi
4005b3: 83 c7 11 add $0x11,%edi
4005b6: 83 c0 11 add $0x11,%eax
4005b9: 41 83 c2 11 add $0x11,%r10d
4005bd: 41 83 c3 11 add $0x11,%r11d
4005c1: 89 44 24 10 mov %eax,0x10(%rsp)
4005c5: 44 89 54 24 08 mov %r10d,0x8(%rsp)
4005ca: 44 89 1c 24 mov %r11d,(%rsp)
4005ce: e8 0d ff ff ff callq 4004e0 <kt_func3>
4005d3: 48 83 c4 18 add $0x18,%rsp
4005d7: c3 retq

How would you propose recovering the value which was in %r9d on
entrance to this function? Or %ecx? It can't be done. A
too-clever-for-its-own-good compiler might tell us that we could
recreate a read-only copy by unwinding %r9d and then subtracting 0x11,
except that I'm pretty sure the register is call clobbered, so we can't
recreate its value anyway.

--
Daniel Jacobowitz
CodeSourcery, LLC