|
|
dc7ef9 |
commit db9077b7275e86637218a7a7d165cb85a4de116f
|
|
|
dc7ef9 |
Author: Alan Modra <amodra@gmail.com>
|
|
|
dc7ef9 |
Date: Mon Dec 11 17:31:11 2017 +1030
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
PR22576, ppc64_skip_trampoline_code uses wrong r2 for EXEC_REVERSE
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
The TOC pointer register, r2, on powerpc64 is generally not mentioned
|
|
|
dc7ef9 |
in debug info. It is saved and restored by call linkage code, and
|
|
|
dc7ef9 |
set to the callee value either by call stub code (ELFv1) or in the
|
|
|
dc7ef9 |
callee global entry point code (ELFv2). A call stub uses the caller
|
|
|
dc7ef9 |
TOC pointer to access the PLT. So for gdb to read the correct PLT
|
|
|
dc7ef9 |
entry in order to determine the destination of the trampoline, gdb
|
|
|
dc7ef9 |
needs to know the caller r2. When skipping over trampolines in the
|
|
|
dc7ef9 |
normal forward direction, the caller r2 is simply the current value of
|
|
|
dc7ef9 |
r2 (at the start of the trampoline). However, when reversing over
|
|
|
dc7ef9 |
trampolines the current value of r2 is that for the callee. Using
|
|
|
dc7ef9 |
that value results in wild reads of memory rather than the correct PLT
|
|
|
dc7ef9 |
entry.
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
This patch corrects the value of r2 by using the value saved on the
|
|
|
dc7ef9 |
stack for reverse execution. Note that in reverse execution mode it
|
|
|
dc7ef9 |
isn't really necessary for skip_trampoline_code to return the actual
|
|
|
dc7ef9 |
destination, so we're doing a little more work than needed here. Any
|
|
|
dc7ef9 |
non-zero return value would do (and it would be nicer if the interface
|
|
|
dc7ef9 |
was changed to return the start of the stub).
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
PR tdep/22576
|
|
|
dc7ef9 |
* ppc64-tdep.c (ppc64_plt_entry_point): Rewrite to take TOC-relative
|
|
|
dc7ef9 |
PLT offset, and retrieve r2 from stack when executing in reverse.
|
|
|
dc7ef9 |
(ppc64_standard_linkage1_target): Drop pc param. Calculate offset
|
|
|
dc7ef9 |
rather than PLT address.
|
|
|
dc7ef9 |
(ppc64_standard_linkage2_target): Likewise.
|
|
|
dc7ef9 |
(ppc64_standard_linkage3_target): Likewise.
|
|
|
dc7ef9 |
(ppc64_standard_linkage4_target): Likewise.
|
|
|
dc7ef9 |
(ppc64_skip_trampoline_code_1): Adjust to suit.
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
### a/gdb/ChangeLog
|
|
|
dc7ef9 |
### b/gdb/ChangeLog
|
|
|
dc7ef9 |
## -1,3 +1,15 @@
|
|
|
dc7ef9 |
+2017-12-12 Alan Modra <amodra@gmail.com>
|
|
|
dc7ef9 |
+
|
|
|
dc7ef9 |
+ PR tdep/22576
|
|
|
dc7ef9 |
+ * ppc64-tdep.c (ppc64_plt_entry_point): Rewrite to take TOC-relative
|
|
|
dc7ef9 |
+ PLT offset, and retrieve r2 from stack when executing in reverse.
|
|
|
dc7ef9 |
+ (ppc64_standard_linkage1_target): Drop pc param. Calculate offset
|
|
|
dc7ef9 |
+ rather than PLT address.
|
|
|
dc7ef9 |
+ (ppc64_standard_linkage2_target): Likewise.
|
|
|
dc7ef9 |
+ (ppc64_standard_linkage3_target): Likewise.
|
|
|
dc7ef9 |
+ (ppc64_standard_linkage4_target): Likewise.
|
|
|
dc7ef9 |
+ (ppc64_skip_trampoline_code_1): Adjust to suit.
|
|
|
dc7ef9 |
+
|
|
|
dc7ef9 |
2017-12-11 Simon Marchi <simon.marchi@ericsson.com>
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
PR gdb/22556
|
|
|
dc7ef9 |
--- a/gdb/ppc64-tdep.c
|
|
|
dc7ef9 |
+++ b/gdb/ppc64-tdep.c
|
|
|
dc7ef9 |
@@ -49,15 +49,30 @@
|
|
|
dc7ef9 |
| (((spr) & 0x3e0) << 6) \
|
|
|
dc7ef9 |
| (((xo) & 0x3ff) << 1))
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
-/* If PLT is the address of a 64-bit PowerPC PLT entry,
|
|
|
dc7ef9 |
- return the function's entry point. */
|
|
|
dc7ef9 |
+/* PLT_OFF is the TOC-relative offset of a 64-bit PowerPC PLT entry.
|
|
|
dc7ef9 |
+ Return the function's entry point. */
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
static CORE_ADDR
|
|
|
dc7ef9 |
-ppc64_plt_entry_point (struct gdbarch *gdbarch, CORE_ADDR plt)
|
|
|
dc7ef9 |
+ppc64_plt_entry_point (struct frame_info *frame, CORE_ADDR plt_off)
|
|
|
dc7ef9 |
{
|
|
|
dc7ef9 |
+ struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
dc7ef9 |
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
|
dc7ef9 |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
dc7ef9 |
+ CORE_ADDR tocp;
|
|
|
dc7ef9 |
+
|
|
|
dc7ef9 |
+ if (execution_direction == EXEC_REVERSE)
|
|
|
dc7ef9 |
+ {
|
|
|
dc7ef9 |
+ /* If executing in reverse, r2 will have been stored to the stack. */
|
|
|
dc7ef9 |
+ CORE_ADDR sp = get_frame_register_unsigned (frame,
|
|
|
dc7ef9 |
+ tdep->ppc_gp0_regnum + 1);
|
|
|
dc7ef9 |
+ unsigned int sp_off = tdep->elf_abi == POWERPC_ELF_V1 ? 40 : 24;
|
|
|
dc7ef9 |
+ tocp = read_memory_unsigned_integer (sp + sp_off, 8, byte_order);
|
|
|
dc7ef9 |
+ }
|
|
|
dc7ef9 |
+ else
|
|
|
dc7ef9 |
+ tocp = get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 2);
|
|
|
dc7ef9 |
+
|
|
|
dc7ef9 |
/* The first word of the PLT entry is the function entry point. */
|
|
|
dc7ef9 |
- return (CORE_ADDR) read_memory_unsigned_integer (plt, 8, byte_order);
|
|
|
dc7ef9 |
+ return read_memory_unsigned_integer (tocp + plt_off, 8, byte_order);
|
|
|
dc7ef9 |
}
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
/* Patterns for the standard linkage functions. These are built by
|
|
|
dc7ef9 |
@@ -377,74 +392,44 @@ static struct ppc_insn_pattern ppc64_standard_linkage8[] =
|
|
|
dc7ef9 |
the linkage function. */
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
/* If the current thread is about to execute a series of instructions
|
|
|
dc7ef9 |
- at PC matching the ppc64_standard_linkage pattern, and INSN is the result
|
|
|
dc7ef9 |
+ matching the ppc64_standard_linkage pattern, and INSN is the result
|
|
|
dc7ef9 |
from that pattern match, return the code address to which the
|
|
|
dc7ef9 |
standard linkage function will send them. (This doesn't deal with
|
|
|
dc7ef9 |
dynamic linker lazy symbol resolution stubs.) */
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
static CORE_ADDR
|
|
|
dc7ef9 |
-ppc64_standard_linkage1_target (struct frame_info *frame,
|
|
|
dc7ef9 |
- CORE_ADDR pc, unsigned int *insn)
|
|
|
dc7ef9 |
+ppc64_standard_linkage1_target (struct frame_info *frame, unsigned int *insn)
|
|
|
dc7ef9 |
{
|
|
|
dc7ef9 |
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
dc7ef9 |
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
dc7ef9 |
-
|
|
|
dc7ef9 |
- /* The address of the PLT entry this linkage function references. */
|
|
|
dc7ef9 |
- CORE_ADDR plt
|
|
|
dc7ef9 |
- = ((CORE_ADDR) get_frame_register_unsigned (frame,
|
|
|
dc7ef9 |
- tdep->ppc_gp0_regnum + 2)
|
|
|
dc7ef9 |
- + (ppc_insn_d_field (insn[0]) << 16)
|
|
|
dc7ef9 |
- + ppc_insn_ds_field (insn[2]));
|
|
|
dc7ef9 |
+ CORE_ADDR plt_off = ((ppc_insn_d_field (insn[0]) << 16)
|
|
|
dc7ef9 |
+ + ppc_insn_ds_field (insn[2]));
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
- return ppc64_plt_entry_point (gdbarch, plt);
|
|
|
dc7ef9 |
+ return ppc64_plt_entry_point (frame, plt_off);
|
|
|
dc7ef9 |
}
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
static CORE_ADDR
|
|
|
dc7ef9 |
-ppc64_standard_linkage2_target (struct frame_info *frame,
|
|
|
dc7ef9 |
- CORE_ADDR pc, unsigned int *insn)
|
|
|
dc7ef9 |
+ppc64_standard_linkage2_target (struct frame_info *frame, unsigned int *insn)
|
|
|
dc7ef9 |
{
|
|
|
dc7ef9 |
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
dc7ef9 |
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
dc7ef9 |
-
|
|
|
dc7ef9 |
- /* The address of the PLT entry this linkage function references. */
|
|
|
dc7ef9 |
- CORE_ADDR plt
|
|
|
dc7ef9 |
- = ((CORE_ADDR) get_frame_register_unsigned (frame,
|
|
|
dc7ef9 |
- tdep->ppc_gp0_regnum + 2)
|
|
|
dc7ef9 |
- + (ppc_insn_d_field (insn[1]) << 16)
|
|
|
dc7ef9 |
- + ppc_insn_ds_field (insn[3]));
|
|
|
dc7ef9 |
+ CORE_ADDR plt_off = ((ppc_insn_d_field (insn[1]) << 16)
|
|
|
dc7ef9 |
+ + ppc_insn_ds_field (insn[3]));
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
- return ppc64_plt_entry_point (gdbarch, plt);
|
|
|
dc7ef9 |
+ return ppc64_plt_entry_point (frame, plt_off);
|
|
|
dc7ef9 |
}
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
static CORE_ADDR
|
|
|
dc7ef9 |
-ppc64_standard_linkage3_target (struct frame_info *frame,
|
|
|
dc7ef9 |
- CORE_ADDR pc, unsigned int *insn)
|
|
|
dc7ef9 |
+ppc64_standard_linkage3_target (struct frame_info *frame, unsigned int *insn)
|
|
|
dc7ef9 |
{
|
|
|
dc7ef9 |
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
dc7ef9 |
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
dc7ef9 |
+ CORE_ADDR plt_off = ppc_insn_ds_field (insn[1]);
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
- /* The address of the PLT entry this linkage function references. */
|
|
|
dc7ef9 |
- CORE_ADDR plt
|
|
|
dc7ef9 |
- = ((CORE_ADDR) get_frame_register_unsigned (frame,
|
|
|
dc7ef9 |
- tdep->ppc_gp0_regnum + 2)
|
|
|
dc7ef9 |
- + ppc_insn_ds_field (insn[1]));
|
|
|
dc7ef9 |
-
|
|
|
dc7ef9 |
- return ppc64_plt_entry_point (gdbarch, plt);
|
|
|
dc7ef9 |
+ return ppc64_plt_entry_point (frame, plt_off);
|
|
|
dc7ef9 |
}
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
static CORE_ADDR
|
|
|
dc7ef9 |
-ppc64_standard_linkage4_target (struct frame_info *frame,
|
|
|
dc7ef9 |
- CORE_ADDR pc, unsigned int *insn)
|
|
|
dc7ef9 |
+ppc64_standard_linkage4_target (struct frame_info *frame, unsigned int *insn)
|
|
|
dc7ef9 |
{
|
|
|
dc7ef9 |
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
dc7ef9 |
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
dc7ef9 |
-
|
|
|
dc7ef9 |
- CORE_ADDR plt
|
|
|
dc7ef9 |
- = ((CORE_ADDR) get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 2)
|
|
|
dc7ef9 |
- + (ppc_insn_d_field (insn[1]) << 16)
|
|
|
dc7ef9 |
- + ppc_insn_ds_field (insn[2]));
|
|
|
dc7ef9 |
+ CORE_ADDR plt_off = ((ppc_insn_d_field (insn[1]) << 16)
|
|
|
dc7ef9 |
+ + ppc_insn_ds_field (insn[2]));
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
- return ppc64_plt_entry_point (gdbarch, plt);
|
|
|
dc7ef9 |
+ return ppc64_plt_entry_point (frame, plt_off);
|
|
|
dc7ef9 |
}
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
|
|
|
dc7ef9 |
@@ -480,39 +465,39 @@ ppc64_skip_trampoline_code_1 (struct frame_info *frame, CORE_ADDR pc)
|
|
|
dc7ef9 |
{
|
|
|
dc7ef9 |
if (i < ARRAY_SIZE (ppc64_standard_linkage8) - 1
|
|
|
dc7ef9 |
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8, insns))
|
|
|
dc7ef9 |
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
|
|
|
dc7ef9 |
+ pc = ppc64_standard_linkage4_target (frame, insns);
|
|
|
dc7ef9 |
else if (i < ARRAY_SIZE (ppc64_standard_linkage7) - 1
|
|
|
dc7ef9 |
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7,
|
|
|
dc7ef9 |
insns))
|
|
|
dc7ef9 |
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
|
|
|
dc7ef9 |
+ pc = ppc64_standard_linkage3_target (frame, insns);
|
|
|
dc7ef9 |
else if (i < ARRAY_SIZE (ppc64_standard_linkage6) - 1
|
|
|
dc7ef9 |
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6,
|
|
|
dc7ef9 |
insns))
|
|
|
dc7ef9 |
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
|
|
|
dc7ef9 |
+ pc = ppc64_standard_linkage4_target (frame, insns);
|
|
|
dc7ef9 |
else if (i < ARRAY_SIZE (ppc64_standard_linkage5) - 1
|
|
|
dc7ef9 |
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage5,
|
|
|
dc7ef9 |
insns)
|
|
|
dc7ef9 |
&& (insns[8] != 0 || insns[9] != 0))
|
|
|
dc7ef9 |
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
|
|
|
dc7ef9 |
+ pc = ppc64_standard_linkage3_target (frame, insns);
|
|
|
dc7ef9 |
else if (i < ARRAY_SIZE (ppc64_standard_linkage4) - 1
|
|
|
dc7ef9 |
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage4,
|
|
|
dc7ef9 |
insns)
|
|
|
dc7ef9 |
&& (insns[9] != 0 || insns[10] != 0))
|
|
|
dc7ef9 |
- pc = ppc64_standard_linkage4_target (frame, pc, insns);
|
|
|
dc7ef9 |
+ pc = ppc64_standard_linkage4_target (frame, insns);
|
|
|
dc7ef9 |
else if (i < ARRAY_SIZE (ppc64_standard_linkage3) - 1
|
|
|
dc7ef9 |
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3,
|
|
|
dc7ef9 |
insns)
|
|
|
dc7ef9 |
&& (insns[8] != 0 || insns[9] != 0))
|
|
|
dc7ef9 |
- pc = ppc64_standard_linkage3_target (frame, pc, insns);
|
|
|
dc7ef9 |
+ pc = ppc64_standard_linkage3_target (frame, insns);
|
|
|
dc7ef9 |
else if (i < ARRAY_SIZE (ppc64_standard_linkage2) - 1
|
|
|
dc7ef9 |
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage2,
|
|
|
dc7ef9 |
insns)
|
|
|
dc7ef9 |
&& (insns[10] != 0 || insns[11] != 0))
|
|
|
dc7ef9 |
- pc = ppc64_standard_linkage2_target (frame, pc, insns);
|
|
|
dc7ef9 |
+ pc = ppc64_standard_linkage2_target (frame, insns);
|
|
|
dc7ef9 |
else if (i < ARRAY_SIZE (ppc64_standard_linkage1) - 1
|
|
|
dc7ef9 |
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage1,
|
|
|
dc7ef9 |
insns))
|
|
|
dc7ef9 |
- pc = ppc64_standard_linkage1_target (frame, pc, insns);
|
|
|
dc7ef9 |
+ pc = ppc64_standard_linkage1_target (frame, insns);
|
|
|
dc7ef9 |
else
|
|
|
dc7ef9 |
{
|
|
|
dc7ef9 |
/* Scan backward one more instructions if doesn't match. */
|