This is the mail archive of the crossgcc@sourceware.org mailing list for the crossgcc project.

See the CrossGCC FAQ for lots more information.


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: gdb-6.3 on ARM BE "next" command breaks in PLT


could you send your patch to gdb-patches@sourceware.org you can get useful comments there.

Dan Wilder wrote:
Dear Developers,

I've been having difficulty with GDB on ARM big-endian target
dynamic-linked binaries using toolchain built with crosstools-0.38 derived scripts. Briefly, a gdb "next" command breaks in the Procedure Lookup Table (.plt segment) sometimes, rather than fast-forwarding to the next relevant point in the .text segment. I think I have a
solution, attached, and am wondering if anybody has any feedback.


The test program used is not ANSI C compliant. However it compiles cleanly under gcc-3.3.1, the version used in the toolchain, producing a call to memset() in place of the odd-looking, oddly-placed statement with the empty initializer. The developers here complain of similar problems even with ANSI C compliance in their programs. The one that follows happens to be what they asked me to work with. In any case the session below displays the problem when calling the printf preceding the odd line.

---------------------- snip tst.c -----------------------
#include <stdio.h>

int main(int argc, char **argv)
{
  int this, i;
  for (i=1; i<10; i++)
    printf("%d", i);
  printf("\n");
  char other[255] = {};
  printf ("%s\n", other);
}
---------------------- snip tst.c -----------------------

Running under gdb on the target system, in summary I get:

# ./gdb tst
GNU gdb 6.3
(gdb) b main
Breakpoint 1 at 0x8490: file tst.c, line 6.
(gdb) run
Starting program: /home/dwilder/tst
Breakpoint 1, main (argc=1, argv=0xbffffea4) at tst.c:6
  6                  for (i=1; i<10; i++)
(gdb) l
   1       #include <stdio.h>
   2
   3       int main(int argc, char **argv)
   4       {
   5         int this, i;
   6         for (i=1; i<10; i++)
   7           printf("%d", i);
   8         printf("\n");
   9         char other[255] = {};
  10        printf ("%s\n", other);

(gdb) b 8
Breakpoint 2 at 0x84c4: file tst.c, line 8.
   8         printf("\n");
(gdb) n
0x00008384 in ?? ()
(gdb) bt
  #0  0x00008384 in ?? ()

[ 0x8384 is in the .plt section, not the .text ]

(gdb) nexti
  0x00008388 in ?? ()
(gdb) nexti
  0x0000838c in ?? ()
(gdb) nexti
0x40062fa8 in printf () from /lib/libc.so.6

[ at this point backtrace looks OK. Note the first breakpoint caught us in the PLT on the way to printf(), not memset()]

(gdb) bt
#0 0x40062fa8 in printf () from /lib/libc.so.6
#1 0x000084cc in main (argc=1, argv=0xbffffea4) at tst.c:8
(gdb) finish
Run till exit from #0 0x40062fa8 in printf () from /lib/libc.so.6
123456789
main (argc=1, argv=0xbffffea4) at tst.c:9
9 char other[255] = {};
A "next" when the backtrace looks bad results in nothing good. The
developers report having to lurch between "next" and "nexti" to make
a program trace is disruptive to their debugging and error-prone.


In gdb-6.3/gdb/infrun.c there is a function called handle_inferior_event
having about 50 "return" statements.  At line 2244 it has:

/* We stepped out of the stepping range. */

    /* If we are stepping at the source level and entered the runtime
       loader dynamic symbol resolution code, we keep on single stepping
       until we exit the run time loader code and reach the callee's
       address.  */
   if (step_over_calls == STEP_OVER_UNDEBUGGABLE
       && IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))
     {

which looks from the comments and the context like it's supposed
to evaluate to true when we're in .plt.  It doesn't, because
step_over_calls is set to STEP_OVER_ALL at this point.

A little while later there's a somwhat similar clause,
but it compares for either value of step_over_calls:

  if (step_range_end != 1
        && (step_over_calls == STEP_OVER_UNDEBUGGABLE
      || step_over_calls == STEP_OVER_ALL)
        && get_frame_type (get_current_frame ()) ==
      SIGTRAMP_FRAME)

It looks to me like the earlier test should also check for
STEP_OVER_ALL.  My question: does anybody know differently?

I changed the earlier test to read:

  if ((step_over_calls == STEP_OVER_UNDEBUGGABLE
    || step_over_calls == STEP_OVER_ALL)
      && IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))

and now the "next" commands stop only where I'd expect them to:

GNU gdb 6.3
(gdb) b main
Breakpoint 1 at 0x8490: file tst.c, line 6.
(gdb) r
Starting program: /home/dwilder/tst
Breakpoint 1, main (argc=1, argv=0xbffffef4) at tst.c:6
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
7           printf("%d", i);
(gdb) n
6         for (i=1; i<10; i++)
(gdb) n
8         printf("\n");
(gdb) n
123456789
9         char other[255] = {};
(gdb) n
10        printf ("%s\n", other);
(gdb) n

11      }
(gdb) c
Continuing.

Program exited normally.

Patch attached.

--
Dan Wilder
------------------------------------------------------------------------


Patch to fix problem on ARM in which GDB "next" command breaks in the .plt segment rather than at the next source-level statement. In that condition "backtrace" yields deceptive
results and "next" works not at all: you have to use a series
of "nexti" commands to get to a stack frame gdb understands.


--- gdb-6.3/gdb/infrun.c.orig 2005/09/30 10:58:59
+++ gdb-6.3/gdb/infrun.c 2006/02/10 16:03:56
@@ -2247,7 +2247,8 @@
loader dynamic symbol resolution code, we keep on single stepping
until we exit the run time loader code and reach the callee's
address. */
- if (step_over_calls == STEP_OVER_UNDEBUGGABLE
+ if ((step_over_calls == STEP_OVER_UNDEBUGGABLE + || step_over_calls == STEP_OVER_ALL)
&& IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))
{
CORE_ADDR pc_after_resolver =


------------------------------------------------------------------------

------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.org


------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.org


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