Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] Add support for intel IBT
@ 2020-03-13  0:58 Victor Collod
  2020-03-13  1:29 ` H.J. Lu
  0 siblings, 1 reply; 2+ messages in thread
From: Victor Collod @ 2020-03-13  0:58 UTC (permalink / raw)
  To: gdb-patches; +Cc: Victor Collod

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



^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Add support for intel IBT
  2020-03-13  0:58 [PATCH] Add support for intel IBT Victor Collod
@ 2020-03-13  1:29 ` H.J. Lu
  0 siblings, 0 replies; 2+ messages in thread
From: H.J. Lu @ 2020-03-13  1:29 UTC (permalink / raw)
  To: Victor Collod; +Cc: GDB

On Thu, Mar 12, 2020 at 5:59 PM Victor Collod via Gdb-patches
<gdb-patches@sourceware.org> wrote:
>
> 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'.  */

It should be "movl %esp, %ebp", not movq.

> +  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;



-- 
H.J.


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-03-13  1:29 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-13  0:58 [PATCH] Add support for intel IBT Victor Collod
2020-03-13  1:29 ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox