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]

gdb-6.3 on ARM BE "next" command breaks in PLT


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

Attachment: gdb-arm-next.patch
Description: Text document

------
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]