@@ -50,6 +50,14 @@
_t; \
})
+typedef struct InitedAddr {
+ target_ulong addr;
+ bool is_init;
+} InitedAddr;
+
+InitedAddr *windbg_get_KPCR(void);
+InitedAddr *windbg_get_version(void);
+
bool windbg_on_load(void);
#endif
@@ -12,7 +12,54 @@
#include "qemu/osdep.h"
#include "exec/windbgstub-utils.h"
+#ifdef TARGET_X86_64
+# define OFFSET_SELF_PCR 0x18
+# define OFFSET_VERS 0x108
+#else
+# define OFFSET_SELF_PCR 0x1C
+# define OFFSET_VERS 0x34
+#endif
+
bool windbg_on_load(void)
{
- return false;
+ CPUState *cpu = qemu_get_cpu(0);
+ CPUArchState *env = cpu->env_ptr;
+ InitedAddr *KPCR = windbg_get_KPCR();
+ InitedAddr *version = windbg_get_version();
+
+ if (!KPCR->is_init) {
+
+ #ifdef TARGET_X86_64
+ KPCR->addr = env->segs[R_GS].base;
+ #else
+ KPCR->addr = env->segs[R_FS].base;
+ #endif
+
+ static target_ulong prev_KPCR;
+ if (!KPCR->addr || prev_KPCR == KPCR->addr) {
+ return false;
+ }
+ prev_KPCR = KPCR->addr;
+
+ if (KPCR->addr != READ_VMEM(cpu, KPCR->addr + OFFSET_SELF_PCR,
+ target_ulong)) {
+ return false;
+ }
+
+ KPCR->is_init = true;
+ }
+
+ if (!version->is_init && KPCR->is_init) {
+ version->addr = READ_VMEM(cpu, KPCR->addr + OFFSET_VERS,
+ target_ulong);
+ if (!version->addr) {
+ return false;
+ }
+ version->is_init = true;
+ }
+
+ WINDBG_DEBUG("windbg_on_load: KPCR " FMT_ADDR, KPCR->addr);
+ WINDBG_DEBUG("windbg_on_load: version " FMT_ADDR, version->addr);
+
+ return true;
}
@@ -10,3 +10,16 @@
*/
#include "exec/windbgstub-utils.h"
+
+static InitedAddr KPCR;
+static InitedAddr version;
+
+InitedAddr *windbg_get_KPCR(void)
+{
+ return &KPCR;
+}
+
+InitedAddr *windbg_get_version(void)
+{
+ return &version;
+}
@@ -17,6 +17,7 @@
#include "exec/windbgstub.h"
#include "exec/windbgstub-utils.h"
#include "sysemu/kvm.h"
+#include "sysemu/reset.h"
typedef struct WindbgState {
bool is_loaded;
@@ -46,6 +47,13 @@ static void windbg_exit(void)
g_free(windbg_state);
}
+static void windbg_handle_reset(void *opaque)
+{
+ windbg_state->is_loaded = false;
+ windbg_get_KPCR()->is_init = false;
+ windbg_get_version()->is_init = false;
+}
+
void windbg_try_load(void)
{
if (windbg_state && !windbg_state->is_loaded) {
@@ -85,6 +93,8 @@ int windbg_server_start(const char *device)
qemu_chr_fe_set_handlers(&windbg_state->chr, windbg_chr_can_receive,
windbg_chr_receive, NULL, NULL, NULL, NULL, true);
+ qemu_register_reset(windbg_handle_reset, NULL);
+
atexit(windbg_exit);
return 0;
}