apache / brpc

brpc is an Industrial-grade RPC framework using C++ Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. "brpc" means "better RPC".

Home Page:https://brpc.apache.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

support gdb_bthread_stack.py in coredump

weixinwei opened this issue · comments

Is your feature request related to a problem? (你需要的功能是否与某个问题有关?)
gdb coredump中执行'bthread_frame id'报错

Describe the solution you'd like (描述你期望的解决方法)
简单修改gdb源码,实现在gdb coredump中gdb_bthread_stack.py的功能全部可用

Describe alternatives you've considered (描述你想到的折衷方案)

Additional context/screenshots (更多上下文/截图)
默认gdb
image
修改后gdb
image

gdb修改思路:
core target,增加m_registers寄存器缓存变量,用来接收set $rsp等的临时寄存器值;
同时实现虚函数prepare_to_store和store_registers的override。当store_registers时,m_registers保存当前set的寄存器值。
同时修改fetch_registers,如果m_registers有效,就从直接从m_registers中返回给上层调用者。

Patch如下(基于gdb12.1)

diff -uNr gdb-12.1/gdb/corelow.c gdb-new/gdb/corelow.c
--- gdb-12.1/gdb/corelow.c      2024-04-28 14:20:44.560135484 +0800
+++ gdb-new/gdb/corelow.c       2024-04-28 14:33:54.505499546 +0800
@@ -122,6 +122,9 @@
   /* See definition.  */
   void info_proc_mappings (struct gdbarch *gdbarch);

+  void prepare_to_store (struct regcache *) override {}
+  void store_registers (struct regcache *, int) override;
+
 private: /* per-core data */

   /* The core's section table.  Note that these target sections are
@@ -154,6 +157,18 @@
   /* FIXME: kettenis/20031023: Eventually this field should
      disappear.  */
   struct gdbarch *m_core_gdbarch = NULL;
+
+private:
+  /* register cache for the core file.
+     which is used to fetch&save the registers from the core file.
+     so that we call exec 'set $reg = xxx' in the core file.  */
+
+  /* The register buffers.  */
+  std::unique_ptr<gdb_byte[]> m_registers;
+  /* Register cache status.  */
+  std::unique_ptr<register_status[]> m_register_status;
+  /* current ptid */
+  ptid_t current_ptid = null_ptid;
 };

 core_target::core_target ()
@@ -312,6 +327,9 @@
       current_program_space->cbfd.reset (nullptr);
     }

+  m_registers.reset(nullptr);
+  m_register_status.reset(nullptr);
+
   /* Core targets are heap-allocated (see core_target_open), so here
      we delete ourselves.  */
   delete this;
@@ -739,6 +757,13 @@
       return;
     }
 
+  if (m_registers && current_ptid == regcache->ptid ())
+    {
+      memcpy(regcache->m_registers.get(), m_registers.get(), regcache->sizeof_raw_registers);
+      memcpy(regcache->m_register_status.get(), m_register_status.get(), regcache->num_regs);
+      return;
+    }
+
   struct gdbarch *gdbarch = regcache->arch ();
   get_core_registers_cb_data data = { this, regcache };
   gdbarch_iterate_over_regset_sections (gdbarch,
@@ -749,6 +774,25 @@
   for (int i = 0; i < gdbarch_num_regs (regcache->arch ()); i++)
     if (regcache->get_register_status (i) == REG_UNKNOWN)
       regcache->raw_supply (i, NULL);
+
+  if (m_registers == nullptr || current_ptid != regcache->ptid ())
+    {
+      m_registers.reset (new gdb_byte[regcache->sizeof_raw_registers]);
+      m_register_status.reset (new register_status[regcache->num_regs]);
+      current_ptid = regcache->ptid ();
+
+      memcpy(m_registers.get(), regcache->m_registers.get(), regcache->sizeof_raw_registers);
+      memcpy(m_register_status.get(), regcache->m_register_status.get(), regcache->num_regs);
+    }
+}
+
+void
+core_target::store_registers (struct regcache *regcache, int regnum)
+{
+  memcpy(m_registers.get() + regcache->register_offset[regnum],
+         regcache->m_registers.get() + regcache->register_offset[regnum],
+         regcache->sizeof_register[regnum]);
+  m_register_status[regnum] = REG_VALID;
 }

 void
 diff -uNr gdb-12.1/gdb/regcache.c gdb-new/gdb/regcache.c
--- gdb-12.1/gdb/regcache.c     2022-05-02 02:46:31.000000000 +0800
+++ gdb-new/gdb/regcache.c      2024-04-28 14:31:32.225651588 +0800
@@ -198,6 +198,11 @@
       m_registers.reset (new gdb_byte[m_descr->sizeof_raw_registers]);
       m_register_status.reset
        (new register_status[gdbarch_num_regs (gdbarch)] ());
+
+      sizeof_raw_registers = m_descr->sizeof_raw_registers;
+      num_regs = gdbarch_num_regs (gdbarch);
+      register_offset = m_descr->register_offset;
+      sizeof_register = m_descr->sizeof_register;
     }
 }

diff -uNr gdb-12.1/gdb/regcache.h gdb-new/gdb/regcache.h
--- gdb-12.1/gdb/regcache.h     2022-03-20 12:59:56.000000000 +0800
+++ gdb-new/gdb/regcache.h      2024-04-28 14:30:54.680636185 +0800
@@ -260,11 +260,19 @@
   struct regcache_descr *m_descr;

   bool m_has_pseudo;
+
+public:
   /* The register buffers.  */
   std::unique_ptr<gdb_byte[]> m_registers;
   /* Register cache status.  */
   std::unique_ptr<register_status[]> m_register_status;

+  // used for corelow.c
+  long sizeof_raw_registers;
+  int num_regs;
+  long *register_offset;
+  long *sizeof_register;
+
   friend class regcache;
   friend class detached_regcache;
 };