This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB 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]

Re: [RFC] "info registers" is misleading


Fred Fish wrote:
> 
> I had always thought that "info registers" is supposed to tell you
> the actual register contents, and is simply a convenient way to see
> all the registers with one command.  I.E. it is equivalent to
> doing something like:
> 
>         (gdb) p/x $r0
>         (gdb) p/x $r1
>         ...
> 
> While chasing a bug in some THUMB code related to the stack not being
> restored correctly when using the "return xxx" command, I stumbled
> over a case where "info registers" prints the value of r11 differently
> than "p/x $r11" does.
> 
>   Script started on Mon Jan 21 23:33:14 2002
> 
>   $ cat bug.c
>   #include <stdio.h>
> 
>   int
>   callee2 (int n)
>   {
>     return 0;
>   }
> 
>   int
>   callee1 (void)
>   {
>     int n = 1;
>     n = callee2 (n);
>     return n;
>   }
> 
>   int main ()
>   {
>     callee1 ();
>   }
> 
>   $ arm-elf-gcc -mthumb -g -o bug bug.c
> 
>   $ ./gdb-orig -nw -nx bug
>   GNU gdb 2002-01-22-cvs
>   Copyright 2002 Free Software Foundation, Inc.
>   GDB is free software, covered by the GNU General Public License, and you are
>   welcome to change it and/or distribute copies of it under certain conditions.
>   Type "show copying" to see the conditions.
>   There is absolutely no warranty for GDB.  Type "show warranty" for details.
>   This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-elf"...
>   (gdb) tar sim
>   Connected to the simulator.
>   (gdb) load
>   Loading section .init, size 0x14 vma 0x8000
>   Loading section .text, size 0x1570 vma 0x8014
>   Loading section .fini, size 0x10 vma 0x9584
>   Loading section .rodata, size 0x8 vma 0x9594
>   Loading section .data, size 0x84c vma 0x969c
>   Loading section .eh_frame, size 0x4 vma 0x9ee8
>   Loading section .ctors, size 0x8 vma 0x9eec
>   Loading section .dtors, size 0x8 vma 0x9ef4
>   Loading section .jcr, size 0x4 vma 0x9efc
>   Start address 0x80cc
>   Transfer rate: 61440 bits in <1 sec.
>   (gdb) br callee2
>   Breakpoint 1 at 0x81ae: file bug.c, line 6.
>   (gdb) run
>   Starting program: /build/sourceware/gdb/H-i686-pc-linux-gnu/T-arm-elf/gdb/bug
> 
>   Breakpoint 1, callee2 (n=1) at bug.c:6
>   6       return 0;
>   (gdb) info reg
>   r0             0x1    1
>   r1             0x1ffffc       2097148
>   r2             0x1fffe8       2097128
>   r3             0x1fffdc       2097116
>   r4             0x1    1
>   r5             0x1ffffc       2097148
>   r6             0x0    0
>   r7             0x1fffe0       2097120
>   r8             0x0    0
>   r9             0x0    0
>   r10            0x200100       2097408
>   r11            0x1fffe0       2097120
>   r12            0x0    0
>   sp             0x1fffdc       2097116
>   lr             0x81cf 33231
>   pc             0x81ae 33198
>   fps            0x0    0
>   cpsr           0x20000033     536870963
>   (gdb) p/x $r7
>   $1 = 0x1fffe0
>   (gdb) p/x $r11
>   $2 = 0x0
>   (gdb) quit
>   The program is running.  Exit anyway? (y or n) y
> 
> Notice in the above that "info reg" prints 0x1fffe0 for the value of
> r11, while it actually has a value of 0x0.
> 
> The culprit appears to be read_relative_register_raw_bytes_for_frame(),
> which is:
> 
>   /* FIXME: This function increases the confusion between FP_REGNUM
>      and the virtual/pseudo-frame pointer.  */
> 
>   static int
>   read_relative_register_raw_bytes_for_frame (int regnum,
>                                             char *myaddr,
>                                             struct frame_info *frame)
>   {
>     int optim;
>     if (regnum == FP_REGNUM && frame)
>       {
>         /* Put it back in target format. */
>         store_address (myaddr, REGISTER_RAW_SIZE (FP_REGNUM),
>                      (LONGEST) FRAME_FP (frame));
> 
>         return 0;
>       }
>     get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame,
>                       regnum, (enum lval_type *) NULL);
> 
>     if (register_cached (regnum) < 0)
>       return 1;                 /* register value not available */
> 
>     return optim;
>   }
> 
> Getting rid of the section of code that checks for FP_REGNUM:
> 
>     if (regnum == FP_REGNUM && frame)
>       {
>         /* Put it back in target format. */
>         store_address (myaddr, REGISTER_RAW_SIZE (FP_REGNUM),
>                      (LONGEST) FRAME_FP (frame));
> 
>         return 0;
>       }
> 
> gets rid of the problem:
> 
>   $ ./gdb -nw -nx bug
>   GNU gdb 2002-01-22-cvs
>   Copyright 2002 Free Software Foundation, Inc.
>   GDB is free software, covered by the GNU General Public License, and you are
>   welcome to change it and/or distribute copies of it under certain conditions.
>   Type "show copying" to see the conditions.
>   There is absolutely no warranty for GDB.  Type "show warranty" for details.
>   This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-elf"...
>   (gdb) tar sim
>   Connected to the simulator.
>   (gdb) load
>   Loading section .init, size 0x14 vma 0x8000
>   Loading section .text, size 0x1570 vma 0x8014
>   Loading section .fini, size 0x10 vma 0x9584
>   Loading section .rodata, size 0x8 vma 0x9594
>   Loading section .data, size 0x84c vma 0x969c
>   Loading section .eh_frame, size 0x4 vma 0x9ee8
>   Loading section .ctors, size 0x8 vma 0x9eec
>   Loading section .dtors, size 0x8 vma 0x9ef4
>   Loading section .jcr, size 0x4 vma 0x9efc
>   Start address 0x80cc
>   Transfer rate: 61440 bits in <1 sec.
>   (gdb) br callee2
>   Breakpoint 1 at 0x81ae: file bug.c, line 6.
>   (gdb) run
>   Starting program: /build/sourceware/gdb/H-i686-pc-linux-gnu/T-arm-elf/gdb/bug
> 
>   Breakpoint 1, callee2 (n=1) at bug.c:6
>   6       return 0;
>   (gdb) info reg
>   r0             0x1    1
>   r1             0x1ffffc       2097148
>   r2             0x1fffe8       2097128
>   r3             0x1fffdc       2097116
>   r4             0x1    1
>   r5             0x1ffffc       2097148
>   r6             0x0    0
>   r7             0x1fffe0       2097120
>   r8             0x0    0
>   r9             0x0    0
>   r10            0x200100       2097408
>   r11            0x0    0
>   r12            0x0    0
>   sp             0x1fffdc       2097116
>   lr             0x81cf 33231
>   pc             0x81ae 33198
>   fps            0x0    0
>   cpsr           0x20000033     536870963
>   (gdb) p/x $r7
>   $1 = 0x1fffe0
>   (gdb) p/x $r11
>   $2 = 0x0
>   (gdb) quit
>   The program is running.  Exit anyway? (y or n) y
>   $ exit
> 
> Notice now that "info reg" correctly prints 0x0 for r11.
> 
> Any comments on the best way to fix this?  I have no idea what the
> motivation was to treat the frame pointer as a special case when block
> printing the registers.

This is an old old issue.  The frame pointer register
is special.  Info registers does not show the actual
value of the fp register -- it shows the virtual frame pointer
(the address of the function's stack frame).  Usually
it's the same value -- unles you're in a frameless function
(ie. one that does not use the frame pointer register).

Now that we have pseudo-registers, we've talked about 
adding a pseudo-frame-pointer register and using it for
FP_REGNUM, so that the "real" frame pointer register can
always display its real value.


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