From: Victor Collod <vcollod@nvidia.com>
To: <gdb-patches@sourceware.org>
Cc: Victor Collod <vcollod@nvidia.com>
Subject: [PATCH] Add support for intel IBT
Date: Thu, 12 Mar 2020 17:58:52 -0700 [thread overview]
Message-ID: <20200313005852.14788-1-vcollod@nvidia.com> (raw)
Intel IBT adds a new instruction that is used to mark valid indirect
jump targets. Some recent compilers add such instructions at the
beginning of all functions.
Without this patch, gdb does not properly skip the prologue of these
functions, which makes it fail to print function arguments right after
hitting a function breakpoint.
2020-03-12 Victor Collod <vcollod@nvidia.com>
* i386-tdep.c (i386_skip_endbr): add a helper function to skip endbr
instructions.
(i386_analyze_prologue): call i386_skip_endbr.
* amd64-tdep.c (i386_analyze_prologue): skip endbr instructions.
---
gdb/amd64-tdep.c | 74 ++++++++++++++++++++++++++++--------------------
gdb/i386-tdep.c | 19 +++++++++++++
2 files changed, 62 insertions(+), 31 deletions(-)
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 5c56a970d8..bce6dcda47 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2375,12 +2375,13 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
/* There are two variations of movq %rsp, %rbp. */
static const gdb_byte mov_rsp_rbp_1[3] = { 0x48, 0x89, 0xe5 };
static const gdb_byte mov_rsp_rbp_2[3] = { 0x48, 0x8b, 0xec };
+ static const gdb_byte endbr64[4] = { 0xf3, 0x0f, 0x1e, 0xfa };
+
/* Ditto for movl %esp, %ebp. */
static const gdb_byte mov_esp_ebp_1[2] = { 0x89, 0xe5 };
static const gdb_byte mov_esp_ebp_2[2] = { 0x8b, 0xec };
- gdb_byte buf[3];
- gdb_byte op;
+ gdb_byte buf[4];
if (current_pc <= pc)
return current_pc;
@@ -2390,43 +2391,54 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
else
pc = amd64_analyze_stack_align (pc, current_pc, cache);
- op = read_code_unsigned_integer (pc, 1, byte_order);
-
- if (op == 0x55) /* pushq %rbp */
+ /* Check for an IBT ENDBRANCH instruction */
+ read_code (pc, buf, sizeof(endbr64));
+ if (memcmp (buf, endbr64, sizeof(endbr64)) == 0)
{
- /* Take into account that we've executed the `pushq %rbp' that
- starts this instruction sequence. */
- cache->saved_regs[AMD64_RBP_REGNUM] = 0;
- cache->sp_offset += 8;
-
+ pc += sizeof(endbr64);
/* If that's all, return now. */
- if (current_pc <= pc + 1)
- return current_pc;
+ if (current_pc <= pc)
+ return current_pc;
+ }
+
+ /* stop right now if there's no `pushq %rbp' */
+ if (read_code_unsigned_integer (pc, 1, byte_order) != 0x55)
+ return pc;
+
+ /* Take into account that we've executed the `pushq %rbp' that
+ starts this instruction sequence. */
+ cache->saved_regs[AMD64_RBP_REGNUM] = 0;
+ cache->sp_offset += 8;
+
+ pc += 1;
+
+ /* If that's all, return now. */
+ if (current_pc <= pc)
+ return current_pc;
- read_code (pc + 1, buf, 3);
+ read_code (pc, buf, 3);
- /* Check for `movq %rsp, %rbp'. */
- if (memcmp (buf, mov_rsp_rbp_1, 3) == 0
- || memcmp (buf, mov_rsp_rbp_2, 3) == 0)
+ /* Check for `movq %rsp, %rbp'. */
+ if (memcmp (buf, mov_rsp_rbp_1, 3) == 0
+ || memcmp (buf, mov_rsp_rbp_2, 3) == 0)
+ {
+ pc += 3;
+ /* OK, we actually have a frame. */
+ cache->frameless_p = 0;
+ return pc;
+ }
+
+ /* For X32, also check for `movq %esp, %ebp'. */
+ if (gdbarch_ptr_bit (gdbarch) == 32)
+ {
+ if (memcmp (buf, mov_esp_ebp_1, 2) == 0
+ || memcmp (buf, mov_esp_ebp_2, 2) == 0)
{
+ pc += 2;
/* OK, we actually have a frame. */
cache->frameless_p = 0;
- return pc + 4;
+ return pc;
}
-
- /* For X32, also check for `movq %esp, %ebp'. */
- if (gdbarch_ptr_bit (gdbarch) == 32)
- {
- if (memcmp (buf, mov_esp_ebp_1, 2) == 0
- || memcmp (buf, mov_esp_ebp_2, 2) == 0)
- {
- /* OK, we actually have a frame. */
- cache->frameless_p = 0;
- return pc + 3;
- }
- }
-
- return pc + 1;
}
return pc;
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 19876c3553..0d1cee26fe 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -1537,6 +1537,24 @@ struct i386_insn i386_frame_setup_skip_insns[] =
{ 0 }
};
+/* Check whether PC points to an endbr32 instruction. */
+static CORE_ADDR
+i386_skip_endbr(CORE_ADDR pc)
+{
+ static const gdb_byte endbr32[] = { 0xf3, 0x0f, 0x1e, 0xfb };
+
+ gdb_byte buf[sizeof(endbr32)];
+
+ /* Stop there if we can't read the code */
+ if (target_read_code (pc, buf, sizeof(endbr32)))
+ return pc;
+
+ /* If the instruction isn't an endbr32, stop */
+ if (memcmp (buf, endbr32, sizeof(endbr32)) != 0)
+ return pc;
+
+ return pc + sizeof(endbr32);
+}
/* Check whether PC points to a no-op instruction. */
static CORE_ADDR
@@ -1814,6 +1832,7 @@ i386_analyze_prologue (struct gdbarch *gdbarch,
CORE_ADDR pc, CORE_ADDR current_pc,
struct i386_frame_cache *cache)
{
+ pc = i386_skip_endbr (pc);
pc = i386_skip_noop (pc);
pc = i386_follow_jump (gdbarch, pc);
pc = i386_analyze_struct_return (pc, current_pc, cache);
--
2.20.1
next reply other threads:[~2020-03-13 0:59 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-13 0:58 Victor Collod [this message]
2020-03-13 1:29 ` H.J. Lu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200313005852.14788-1-vcollod@nvidia.com \
--to=vcollod@nvidia.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox