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 (描述你想到的折衷方案)
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;
};