* PowerPC PLT stub matching
@ 2018-01-24 6:20 Alan Modra
2018-01-24 6:44 ` Match speculative execution barriers in PowerPC PLT stubs Alan Modra
2018-01-24 16:06 ` PowerPC PLT stub matching Yao Qi
0 siblings, 2 replies; 4+ messages in thread
From: Alan Modra @ 2018-01-24 6:20 UTC (permalink / raw)
To: gdb-patches
This patch fixes a number of bugs in ppc32 plt stub matching code.
1) The 4-insn stub for shared libs and PIEs wasn't matched.
2) The executable stub miscalculated PLT entry address by oring a
sign-extended quantity rather than adding.
3) Comments were not accurate.
In addition, the insn arrays are made const. Regression tested
powerpc64-linux, powerpc-linux and powerpc64le-linux. OK?
* ppc-linux-tdep.c (powerpc32_plt_stub): Make const.
(powerpc32_plt_stub_so_1): Rename from powerpc32_plt_stub_so.
Remove nop. Make const. Comment.
(powerpc32_plt_stub_so_2): New.
(POWERPC32_PLT_CHECK_LEN): Rename from POWERPC32_PLT_STUB_LEN.
Correct count. Update uses.
(ppc_skip_trampoline_code): Match powerpc32_plt_stub_so_2 too.
Move common code reading PLT entry word. Correct
powerpc32_plt_stub PLT address calculation.
* ppc64-tdep.c (ppc64_standard_linkage1): Make const.
(ppc64_standard_linkage2, ppc64_standard_linkage3): Likewise.
(ppc64_standard_linkage4, ppc64_standard_linkage5): Likewise.
(ppc64_standard_linkage6, ppc64_standard_linkage7): Likewise.
(ppc64_standard_linkage8): Likewise.
* rs6000-tdep.c (ppc_insns_match_pattern): Make pattern const.
Correct insns description.
* ppc-tdep.h (ppc_insns_match_pattern): Update prototype.
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index bbe9e89..ed0ea13 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -256,8 +256,8 @@ ppc_linux_return_value (struct gdbarch *gdbarch, struct value *function,
readbuf, writebuf);
}
-/* PLT stub in executable. */
-static struct ppc_insn_pattern powerpc32_plt_stub[] =
+/* PLT stub in an executable. */
+static const struct ppc_insn_pattern powerpc32_plt_stub[] =
{
{ 0xffff0000, 0x3d600000, 0 }, /* lis r11, xxxx */
{ 0xffff0000, 0x816b0000, 0 }, /* lwz r11, xxxx(r11) */
@@ -266,16 +266,30 @@ static struct ppc_insn_pattern powerpc32_plt_stub[] =
{ 0, 0, 0 }
};
-/* PLT stub in shared library. */
-static struct ppc_insn_pattern powerpc32_plt_stub_so[] =
+/* PLT stubs in a shared library or PIE.
+ 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, 0x60000000, 0 }, /* nop */
{ 0, 0, 0 }
};
-#define POWERPC32_PLT_STUB_LEN ARRAY_SIZE (powerpc32_plt_stub)
+
+/* The second variant is used when the PLT entry is more than +/-32k
+ from the GOT pointer (r30). */
+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 */
+ { 0, 0, 0 }
+ };
+
+/* The max number of insns we check using ppc_insns_match_pattern. */
+#define POWERPC32_PLT_CHECK_LEN (ARRAY_SIZE (powerpc32_plt_stub) - 1)
/* Check if PC is in PLT stub. For non-secure PLT, stub is in .plt
section. For secure PLT, stub is in .text and we need to check
@@ -306,13 +320,13 @@ 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 PLT
+ we only look-behind at most 4 instructions (the max length of a PLT
stub sequence. */
static CORE_ADDR
ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
- unsigned int insnbuf[POWERPC32_PLT_STUB_LEN];
+ unsigned int insnbuf[POWERPC32_PLT_CHECK_LEN];
struct gdbarch *gdbarch = get_frame_arch (frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -323,40 +337,47 @@ 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 more 4 instructions. */
+ scan_limit = 4; /* At most 4 instructions. */
for (i = 0; i < scan_limit; i++)
{
if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
{
- /* Insn pattern is
+ /* Calculate PLT entry address from
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);
+ lwz r11, xxxx(r11). */
+ 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
+ && ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so_1,
+ insnbuf))
+ {
+ /* Calculate PLT entry address from
+ lwz r11, xxxx(r30). */
+ target = (ppc_insn_d_field (insnbuf[0])
+ + get_frame_register_unsigned (frame,
+ tdep->ppc_gp0_regnum + 30));
}
- else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so,
+ else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so_2,
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);
+ /* Calculate PLT entry address from
+ addis r11, r30, xxxx
+ lwz r11, xxxx(r11). */
+ target = ((ppc_insn_d_field (insnbuf[0]) << 16)
+ + ppc_insn_d_field (insnbuf[1])
+ + get_frame_register_unsigned (frame,
+ tdep->ppc_gp0_regnum + 30));
}
else
{
- /* Scan backward one more instructions if doesn't match. */
+ /* Scan backward one more instruction if it doesn't match. */
pc -= 4;
continue;
}
+ target = read_memory_unsigned_integer (target, 4, byte_order);
return target;
}
diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h
index 3004744..156f82d 100644
--- a/gdb/ppc-tdep.h
+++ b/gdb/ppc-tdep.h
@@ -330,7 +330,7 @@ struct ppc_insn_pattern
};
extern int ppc_insns_match_pattern (struct frame_info *frame, CORE_ADDR pc,
- struct ppc_insn_pattern *pattern,
+ const struct ppc_insn_pattern *pattern,
unsigned int *insns);
extern CORE_ADDR ppc_insn_d_field (unsigned int insn);
diff --git a/gdb/ppc64-tdep.c b/gdb/ppc64-tdep.c
index 7417232..5d8ccb4 100644
--- a/gdb/ppc64-tdep.c
+++ b/gdb/ppc64-tdep.c
@@ -80,7 +80,7 @@ ppc64_plt_entry_point (struct frame_info *frame, CORE_ADDR plt_off)
/* Old ELFv1 PLT call stub. */
-static struct ppc_insn_pattern ppc64_standard_linkage1[] =
+static const struct ppc_insn_pattern ppc64_standard_linkage1[] =
{
/* addis r12, r2, <any> */
{ insn_d (-1, -1, -1, 0), insn_d (15, 12, 2, 0), 0 },
@@ -119,7 +119,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage1[] =
instructions following "cmpldi r2, 0", "bnectr+" and "b <glink_i>",
but there isn't any need to match them. */
-static struct ppc_insn_pattern ppc64_standard_linkage2[] =
+static const struct ppc_insn_pattern ppc64_standard_linkage2[] =
{
/* std r2, 40(r1) <optional> */
{ -1, insn_ds (62, 2, 1, 40, 0), 1 },
@@ -162,7 +162,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage2[] =
/* ELFv1 PLT call stub to access PLT entries within +/- 32k of r2. */
-static struct ppc_insn_pattern ppc64_standard_linkage3[] =
+static const struct ppc_insn_pattern ppc64_standard_linkage3[] =
{
/* std r2, 40(r1) <optional> */
{ -1, insn_ds (62, 2, 1, 40, 0), 1 },
@@ -201,7 +201,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage3[] =
A more modern variant of ppc64_standard_linkage2 differing in
register usage. */
-static struct ppc_insn_pattern ppc64_standard_linkage4[] =
+static const struct ppc_insn_pattern ppc64_standard_linkage4[] =
{
/* std r2, 40(r1) <optional> */
{ -1, insn_ds (62, 2, 1, 40, 0), 1 },
@@ -243,7 +243,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage4[] =
A more modern variant of ppc64_standard_linkage3 differing in
register usage. */
-static struct ppc_insn_pattern ppc64_standard_linkage5[] =
+static const struct ppc_insn_pattern ppc64_standard_linkage5[] =
{
/* std r2, 40(r1) <optional> */
{ -1, insn_ds (62, 2, 1, 40, 0), 1 },
@@ -280,7 +280,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage5[] =
/* ELFv2 PLT call stub to access PLT entries more than +/- 32k from r2. */
-static struct ppc_insn_pattern ppc64_standard_linkage6[] =
+static const struct ppc_insn_pattern ppc64_standard_linkage6[] =
{
/* std r2, 24(r1) <optional> */
{ -1, insn_ds (62, 2, 1, 24, 0), 1 },
@@ -302,7 +302,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage6[] =
/* ELFv2 PLT call stub to access PLT entries within +/- 32k of r2. */
-static struct ppc_insn_pattern ppc64_standard_linkage7[] =
+static const struct ppc_insn_pattern ppc64_standard_linkage7[] =
{
/* std r2, 24(r1) <optional> */
{ -1, insn_ds (62, 2, 1, 24, 0), 1 },
@@ -322,7 +322,7 @@ static struct ppc_insn_pattern ppc64_standard_linkage7[] =
/* ELFv2 PLT call stub to access PLT entries more than +/- 32k from r2,
supporting fusion. */
-static struct ppc_insn_pattern ppc64_standard_linkage8[] =
+static const struct ppc_insn_pattern ppc64_standard_linkage8[] =
{
/* std r2, 24(r1) <optional> */
{ -1, insn_ds (62, 2, 1, 24, 0), 1 },
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index f81064e..3ec3817 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -6717,17 +6717,17 @@ read_insn (struct frame_info *frame, CORE_ADDR pc)
'struct ppc_insn_pattern' objects, terminated by an entry whose
mask is zero.
- When the match is successful, fill INSN[i] with what PATTERN[i]
+ When the match is successful, fill INSNS[i] with what PATTERN[i]
matched. If PATTERN[i] is optional, and the instruction wasn't
- present, set INSN[i] to 0 (which is not a valid PPC instruction).
- INSN should have as many elements as PATTERN. Note that, if
- PATTERN contains optional instructions which aren't present in
- memory, then INSN will have holes, so INSN[i] isn't necessarily the
- i'th instruction in memory. */
+ present, set INSNS[i] to 0 (which is not a valid PPC instruction).
+ INSNS should have as many elements as PATTERN, minus the terminator.
+ Note that, if PATTERN contains optional instructions which aren't
+ present in memory, then INSNS will have holes, so INSNS[i] isn't
+ necessarily the i'th instruction in memory. */
int
ppc_insns_match_pattern (struct frame_info *frame, CORE_ADDR pc,
- struct ppc_insn_pattern *pattern,
+ const struct ppc_insn_pattern *pattern,
unsigned int *insns)
{
int i;
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 4+ messages in thread
* Match speculative execution barriers in PowerPC PLT stubs
2018-01-24 6:20 PowerPC PLT stub matching Alan Modra
@ 2018-01-24 6:44 ` Alan Modra
2018-01-24 16:06 ` PowerPC PLT stub matching Yao Qi
1 sibling, 0 replies; 4+ messages in thread
From: Alan Modra @ 2018-01-24 6:44 UTC (permalink / raw)
To: gdb-patches
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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: PowerPC PLT stub matching
2018-01-24 6:20 PowerPC PLT stub matching Alan Modra
2018-01-24 6:44 ` Match speculative execution barriers in PowerPC PLT stubs Alan Modra
@ 2018-01-24 16:06 ` Yao Qi
2018-01-26 5:42 ` Alan Modra
1 sibling, 1 reply; 4+ messages in thread
From: Yao Qi @ 2018-01-24 16:06 UTC (permalink / raw)
To: Alan Modra; +Cc: gdb-patches
Alan Modra <amodra@gmail.com> writes:
Hi Alan,
Thanks for the clean up, patch is good to me. Please push.
A general question below,
> -/* PLT stub in executable. */
> -static struct ppc_insn_pattern powerpc32_plt_stub[] =
> +/* PLT stub in an executable. */
> +static const struct ppc_insn_pattern powerpc32_plt_stub[] =
> {
> { 0xffff0000, 0x3d600000, 0 }, /* lis r11, xxxx */
> { 0xffff0000, 0x816b0000, 0 }, /* lwz r11, xxxx(r11) */
> @@ -266,16 +266,30 @@ static struct ppc_insn_pattern powerpc32_plt_stub[] =
> { 0, 0, 0 }
> };
>
> -/* PLT stub in shared library. */
> -static struct ppc_insn_pattern powerpc32_plt_stub_so[] =
> +/* PLT stubs in a shared library or PIE.
> + 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, 0x60000000, 0 }, /* nop */
> { 0, 0, 0 }
> };
> -#define POWERPC32_PLT_STUB_LEN ARRAY_SIZE (powerpc32_plt_stub)
> +
> +/* The second variant is used when the PLT entry is more than +/-32k
> + from the GOT pointer (r30). */
> +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 */
> + { 0, 0, 0 }
> + };
These instruction sequences reflect what
bfd/elf32-ppc.c:write_glink_stub does, IIUC. Is there any way we can
correlate these two sides, PLT stub generation and matching? Ideally, I
want to such sequences are defined once, but shared by linker and debugger.
--
Yao (齐尧)
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: PowerPC PLT stub matching
2018-01-24 16:06 ` PowerPC PLT stub matching Yao Qi
@ 2018-01-26 5:42 ` Alan Modra
0 siblings, 0 replies; 4+ messages in thread
From: Alan Modra @ 2018-01-26 5:42 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
On Wed, Jan 24, 2018 at 04:06:02PM +0000, Yao Qi wrote:
> These instruction sequences reflect what
> bfd/elf32-ppc.c:write_glink_stub does, IIUC.
Yes, and gold/powerpc.cc:Stub_table::do_write.
> Is there any way we can
> correlate these two sides, PLT stub generation and matching? Ideally, I
> want to such sequences are defined once, but shared by linker and debugger.
It might be possible, but I think the resulting data structure and
code would be a mess, particularly for ppc64 given the number of
variations of PLT stubs.
Thanks for the review! Committed.
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2018-01-26 5:42 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-24 6:20 PowerPC PLT stub matching Alan Modra
2018-01-24 6:44 ` Match speculative execution barriers in PowerPC PLT stubs Alan Modra
2018-01-24 16:06 ` PowerPC PLT stub matching Yao Qi
2018-01-26 5:42 ` Alan Modra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).