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]

[RFA] OSF/1 - "next" over prologueless function call


Hello,

We have recently noticed this failure. To demonstrate it, you'll need to
use the GNAT compiler because the sources that caused the problem are in
the GNAT runtime.

Use the following little Ada program:

        with Ada.Text_IO; use Ada.Text_IO;
        
        procedure Foo is
        begin
           Put_Line ("Hello World.");
           Put_Line ("Me again.");
        end Foo;

Compile it using the following command:

        % gnatmake -g foo

The following GDB transcript demonstrates the problem:

        (gdb) b foo.adb:5
        Breakpoint 1 at 0x120015a18: file foo.adb, line 5.
        (gdb) run
        Starting program: /[...]/foo 
        
        Breakpoint 1, _ada_foo () at foo.adb:5
        5          Put_Line ("Hello World.");
        (gdb) n
        0x0000000120023fe8 in ada__text_io__put_line__2 () at a-textio.adb:6
        6       a-textio.adb: No such file or directory.
                in a-textio.adb

The expected behavior was for GDB to stop at line 6 of foo.adb, not
inside Put_Line:

        (gdb) n
        Hello World.
        6          Put_Line ("Me again.");

Here is what happens. First, after having hit the breakpoint at line 5,
GDB sees the following code for line 5:

        #.stabn        68,0,5,$LM2
        lda $1,$LC0
        lda $2,$LC1
        bis $31,$1,$16
        bis $31,$2,$17
        jsr $26,ada__text_io__put_line__2
        ldgp $29,0($26)

(for the curious, LC0 and LC1 are the string "Hello World." and its
bounds).

That's the assembly code as generated by GCC. However, if you look at
the actual assembly code, as produced after the link, you will see
that the OSF/1 linker has done a little optimization (which I find is
done quite often). Here is how the jsr instruction has been modified:

        bsr     ra,0x120023fe8 <ada__text_io__put_line__2+8>

The jump is actually made to the third instruction of Put_Line.
So when GDB starts doing the "next" operation, it eventually receives
a sigtrap. Normally, GDB should detect that we are inside a function
call and therefore should step_over_function(). But it fails to recognize
this situation because of the conjunction of the following two factors:

        1. The stop_pc is not at the "official" Put_Line function
           start address

        2. The function does not have a prologue

So the following test fails in infrun.c:handle_inferior_event() fails,
and GDB incorrectly thinks that we have landed at the next line of code:

  if (((stop_pc == ecs->stop_func_start /* Quick test */
        || in_prologue (stop_pc, ecs->stop_func_start))
       && !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
      || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, ecs->stop_func_name)
      || ecs->stop_func_name == 0)

Just FYI, the first instructions of Put_Line are:

    <ada__text_io__put_line__2+0>:       ldah    gp,8191(t12)
    <ada__text_io__put_line__2+4>:       lda     gp,-1088(gp)
    <ada__text_io__put_line__2+8>:       ldq     t8,-28008(gp)
    <ada__text_io__put_line__2+12>:      nop
    <ada__text_io__put_line__2+16>:      mov     a0,t0
    <ada__text_io__put_line__2+20>:      mov     a1,a2
    <ada__text_io__put_line__2+24>:      ldq     a0,0(t8)
    <ada__text_io__put_line__2+28>:      mov     t0,a1
    <ada__text_io__put_line__2+32>:      ldq     t12,-30040(gp)
    <ada__text_io__put_line__2+36>:      jmp     zero,(t12),0x120023d50 <ada__text_io__put_line>

If it wasn't for the linker optimization, the check for "top_pc ==
ecs->stop_func_start" would probably have kicked in, and all would
have been fine.

So I suggest we refine this test to use a new gdbarch function which,
by default, would be the exact equivalent of this equality check. But
I then provide an OSF/1-specific version of this function that checks
that we stopped either at the first instruction of the function, or
right after the couple of instructions forming the ldgp macro.

2003-12-01  J. Brobecker  <brobecker@gnat.com>

        * gdbarch.sh (at_function_start): New gdbarch function.
        * gdbarch.h: Regenerate.
        * gdbarch.c: Regenerate.
        * arch-utils.c (default_at_function_start): New function.
        * arch-utils.h (default_at_function_start): Add prototype.
        * infrun.c (handle_inferior_event): Use new gdbarch function
        at_function_start to properly detect function calls during
        STEP_OVER_ALL.
        * alpha-osf1-tdep.c (alpha_osf1_at_function_start): New function.
        (alpha_osf1_init_abi): Set the gdbarch at_function_call function.

Tested on alpha-osf1 and x86-linux. No regression.

OK to apply?

Thanks,
-- 
Joel

Attachment: next.diff
Description: Text document


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