From: Simon Marchi Date: Mon, 16 Mar 2020 21:36:09 +0000 (-0400) Subject: gdb: use two displaced step buffers on amd64-linux X-Git-Url: https://git.efficios.com/?a=commitdiff_plain;h=0dda35b49a9e5f10682d6e5bb99f03267bb64e34;p=deliverable%2Fbinutils-gdb.git gdb: use two displaced step buffers on amd64-linux At least as observed with gcc 9, there is enough space at _start to have two displaced stepping buffers of 16 bytes. An alternative way is to call mmap in the inferior to allocate one or more executable pages. However, this is more intrusive. --- diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 4cb33d5b5d..ef19be275f 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -44,6 +44,7 @@ #include "glibc-tdep.h" #include "arch/amd64.h" #include "target-descriptions.h" +#include "observable.h" /* The syscall's XML filename for i386. */ #define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml" @@ -1818,12 +1819,29 @@ get_amd64_linux_per_inferior (inferior *inf, gdbarch *arch) if (per_inf == nullptr) { - /* Figure out where the displaced step buffer is. */ - CORE_ADDR disp_step_buffer_addr = linux_displaced_step_location (arch); - - per_inf = amd64_linux_per_inferior_data.emplace (inf, disp_step_buffer_addr); + std::vector 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; } @@ -1835,6 +1853,7 @@ 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); } @@ -2328,6 +2347,18 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) (gdbarch, svr4_ilp32_fetch_link_map_offsets); } +static void +amd64_linux_inferior_appeared (inferior *inf) +{ + amd64_linux_per_inferior_data.clear (inf); +} + +static void +amd64_linux_inferior_execd (inferior *inf) +{ + amd64_linux_per_inferior_data.clear (inf); +} + void _initialize_amd64_linux_tdep (); void _initialize_amd64_linux_tdep () @@ -2336,4 +2367,7 @@ _initialize_amd64_linux_tdep () GDB_OSABI_LINUX, amd64_linux_init_abi); gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x64_32, GDB_OSABI_LINUX, amd64_x32_linux_init_abi); + + gdb::observers::inferior_appeared.attach (amd64_linux_inferior_appeared); + gdb::observers::inferior_execd.attach (amd64_linux_inferior_execd); } diff --git a/gdb/displaced-stepping.h b/gdb/displaced-stepping.h index 7bb02b3bbf..e637c38925 100644 --- a/gdb/displaced-stepping.h +++ b/gdb/displaced-stepping.h @@ -142,6 +142,11 @@ struct multiple_displaced_buffer_manager displaced_step_finish_status finish (gdbarch *arch, thread_info *thread, gdb_signal sig); + CORE_ADDR first_buf_addr () const + { + return m_buffers[0].m_buffer_addr; + } + private: std::vector m_buffers; }; diff --git a/gdb/infrun.c b/gdb/infrun.c index c155899ea6..82aef283a6 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1252,6 +1252,8 @@ follow_exec (ptid_t ptid, const char *exec_file_target) to symbol_file_command...). */ insert_breakpoints (); + gdb::observers::inferior_execd.notify (inf); + /* The next resume of this inferior should bring it to the shlib startup breakpoints. (If the user had also set bp's on "main" from the old (parent) process, then they'll auto- diff --git a/gdb/observable.c b/gdb/observable.c index 81aa392cc2..8462b44c25 100644 --- a/gdb/observable.c +++ b/gdb/observable.c @@ -63,6 +63,7 @@ DEFINE_OBSERVABLE (inferior_added); DEFINE_OBSERVABLE (inferior_appeared); DEFINE_OBSERVABLE (inferior_exit); DEFINE_OBSERVABLE (inferior_removed); +DEFINE_OBSERVABLE (inferior_execd); DEFINE_OBSERVABLE (memory_changed); DEFINE_OBSERVABLE (before_prompt); DEFINE_OBSERVABLE (gdb_datadir_changed); diff --git a/gdb/observable.h b/gdb/observable.h index 070cf0f18e..eafcfb2938 100644 --- a/gdb/observable.h +++ b/gdb/observable.h @@ -184,6 +184,9 @@ extern observable inferior_exit; This method is called immediately before freeing INF. */ extern observable inferior_removed; +/* The inferior INF has exec'ed a new executable file. */ +extern observable inferior_execd; + /* Bytes from DATA to DATA + LEN have been written to the inferior at ADDR. */ extern observable