This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Match speculative execution barriers in PowerPC PLT stubs
- From: Alan Modra <amodra at gmail dot com>
- To: gdb-patches at sourceware dot org
- Date: Wed, 24 Jan 2018 17:14:23 +1030
- Subject: Match speculative execution barriers in PowerPC PLT stubs
- Authentication-results: sourceware.org; auth=none
- References: <20180124062015.GN20622@bubble.grove.modra.org>
This patch teaches gdb about the PLT stub code emitted by
ld --no-speculate-indirect-jumps. Regression tested
powerpc64-linux, powerpc-linux and powerpc64le-linux. OK?
* ppc-linux-tdep.c (powerpc32_plt_stub): Match stub with
speculative execution barrier.
(powerpc32_plt_stub_so_1, powerpc32_plt_stub_so_2): Likewise.
(ppc_skip_trampoline_code): Scan backwards 6 insns. Check that
either "bctr" or "crset eq" is present in PLT stubs.
* ppc64-tdep.c (ppc64_standard_linkage4): Match stub with
speculative execution barrier.
(ppc64_standard_linkage5): Likewise
(ppc64_standard_linkage7, ppc64_standard_linkage8): Likewise.
(ppc64_skip_trampoline_code_1): Check that either "bctr" or
"crset eq" is present.
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index ed0ea13..541df39 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -256,24 +256,28 @@ ppc_linux_return_value (struct gdbarch *gdbarch, struct value *function,
readbuf, writebuf);
}
-/* PLT stub in an executable. */
+/* PLT stub in an executable. The form with an execution barrier has
+ two more insns following the "crset eq" that we don't check. */
static const struct ppc_insn_pattern powerpc32_plt_stub[] =
{
{ 0xffff0000, 0x3d600000, 0 }, /* lis r11, xxxx */
{ 0xffff0000, 0x816b0000, 0 }, /* lwz r11, xxxx(r11) */
{ 0xffffffff, 0x7d6903a6, 0 }, /* mtctr r11 */
- { 0xffffffff, 0x4e800420, 0 }, /* bctr */
+ { 0xffffffff, 0x4e800420, 1 }, /* bctr <option 1> */
+ { 0xffffffff, 0x4c421242, 1 }, /* crset eq <option 2> */
{ 0, 0, 0 }
};
-/* PLT stubs in a shared library or PIE.
+/* PLT stubs in a shared library or PIE. As above, "crset eq" is
+ followed by two more insns.
The first variant is used when the PLT entry is within +/-32k of
the GOT pointer (r30). */
static const struct ppc_insn_pattern powerpc32_plt_stub_so_1[] =
{
{ 0xffff0000, 0x817e0000, 0 }, /* lwz r11, xxxx(r30) */
{ 0xffffffff, 0x7d6903a6, 0 }, /* mtctr r11 */
- { 0xffffffff, 0x4e800420, 0 }, /* bctr */
+ { 0xffffffff, 0x4e800420, 1 }, /* bctr <option 1> */
+ { 0xffffffff, 0x4c421242, 1 }, /* crset eq <option 2> */
{ 0, 0, 0 }
};
@@ -284,7 +288,8 @@ static const struct ppc_insn_pattern powerpc32_plt_stub_so_2[] =
{ 0xffff0000, 0x3d7e0000, 0 }, /* addis r11, r30, xxxx */
{ 0xffff0000, 0x816b0000, 0 }, /* lwz r11, xxxx(r11) */
{ 0xffffffff, 0x7d6903a6, 0 }, /* mtctr r11 */
- { 0xffffffff, 0x4e800420, 0 }, /* bctr */
+ { 0xffffffff, 0x4e800420, 1 }, /* bctr <option 1> */
+ { 0xffffffff, 0x4c421242, 1 }, /* crset eq <option 2> */
{ 0, 0, 0 }
};
@@ -320,7 +325,7 @@ powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
When the execution direction is EXEC_REVERSE, scan backward to
check whether we are in the middle of a PLT stub. Currently,
- we only look-behind at most 4 instructions (the max length of a PLT
+ we only look-behind at most 6 instructions (the max length of a PLT
stub sequence. */
static CORE_ADDR
@@ -337,11 +342,12 @@ ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
/* 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 most 4 instructions. */
+ scan_limit = 6; /* At most 6 instructions. */
for (i = 0; i < scan_limit; i++)
{
- if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
+ if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf)
+ && (insnbuf[3] != 0 || insnbuf[4] != 0))
{
/* Calculate PLT entry address from
lis r11, xxxx
@@ -349,9 +355,10 @@ ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
target = ((ppc_insn_d_field (insnbuf[0]) << 16)
+ ppc_insn_d_field (insnbuf[1]));
}
- else if (i < ARRAY_SIZE (powerpc32_plt_stub_so_1) - 1
+ else if (i < ARRAY_SIZE (powerpc32_plt_stub_so_1)
&& ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so_1,
- insnbuf))
+ insnbuf)
+ && (insnbuf[2] != 0 || insnbuf[3] != 0))
{
/* Calculate PLT entry address from
lwz r11, xxxx(r30). */
@@ -360,7 +367,8 @@ ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
tdep->ppc_gp0_regnum + 30));
}
else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so_2,
- insnbuf))
+ insnbuf)
+ && (insnbuf[3] != 0 || insnbuf[4] != 0))
{
/* Calculate PLT entry address from
addis r11, r30, xxxx
diff --git a/gdb/ppc64-tdep.c b/gdb/ppc64-tdep.c
index 5d8ccb4..1249a4d 100644
--- a/gdb/ppc64-tdep.c
+++ b/gdb/ppc64-tdep.c
@@ -236,6 +236,9 @@ static const struct ppc_insn_pattern ppc64_standard_linkage4[] =
/* cmpldi r2, 0 <optional> */
{ -1, 0x28220000, 1 },
+ /* crset eq <optional> */
+ { -1, 0x4c421242, 1 },
+
{ 0, 0, 0 }
};
@@ -275,6 +278,9 @@ static const struct ppc_insn_pattern ppc64_standard_linkage5[] =
/* cmpldi r2, 0 <optional> */
{ -1, 0x28220000, 1 },
+ /* crset eq <optional> */
+ { -1, 0x4c421242, 1 },
+
{ 0, 0, 0 }
};
@@ -313,8 +319,11 @@ static const struct ppc_insn_pattern ppc64_standard_linkage7[] =
/* mtctr r12 */
{ insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
- /* bctr */
- { -1, 0x4e800420, 0 },
+ /* bctr <optional> */
+ { -1, 0x4e800420, 1 },
+
+ /* crset eq <optional> */
+ { -1, 0x4c421242, 1 },
{ 0, 0, 0 }
};
@@ -336,8 +345,11 @@ static const struct ppc_insn_pattern ppc64_standard_linkage8[] =
/* mtctr r12 */
{ insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
- /* bctr */
- { -1, 0x4e800420, 0 },
+ /* bctr <optional> */
+ { -1, 0x4e800420, 1 },
+
+ /* crset eq <optional> */
+ { -1, 0x4c421242, 1 },
{ 0, 0, 0 }
};
@@ -463,12 +475,15 @@ ppc64_skip_trampoline_code_1 (struct frame_info *frame, CORE_ADDR pc)
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))
+ if (i < ARRAY_SIZE (ppc64_standard_linkage8)
+ && ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage8,
+ insns)
+ && (insns[4] != 0 || insns[5] != 0))
pc = ppc64_standard_linkage4_target (frame, insns);
- else if (i < ARRAY_SIZE (ppc64_standard_linkage7) - 1
+ else if (i < ARRAY_SIZE (ppc64_standard_linkage7)
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7,
- insns))
+ insns)
+ && (insns[3] != 0 || insns[4] != 0))
pc = ppc64_standard_linkage3_target (frame, insns);
else if (i < ARRAY_SIZE (ppc64_standard_linkage6) - 1
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6,
@@ -477,12 +492,12 @@ ppc64_skip_trampoline_code_1 (struct frame_info *frame, CORE_ADDR pc)
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))
+ && (insns[8] != 0 || insns[9] != 0 || insns[10] != 0))
pc = ppc64_standard_linkage3_target (frame, 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))
+ && (insns[9] != 0 || insns[10] != 0 || insns[11] != 0))
pc = ppc64_standard_linkage4_target (frame, insns);
else if (i < ARRAY_SIZE (ppc64_standard_linkage3) - 1
&& ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3,
--
Alan Modra
Australia Development Lab, IBM