+/* The instruction sequences used in x86_64 machines for a
+ disabled is-enabled probe. */
+
+const gdb_byte amd64_dtrace_disabled_probe_sequence_1[] = {
+ /* xor %rax, %rax */ 0x48, 0x33, 0xc0,
+ /* nop */ 0x90,
+ /* nop */ 0x90
+};
+
+const gdb_byte amd64_dtrace_disabled_probe_sequence_2[] = {
+ /* xor %rax, %rax */ 0x48, 0x33, 0xc0,
+ /* ret */ 0xc3,
+ /* nop */ 0x90
+};
+
+/* The instruction sequence used in x86_64 machines for enabling a
+ DTrace is-enabled probe. */
+
+const gdb_byte amd64_dtrace_enable_probe_sequence[] = {
+ /* mov $0x1, %eax */ 0xb8, 0x01, 0x00, 0x00, 0x00
+};
+
+/* The instruction sequence used in x86_64 machines for disabling a
+ DTrace is-enabled probe. */
+
+const gdb_byte amd64_dtrace_disable_probe_sequence[] = {
+ /* xor %rax, %rax; nop; nop */ 0x48, 0x33, 0xC0, 0x90, 0x90
+};
+
+/* Implementation of `gdbarch_dtrace_probe_is_enabled', as defined in
+ gdbarch.h. */
+
+static int
+amd64_dtrace_probe_is_enabled (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_byte buf[5];
+
+ /* This function returns 1 if the instructions at ADDR do _not_
+ follow any of the amd64_dtrace_disabled_probe_sequence_*
+ patterns.
+
+ Note that ADDR is offset 3 bytes from the beginning of these
+ sequences. */
+
+ read_code (addr - 3, buf, 5);
+ return (memcmp (buf, amd64_dtrace_disabled_probe_sequence_1, 5) != 0
+ && memcmp (buf, amd64_dtrace_disabled_probe_sequence_2, 5) != 0);
+}
+
+/* Implementation of `gdbarch_dtrace_enable_probe', as defined in
+ gdbarch.h. */
+
+static void
+amd64_dtrace_enable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ /* Note also that ADDR is offset 3 bytes from the beginning of
+ amd64_dtrace_enable_probe_sequence. */
+
+ write_memory (addr - 3, amd64_dtrace_enable_probe_sequence, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_disable_probe', as defined in
+ gdbarch.h. */
+
+static void
+amd64_dtrace_disable_probe (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ /* Note also that ADDR is offset 3 bytes from the beginning of
+ amd64_dtrace_disable_probe_sequence. */
+
+ write_memory (addr - 3, amd64_dtrace_disable_probe_sequence, 5);
+}
+
+/* Implementation of `gdbarch_dtrace_parse_probe_argument', as defined
+ in gdbarch.h. */
+
+static void
+amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
+ struct expr_builder *builder,
+ int narg)
+{
+ struct stoken str;
+
+ /* DTrace probe arguments can be found on the ABI-defined places for
+ regular arguments at the current PC. The probe abstraction
+ currently supports up to 12 arguments for probes. */
+
+ if (narg < 6)
+ {
+ static const int arg_reg_map[6] =
+ {
+ AMD64_RDI_REGNUM, /* Arg 1. */
+ AMD64_RSI_REGNUM, /* Arg 2. */
+ AMD64_RDX_REGNUM, /* Arg 3. */
+ AMD64_RCX_REGNUM, /* Arg 4. */
+ AMD64_R8_REGNUM, /* Arg 5. */
+ AMD64_R9_REGNUM /* Arg 6. */
+ };
+ int regno = arg_reg_map[narg];
+ const char *regname = user_reg_map_regnum_to_name (gdbarch, regno);
+
+ write_exp_elt_opcode (builder, OP_REGISTER);
+ str.ptr = regname;
+ str.length = strlen (regname);
+ write_exp_string (builder, str);
+ write_exp_elt_opcode (builder, OP_REGISTER);
+ }
+ else
+ {
+ /* Additional arguments are passed on the stack. */
+ const char *regname = user_reg_map_regnum_to_name (gdbarch, AMD64_RSP_REGNUM);
+
+ /* Displacement. */
+ write_exp_elt_opcode (builder, OP_LONG);
+ write_exp_elt_type (builder, builtin_type (gdbarch)->builtin_long);
+ write_exp_elt_longcst (builder, narg - 6);
+ write_exp_elt_opcode (builder, OP_LONG);
+
+ /* Register: SP. */
+ write_exp_elt_opcode (builder, OP_REGISTER);
+ str.ptr = regname;
+ str.length = strlen (regname);
+ write_exp_string (builder, str);
+ write_exp_elt_opcode (builder, OP_REGISTER);
+
+ write_exp_elt_opcode (builder, BINOP_ADD);
+
+ /* Cast to long. */
+ write_exp_elt_opcode (builder, UNOP_CAST);
+ write_exp_elt_type (builder,
+ lookup_pointer_type (builtin_type (gdbarch)->builtin_long));
+ write_exp_elt_opcode (builder, UNOP_CAST);
+
+ write_exp_elt_opcode (builder, UNOP_IND);
+ }
+}
+
+struct amd64_linux_per_inferior
+{
+ amd64_linux_per_inferior (gdb::array_view<CORE_ADDR> disp_step_buffer_addrs)
+ : disp_step_buf_mgr (disp_step_buffer_addrs)
+ {}
+
+ multiple_displaced_buffer_manager disp_step_buf_mgr;
+};
+
+static const inferior_key<amd64_linux_per_inferior>
+ amd64_linux_per_inferior_data;
+
+/* Get the per-inferior AMD64/Linux data for INF. */
+
+static amd64_linux_per_inferior *
+get_amd64_linux_per_inferior (inferior *inf, gdbarch *arch)
+{
+ amd64_linux_per_inferior *per_inf = amd64_linux_per_inferior_data.get (inf);
+
+ if (per_inf == nullptr)
+ {
+ std::vector<CORE_ADDR> buffers;
+#if 0
+ /* Alternative implementation that maps some pages in the inferior,
+ allowing to have many buffers. */
+ CORE_ADDR displaced_step_mmap = gdbarch_infcall_mmap (arch, 16384, GDB_MMAP_PROT_READ | GDB_MMAP_PROT_EXEC);
+ gdb_assert (displaced_step_mmap != 0);
+
+ for (int i = 0; i < 1024; i++)
+ buffers.push_back (displaced_step_mmap + 16 * i);
+
+#else
+ /* Figure out where the displaced step buffers are. */
+ CORE_ADDR addr = linux_displaced_step_location (arch);
+ buffers.push_back (addr);
+ buffers.push_back (addr + gdbarch_max_insn_length (arch));
+#endif
+ per_inf = amd64_linux_per_inferior_data.emplace (inf, buffers);
+ }
+
+ CORE_ADDR addr = per_inf->disp_step_buf_mgr.first_buf_addr ();
+ CORE_ADDR cur_addr = linux_displaced_step_location (arch);
+ gdb_assert (addr == cur_addr);
+
+ return per_inf;
+}
+
+/* Implementation of the gdbarch_displaced_step_prepare method. */
+
+static displaced_step_prepare_status
+amd64_linux_displaced_step_prepare (gdbarch *arch, thread_info *thread)
+{
+ amd64_linux_per_inferior *per_inferior
+ = get_amd64_linux_per_inferior (thread->inf, arch);
+
+
+ return per_inferior->disp_step_buf_mgr.prepare (thread);
+}
+
+/* Implementation of the gdbarch_displaced_step_finish method. */
+
+static displaced_step_finish_status
+amd64_linux_displaced_step_finish (gdbarch *arch, thread_info *thread,
+ gdb_signal sig)
+{
+ amd64_linux_per_inferior *per_inferior
+ = get_amd64_linux_per_inferior (thread->inf, arch);
+
+ return per_inferior->disp_step_buf_mgr.finish (arch, thread, sig);
+}
+