Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Aktemur, Tankut Baris" <tankut.baris.aktemur@intel.com>
To: Luis Machado <luis.machado@linaro.org>,
	"gdb-patches@sourceware.org"	<gdb-patches@sourceware.org>
Subject: RE: [PATCH] [AArch64] Recognize more program breakpoint patterns
Date: Thu, 09 Jan 2020 15:59:00 -0000	[thread overview]
Message-ID: <BYAPR11MB3030C0137E32629A7DCBC1A8C4390@BYAPR11MB3030.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20191223173432.16955-1-luis.machado@linaro.org>

On Monday, December 23, 2019 6:35 PM, Luis Machado wrote:
> 
> It was reported to me that program breakpoints (permanent ones inserted into
> the code itself) other than the one GDB uses for AArch64 (0xd4200000) do not
> generate visible stops when continuing, and GDB will continue spinning
> infinitely.
> 
> This happens because GDB, upon hitting one of those program breakpoints, thinks
> the SIGTRAP came from a delayed breakpoint hit...
> 
> (gdb) x/i $pc
> => 0x4005c0 <problem_function>: brk     #0x90f
> (gdb) c
> Continuing.
> infrun: clear_proceed_status_thread (process 14198)
> infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT)
> infrun: proceed: resuming process 14198
> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0
> infrun: infrun_async(1)
> infrun: prepare_to_wait
> infrun: target_wait (-1.0.0, status) =
> infrun:   14198.14198.0 [process 14198],
> infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: stop_pc = 0x4005c0
> infrun: delayed software breakpoint trap, ignoring
> infrun: no stepping, continue
> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0
> infrun: prepare_to_wait
> infrun: target_wait (-1.0.0, status) =
> infrun:   14198.14198.0 [process 14198],
> infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: stop_pc = 0x4005c0
> infrun: delayed software breakpoint trap, ignoring
> infrun: no stepping, continue
> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0
> infrun: prepare_to_wait
> infrun: target_wait (-1.0.0, status) =
> infrun:   14198.14198.0 [process 14198],
> infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: stop_pc = 0x4005c0
> infrun: delayed software breakpoint trap, ignoring
> infrun: no stepping, continue
> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0
> infrun: prepare_to_wait
> infrun: target_wait (-1.0.0, status) =
> infrun:   14198.14198.0 [process 14198],
> infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: stop_pc = 0x4005c0
> infrun: delayed software breakpoint trap, ignoring
> infrun: no stepping, continue
> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14198] at 0x4005c0
> infrun: prepare_to_wait
> infrun: target_wait (-1.0.0, status) =
> infrun:   14198.14198.0 [process 14198],
> infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
> ...
> 
> ... which is not the case.
> 
> If the program breakpoint is one GDB recognizes, then it will stop when it
> hits it.
> 
> (gdb) x/i $pc
> => 0x4005c0 <problem_function>: brk     #0x0
> (gdb) c
> Continuing.
> infrun: clear_proceed_status_thread (process 14193)
> infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT)
> infrun: proceed: resuming process 14193
> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 14193] at 0x4005c0
> infrun: infrun_async(1)
> infrun: prepare_to_wait
> infrun: target_wait (-1.0.0, status) =
> infrun:   14193.14193.0 [process 14193],
> infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: stop_pc = 0x4005c0
> infrun: random signal (GDB_SIGNAL_TRAP)
> infrun: stop_waiting
> infrun: stop_all_threads
> infrun: stop_all_threads, pass=0, iterations=0
> infrun:   process 14193 not executing
> infrun: stop_all_threads, pass=1, iterations=1
> infrun:   process 14193 not executing
> infrun: stop_all_threads done
> 
> Program received signal SIGTRAP, Trace/breakpoint trap.
> problem_function () at brk_0.c:7
> 7        asm("brk %0\n\t" ::"n"(0x0));
> infrun: infrun_async(0)
> 
> Otherwise GDB will keep trying to resume the inferior and will keep
> seeing the SIGTRAP's, without stopping.
> 
> To the user it appears GDB has gone into an infinite loop, interruptible only
> by Ctrl-C.
> 
> Also, windbg seems to use a different variation of AArch64 breakpoint compared
> to GDB. This causes problems when debugging Windows on ARM binaries, when
> program breakpoints are being used.
> 
> The proposed patch creates a new gdbarch method (gdbarch_insn_is_breakpoint)
> that tells GDB whether the underlying instruction is a breakpoint instruction
> or not.
> 
> This is more general than only checking for the instruction GDB uses as
> breakpoint.
> 
> The existing logic is still preserved for targets that do not implement this
> new gdbarch method.
> 
> The end result is like so:
> 
> (gdb) x/i $pc
> => 0x4005c0 <problem_function>: brk     #0x90f
> (gdb) c
> Continuing.
> infrun: clear_proceed_status_thread (process 16417)
> infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT)
> infrun: proceed: resuming process 16417
> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 16417] at 0x4005c0
> infrun: infrun_async(1)
> infrun: prepare_to_wait
> infrun: target_wait (-1.0.0, status) =
> infrun:   16417.16417.0 [process 16417],
> infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: handle_inferior_event status->kind = stopped, signal = GDB_SIGNAL_TRAP
> infrun: stop_pc = 0x4005c0
> infrun: random signal (GDB_SIGNAL_TRAP)
> infrun: stop_waiting
> infrun: stop_all_threads
> infrun: stop_all_threads, pass=0, iterations=0
> infrun:   process 16417 not executing
> infrun: stop_all_threads, pass=1, iterations=1
> infrun:   process 16417 not executing
> infrun: stop_all_threads done
> 
> Program received signal SIGTRAP, Trace/breakpoint trap.
> problem_function () at brk.c:7
> 7        asm("brk %0\n\t" ::"n"(0x900 + 0xf));
> infrun: infrun_async(0)
> 
> Does this change look ok?
> 
> gdb/ChangeLog:
> 
> 2019-12-23  Luis Machado  <luis.machado@linaro.org>
> 
> 	* aarch64-tdep.c (BRK_INSN_MASK): Define to 0xd4200000.
> 	(aarch64_insn_is_breakpoint): New function.
> 	(aarch64_gdbarch_init): Set gdbarch_insn_is_breakpoint hook.
> 	* arch-utils.c (default_insn_is_breakpoint): New function.
> 	* arch-utils.h (default_insn_is_breakpoint): New prototype.
> 	* breakpoint.c (program_breakpoint_here): Updated to use
> 	  gdbarch_insn_is_breakpoint.
> 	Update documentation to clarify behavior.
> 	* gdbarch.c: Regenerate.
> 	* gdbarch.h: Regenerate.
> 	* gdbarch.sh (gdbarch_insn_is_breakpoint): New method.
> 
> Change-Id: I96eb27151442f435560a58c87eac48b0f68432bc
> ---
>  gdb/aarch64-tdep.c | 25 +++++++++++++++++++++++++
>  gdb/arch-utils.c   |  7 +++++++
>  gdb/arch-utils.h   |  3 +++
>  gdb/breakpoint.c   | 19 ++++++++++++++-----
>  gdb/gdbarch.c      | 23 +++++++++++++++++++++++
>  gdb/gdbarch.h      |  7 +++++++
>  gdb/gdbarch.sh     |  4 ++++
>  7 files changed, 83 insertions(+), 5 deletions(-)
> 
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index 1d5fb2001d..c69361d4ea 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -1201,6 +1201,28 @@ aarch64_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op,
>    return false;
>  }
> 
> +#define BRK_INSN_MASK 0xd4200000

I have a general question here.  Given that GDB is using C++11, would it
make more sense to have this as

  static constexpr uint32_t BRK_INSN_MASK = 0xd4200000;

for more type-safety for the uses of this #define?

> +
> +/* Implementation of gdbarch_insn_is_breakpoint for aarch64.  */
> +
> +static bool
> +aarch64_insn_is_breakpoint (gdbarch *gdbarch,
> +			    const gdb_byte *insn,
> +			    unsigned int insn_size)
> +{
> +  gdb_assert (insn != nullptr);
> +
> +  uint32_t i;
> +
> +  i = (uint32_t) extract_unsigned_integer (insn, insn_size,
> +					   gdbarch_byte_order (gdbarch));

The declaration and the definition can be combined.

> +
> +  /* Check if INSN is a BRK instruction pattern.  There are multiple choices
> +     of such instructions with different immediate values.  Different OS' may
> +     use a different variation, but they have the same outcome.  */
> +  return (i & BRK_INSN_MASK) == BRK_INSN_MASK;
> +}
> +
>  /* When arguments must be pushed onto the stack, they go on in reverse
>     order.  The code below implements a FILO (stack) to do this.  */
> 
> @@ -3357,6 +3379,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    set_gdbarch_execute_dwarf_cfa_vendor_op (gdbarch,
>  					   aarch64_execute_dwarf_cfa_vendor_op);
> 
> +  /* Permanent/Program breakpoint handling.  */
> +  set_gdbarch_insn_is_breakpoint (gdbarch, aarch64_insn_is_breakpoint);
> +
>    /* Add some default predicates.  */
>    frame_unwind_append_unwinder (gdbarch, &aarch64_stub_unwind);
>    dwarf2_append_unwinders (gdbarch);
> diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
> index a1a003f91f..99c9f281be 100644
> --- a/gdb/arch-utils.c
> +++ b/gdb/arch-utils.c
> @@ -876,6 +876,13 @@ int default_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr)
>    return 0;
>  }
> 
> +bool default_insn_is_breakpoint (struct gdbarch *gdbarch,

Function name shall start at column 0.

Regards,
-Baris

Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Gary Kershaw
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

  parent reply	other threads:[~2020-01-09 15:59 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-23 17:34 Luis Machado
2020-01-09 14:52 ` Alan Hayward
2020-01-09 15:45   ` Luis Machado
2020-01-09 16:26     ` Alan Hayward
2020-01-10 14:58       ` Luis Machado
2020-01-10 16:53         ` Alan Hayward
2020-01-09 15:59 ` Aktemur, Tankut Baris [this message]
2020-01-13 17:03 ` [PATCH 1/2] " Luis Machado
2020-01-13 17:06   ` [PATCH 2/2] [AArch64] Test handling of additional brk instruction patterns Luis Machado
2020-01-13 17:25   ` [PATCH 1/2] [AArch64] Recognize more program breakpoint patterns Luis Machado

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=BYAPR11MB3030C0137E32629A7DCBC1A8C4390@BYAPR11MB3030.namprd11.prod.outlook.com \
    --to=tankut.baris.aktemur@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=luis.machado@linaro.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