[ppc64le] Use skip_entrypoint for skip_trampoline_code

ppc64le loses control when stepping between two PLT-called functions inside
a shared library:

29        shlib_second (); /* first-hit */^M
(gdb) PASS: gdb.base/solib-intra-step.exp: first-hit
step^M
^M
Program received signal SIGABRT, Aborted.^M
0x00003fffb7cbe578 in __GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56^M
56        return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);^M
(gdb) FAIL: gdb.base/solib-intra-step.exp: second-hit
->
29        shlib_second (); /* first-hit */^M
(gdb) PASS: gdb.base/solib-intra-step.exp: first-hit
step^M
shlib_second () at ./gdb.base/solib-intra-step-lib.c:23^M
23        abort (); /* second-hit */^M
(gdb) PASS: gdb.base/solib-intra-step.exp: second-hit

This is because gdbarch_skip_trampoline_code() will resolve the final function
as shlib_second+0 and place there the breakpoint, but ld.so will jump after
the breakpoint - at shlib_second+8 - as it is ELFv2 local symbol optimization:

Dump of assembler code for function shlib_second:
   0x0000000000000804 <+0>:     addis   r2,r12,2
   0x0000000000000808 <+4>:     addi    r2,r2,30668
   0x000000000000080c <+8>:     mflr    r0

Currently gdbarch_skip_entrypoint() has been called in skip_prologue_sal() and
fill_in_stop_func() but that is not enough.  I believe
gdbarch_skip_entrypoint() should be called after every
gdbarch_skip_trampoline_code().

gdb/ChangeLog
2015-09-15  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* linespec.c (minsym_found): Call gdbarch_skip_entrypoint.
	* ppc64-tdep.c (ppc64_skip_trampoline_code): Rename to ...
	(ppc64_skip_trampoline_code_1): ... here.
	(ppc64_skip_trampoline_code): New wrapper function.
	* symtab.c (find_function_start_sal): Call gdbarch_skip_entrypoint.

gdb/testsuite/ChangeLog
2015-09-15  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.opt/solib-intra-step-lib.c: New file.
	* gdb.opt/solib-intra-step-main.c: New file.
	* gdb.opt/solib-intra-step.exp: New file.
This commit is contained in:
Jan Kratochvil 2015-09-15 19:08:04 +02:00
parent d57e0d5022
commit 141c5cc4c4
8 changed files with 177 additions and 2 deletions

View File

@ -1,3 +1,11 @@
2015-09-15 Jan Kratochvil <jan.kratochvil@redhat.com>
* linespec.c (minsym_found): Call gdbarch_skip_entrypoint.
* ppc64-tdep.c (ppc64_skip_trampoline_code): Rename to ...
(ppc64_skip_trampoline_code_1): ... here.
(ppc64_skip_trampoline_code): New wrapper function.
* symtab.c (find_function_start_sal): Call gdbarch_skip_entrypoint.
2015-09-15 Yao Qi <yao.qi@linaro.org>
* aarch64-linux-nat.c (aarch64_linux_can_do_single_step): New

View File

@ -3570,6 +3570,8 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
sal.pc = MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
sal.pc = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc,
&current_target);
if (gdbarch_skip_entrypoint_p (gdbarch))
sal.pc = gdbarch_skip_entrypoint (gdbarch, sal.pc);
}
else
skip_prologue_sal (&sal);

View File

@ -454,8 +454,8 @@ ppc64_standard_linkage4_target (struct frame_info *frame,
When the execution direction is EXEC_REVERSE, scan backward to
check whether we are in the middle of a PLT stub. */
CORE_ADDR
ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
static CORE_ADDR
ppc64_skip_trampoline_code_1 (struct frame_info *frame, CORE_ADDR pc)
{
#define MAX(a,b) ((a) > (b) ? (a) : (b))
unsigned int insns[MAX (MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage1),
@ -530,6 +530,20 @@ ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
return 0;
}
/* Wrapper of ppc64_skip_trampoline_code_1 checking also
ppc_elfv2_skip_entrypoint. */
CORE_ADDR
ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
pc = ppc64_skip_trampoline_code_1 (frame, pc);
if (pc != 0 && gdbarch_skip_entrypoint_p (gdbarch))
pc = gdbarch_skip_entrypoint (gdbarch, pc);
return pc;
}
/* Support for convert_from_func_ptr_addr (ARCH, ADDR, TARG) on PPC64
GNU/Linux.

View File

@ -3629,7 +3629,11 @@ find_function_start_sal (struct symbol *sym, int funfirstline)
&& (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
|| SYMTAB_LANGUAGE (sal.symtab) == language_asm))
{
struct gdbarch *gdbarch = symbol_arch (sym);
sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
if (gdbarch_skip_entrypoint_p (gdbarch))
sal.pc = gdbarch_skip_entrypoint (gdbarch, sal.pc);
return sal;
}

View File

@ -1,3 +1,9 @@
2015-09-15 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.opt/solib-intra-step-lib.c: New file.
* gdb.opt/solib-intra-step-main.c: New file.
* gdb.opt/solib-intra-step.exp: New file.
2015-09-15 Pedro Alves <palves@redhat.com>
* gdb.threads/non-ldr-exc-3.exp (do_test): Use

View File

@ -0,0 +1,30 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2015 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <stdlib.h>
void
shlib_second (int dummy)
{ /* second-retry */
abort (); /* second-hit */
}
void
shlib_first (void)
{ /* first-retry */
shlib_second (0); /* first-hit */
}

View File

@ -0,0 +1,25 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2015 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
extern void shlib_first (void);
int
main (void)
{
shlib_first ();
return 0;
}

View File

@ -0,0 +1,86 @@
# Copyright 2015 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
standard_testfile
if {[skip_shlib_tests]} {
return 0
}
# Library file.
set libname "${testfile}-lib"
set srcfile_lib ${srcdir}/${subdir}/${libname}.c
set binfile_lib [standard_output_file ${libname}.so]
set lib_flags [list debug optimize=-O2]
# Binary file.
set testfile "${testfile}-main"
set srcfile ${srcdir}/${subdir}/${testfile}.c
set binfile [standard_output_file ${testfile}]
set bin_flags [list debug shlib=${binfile_lib}]
if [get_compiler_info] {
return -1
}
if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
|| [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } {
untested "Could not compile $binfile_lib or $binfile."
return -1
}
clean_restart ${binfile}
gdb_load_shlibs $binfile_lib
if ![runto_main] then {
return 0
}
set test "first-hit"
gdb_test_multiple "step" $test {
-re " first-hit .*\r\n$gdb_prompt $" {
pass $test
}
-re " first-retry .*\r\n$gdb_prompt $" {
gdb_test "step" " first-hit .*" "first-hit (optimized)"
}
}
set test "second-hit"
gdb_test_multiple "step" $test {
-re " second-hit .*\r\n$gdb_prompt $" {
pass $test
}
-re " first-retry .*\r\n$gdb_prompt $" {
set test "second-hit (optimized 1)"
gdb_test_multiple "step" $test {
-re " second-hit .*\r\n$gdb_prompt $" {
pass $test
}
-re " first-hit .*\r\n$gdb_prompt $" {
gdb_test "step" " second-hit .*" "second-hit (optimized 2)"
}
}
}
-re " second-retry .*\r\n$gdb_prompt $" {
gdb_test "step" " second-hit .*" "second-hit (optimized 3)"
}
}
if ![runto_main] then {
return 0
}
gdb_breakpoint "shlib_second"
gdb_continue_to_breakpoint "second-hit" ".* (second-hit|second-retry) .*"