* [RFA] OSF/1 - "next" over prologueless function call
@ 2003-12-02 4:26 Joel Brobecker
2003-12-02 4:30 ` Daniel Jacobowitz
` (2 more replies)
0 siblings, 3 replies; 18+ messages in thread
From: Joel Brobecker @ 2003-12-02 4:26 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 4614 bytes --]
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 #2: next.diff --]
[-- Type: text/plain, Size: 5699 bytes --]
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.288
diff -u -p -r1.288 gdbarch.sh
--- gdbarch.sh 14 Nov 2003 21:22:42 -0000 1.288
+++ gdbarch.sh 2 Dec 2003 03:52:38 -0000
@@ -771,6 +771,24 @@ F::FETCH_POINTER_ARGUMENT:CORE_ADDR:fetc
# Return the appropriate register set for a core file section with
# name SECT_NAME and size SECT_SIZE.
M:::const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size
+
+# Return nonzero if PC points to the first "effective" instruction of
+# the function starting at FUNC_START.
+#
+# The default implementation which should be appropriate for most
+# targets is to return nonzero if PC is equal to FUNC_START. However,
+# it can happen that the address of a subroutine call instruction
+# is changed to jump slightly after the begining of the function,
+# thus making the "effective" function start address a bit different
+# from the start address read from the symbol table or the debugging
+# information.
+#
+# For instance, on alpha-tru64, the first two instructions of a function
+# are often setting up the GP. The linker sometimes determines that
+# these instructions are not needed for the proper execution of the
+# program and therefore virtually optimizes them out by changing the
+# jump address to branch 2 instructions later.
+f:2:AT_FUNCTION_START:int:at_function_start:CORE_ADDR pc, CORE_ADDR func_start:pc, func_start::0:default_at_function_start::0
EOF
}
Index: arch-utils.c
===================================================================
RCS file: /cvs/src/src/gdb/arch-utils.c,v
retrieving revision 1.108
diff -u -p -r1.108 arch-utils.c
--- arch-utils.c 14 Nov 2003 21:22:42 -0000 1.108
+++ arch-utils.c 2 Dec 2003 03:52:39 -0000
@@ -370,6 +370,12 @@ default_stabs_argument_has_addr (struct
return 0;
}
+int
+default_at_function_start (CORE_ADDR pc, CORE_ADDR func_start)
+{
+ return pc == func_start;
+}
+
\f
/* Functions to manipulate the endianness of the target. */
Index: arch-utils.h
===================================================================
RCS file: /cvs/src/src/gdb/arch-utils.h,v
retrieving revision 1.65
diff -u -p -r1.65 arch-utils.h
--- arch-utils.h 23 Nov 2003 21:32:42 -0000 1.65
+++ arch-utils.h 2 Dec 2003 03:52:39 -0000
@@ -142,6 +142,8 @@ extern void legacy_value_to_register (st
extern int default_stabs_argument_has_addr (struct gdbarch *gdbarch,
struct type *type);
+extern int default_at_function_start (CORE_ADDR pc, CORE_ADDR func_start);
+
/* For compatibility with older architectures, returns
(LEGACY_SIM_REGNO_IGNORE) when the register doesn't have a valid
name. */
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.122
diff -u -p -r1.122 infrun.c
--- infrun.c 25 Nov 2003 16:01:36 -0000 1.122
+++ infrun.c 2 Dec 2003 03:52:41 -0000
@@ -2472,7 +2472,7 @@ process_event_stop_test:
return;
}
- if (((stop_pc == ecs->stop_func_start /* Quick test */
+ if (((AT_FUNCTION_START (stop_pc, ecs->stop_func_start)
|| 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)
Index: alpha-osf1-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alpha-osf1-tdep.c,v
retrieving revision 1.16
diff -u -p -r1.16 alpha-osf1-tdep.c
--- alpha-osf1-tdep.c 27 Aug 2003 19:02:03 -0000 1.16
+++ alpha-osf1-tdep.c 2 Dec 2003 03:52:41 -0000
@@ -45,6 +45,47 @@ alpha_osf1_sigcontext_addr (struct frame
return (read_memory_integer (get_frame_base (frame), 8));
}
+static int
+alpha_osf1_at_function_start (CORE_ADDR pc, CORE_ADDR func_start)
+{
+ /* A function prologue typically starts with 2 instructions setting
+ up the GP. But the linker sometimes changes the jump address of
+ subroutine calls because it has determined that these 2 instructions
+ do not make any difference in the execution of the program. So it
+ has virtually optimized them out by changing the jump address
+ inside the function call to branch just after these 2 instructions.
+
+ As a consequence, the "effective" start address of a given function
+ can be either the first instruction of this function, or the third
+ instruction if the first two instructions are setting up the GP.
+
+ It is important to recognize these two cases during a "next" in
+ order to properly detect function calls that land into a prologueless
+ function which first two instructions have been shunted by the linker. */
+
+ if (pc == func_start)
+ return 1;
+
+ if (pc == func_start + 8)
+ {
+ unsigned int inst;
+
+ /* ldah $gp,n($t12) */
+ inst = alpha_read_insn (func_start);
+ if ((inst & 0xffff0000) != 0x27bb0000)
+ return 0;
+
+ /* lda $gp,n($gp) */
+ inst = alpha_read_insn (func_start + 4);
+ if ((inst & 0xffff0000) != 0x23bd0000)
+ return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
static void
alpha_osf1_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
@@ -59,6 +100,7 @@ alpha_osf1_init_abi (struct gdbarch_info
on multi-processor machines. We need to use software single stepping
instead. */
set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
+ set_gdbarch_at_function_start (gdbarch, alpha_osf1_at_function_start);
tdep->sigcontext_addr = alpha_osf1_sigcontext_addr;
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-02 4:26 [RFA] OSF/1 - "next" over prologueless function call Joel Brobecker
@ 2003-12-02 4:30 ` Daniel Jacobowitz
2003-12-02 6:06 ` Joel Brobecker
2003-12-02 6:35 ` Richard Henderson
2003-12-03 4:19 ` Andrew Cagney
2 siblings, 1 reply; 18+ messages in thread
From: Daniel Jacobowitz @ 2003-12-02 4:30 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Mon, Dec 01, 2003 at 08:26:46PM -0800, Joel Brobecker wrote:
>
> 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.
About the general principle, I'm unsure - I'd like to think a little
more or have someone else's opinion. But about the OSF/1 specific
target hook: no, this should be an Alpha-specific target hook instead.
The GNU tools perform this same optimization (and may do something
similar on MIPS soon).
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-02 4:30 ` Daniel Jacobowitz
@ 2003-12-02 6:06 ` Joel Brobecker
0 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2003-12-02 6:06 UTC (permalink / raw)
To: gdb-patches
> About the general principle, I'm unsure - I'd like to think a little
> more or have someone else's opinion. But about the OSF/1 specific
> target hook: no, this should be an Alpha-specific target hook instead.
> The GNU tools perform this same optimization (and may do something
> similar on MIPS soon).
Thanks.
I wasn't sure whether this was an OSF/1-only optimization, or an
optimization that might be used by other tools, so I stayed conservative
and chose to define it in alpha-osf1-tdep.c. The hook can be moved to
alpha-tdep.c instead, if the general principle is kept.
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-02 4:26 [RFA] OSF/1 - "next" over prologueless function call Joel Brobecker
2003-12-02 4:30 ` Daniel Jacobowitz
@ 2003-12-02 6:35 ` Richard Henderson
2003-12-02 7:21 ` Joel Brobecker
2003-12-02 13:55 ` Daniel Jacobowitz
2003-12-03 4:19 ` Andrew Cagney
2 siblings, 2 replies; 18+ messages in thread
From: Richard Henderson @ 2003-12-02 6:35 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Mon, Dec 01, 2003 at 08:26:46PM -0800, Joel Brobecker wrote:
> + if (pc == func_start)
> + return 1;
> +
> + if (pc == func_start + 8)
> + {
> + unsigned int inst;
> +
> + /* ldah $gp,n($t12) */
> + inst = alpha_read_insn (func_start);
> + if ((inst & 0xffff0000) != 0x27bb0000)
> + return 0;
> +
> + /* lda $gp,n($gp) */
> + inst = alpha_read_insn (func_start + 4);
> + if ((inst & 0xffff0000) != 0x23bd0000)
> + return 0;
Is there any chance we could get hold of the symbol associated with
this function start? On ELF detecting this condition can be
streamlined to
sym->st_other & STO_ALPHA_STD_GPLOAD == STO_ALPHA_STD_GPLOAD
or from bfd, elf_link_hash_entry.other, though I don't remember off
the top of my head how to get at the elf hash entry from asymbol.
And yes indeed, the gnu tools do this same optimization. Both at
compile time and link time.
r~
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-02 6:35 ` Richard Henderson
@ 2003-12-02 7:21 ` Joel Brobecker
2003-12-02 15:14 ` Daniel Jacobowitz
2003-12-02 13:55 ` Daniel Jacobowitz
1 sibling, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2003-12-02 7:21 UTC (permalink / raw)
To: Richard Henderson; +Cc: gdb-patches
> Is there any chance we could get hold of the symbol associated with
> this function start?
I don't know. I think that information is lost after we've read
in the symbol table. However...
> On ELF detecting this condition can be
> streamlined to
>
> sym->st_other & STO_ALPHA_STD_GPLOAD == STO_ALPHA_STD_GPLOAD
>
> or from bfd, elf_link_hash_entry.other, though I don't remember off
> the top of my head how to get at the elf hash entry from asymbol.
... I see some target-specific code uses a grab-bag field of the
minimal_symbol structure to store some target-specific information
(field "info"). I don't particularly fancy typeless fields like this,
but, just thinking aloud, we could add a new fields holding some flags
which would be defined in gdb in an manor independent of the target.
Also: OSF/1 uses ECOFF. Fortunately, the information seems to be there
too. If you look at a Procedure Descritptor Table Entry, one finds
that it has 2 fields named: "gp_prologue" (byte size of the gp
prologue), and "gp_used" (flag set if the procedure uses gp). I am
not completely clear about the exact significance of the first field,
but it's a promising start.
So that's indeed another approach that the maintainers can consider,
I would say.
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-02 7:21 ` Joel Brobecker
@ 2003-12-02 15:14 ` Daniel Jacobowitz
2003-12-03 1:54 ` Joel Brobecker
0 siblings, 1 reply; 18+ messages in thread
From: Daniel Jacobowitz @ 2003-12-02 15:14 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Richard Henderson, gdb-patches
On Mon, Dec 01, 2003 at 11:21:13PM -0800, Joel Brobecker wrote:
> > Is there any chance we could get hold of the symbol associated with
> > this function start?
>
> I don't know. I think that information is lost after we've read
> in the symbol table. However...
>
> > On ELF detecting this condition can be
> > streamlined to
> >
> > sym->st_other & STO_ALPHA_STD_GPLOAD == STO_ALPHA_STD_GPLOAD
> >
> > or from bfd, elf_link_hash_entry.other, though I don't remember off
> > the top of my head how to get at the elf hash entry from asymbol.
>
> ... I see some target-specific code uses a grab-bag field of the
> minimal_symbol structure to store some target-specific information
> (field "info"). I don't particularly fancy typeless fields like this,
> but, just thinking aloud, we could add a new fields holding some flags
> which would be defined in gdb in an manor independent of the target.
>
> Also: OSF/1 uses ECOFF. Fortunately, the information seems to be there
> too. If you look at a Procedure Descritptor Table Entry, one finds
> that it has 2 fields named: "gp_prologue" (byte size of the gp
> prologue), and "gp_used" (flag set if the procedure uses gp). I am
> not completely clear about the exact significance of the first field,
> but it's a promising start.
Is this descriptor easily accessible? I imagine that gp_prologue is
the byte offset into the function at which you'd jump if you're
bypassing the GP load. So it becomes pc == func_start || ECOFF and pc
== func_start + gp_prologue || ELF and something similar.
Avoiding parsing the code would make me a lot happier.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-02 15:14 ` Daniel Jacobowitz
@ 2003-12-03 1:54 ` Joel Brobecker
0 siblings, 0 replies; 18+ messages in thread
From: Joel Brobecker @ 2003-12-03 1:54 UTC (permalink / raw)
To: gdb-patches
> Is this descriptor easily accessible? I imagine that gp_prologue is
> the byte offset into the function at which you'd jump if you're
> bypassing the GP load. So it becomes pc == func_start || ECOFF and pc
> == func_start + gp_prologue || ELF and something similar.
>
> Avoiding parsing the code would make me a lot happier.
I think it is, although not easily yet (or rather, not in a
target-independent way). Here is how I understood the code:
First, we have mdebugread.c:parse_type(), case symbol type equal
to stEnd:
else if (sh->sc == scText &&
(top_stack->blocktype == stProc ||
top_stack->blocktype == stStaticProc))
{
[...]
/* Make up special symbol to contain procedure specific info */
s = new_symbol (MIPS_EFI_SYMBOL_NAME);
[...]
e = ((struct mips_extra_func_info *)
obstack_alloc (¤t_objfile->symbol_obstack,
sizeof (struct mips_extra_func_info)));
memset (e, 0, sizeof (struct mips_extra_func_info));
SYMBOL_VALUE (s) = (long) e;
[...]
add_symbol (s, top_stack->cur_block);
So for each procedure we encounter in the debugging data, we create
a virtual nested procedure with a special name, and the SYMBOL_VALUE
of this symbol is a struct mips_extra_func_info (the actual definition
for this type is achived via a #define in the tm file).
Then later on, when we convert psymtabs into symtabs, we call
mdebugread.c:parse_procedure(). For each procedure, this function
looks up the special symbol we created earlier, and then stuffes
the mips_extra_func_info data with the procedure descriptor:
static void
parse_procedure (PDR *pr, struct symtab *search_symtab,
struct partial_symtab *pst)
{
[...]
i = mylookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, LOC_CONST);
if (i)
{
e = (struct mips_extra_func_info *) SYMBOL_VALUE (i);
e->pdr = *pr;
And finally, I see some code in alpha-mdebug-tdep.c which uses that
symbol to dig this information out, given any PC:
static alpha_extra_func_info_t find_proc_desc (CORE_ADDR pc);
I did check with a few trivial examples the value of the gp_prologue
gd_used fields, and it "checks". gp_used is indeed set when the function
starts with the two gp load instructions, and gp_prologue is then equal
to 8. Otherwise, it is set to 0.
If you prefer to use this data rather than relying on code parsing
(which we already do for skip_prologue, btw), using this data seems
to promising. The question then becomes: how will we make this available
in a general (non-target-specific) form? Should we add an extra data
field in struct symbol for instance (I already hear some people
screaming :-)?
You may also see that we have a little hack in objfiles.c:
#ifdef MIPS_EFI_SYMBOL_NAME
/* Relocate Extra Function Info for ecoff. */
else if (SYMBOL_CLASS (sym) == LOC_CONST
&& SYMBOL_DOMAIN (sym) == LABEL_DOMAIN
&& strcmp (DEPRECATED_SYMBOL_NAME (sym), MIPS_EFI_SYMBOL_NAME) == 0)
ecoff_relocate_efi (sym, ANOFFSET (delta, s->block_line_section));
#endif
But I don't think we want to pollute more GDB code with this sort
of hack :)
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-02 6:35 ` Richard Henderson
2003-12-02 7:21 ` Joel Brobecker
@ 2003-12-02 13:55 ` Daniel Jacobowitz
1 sibling, 0 replies; 18+ messages in thread
From: Daniel Jacobowitz @ 2003-12-02 13:55 UTC (permalink / raw)
To: Richard Henderson; +Cc: Joel Brobecker, gdb-patches
On Mon, Dec 01, 2003 at 10:35:32PM -0800, Richard Henderson wrote:
> On Mon, Dec 01, 2003 at 08:26:46PM -0800, Joel Brobecker wrote:
> > + if (pc == func_start)
> > + return 1;
> > +
> > + if (pc == func_start + 8)
> > + {
> > + unsigned int inst;
> > +
> > + /* ldah $gp,n($t12) */
> > + inst = alpha_read_insn (func_start);
> > + if ((inst & 0xffff0000) != 0x27bb0000)
> > + return 0;
> > +
> > + /* lda $gp,n($gp) */
> > + inst = alpha_read_insn (func_start + 4);
> > + if ((inst & 0xffff0000) != 0x23bd0000)
> > + return 0;
>
> Is there any chance we could get hold of the symbol associated with
> this function start? On ELF detecting this condition can be
> streamlined to
>
> sym->st_other & STO_ALPHA_STD_GPLOAD == STO_ALPHA_STD_GPLOAD
>
> or from bfd, elf_link_hash_entry.other, though I don't remember off
> the top of my head how to get at the elf hash entry from asymbol.
I don't think you can. They're not added to a link hash table unless
you're actually linking.
It looks like there's no way to go from the asymbol to the ELF symbol
either, and st_other isn't stashed anywhere.
> And yes indeed, the gnu tools do this same optimization. Both at
> compile time and link time.
>
>
> r~
>
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-02 4:26 [RFA] OSF/1 - "next" over prologueless function call Joel Brobecker
2003-12-02 4:30 ` Daniel Jacobowitz
2003-12-02 6:35 ` Richard Henderson
@ 2003-12-03 4:19 ` Andrew Cagney
2003-12-04 0:55 ` Joel Brobecker
2 siblings, 1 reply; 18+ messages in thread
From: Andrew Cagney @ 2003-12-03 4:19 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
> 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)
>
See my recent comments further down in that file. I think GDB should be
using:
frame_id_unwind(current_frame) == frame_id_from_before_stepi
to determine if it did a step into a function. What happens if that is
used?
Andrew
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-03 4:19 ` Andrew Cagney
@ 2003-12-04 0:55 ` Joel Brobecker
2003-12-04 1:49 ` Andrew Cagney
0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2003-12-04 0:55 UTC (permalink / raw)
To: Andrew Cagney; +Cc: gdb-patches
> See my recent comments further down in that file. I think GDB should be
> using:
>
> frame_id_unwind(current_frame) == frame_id_from_before_stepi
>
> to determine if it did a step into a function. What happens if that is
> used?
Sounds like a good idea, almost obvious actually :-). I tried the
following change on osf1 and x86-linux without any regression, and it
does solve the problem on osf1.
However, I tried it on sparc-solaris with the gdb-6.0 sources because
I knew this target hasn't transitioned to the new frame framework.
It doesn't look like GDB is liking this change there (I've got a lot of
timeouts in call-ar-st). I am currently retrying on the head right now,
hoping the testsuite completes in a reasonable amount of time.
--- infrun.c 25 Nov 2003 16:01:36 -0000 1.122
+++ infrun.c 3 Dec 2003 19:24:07 -0000
@@ -2473,6 +2473,8 @@ process_event_stop_test:
}
if (((stop_pc == ecs->stop_func_start /* Quick test */
+ || frame_id_eq (get_frame_id (get_prev_frame (get_current_frame ())),
+ step_frame_id)
|| 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)
Stay tuned.
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-04 0:55 ` Joel Brobecker
@ 2003-12-04 1:49 ` Andrew Cagney
2003-12-04 23:24 ` Joel Brobecker
0 siblings, 1 reply; 18+ messages in thread
From: Andrew Cagney @ 2003-12-04 1:49 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>> See my recent comments further down in that file. I think GDB should be
>> using:
>>
>> frame_id_unwind(current_frame) == frame_id_from_before_stepi
>>
>> to determine if it did a step into a function. What happens if that is
>> used?
>
>
> Sounds like a good idea, almost obvious actually :-). I tried the
> following change on osf1 and x86-linux without any regression, and it
> does solve the problem on osf1.
(only took 15 years to realise how "obvious" it was :-)
> However, I tried it on sparc-solaris with the gdb-6.0 sources because
> I knew this target hasn't transitioned to the new frame framework.
> It doesn't look like GDB is liking this change there (I've got a lot of
> timeouts in call-ar-st). I am currently retrying on the head right now,
> hoping the testsuite completes in a reasonable amount of time.
>
>
> --- infrun.c 25 Nov 2003 16:01:36 -0000 1.122
> +++ infrun.c 3 Dec 2003 19:24:07 -0000
> @@ -2473,6 +2473,8 @@ process_event_stop_test:
> }
>
> if (((stop_pc == ecs->stop_func_start /* Quick test */
> + || frame_id_eq (get_frame_id (get_prev_frame (get_current_frame ())),
> + step_frame_id)
> || 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)
>
>
> Stay tuned.
You can use legacy_frame_p for differentiating old and new code.
Hmm, is "stop_pc == ecs->stop_func_start" a valid test, what happens if
the program is at 1: and there's a next?
foo:
...
1: goto foo
Hmm, is in_prologue() adding value when frame_id always works? Unless
it's being used to handle stepping through a prologue?
Andrew
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-04 1:49 ` Andrew Cagney
@ 2003-12-04 23:24 ` Joel Brobecker
2003-12-04 23:28 ` Daniel Jacobowitz
2003-12-05 20:19 ` Andrew Cagney
0 siblings, 2 replies; 18+ messages in thread
From: Joel Brobecker @ 2003-12-04 23:24 UTC (permalink / raw)
To: Andrew Cagney; +Cc: gdb-patches
> (only took 15 years to realise how "obvious" it was :-)
Right. It's only "obvious" because the we now have a frame ID which
particularity is to be unique... Given how long it must have taken to
"invent the wheel", maybe we didn't do too bad :-).
> >However, I tried it on sparc-solaris with the gdb-6.0 sources because
> >I knew this target hasn't transitioned to the new frame framework.
> >It doesn't look like GDB is liking this change there (I've got a lot of
> >timeouts in call-ar-st). I am currently retrying on the head right now,
> >hoping the testsuite completes in a reasonable amount of time.
I redid the testing this time using the head, and found no new
regression introduced by this change [1].
> >--- infrun.c 25 Nov 2003 16:01:36 -0000 1.122
> >+++ infrun.c 3 Dec 2003 19:24:07 -0000
> >@@ -2473,6 +2473,8 @@ process_event_stop_test:
> > }
> >
> > if (((stop_pc == ecs->stop_func_start /* Quick test */
> >+ || frame_id_eq (get_frame_id (get_prev_frame (get_current_frame
> >())),
> >+ step_frame_id)
> > || 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)
> You can use legacy_frame_p for differentiating old and new code.
Yes. Despite the relative success on sparc-solaris (no new regression),
I wasn't sure whether this wasn't potentially introducing new problems
on the architectures where the legacy frames are still used. So I added
it to the condition.
That gives us a pretty horrible condition, something like that:
if (((stop_pc == ecs->stop_func_start /* Quick test */
|| (!legacy_frame_pd (current_gdbarch)
&& frame_id_eq
(get_frame_id (get_prev_frame (get_current_frame ())),
step_frame_id))
|| 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)
How about we move this into a function?
My current version only replaces the condition I added by:
|| frame_in_procedure_called_during_step ()
So the condition stay relatively readable (not too many levels in terms
of nesting). But maybe it's time to turn the entire condition into a
function and add more comments.
Something like this?
static int
inside_function_called_from_step (CORE_ADDR stop_pc,
CORE_ADDR stop_func_start)
{
/* If bla bla bla */
if (stop_pc == stop_func_start
&& !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
return 1;
/* If the frame ID of the previous frame is equal to step_frame_id,
then this function was indeed called during a step. Only rely
on this test if we don't use the legacy frames. */
if (!legacy_frame_p (current_gdbarch)
&& frame_id_eq (...)
&& !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
return 1;
/* cagney/2003-12-04: Do we really need this, now that we check the
previous frame id? */
if (in_prologue (stop_pc, ecs->stop_func_start))
&& !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
return 1;
/* Don't stop stepping inside a solib call trampoline. */
if (IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name))
return 1;
/* Hmmm, continue stepping if we don't know anything about where
we landed. */
if (stop_func_name == 0)
return 1;
return 0;
}
The trouble is that this change is not completly mechanical. And
we also end up repeating the "!IN_SOLIB_CALL_TRAMPOLINE" test.
We can also coalesce the first 3 tests into one if, but then
we lose a bit the advantage of using a function.
Anyway, it's more a matter of style, so I will defer to the preference
of the maintainers, and send a patch along these lines. If we decide
to move the entire condition into a new function, I can send 2 patches:
One that moves the current condition, and then another that fixes
the osf1 problem.
> Hmm, is "stop_pc == ecs->stop_func_start" a valid test, what happens if
> the program is at 1: and there's a next?
>
> foo:
> ...
> 1: goto foo
Unless the function is completely prologueless, all should be well
because the goto will branch at a location past the first instruction.
If the function is prologueless, however... I think this would be a rare
occurrence.
> Hmm, is in_prologue() adding value when frame_id always works? Unless
> it's being used to handle stepping through a prologue?
Not sure about the real intent of in_prologue(). I know it saved us
most of the time in the osf/1 case, but was it the primary intent
when this condition was added? I think that once we have answered
this question, we will be able to decide whether or not this condition
can be removed.
I also realize that I may not have been clear about the usage of
legacy_frame_p. I am a bit nervous at doing without, but you may be
more confident than me, since I don't have much knowledge of the new
frame architecture yet. So the choice of using it or not is still open.
Thanks,
--
Joel
[1]: There was one glitch that occurred during the testing, though.
Even before I applied any change, the structs.exp test keeps
timeouting. I tried letting it complete, but had to stop it
after an entire night of timeouts. So I did my testing after
having deactivated this test.
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-04 23:24 ` Joel Brobecker
@ 2003-12-04 23:28 ` Daniel Jacobowitz
2003-12-05 20:19 ` Andrew Cagney
1 sibling, 0 replies; 18+ messages in thread
From: Daniel Jacobowitz @ 2003-12-04 23:28 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Andrew Cagney, gdb-patches
On Thu, Dec 04, 2003 at 03:24:10PM -0800, Joel Brobecker wrote:
> Anyway, it's more a matter of style, so I will defer to the preference
> of the maintainers, and send a patch along these lines. If we decide
> to move the entire condition into a new function, I can send 2 patches:
> One that moves the current condition, and then another that fixes
> the osf1 problem.
Personally, I think this sounds great.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-04 23:24 ` Joel Brobecker
2003-12-04 23:28 ` Daniel Jacobowitz
@ 2003-12-05 20:19 ` Andrew Cagney
2003-12-08 23:25 ` Joel Brobecker
1 sibling, 1 reply; 18+ messages in thread
From: Andrew Cagney @ 2003-12-05 20:19 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 5495 bytes --]
> (only took 15 years to realise how "obvious" it was :-)
>
>
> Right. It's only "obvious" because the we now have a frame ID which
> particularity is to be unique... Given how long it must have taken to
> "invent the wheel", maybe we didn't do too bad :-).
See the comments in the attached ...
>> You can use legacy_frame_p for differentiating old and new code.
>
>
> Yes. Despite the relative success on sparc-solaris (no new regression),
> I wasn't sure whether this wasn't potentially introducing new problems
> on the architectures where the legacy frames are still used. So I added
> it to the condition.
>
> That gives us a pretty horrible condition, something like that:
>
> if (((stop_pc == ecs->stop_func_start /* Quick test */
> || (!legacy_frame_pd (current_gdbarch)
> && frame_id_eq
> (get_frame_id (get_prev_frame (get_current_frame ())),
> step_frame_id))
> || 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)
>
> How about we move this into a function?
There are several things we could move to a function ....
> My current version only replaces the condition I added by:
>
> || frame_in_procedure_called_during_step ()
>
> So the condition stay relatively readable (not too many levels in terms
> of nesting). But maybe it's time to turn the entire condition into a
> function and add more comments.
>
> Something like this?
>
> static int
> inside_function_called_from_step (CORE_ADDR stop_pc,
> CORE_ADDR stop_func_start)
> {
> /* If bla bla bla */
> if (stop_pc == stop_func_start
> && !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
> return 1;
>
> /* If the frame ID of the previous frame is equal to step_frame_id,
> then this function was indeed called during a step. Only rely
> on this test if we don't use the legacy frames. */
> if (!legacy_frame_p (current_gdbarch)
> && frame_id_eq (...)
> && !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
> return 1;
>
> /* cagney/2003-12-04: Do we really need this, now that we check the
> previous frame id? */
> if (in_prologue (stop_pc, ecs->stop_func_start))
> && !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, stop_func_name))
> return 1;
>
> /* Don't stop stepping inside a solib call trampoline. */
> if (IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name))
> return 1;
>
> /* Hmmm, continue stepping if we don't know anything about where
> we landed. */
> if (stop_func_name == 0)
> return 1;
>
> return 0;
> }
>
> The trouble is that this change is not completly mechanical. And
> we also end up repeating the "!IN_SOLIB_CALL_TRAMPOLINE" test.
> We can also coalesce the first 3 tests into one if, but then
> we lose a bit the advantage of using a function.
There's always plan B.
Looking at the body of that IF, I believe it always returns. That
should let us do:
if (legacy_frame_p ())
if (all the existing tests)
call a function to do the body of work ()
return;
else if (our new improved test)
call a function to do the body of work ()
return;
that way the legacy and non legacy cases are clearly split - we're free
to refine the new conditional with out worrying about breaking the old
code. However ....
(Oh, what exactly is that body of code doing - any ideas?)
> Anyway, it's more a matter of style, so I will defer to the preference
> of the maintainers, and send a patch along these lines. If we decide
> to move the entire condition into a new function, I can send 2 patches:
> One that moves the current condition, and then another that fixes
> the osf1 problem.
>
>
>> Hmm, is "stop_pc == ecs->stop_func_start" a valid test, what happens if
>> the program is at 1: and there's a next?
>>
>> foo:
>> ...
>> 1: goto foo
>
>
> Unless the function is completely prologueless, all should be well
> because the goto will branch at a location past the first instruction.
> If the function is prologueless, however... I think this would be a rare
> occurrence.
I'm not so sure :-( In fact any lack of such code suggests a GCC
optimizer bug :-)
>> Hmm, is in_prologue() adding value when frame_id always works? Unless
>> it's being used to handle stepping through a prologue?
>
>
> Not sure about the real intent of in_prologue(). I know it saved us
> most of the time in the osf/1 case, but was it the primary intent
> when this condition was added? I think that once we have answered
> this question, we will be able to decide whether or not this condition
> can be removed.
... valid point.
Staring at that code its doing so many things its depressing:
- step into function
- step over function
- step out of function
- step over trampoline
but the basic intent was possibly step into a function and then skip
over its prologue?
So I'm guessing for the moment just replace
stop_pc == ecs->stop_func_start
with the frame id test in the new code?
:-(
> I also realize that I may not have been clear about the usage of
> legacy_frame_p. I am a bit nervous at doing without, but you may be
> more confident than me, since I don't have much knowledge of the new
> frame architecture yet. So the choice of using it or not is still open.
Andrew
[-- Attachment #2: x --]
[-- Type: text/plain, Size: 13167 bytes --]
1.155 (grossman 24-Oct-95): #if 0
1.155 (grossman 24-Oct-95): /* I disabled this test because it was too complicated and slow. The
1.155 (grossman 24-Oct-95): SKIP_PROLOGUE was especially slow, because it caused unnecessary
1.155 (grossman 24-Oct-95): prologue examination on various architectures. The code in the #else
1.155 (grossman 24-Oct-95): clause has been tested on the Sparc, Mips, PA, and Power
1.155 (grossman 24-Oct-95): architectures, so it's pretty likely to be correct. -Stu 10/24/95 */
1.155 (grossman 24-Oct-95):
1.137 (kingdon 08-Oct-94): /* See if we left the step range due to a subroutine call that
1.137 (kingdon 08-Oct-94): we should proceed to the end of. */
1.137 (kingdon 08-Oct-94):
1.80 (kingdon 11-Jul-93): if (stop_func_start)
1.80 (kingdon 11-Jul-93): {
1.130 (grossman 02-Jun-94): struct symtab *s;
1.130 (grossman 02-Jun-94):
1.80 (kingdon 11-Jul-93): /* Do this after the IN_SIGTRAMP check; it might give
1.80 (kingdon 11-Jul-93): an error. */
1.80 (kingdon 11-Jul-93): prologue_pc = stop_func_start;
1.130 (grossman 02-Jun-94):
1.130 (grossman 02-Jun-94): /* Don't skip the prologue if this is assembly source */
1.130 (grossman 02-Jun-94): s = find_pc_symtab (stop_pc);
1.130 (grossman 02-Jun-94): if (s && s->language != language_asm)
1.130 (grossman 02-Jun-94): SKIP_PROLOGUE (prologue_pc);
1.80 (kingdon 11-Jul-93): }
1.1 (rich 28-Mar-91):
1.101 (kingdon 17-Oct-93): if ((/* Might be a non-recursive call. If the symbols are missing
1.101 (kingdon 17-Oct-93): enough that stop_func_start == prev_func_start even though
1.101 (kingdon 17-Oct-93): they are really two functions, we will treat some calls as
1.101 (kingdon 17-Oct-93): jumps. */
1.101 (kingdon 17-Oct-93): stop_func_start != prev_func_start
1.101 (kingdon 17-Oct-93):
1.101 (kingdon 17-Oct-93): /* Might be a recursive call if either we have a prologue
1.101 (kingdon 17-Oct-93): or the call instruction itself saves the PC on the stack. */
1.101 (kingdon 17-Oct-93): || prologue_pc != stop_func_start
1.137 (kingdon 08-Oct-94): || read_sp () != step_sp)
1.105 (grossman 26-Oct-93): && (/* PC is completely out of bounds of any known objfiles. Treat
1.105 (grossman 26-Oct-93): like a subroutine call. */
1.105 (grossman 26-Oct-93): ! stop_func_start
1.101 (kingdon 17-Oct-93):
1.110 (kingdon 30-Dec-93): /* If we do a call, we will be at the start of a function... */
1.101 (kingdon 17-Oct-93): || stop_pc == stop_func_start
1.37 (bothner 01-Mar-92):
1.110 (kingdon 30-Dec-93): /* ...except on the Alpha with -O (and also Irix 5 and
1.110 (kingdon 30-Dec-93): perhaps others), in which we might call the address
1.110 (kingdon 30-Dec-93): after the load of gp. Since prologues don't contain
1.110 (kingdon 30-Dec-93): calls, we can't return to within one, and we don't
1.110 (kingdon 30-Dec-93): jump back into them, so this check is OK. */
1.110 (kingdon 30-Dec-93):
1.101 (kingdon 17-Oct-93): || stop_pc < prologue_pc
1.101 (kingdon 17-Oct-93):
1.134 (schauer 15-Jul-94): /* ...and if it is a leaf function, the prologue might
1.134 (schauer 15-Jul-94): consist of gp loading only, so the call transfers to
1.134 (schauer 15-Jul-94): the first instruction after the prologue. */
1.134 (schauer 15-Jul-94): || (stop_pc == prologue_pc
1.134 (schauer 15-Jul-94):
1.134 (schauer 15-Jul-94): /* Distinguish this from the case where we jump back
1.134 (schauer 15-Jul-94): to the first instruction after the prologue,
1.134 (schauer 15-Jul-94): within a function. */
1.134 (schauer 15-Jul-94): && stop_func_start != prev_func_start)
1.134 (schauer 15-Jul-94):
1.101 (kingdon 17-Oct-93): /* If we end up in certain places, it means we did a subroutine
1.101 (kingdon 17-Oct-93): call. I'm not completely sure this is necessary now that we
1.101 (kingdon 17-Oct-93): have the above checks with stop_func_start (and now that
1.102 (kingdon 17-Oct-93): find_pc_partial_function is pickier). */
1.140 (law 24-Nov-94): || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
1.101 (kingdon 17-Oct-93):
1.101 (kingdon 17-Oct-93): /* If none of the above apply, it is a jump within a function,
1.101 (kingdon 17-Oct-93): or a return from a subroutine. The other case is longjmp,
1.101 (kingdon 17-Oct-93): which can no longer happen here as long as the
1.101 (kingdon 17-Oct-93): handling_longjmp stuff is working. */
1.101 (kingdon 17-Oct-93): ))
1.130 (grossman 02-Jun-94): #else
1.130 (grossman 02-Jun-94): /* This is experimental code which greatly simplifies the subroutine call
1.130 (grossman 02-Jun-94): test. I've actually tested on the Alpha, and it works great. -Stu */
1.130 (grossman 02-Jun-94):
1.155 (grossman 24-Oct-95): if (stop_pc == stop_func_start /* Quick test */
1.155 (grossman 24-Oct-95): || in_prologue (stop_pc, stop_func_start)
1.155 (grossman 24-Oct-95): || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
1.155 (grossman 24-Oct-95): || stop_func_start == 0)
1.130 (grossman 02-Jun-94): #endif
1.155 (grossman 24-Oct-95):
1.80 (kingdon 11-Jul-93): {
1.80 (kingdon 11-Jul-93): /* It's a subroutine call. */
1.34 (grossman 22-Feb-92):
1.80 (kingdon 11-Jul-93): if (step_over_calls == 0)
1.80 (kingdon 11-Jul-93): {
1.80 (kingdon 11-Jul-93): /* I presume that step_over_calls is only 0 when we're
1.80 (kingdon 11-Jul-93): supposed to be stepping at the assembly language level
1.80 (kingdon 11-Jul-93): ("stepi"). Just stop. */
1.80 (kingdon 11-Jul-93): stop_step = 1;
1.80 (kingdon 11-Jul-93): break;
1.80 (kingdon 11-Jul-93): }
1.37 (bothner 01-Mar-92):
1.80 (kingdon 11-Jul-93): if (step_over_calls > 0)
1.80 (kingdon 11-Jul-93): /* We're doing a "next". */
1.80 (kingdon 11-Jul-93): goto step_over_function;
1.80 (kingdon 11-Jul-93):
1.80 (kingdon 11-Jul-93): /* If we are in a function call trampoline (a stub between
1.80 (kingdon 11-Jul-93): the calling routine and the real function), locate the real
1.80 (kingdon 11-Jul-93): function. That's what tells us (a) whether we want to step
1.80 (kingdon 11-Jul-93): into it at all, and (b) what prologue we want to run to
1.80 (kingdon 11-Jul-93): the end of, if we do step into it. */
1.80 (kingdon 11-Jul-93): tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
1.80 (kingdon 11-Jul-93): if (tmp != 0)
1.80 (kingdon 11-Jul-93): stop_func_start = tmp;
1.80 (kingdon 11-Jul-93):
1.80 (kingdon 11-Jul-93): /* If we have line number information for the function we
1.80 (kingdon 11-Jul-93): are thinking of stepping into, step into it.
1.80 (kingdon 11-Jul-93):
1.80 (kingdon 11-Jul-93): If there are several symtabs at that PC (e.g. with include
1.80 (kingdon 11-Jul-93): files), just want to know whether *any* of them have line
1.80 (kingdon 11-Jul-93): numbers. find_pc_line handles this. */
1.80 (kingdon 11-Jul-93): {
1.80 (kingdon 11-Jul-93): struct symtab_and_line tmp_sal;
1.77 (kingdon 29-Jun-93):
1.80 (kingdon 11-Jul-93): tmp_sal = find_pc_line (stop_func_start, 0);
1.80 (kingdon 11-Jul-93): if (tmp_sal.line != 0)
1.80 (kingdon 11-Jul-93): goto step_into_function;
1.80 (kingdon 11-Jul-93): }
1.77 (kingdon 29-Jun-93):
1.37 (bothner 01-Mar-92): step_over_function:
1.80 (kingdon 11-Jul-93): /* A subroutine call has happened. */
1.80 (kingdon 11-Jul-93): {
1.80 (kingdon 11-Jul-93): /* Set a special breakpoint after the return */
1.80 (kingdon 11-Jul-93): struct symtab_and_line sr_sal;
1.80 (kingdon 11-Jul-93): sr_sal.pc =
1.80 (kingdon 11-Jul-93): ADDR_BITS_REMOVE
1.80 (kingdon 11-Jul-93): (SAVED_PC_AFTER_CALL (get_current_frame ()));
1.80 (kingdon 11-Jul-93): sr_sal.symtab = NULL;
1.80 (kingdon 11-Jul-93): sr_sal.line = 0;
1.80 (kingdon 11-Jul-93): step_resume_breakpoint =
1.80 (kingdon 11-Jul-93): set_momentary_breakpoint (sr_sal, get_current_frame (),
1.80 (kingdon 11-Jul-93): bp_step_resume);
1.137 (kingdon 08-Oct-94): step_resume_breakpoint->frame = step_frame_address;
1.80 (kingdon 11-Jul-93): if (breakpoints_inserted)
1.80 (kingdon 11-Jul-93): insert_breakpoints ();
1.80 (kingdon 11-Jul-93): }
1.80 (kingdon 11-Jul-93): goto keep_going;
1.34 (grossman 22-Feb-92):
1.37 (bothner 01-Mar-92): step_into_function:
1.80 (kingdon 11-Jul-93): /* Subroutine call with source code we should not step over.
1.80 (kingdon 11-Jul-93): Do step to the first line of code in it. */
1.130 (grossman 02-Jun-94): {
1.130 (grossman 02-Jun-94): struct symtab *s;
1.130 (grossman 02-Jun-94):
1.130 (grossman 02-Jun-94): s = find_pc_symtab (stop_pc);
1.130 (grossman 02-Jun-94): if (s && s->language != language_asm)
1.130 (grossman 02-Jun-94): SKIP_PROLOGUE (stop_func_start);
1.130 (grossman 02-Jun-94): }
1.80 (kingdon 11-Jul-93): sal = find_pc_line (stop_func_start, 0);
1.80 (kingdon 11-Jul-93): /* Use the step_resume_break to step until
1.80 (kingdon 11-Jul-93): the end of the prologue, even if that involves jumps
1.80 (kingdon 11-Jul-93): (as it seems to on the vax under 4.2). */
1.80 (kingdon 11-Jul-93): /* If the prologue ends in the middle of a source line,
1.111 (schauer 01-Jan-94): continue to the end of that source line (if it is still
1.111 (schauer 01-Jan-94): within the function). Otherwise, just go to end of prologue. */
1.1 (rich 28-Mar-91): #ifdef PROLOGUE_FIRSTLINE_OVERLAP
1.80 (kingdon 11-Jul-93): /* no, don't either. It skips any code that's
1.80 (kingdon 11-Jul-93): legitimately on the first line. */
1.1 (rich 28-Mar-91): #else
1.111 (schauer 01-Jan-94): if (sal.end && sal.pc != stop_func_start && sal.end < stop_func_end)
1.80 (kingdon 11-Jul-93): stop_func_start = sal.end;
1.1 (rich 28-Mar-91): #endif
1.37 (bothner 01-Mar-92):
1.80 (kingdon 11-Jul-93): if (stop_func_start == stop_pc)
1.80 (kingdon 11-Jul-93): {
1.80 (kingdon 11-Jul-93): /* We are already there: stop now. */
1.80 (kingdon 11-Jul-93): stop_step = 1;
1.80 (kingdon 11-Jul-93): break;
1.80 (kingdon 11-Jul-93): }
1.80 (kingdon 11-Jul-93): else
1.80 (kingdon 11-Jul-93): /* Put the step-breakpoint there and go until there. */
1.80 (kingdon 11-Jul-93): {
1.80 (kingdon 11-Jul-93): struct symtab_and_line sr_sal;
1.80 (kingdon 11-Jul-93):
1.80 (kingdon 11-Jul-93): sr_sal.pc = stop_func_start;
1.80 (kingdon 11-Jul-93): sr_sal.symtab = NULL;
1.80 (kingdon 11-Jul-93): sr_sal.line = 0;
1.80 (kingdon 11-Jul-93): /* Do not specify what the fp should be when we stop
1.80 (kingdon 11-Jul-93): since on some machines the prologue
1.80 (kingdon 11-Jul-93): is where the new fp value is established. */
1.80 (kingdon 11-Jul-93): step_resume_breakpoint =
1.89 (kingdon 18-Sep-93): set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
1.80 (kingdon 11-Jul-93): if (breakpoints_inserted)
1.80 (kingdon 11-Jul-93): insert_breakpoints ();
1.80 (kingdon 11-Jul-93):
1.80 (kingdon 11-Jul-93): /* And make sure stepping stops right away then. */
1.80 (kingdon 11-Jul-93): step_range_end = step_range_start;
1.1 (rich 28-Mar-91): }
1.80 (kingdon 11-Jul-93): goto keep_going;
1.80 (kingdon 11-Jul-93): }
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-05 20:19 ` Andrew Cagney
@ 2003-12-08 23:25 ` Joel Brobecker
2003-12-09 23:10 ` Andrew Cagney
0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2003-12-08 23:25 UTC (permalink / raw)
To: Andrew Cagney; +Cc: gdb-patches
Sorry for the delay in my answers. I am traveling again now, and
will be on and off until next week.
> There's always plan B.
>
> Looking at the body of that IF, I believe it always returns. That
> should let us do:
>
> if (legacy_frame_p ())
> if (all the existing tests)
> call a function to do the body of work ()
> return;
> else if (our new improved test)
> call a function to do the body of work ()
> return;
>
> that way the legacy and non legacy cases are clearly split - we're free
> to refine the new conditional with out worrying about breaking the old
> code. However ....
We might have to take that route, because I rechecked on Solaris, and I
forgot (yes, I forgot) to make the change there before I reran the test,
so of course there were no regressions. I feel very embarrassed.
> So I'm guessing for the moment just replace
> stop_pc == ecs->stop_func_start
> with the frame id test in the new code?
That works with x86-linux and alpha-tru64, but unfortunately breaks
on sparc-solaris. Maybe something minor, but the call-ar-st starts
timeouting and takes forever to complete after that change.
So I think we should follow your suggestion above and separate
completely the two conditions, conditionalized by legacy_frame_p().
The function name we could use, at least for now, could be
handle_subroutine_call() or handle_step_into_function().
It seems that the correct test when legacy_frame_p() is nonzero
would only be the frame ID equality test, but I must admit being
nervous again not knowing how reliable the new frame implementations
are... Despite the fact that the current heuristics (check if PC ==
address of function first instruction or is inside function prologue)
doesn't cover 100% of the cases, it was still a simple, platform
independent, solid test that worked in most cases. We are about to
replace that by something that's a bit more complex and might cause some
unexpected behavior if the unwinder fails to unwind properly (imagine
for instance that the unwinder skipped one frame).
I am really torn, so I am relying on you who has had a closer look at
the frame implementations that have been converted so far. If it was
just me, I would be very conservative and simply add and extra
|| (legacy_frame_p() && frame_id_eq (...))
It only fixes one problem, but the changes of introducing another is
smaller. I am a coward :-).
--
Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
2003-12-08 23:25 ` Joel Brobecker
@ 2003-12-09 23:10 ` Andrew Cagney
0 siblings, 0 replies; 18+ messages in thread
From: Andrew Cagney @ 2003-12-09 23:10 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
> So I think we should follow your suggestion above and separate
> completely the two conditions, conditionalized by legacy_frame_p().
> The function name we could use, at least for now, could be
> handle_subroutine_call() or handle_step_into_function().
>
> It seems that the correct test when legacy_frame_p() is nonzero
> would only be the frame ID equality test, but I must admit being
> nervous again not knowing how reliable the new frame implementations
> are... Despite the fact that the current heuristics (check if PC ==
> address of function first instruction or is inside function prologue)
> doesn't cover 100% of the cases, it was still a simple, platform
> independent, solid test that worked in most cases. We are about to
> replace that by something that's a bit more complex and might cause some
> unexpected behavior if the unwinder fails to unwind properly (imagine
> for instance that the unwinder skipped one frame).
The new frame code is reliable. If it wasn't many other areas of the
testsuite will fail. I'm ok with the change going in with the new
handle_step_into_function().
Andrew
> I am really torn, so I am relying on you who has had a closer look at
> the frame implementations that have been converted so far. If it was
> just me, I would be very conservative and simply add and extra
>
> || (legacy_frame_p() && frame_id_eq (...))
>
> It only fixes one problem, but the changes of introducing another is
> smaller. I am a coward :-).
>
> -- Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
@ 2003-12-02 5:49 Michael Elizabeth Chastain
0 siblings, 0 replies; 18+ messages in thread
From: Michael Elizabeth Chastain @ 2003-12-02 5:49 UTC (permalink / raw)
To: brobecker, drow; +Cc: gdb-patches
drow> But about the OSF/1 specific target hook: no, this should be an
drow> Alpha-specific target hook instead.
I agree with Daniel here.
I have little expertise on 64-bit architectures, but I expect
this would be a common optimization for architectures where
there is a $gp or similar register which needs to be loaded
at the beginning of each function, and a linker can figure out
that $gp has the same value across many different functions.
Michael C
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFA] OSF/1 - "next" over prologueless function call
@ 2003-12-02 7:53 Michael Elizabeth Chastain
0 siblings, 0 replies; 18+ messages in thread
From: Michael Elizabeth Chastain @ 2003-12-02 7:53 UTC (permalink / raw)
To: brobecker, ezannoni, rth; +Cc: gdb-patches
Hi Joel,
> ... I see some target-specific code uses a grab-bag field of the
> minimal_symbol structure to store some target-specific information
> (field "info"). I don't particularly fancy typeless fields like this,
> but, just thinking aloud, we could add a new fields holding some flags
> which would be defined in gdb in an manor independent of the target.
I would like to clean up the "info" field.
The only thing it's used for is these target-specific bit flags.
It's really stupid that it's a "void *"!
http://sources.redhat.com/ml/gdb/2003-11/msg00094.html
When I get some more cycles, and Elena gets some more cycles,
I'll bring it up for discussion again.
Michael C
too tired to work, not too tired to blabber
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2003-12-09 23:10 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-12-02 4:26 [RFA] OSF/1 - "next" over prologueless function call Joel Brobecker
2003-12-02 4:30 ` Daniel Jacobowitz
2003-12-02 6:06 ` Joel Brobecker
2003-12-02 6:35 ` Richard Henderson
2003-12-02 7:21 ` Joel Brobecker
2003-12-02 15:14 ` Daniel Jacobowitz
2003-12-03 1:54 ` Joel Brobecker
2003-12-02 13:55 ` Daniel Jacobowitz
2003-12-03 4:19 ` Andrew Cagney
2003-12-04 0:55 ` Joel Brobecker
2003-12-04 1:49 ` Andrew Cagney
2003-12-04 23:24 ` Joel Brobecker
2003-12-04 23:28 ` Daniel Jacobowitz
2003-12-05 20:19 ` Andrew Cagney
2003-12-08 23:25 ` Joel Brobecker
2003-12-09 23:10 ` Andrew Cagney
2003-12-02 5:49 Michael Elizabeth Chastain
2003-12-02 7:53 Michael Elizabeth Chastain
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox