aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei-cheng Wang <cole945@gmail.com>2015-01-17 14:30:59 +0800
committerCole Wang <cole945@gmail.com>2015-01-17 19:48:22 +0800
commitcf90fd9a07e8998540bf74f293d348a6653ac120 (patch)
tree21337cfdef7297895e07abba7a54aa0c6a0c25a9
parentb4cdae6fe51e532e0b1069c6960b14a610182d14 (diff)
downloadgdb-cf90fd9a07e8998540bf74f293d348a6653ac120.zip
gdb-cf90fd9a07e8998540bf74f293d348a6653ac120.tar.gz
gdb-cf90fd9a07e8998540bf74f293d348a6653ac120.tar.bz2
Skip-trampoline for PowerPC reverse-stepping.
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/ppc-linux-tdep.c58
-rw-r--r--gdb/ppc64-tdep.c88
3 files changed, 105 insertions, 47 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6866edb..d4008e9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,4 +1,10 @@
2015-01-17 Wei-cheng Wang <cole945@gmail.com>
+
+ * ppc-linux-tdep.c (ppc_skip_trampoline_code):
+ Scan PLT stub backward for reverse debugging.
+ * ppc64-tdep.c (ppc64_skip_trampoline_code): Likewise.
+
+2015-01-17 Wei-cheng Wang <cole945@gmail.com>
Ulrich Weigand <uweigand@de.ibm.com>
* configure.tgt (powerpc*-*-linux): Add linux-record.o to
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index dcfd3bb..13bb479 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -51,6 +51,7 @@
#include "linux-tdep.h"
#include "linux-record.h"
#include "record-full.h"
+#include "infrun.h"
#include "stap-probe.h"
#include "ax.h"
@@ -314,31 +315,50 @@ ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR target = 0;
+ int scan_limit, i;
- if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
- {
- /* Insn pattern is
- lis r11, xxxx
- lwz r11, xxxx(r11)
- Branch target is in r11. */
-
- target = (ppc_insn_d_field (insnbuf[0]) << 16)
- | ppc_insn_d_field (insnbuf[1]);
- target = read_memory_unsigned_integer (target, 4, byte_order);
- }
+ scan_limit = 1;
+ /* When reverse-debugging, scan backward to check whether we are
+ in the middle of trampoline code. */
+ if (execution_direction == EXEC_REVERSE)
+ scan_limit = 4; /* At more 4 instructions. */
- if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so, insnbuf))
+ for (i = 0; i < scan_limit; i++)
{
- /* Insn pattern is
- lwz r11, xxxx(r30)
- Branch target is in r11. */
+ if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
+ {
+ /* Insn pattern is
+ lis r11, xxxx
+ lwz r11, xxxx(r11)
+ Branch target is in r11. */
+
+ target = (ppc_insn_d_field (insnbuf[0]) << 16)
+ | ppc_insn_d_field (insnbuf[1]);
+ target = read_memory_unsigned_integer (target, 4, byte_order);
+ }
+ else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so,
+ insnbuf))
+ {
+ /* Insn pattern is
+ lwz r11, xxxx(r30)
+ Branch target is in r11. */
+
+ target = get_frame_register_unsigned (frame,
+ tdep->ppc_gp0_regnum + 30)
+ + ppc_insn_d_field (insnbuf[0]);
+ target = read_memory_unsigned_integer (target, 4, byte_order);
+ }
+ else
+ {
+ /* Scan backward one more instructions if doesn't match. */
+ pc -= 4;
+ continue;
+ }
- target = get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 30)
- + ppc_insn_d_field (insnbuf[0]);
- target = read_memory_unsigned_integer (target, 4, byte_order);
+ return target;
}
- return target;
+ return 0;
}
/* Wrappers to handle Linux-only registers. */
diff --git a/gdb/ppc64-tdep.c b/gdb/ppc64-tdep.c
index 60ef86a..66d7b23 100644
--- a/gdb/ppc64-tdep.c
+++ b/gdb/ppc64-tdep.c
@@ -20,6 +20,7 @@
#include "defs.h"
#include "frame.h"
#include "gdbcore.h"
+#include "infrun.h"
#include "ppc-tdep.h"
#include "ppc64-tdep.h"
#include "elf-bfd.h"
@@ -464,35 +465,66 @@ ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
ARRAY_SIZE (ppc64_standard_linkage8))))
- 1];
CORE_ADDR target;
+ int scan_limit, i;
- if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7, insns))
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6, insns))
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage5, insns)
- && (insns[8] != 0 || insns[9] != 0))
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage4, insns)
- && (insns[9] != 0 || insns[10] != 0))
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3, insns)
- && (insns[8] != 0 || insns[9] != 0))
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage2, insns)
- && (insns[10] != 0 || insns[11] != 0))
- pc = ppc64_standard_linkage2_target (frame, pc, insns);
- else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage1, insns))
- pc = ppc64_standard_linkage1_target (frame, pc, insns);
- else
- return 0;
-
- /* The PLT descriptor will either point to the already resolved target
- address, or else to a glink stub. As the latter carry synthetic @plt
- symbols, find_solib_trampoline_target should be able to resolve them. */
- target = find_solib_trampoline_target (frame, pc);
- return target ? target : pc;
+ scan_limit = 1;
+ /* When reverse-debugging, scan backward to check whether we are
+ in the middle of trampoline code. */
+ if (execution_direction == EXEC_REVERSE)
+ scan_limit = ARRAY_SIZE (insns) - 1;
+
+ for (i = 0; i < scan_limit; i++)
+ {
+ if (i < ARRAY_SIZE (ppc64_standard_linkage8) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
+ pc = ppc64_standard_linkage4_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage7) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7,
+ insns))
+ pc = ppc64_standard_linkage3_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage6) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6,
+ insns))
+ pc = ppc64_standard_linkage4_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage5) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage5,
+ insns)
+ && (insns[8] != 0 || insns[9] != 0))
+ pc = ppc64_standard_linkage3_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage4) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage4,
+ insns)
+ && (insns[9] != 0 || insns[10] != 0))
+ pc = ppc64_standard_linkage4_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage3) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3,
+ insns)
+ && (insns[8] != 0 || insns[9] != 0))
+ pc = ppc64_standard_linkage3_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage2) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage2,
+ insns)
+ && (insns[10] != 0 || insns[11] != 0))
+ pc = ppc64_standard_linkage2_target (frame, pc, insns);
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage1) - 1
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage1,
+ insns))
+ pc = ppc64_standard_linkage1_target (frame, pc, insns);
+ else
+ {
+ /* Scan backward one more instructions if doesn't match. */
+ pc -= 4;
+ continue;
+ }
+
+ /* The PLT descriptor will either point to the already resolved target
+ address, or else to a glink stub. As the latter carry synthetic @plt
+ symbols, find_solib_trampoline_target should be able to resolve them. */
+ target = find_solib_trampoline_target (frame, pc);
+ return target ? target : pc;
+ }
+
+ return 0;
}
/* Support for convert_from_func_ptr_addr (ARCH, ADDR, TARG) on PPC64