* [Qemu-devel] [PATCH] x86_64 debug registers for gdb
@ 2006-09-19 20:51 Jason Wessel
2007-04-18 20:53 ` [Qemu-devel] " Jan Kiszka
0 siblings, 1 reply; 10+ messages in thread
From: Jason Wessel @ 2006-09-19 20:51 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 226 bytes --]
This patch fixes the registers for the 'g' and 'G' packets for the
qemu-system-x86_64 target. It allows gdb 6.5 to debug a linux kernel
and get a stack back trace.
signed-off-by: jason.wessel@windriver.com
Thanks,
Jason.
[-- Attachment #2: x86-64_gdb.patch --]
[-- Type: text/plain, Size: 2151 bytes --]
Index: qemu/gdbstub.c
===================================================================
--- qemu.orig/gdbstub.c
+++ qemu/gdbstub.c
@@ -184,9 +184,70 @@ static int put_packet(GDBState *s, char
}
return 0;
}
+#if defined(TARGET_X86_64)
+/* Defines from GDB register struct numbers */
+#define _RAX 0
+#define _RDX 1
+#define _RCX 2
+#define _RBX 3
+#define _RSI 4
+#define _RDI 5
+#define _RBP 6
+#define _RSP 7
+#define _R8 8
+#define _R9 9
+#define _R10 10
+#define _R11 11
+#define _R12 12
+#define _R13 13
+#define _R14 14
+#define _R15 15
+#define _PC 16
+#define _PS 17
-#if defined(TARGET_I386)
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+ uint64_t *registers = (uint64_t *)mem_buf;
+ int i;
+
+ registers[_RAX] = env->regs[R_EAX];
+ registers[_RBX] = env->regs[R_EBX];
+ registers[_RCX] = env->regs[R_ECX];
+ registers[_RDX] = env->regs[R_EDX];
+ registers[_RSI] = env->regs[R_ESI];
+ registers[_RDI] = env->regs[R_EDI];
+ registers[_RBP] = env->regs[R_EBP];
+ registers[_RSP] = env->regs[R_ESP];
+ for (i = 8; i < 16; i++)
+ registers[i] = env->regs[i];
+ registers[_PC] = env->eip;
+ registers[_PS] = env->eflags;
+ for(i = 0; i < 18; i++)
+ tswapl(registers[i]);
+
+ return 18 * 8;
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+ uint32_t *registers = (uint32_t *)mem_buf;
+ int i;
+
+ env->regs[R_EAX] = tswapl(registers[_RAX]);
+ env->regs[R_EBX] = tswapl(registers[_RBX]);
+ env->regs[R_ECX] = tswapl(registers[_RCX]);
+ env->regs[R_EDX] = tswapl(registers[_RDX]);
+ env->regs[R_ESI] = tswapl(registers[_RSI]);
+ env->regs[R_EDI] = tswapl(registers[_RDI]);
+ env->regs[R_EBP] = tswapl(registers[_RBP]);
+ env->regs[R_ESP] = tswapl(registers[_RSP]);
+ for (i = 8; i < 16; i++)
+ env->regs[i] = tswapl(registers[i]);
+ env->eip = tswapl(registers[_PC]);
+ env->eflags = tswapl(registers[_PS]);
+}
+#elif defined(TARGET_I386)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
uint32_t *registers = (uint32_t *)mem_buf;
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2006-09-19 20:51 [Qemu-devel] [PATCH] x86_64 debug registers for gdb Jason Wessel
@ 2007-04-18 20:53 ` Jan Kiszka
2007-04-19 15:11 ` Paul Brook
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kiszka @ 2007-04-18 20:53 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 3048 bytes --]
Jason Wessel wrote:
> This patch fixes the registers for the 'g' and 'G' packets for the
> qemu-system-x86_64 target. It allows gdb 6.5 to debug a linux kernel
> and get a stack back trace.
Here comes a corrected (RBX and RDX were mixed) and slightly enhanced
(segment register reading, don't know how writing should look like)
version of this patch. Tested successfully with qemu-0.9.0 and gdb-6.6.
Would be nice to see this support in the next qemu release.
Jan
Index: qemu-0.9.0/gdbstub.c
===================================================================
--- qemu-0.9.0.orig/gdbstub.c
+++ qemu-0.9.0/gdbstub.c
@@ -220,9 +220,78 @@ static int put_packet(GDBState *s, char
}
return 0;
}
+#if defined(TARGET_X86_64)
+/* Defines from GDB register struct numbers */
+#define _RAX 0
+#define _RBX 1
+#define _RCX 2
+#define _RDX 3
+#define _RSI 4
+#define _RDI 5
+#define _RBP 6
+#define _RSP 7
+#define _R8 8
+#define _R15 15
+#define _PC 16
+#define _PS 17
+#define _CS 18
+#define _SS 19
+#define _DS 20
+#define _ES 21
+#define _FS 22
+#define _GS 23
+#define _NREGS 24
-#if defined(TARGET_I386)
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+ uint64_t *registers = (uint64_t *)mem_buf;
+ int i;
+
+ registers[_RAX] = env->regs[R_EAX];
+ registers[_RBX] = env->regs[R_EBX];
+ registers[_RCX] = env->regs[R_ECX];
+ registers[_RDX] = env->regs[R_EDX];
+ registers[_RSI] = env->regs[R_ESI];
+ registers[_RDI] = env->regs[R_EDI];
+ registers[_RBP] = env->regs[R_EBP];
+ registers[_RSP] = env->regs[R_ESP];
+ for (i = 8; i < 16; i++)
+ registers[i] = env->regs[i];
+ registers[_PC] = env->eip;
+ registers[_PS] = env->eflags;
+ registers[_CS] = env->segs[R_CS].selector;
+ registers[_SS] = env->segs[R_SS].selector;
+ registers[_DS] = env->segs[R_DS].selector;
+ registers[_ES] = env->segs[R_ES].selector;
+ registers[_FS] = env->segs[R_FS].selector;
+ registers[_GS] = env->segs[R_GS].selector;
+
+ for(i = 0; i < _NREGS; i++)
+ tswapl(registers[i]);
+
+ return _NREGS * 8;
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+ uint32_t *registers = (uint32_t *)mem_buf;
+ int i;
+
+ env->regs[R_EAX] = tswapl(registers[_RAX]);
+ env->regs[R_EBX] = tswapl(registers[_RBX]);
+ env->regs[R_ECX] = tswapl(registers[_RCX]);
+ env->regs[R_EDX] = tswapl(registers[_RDX]);
+ env->regs[R_ESI] = tswapl(registers[_RSI]);
+ env->regs[R_EDI] = tswapl(registers[_RDI]);
+ env->regs[R_EBP] = tswapl(registers[_RBP]);
+ env->regs[R_ESP] = tswapl(registers[_RSP]);
+ for (i = 8; i < 16; i++)
+ env->regs[i] = tswapl(registers[i]);
+ env->eip = tswapl(registers[_PC]);
+ env->eflags = tswapl(registers[_PS]);
+}
+#elif defined(TARGET_I386)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
uint32_t *registers = (uint32_t *)mem_buf;
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2007-04-18 20:53 ` [Qemu-devel] " Jan Kiszka
@ 2007-04-19 15:11 ` Paul Brook
2007-04-19 21:30 ` Jan Kiszka
0 siblings, 1 reply; 10+ messages in thread
From: Paul Brook @ 2007-04-19 15:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Jan Kiszka
On Wednesday 18 April 2007 21:53, Jan Kiszka wrote:
> Jason Wessel wrote:
> > This patch fixes the registers for the 'g' and 'G' packets for the
> > qemu-system-x86_64 target. It allows gdb 6.5 to debug a linux kernel
> > and get a stack back trace.
>
> Here comes a corrected (RBX and RDX were mixed) and slightly enhanced
> (segment register reading, don't know how writing should look like)
> version of this patch. Tested successfully with qemu-0.9.0 and gdb-6.6.
> Would be nice to see this support in the next qemu release.
Can't you recycle the i386 code, like other 64-bit targets do?
Paul
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2007-04-19 15:11 ` Paul Brook
@ 2007-04-19 21:30 ` Jan Kiszka
2007-04-20 12:55 ` Paul Brook
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kiszka @ 2007-04-19 21:30 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 5403 bytes --]
Paul Brook wrote:
> On Wednesday 18 April 2007 21:53, Jan Kiszka wrote:
>> Jason Wessel wrote:
>>> This patch fixes the registers for the 'g' and 'G' packets for the
>>> qemu-system-x86_64 target. It allows gdb 6.5 to debug a linux kernel
>>> and get a stack back trace.
>> Here comes a corrected (RBX and RDX were mixed) and slightly enhanced
>> (segment register reading, don't know how writing should look like)
>> version of this patch. Tested successfully with qemu-0.9.0 and gdb-6.6.
>> Would be nice to see this support in the next qemu release.
>
> Can't you recycle the i386 code, like other 64-bit targets do?
>
For sure I can :). Is this version better? According to a quick check, it gives identical binaries on i386 and appears to work fine on x86_64.
Jan
---
gdbstub.c | 99 ++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 62 insertions(+), 37 deletions(-)
Index: qemu-0.9.0/gdbstub.c
===================================================================
--- qemu-0.9.0.orig/gdbstub.c
+++ qemu-0.9.0/gdbstub.c
@@ -223,63 +223,88 @@ static int put_packet(GDBState *s, char
#if defined(TARGET_I386)
+#if defined(TARGET_X86_64)
+#define _GP_REGS 16
+#define _FPCTL_OFS 34
+#define _NREGS 42
+#else /* i386 */
+#define _GP_REGS 8
+#define _FPCTL_OFS 36
+#define _NREGS 44
+#endif
+
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
- uint32_t *registers = (uint32_t *)mem_buf;
+ target_ulong *registers = (target_ulong *)mem_buf;
int i, fpus;
- for(i = 0; i < 8; i++) {
+ for(i = 0; i < _GP_REGS; i++)
registers[i] = env->regs[i];
- }
- registers[8] = env->eip;
- registers[9] = env->eflags;
- registers[10] = env->segs[R_CS].selector;
- registers[11] = env->segs[R_SS].selector;
- registers[12] = env->segs[R_DS].selector;
- registers[13] = env->segs[R_ES].selector;
- registers[14] = env->segs[R_FS].selector;
- registers[15] = env->segs[R_GS].selector;
+#if defined(TARGET_X86_64)
+ /* Fix-up register mapping */
+ registers[1] = env->regs[R_EBX];
+ registers[2] = env->regs[R_ECX];
+ registers[3] = env->regs[R_EDX];
+#endif
+
+ registers[_GP_REGS] = env->eip;
+ registers[_GP_REGS+1] = env->eflags;
+
+ registers[_GP_REGS+2] = env->segs[R_CS].selector;
+ registers[_GP_REGS+3] = env->segs[R_SS].selector;
+ registers[_GP_REGS+4] = env->segs[R_DS].selector;
+ registers[_GP_REGS+5] = env->segs[R_ES].selector;
+ registers[_GP_REGS+6] = env->segs[R_FS].selector;
+ registers[_GP_REGS+7] = env->segs[R_GS].selector;
+
/* XXX: convert floats */
- for(i = 0; i < 8; i++) {
- memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
- }
- registers[36] = env->fpuc;
+ for (i = 0; i < 8; i++)
+ memcpy(mem_buf + (_GP_REGS+8) * sizeof(target_ulong) + i * 10,
+ &env->fpregs[i], 10);
+
+ registers[_FPCTL_OFS] = env->fpuc;
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- registers[37] = fpus;
- registers[38] = 0; /* XXX: convert tags */
- registers[39] = 0; /* fiseg */
- registers[40] = 0; /* fioff */
- registers[41] = 0; /* foseg */
- registers[42] = 0; /* fooff */
- registers[43] = 0; /* fop */
-
- for(i = 0; i < 16; i++)
+ registers[_FPCTL_OFS+1] = fpus;
+ registers[_FPCTL_OFS+2] = 0; /* XXX: convert tags */
+ registers[_FPCTL_OFS+3] = 0; /* fiseg */
+ registers[_FPCTL_OFS+4] = 0; /* fioff */
+ registers[_FPCTL_OFS+5] = 0; /* foseg */
+ registers[_FPCTL_OFS+6] = 0; /* fooff */
+ registers[_FPCTL_OFS+7] = 0; /* fop */
+
+ for (i = 0; i < _GP_REGS+8; i++)
tswapls(®isters[i]);
- for(i = 36; i < 44; i++)
+ for (i = _FPCTL_OFS; i < _FPCTL_OFS+8; i++)
tswapls(®isters[i]);
- return 44 * 4;
+ return _NREGS * sizeof(target_ulong);
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
- uint32_t *registers = (uint32_t *)mem_buf;
+ target_ulong *registers = (target_ulong *)mem_buf;
int i;
- for(i = 0; i < 8; i++) {
+ for(i = 0; i < _GP_REGS; i++)
env->regs[i] = tswapl(registers[i]);
- }
- env->eip = tswapl(registers[8]);
- env->eflags = tswapl(registers[9]);
+#if defined(TARGET_X86_64)
+ /* Fix-up register mapping */
+ env->regs[R_EBX] = tswapl(registers[1]);
+ env->regs[R_ECX] = tswapl(registers[2]);
+ env->regs[R_EDX] = tswapl(registers[3]);
+#endif
+
+ env->eip = tswapl(registers[_GP_REGS]);
+ env->eflags = tswapl(registers[_GP_REGS+1]);
#if defined(CONFIG_USER_ONLY)
#define LOAD_SEG(index, sreg)\
if (tswapl(registers[index]) != env->segs[sreg].selector)\
cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
- LOAD_SEG(10, R_CS);
- LOAD_SEG(11, R_SS);
- LOAD_SEG(12, R_DS);
- LOAD_SEG(13, R_ES);
- LOAD_SEG(14, R_FS);
- LOAD_SEG(15, R_GS);
+ LOAD_SEG(_GP_REGS+2, R_CS);
+ LOAD_SEG(_GP_REGS+3, R_SS);
+ LOAD_SEG(_GP_REGS+4, R_DS);
+ LOAD_SEG(_GP_REGS+5, R_ES);
+ LOAD_SEG(_GP_REGS+6, R_FS);
+ LOAD_SEG(_GP_REGS+7, R_GS);
#endif
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2007-04-19 21:30 ` Jan Kiszka
@ 2007-04-20 12:55 ` Paul Brook
2007-04-20 22:15 ` Jan Kiszka
0 siblings, 1 reply; 10+ messages in thread
From: Paul Brook @ 2007-04-20 12:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Jan Kiszka
On Thursday 19 April 2007 22:30, Jan Kiszka wrote:
> + registers[_GP_REGS+2] = env->segs[R_CS].selector;
> + registers[_GP_REGS+3] = env->segs[R_SS].selector;
> + registers[_GP_REGS+4] = env->segs[R_DS].selector;
> + registers[_GP_REGS+5] = env->segs[R_ES].selector;
> + registers[_GP_REGS+6] = env->segs[R_FS].selector;
> + registers[_GP_REGS+7] = env->segs[R_GS].selector;
>
> + registers[_FPCTL_OFS] = env->fpuc;
> + registers[_FPCTL_OFS+1] = fpus;
> + registers[_FPCTL_OFS+2] = 0; /* XXX: convert tags */
> + registers[_FPCTL_OFS+3] = 0; /* fiseg */
> + registers[_FPCTL_OFS+4] = 0; /* fioff */
> + registers[_FPCTL_OFS+5] = 0; /* foseg */
> + registers[_FPCTL_OFS+6] = 0; /* fooff */
> + registers[_FPCTL_OFS+7] = 0; /* fop */
> + for (i = _FPCTL_OFS; i < _FPCTL_OFS+8; i++)
> tswapls(®isters[i]);
These are all wrong on x86-64.
Paul
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2007-04-20 12:55 ` Paul Brook
@ 2007-04-20 22:15 ` Jan Kiszka
2007-04-20 23:13 ` Paul Brook
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kiszka @ 2007-04-20 22:15 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1175 bytes --]
Paul Brook wrote:
> On Thursday 19 April 2007 22:30, Jan Kiszka wrote:
>> + registers[_GP_REGS+2] = env->segs[R_CS].selector;
>> + registers[_GP_REGS+3] = env->segs[R_SS].selector;
>> + registers[_GP_REGS+4] = env->segs[R_DS].selector;
>> + registers[_GP_REGS+5] = env->segs[R_ES].selector;
>> + registers[_GP_REGS+6] = env->segs[R_FS].selector;
>> + registers[_GP_REGS+7] = env->segs[R_GS].selector;
>>
>> + registers[_FPCTL_OFS] = env->fpuc;
>> + registers[_FPCTL_OFS+1] = fpus;
>> + registers[_FPCTL_OFS+2] = 0; /* XXX: convert tags */
>> + registers[_FPCTL_OFS+3] = 0; /* fiseg */
>> + registers[_FPCTL_OFS+4] = 0; /* fioff */
>> + registers[_FPCTL_OFS+5] = 0; /* foseg */
>> + registers[_FPCTL_OFS+6] = 0; /* fooff */
>> + registers[_FPCTL_OFS+7] = 0; /* fop */
>> + for (i = _FPCTL_OFS; i < _FPCTL_OFS+8; i++)
>> tswapls(®isters[i]);
>
> These are all wrong on x86-64.
>
Then what about pointing me to the correct information to fix this, hmm?
I browsed gdb code and docs but found no obvious packet format
description. Constructive help is welcome, likely I'm just blind.
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2007-04-20 22:15 ` Jan Kiszka
@ 2007-04-20 23:13 ` Paul Brook
2007-04-21 17:45 ` Jan Kiszka
0 siblings, 1 reply; 10+ messages in thread
From: Paul Brook @ 2007-04-20 23:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Jan Kiszka
> > These are all wrong on x86-64.
>
> Then what about pointing me to the correct information to fix this, hmm?
> I browsed gdb code and docs but found no obvious packet format
> description. Constructive help is welcome, likely I'm just blind.
gdb/amd64-tdep.c is the authorative source. Specifically amd64_register_info.
Similar information also in gdb/regformats/reg-x86-64.dat
Paul
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2007-04-20 23:13 ` Paul Brook
@ 2007-04-21 17:45 ` Jan Kiszka
2007-04-23 9:13 ` Jan Kiszka
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kiszka @ 2007-04-21 17:45 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 6088 bytes --]
Paul Brook wrote:
>>> These are all wrong on x86-64.
>> Then what about pointing me to the correct information to fix this, hmm?
>> I browsed gdb code and docs but found no obvious packet format
>> description. Constructive help is welcome, likely I'm just blind.
>
> gdb/amd64-tdep.c is the authorative source. Specifically amd64_register_info.
> Similar information also in gdb/regformats/reg-x86-64.dat
>
Yep, I was blind.
Here comes another try. Please have a look/comment on the following
specifically:
- Why is there no fpu-related code in cpu_gdb_write_registers()? Is fpu
debugging only partially supported yet?
- I included xmm and mxcsr regs into cpu_gdb_read_registers(), but I'm
not sure if it's correct (byte ordering, format of mxcsr)
- If I understood gdb correctly, fpu registers (st0..7) are always
encoded in an arch-neutral format, no conversion on exchange is
needed. Thus, is it correct to remove the related "XXX" comment from
cpu_gdb_read_registers()?
- Would it be simple to get the remaining fpu control registers right?
Just to take the chance and finalise this code if we are already at
it.
Jan
---
gdbstub.c | 118 ++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 73 insertions(+), 45 deletions(-)
Index: qemu-0.9.0/gdbstub.c
===================================================================
--- qemu-0.9.0.orig/gdbstub.c
+++ qemu-0.9.0/gdbstub.c
@@ -222,64 +222,92 @@ static int put_packet(GDBState *s, char
}
#if defined(TARGET_I386)
+struct x86_gdb_regs {
+ target_ulong gp[CPU_NB_REGS];
+ target_ulong ip;
+ uint32_t flags;
+ uint32_t segm[6];
+ uint8_t fpreg[8][10];
+ uint32_t fpctrl[8];
+ uint64_t xmm[CPU_NB_REGS][2];
+ uint32_t mxcsr;
+} __attribute__((packed));
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
- uint32_t *registers = (uint32_t *)mem_buf;
+ struct x86_gdb_regs *regs = (struct x86_gdb_regs *)mem_buf;
int i, fpus;
- for(i = 0; i < 8; i++) {
- registers[i] = env->regs[i];
- }
- registers[8] = env->eip;
- registers[9] = env->eflags;
- registers[10] = env->segs[R_CS].selector;
- registers[11] = env->segs[R_SS].selector;
- registers[12] = env->segs[R_DS].selector;
- registers[13] = env->segs[R_ES].selector;
- registers[14] = env->segs[R_FS].selector;
- registers[15] = env->segs[R_GS].selector;
- /* XXX: convert floats */
- for(i = 0; i < 8; i++) {
- memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
- }
- registers[36] = env->fpuc;
+ for(i = 0; i < CPU_NB_REGS; i++)
+ regs->gp[i] = tswapl(env->regs[i]);
+#if defined(TARGET_X86_64)
+ /* Fix-up register mapping */
+ regs->gp[1] = tswapl(env->regs[R_EBX]);
+ regs->gp[2] = tswapl(env->regs[R_ECX]);
+ regs->gp[3] = tswapl(env->regs[R_EDX]);
+#endif
+
+ regs->ip = tswapl(env->eip);
+ regs->flags = tswap32(env->eflags);
+
+ regs->segm[0] = tswap32(env->segs[R_CS].selector);
+ regs->segm[1] = tswap32(env->segs[R_SS].selector);
+ regs->segm[2] = tswap32(env->segs[R_DS].selector);
+ regs->segm[3] = tswap32(env->segs[R_ES].selector);
+ regs->segm[4] = tswap32(env->segs[R_FS].selector);
+ regs->segm[5] = tswap32(env->segs[R_GS].selector);
+
+ for (i = 0; i < 8; i++)
+ memcpy(regs->fpreg[i], &env->fpregs[i], 10);
+
+ regs->fpctrl[0] = tswap32(env->fpuc);
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- registers[37] = fpus;
- registers[38] = 0; /* XXX: convert tags */
- registers[39] = 0; /* fiseg */
- registers[40] = 0; /* fioff */
- registers[41] = 0; /* foseg */
- registers[42] = 0; /* fooff */
- registers[43] = 0; /* fop */
-
- for(i = 0; i < 16; i++)
- tswapls(®isters[i]);
- for(i = 36; i < 44; i++)
- tswapls(®isters[i]);
- return 44 * 4;
+ regs->fpctrl[1] = tswap32(fpus);
+ regs->fpctrl[2] = 0; /* XXX: convert tags */
+ regs->fpctrl[3] = 0; /* fiseg */
+ regs->fpctrl[4] = 0; /* fioff */
+ regs->fpctrl[5] = 0; /* foseg */
+ regs->fpctrl[6] = 0; /* fooff */
+ regs->fpctrl[7] = 0; /* fop */
+
+ for (i = 0; i < CPU_NB_REGS; i++) {
+ regs->xmm[i][0] = tswap64(&env->xmm_regs[i].XMM_Q(0));
+ regs->xmm[i][1] = tswap64(&env->xmm_regs[i].XMM_Q(1));
+ }
+
+ regs->mxcsr = tswap32(env->mxcsr);
+
+ return sizeof(struct x86_gdb_regs);
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
- uint32_t *registers = (uint32_t *)mem_buf;
+ struct x86_gdb_regs *regs = (struct x86_gdb_regs *)mem_buf;
int i;
- for(i = 0; i < 8; i++) {
- env->regs[i] = tswapl(registers[i]);
- }
- env->eip = tswapl(registers[8]);
- env->eflags = tswapl(registers[9]);
+ for (i = 0; i < CPU_NB_REGS; i++)
+ env->regs[i] = tswapl(regs->gp[i]);
+#if defined(TARGET_X86_64)
+ /* Fix-up register mapping */
+ env->regs[R_EBX] = tswapl(regs->gp[1]);
+ env->regs[R_ECX] = tswapl(regs->gp[2]);
+ env->regs[R_EDX] = tswapl(regs->gp[3]);
+#endif
+
+ env->eip = tswapl(regs->ip);
+ env->eflags = tswap32(regs->flags);
+
#if defined(CONFIG_USER_ONLY)
-#define LOAD_SEG(index, sreg)\
- if (tswapl(registers[index]) != env->segs[sreg].selector)\
- cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
- LOAD_SEG(10, R_CS);
- LOAD_SEG(11, R_SS);
- LOAD_SEG(12, R_DS);
- LOAD_SEG(13, R_ES);
- LOAD_SEG(14, R_FS);
- LOAD_SEG(15, R_GS);
+#define LOAD_SEG(index, sreg) \
+ if (tswap32(regs->segm[index]) != env->segs[sreg].selector) \
+ cpu_x86_load_seg(env, sreg, tswap32(regs->segm[index]));
+
+ LOAD_SEG(0, R_CS);
+ LOAD_SEG(1, R_SS);
+ LOAD_SEG(2, R_DS);
+ LOAD_SEG(3, R_ES);
+ LOAD_SEG(4, R_FS);
+ LOAD_SEG(5, R_GS);
#endif
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 249 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2007-04-21 17:45 ` Jan Kiszka
@ 2007-04-23 9:13 ` Jan Kiszka
2007-04-23 15:47 ` Jan Kiszka
0 siblings, 1 reply; 10+ messages in thread
From: Jan Kiszka @ 2007-04-23 9:13 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 5170 bytes --]
Jan Kiszka wrote:
> + for (i = 0; i < CPU_NB_REGS; i++) {
> + regs->xmm[i][0] = tswap64(&env->xmm_regs[i].XMM_Q(0));
> + regs->xmm[i][1] = tswap64(&env->xmm_regs[i].XMM_Q(1));
> + }
Copy&paste nonsense. Corrected version attached.
Jan
---
gdbstub.c | 118 ++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 73 insertions(+), 45 deletions(-)
Index: qemu-0.9.0/gdbstub.c
===================================================================
--- qemu-0.9.0.orig/gdbstub.c
+++ qemu-0.9.0/gdbstub.c
@@ -222,64 +222,92 @@ static int put_packet(GDBState *s, char
}
#if defined(TARGET_I386)
+struct x86_gdb_regs {
+ target_ulong gp[CPU_NB_REGS];
+ target_ulong ip;
+ uint32_t flags;
+ uint32_t segm[6];
+ uint8_t fpreg[8][10];
+ uint32_t fpctrl[8];
+ uint64_t xmm[CPU_NB_REGS][2];
+ uint32_t mxcsr;
+} __attribute__((packed));
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
- uint32_t *registers = (uint32_t *)mem_buf;
+ struct x86_gdb_regs *regs = (struct x86_gdb_regs *)mem_buf;
int i, fpus;
- for(i = 0; i < 8; i++) {
- registers[i] = env->regs[i];
- }
- registers[8] = env->eip;
- registers[9] = env->eflags;
- registers[10] = env->segs[R_CS].selector;
- registers[11] = env->segs[R_SS].selector;
- registers[12] = env->segs[R_DS].selector;
- registers[13] = env->segs[R_ES].selector;
- registers[14] = env->segs[R_FS].selector;
- registers[15] = env->segs[R_GS].selector;
- /* XXX: convert floats */
- for(i = 0; i < 8; i++) {
- memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
- }
- registers[36] = env->fpuc;
+ for(i = 0; i < CPU_NB_REGS; i++)
+ regs->gp[i] = tswapl(env->regs[i]);
+#if defined(TARGET_X86_64)
+ /* Fix-up register mapping */
+ regs->gp[1] = tswapl(env->regs[R_EBX]);
+ regs->gp[2] = tswapl(env->regs[R_ECX]);
+ regs->gp[3] = tswapl(env->regs[R_EDX]);
+#endif
+
+ regs->ip = tswapl(env->eip);
+ regs->flags = tswap32(env->eflags);
+
+ regs->segm[0] = tswap32(env->segs[R_CS].selector);
+ regs->segm[1] = tswap32(env->segs[R_SS].selector);
+ regs->segm[2] = tswap32(env->segs[R_DS].selector);
+ regs->segm[3] = tswap32(env->segs[R_ES].selector);
+ regs->segm[4] = tswap32(env->segs[R_FS].selector);
+ regs->segm[5] = tswap32(env->segs[R_GS].selector);
+
+ for (i = 0; i < 8; i++)
+ memcpy(regs->fpreg[i], &env->fpregs[i], 10);
+
+ regs->fpctrl[0] = tswap32(env->fpuc);
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- registers[37] = fpus;
- registers[38] = 0; /* XXX: convert tags */
- registers[39] = 0; /* fiseg */
- registers[40] = 0; /* fioff */
- registers[41] = 0; /* foseg */
- registers[42] = 0; /* fooff */
- registers[43] = 0; /* fop */
-
- for(i = 0; i < 16; i++)
- tswapls(®isters[i]);
- for(i = 36; i < 44; i++)
- tswapls(®isters[i]);
- return 44 * 4;
+ regs->fpctrl[1] = tswap32(fpus);
+ regs->fpctrl[2] = 0; /* XXX: convert tags */
+ regs->fpctrl[3] = 0; /* fiseg */
+ regs->fpctrl[4] = 0; /* fioff */
+ regs->fpctrl[5] = 0; /* foseg */
+ regs->fpctrl[6] = 0; /* fooff */
+ regs->fpctrl[7] = 0; /* fop */
+
+ for (i = 0; i < CPU_NB_REGS; i++) {
+ regs->xmm[i][0] = tswap64(env->xmm_regs[i].XMM_Q(0));
+ regs->xmm[i][1] = tswap64(env->xmm_regs[i].XMM_Q(1));
+ }
+
+ regs->mxcsr = tswap32(env->mxcsr);
+
+ return sizeof(struct x86_gdb_regs);
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
- uint32_t *registers = (uint32_t *)mem_buf;
+ struct x86_gdb_regs *regs = (struct x86_gdb_regs *)mem_buf;
int i;
- for(i = 0; i < 8; i++) {
- env->regs[i] = tswapl(registers[i]);
- }
- env->eip = tswapl(registers[8]);
- env->eflags = tswapl(registers[9]);
+ for (i = 0; i < CPU_NB_REGS; i++)
+ env->regs[i] = tswapl(regs->gp[i]);
+#if defined(TARGET_X86_64)
+ /* Fix-up register mapping */
+ env->regs[R_EBX] = tswapl(regs->gp[1]);
+ env->regs[R_ECX] = tswapl(regs->gp[2]);
+ env->regs[R_EDX] = tswapl(regs->gp[3]);
+#endif
+
+ env->eip = tswapl(regs->ip);
+ env->eflags = tswap32(regs->flags);
+
#if defined(CONFIG_USER_ONLY)
-#define LOAD_SEG(index, sreg)\
- if (tswapl(registers[index]) != env->segs[sreg].selector)\
- cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
- LOAD_SEG(10, R_CS);
- LOAD_SEG(11, R_SS);
- LOAD_SEG(12, R_DS);
- LOAD_SEG(13, R_ES);
- LOAD_SEG(14, R_FS);
- LOAD_SEG(15, R_GS);
+#define LOAD_SEG(index, sreg) \
+ if (tswap32(regs->segm[index]) != env->segs[sreg].selector) \
+ cpu_x86_load_seg(env, sreg, tswap32(regs->segm[index]));
+
+ LOAD_SEG(0, R_CS);
+ LOAD_SEG(1, R_SS);
+ LOAD_SEG(2, R_DS);
+ LOAD_SEG(3, R_ES);
+ LOAD_SEG(4, R_FS);
+ LOAD_SEG(5, R_GS);
#endif
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] Re: [PATCH] x86_64 debug registers for gdb
2007-04-23 9:13 ` Jan Kiszka
@ 2007-04-23 15:47 ` Jan Kiszka
0 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2007-04-23 15:47 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 5230 bytes --]
Hi again,
here is now a version that I tested a bit longer than 5 minutes (it
actually helped to nail down a Xenomai kernel bug).
The general purpose register mapping for x86_64 was still wrong. I'm now
directing the indices through a mapping table because I didn't dare to
redefine R_EBX&friends on x86_64. The latter would be the simplest way
if nothing else depends on the current values - which I can't tell.
My other questions are still valid as well.
Jan
---
gdbstub.c | 116 +++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 71 insertions(+), 45 deletions(-)
Index: qemu-0.9.0/gdbstub.c
===================================================================
--- qemu-0.9.0.orig/gdbstub.c
+++ qemu-0.9.0/gdbstub.c
@@ -222,64 +222,90 @@ static int put_packet(GDBState *s, char
}
#if defined(TARGET_I386)
+struct x86_gdb_regs {
+ target_ulong gp[CPU_NB_REGS];
+ target_ulong ip;
+ uint32_t flags;
+ uint32_t segm[6];
+ uint8_t fpreg[8][10];
+ uint32_t fpctrl[8];
+ uint64_t xmm[CPU_NB_REGS][2];
+ uint32_t mxcsr;
+} __attribute__((packed));
+
+#if defined(TARGET_X86_64)
+static int gpreg_map[] = {
+ R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,
+ 8, 9, 10, 11, 12, 13, 14, 15
+};
+#define MAP_GPREG(n) gpreg_map[n]
+#else
+#define MAP_GPREG(n) (n)
+#endif
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
- uint32_t *registers = (uint32_t *)mem_buf;
+ struct x86_gdb_regs *regs = (struct x86_gdb_regs *)mem_buf;
int i, fpus;
- for(i = 0; i < 8; i++) {
- registers[i] = env->regs[i];
- }
- registers[8] = env->eip;
- registers[9] = env->eflags;
- registers[10] = env->segs[R_CS].selector;
- registers[11] = env->segs[R_SS].selector;
- registers[12] = env->segs[R_DS].selector;
- registers[13] = env->segs[R_ES].selector;
- registers[14] = env->segs[R_FS].selector;
- registers[15] = env->segs[R_GS].selector;
- /* XXX: convert floats */
- for(i = 0; i < 8; i++) {
- memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
- }
- registers[36] = env->fpuc;
+ for (i = 0; i < CPU_NB_REGS; i++)
+ regs->gp[i] = tswapl(env->regs[MAP_GPREG(i)]);
+
+ regs->ip = tswapl(env->eip);
+ regs->flags = tswap32(env->eflags);
+
+ regs->segm[0] = tswap32(env->segs[R_CS].selector);
+ regs->segm[1] = tswap32(env->segs[R_SS].selector);
+ regs->segm[2] = tswap32(env->segs[R_DS].selector);
+ regs->segm[3] = tswap32(env->segs[R_ES].selector);
+ regs->segm[4] = tswap32(env->segs[R_FS].selector);
+ regs->segm[5] = tswap32(env->segs[R_GS].selector);
+
+ for (i = 0; i < 8; i++)
+ memcpy(regs->fpreg[i], &env->fpregs[i], 10);
+
+ regs->fpctrl[0] = tswap32(env->fpuc);
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
- registers[37] = fpus;
- registers[38] = 0; /* XXX: convert tags */
- registers[39] = 0; /* fiseg */
- registers[40] = 0; /* fioff */
- registers[41] = 0; /* foseg */
- registers[42] = 0; /* fooff */
- registers[43] = 0; /* fop */
-
- for(i = 0; i < 16; i++)
- tswapls(®isters[i]);
- for(i = 36; i < 44; i++)
- tswapls(®isters[i]);
- return 44 * 4;
+ regs->fpctrl[1] = tswap32(fpus);
+ regs->fpctrl[2] = 0; /* XXX: convert tags */
+ regs->fpctrl[3] = 0; /* fiseg */
+ regs->fpctrl[4] = 0; /* fioff */
+ regs->fpctrl[5] = 0; /* foseg */
+ regs->fpctrl[6] = 0; /* fooff */
+ regs->fpctrl[7] = 0; /* fop */
+
+ for (i = 0; i < CPU_NB_REGS; i++) {
+ regs->xmm[i][0] = tswap64(env->xmm_regs[i].XMM_Q(0));
+ regs->xmm[i][1] = tswap64(env->xmm_regs[i].XMM_Q(1));
+ }
+
+ regs->mxcsr = tswap32(env->mxcsr);
+
+ return sizeof(struct x86_gdb_regs);
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
- uint32_t *registers = (uint32_t *)mem_buf;
+ struct x86_gdb_regs *regs = (struct x86_gdb_regs *)mem_buf;
int i;
- for(i = 0; i < 8; i++) {
- env->regs[i] = tswapl(registers[i]);
- }
- env->eip = tswapl(registers[8]);
- env->eflags = tswapl(registers[9]);
+ for (i = 0; i < CPU_NB_REGS; i++)
+ env->regs[MAP_GPREG(i)] = tswapl(regs->gp[i]);
+
+ env->eip = tswapl(regs->ip);
+ env->eflags = tswap32(regs->flags);
+
#if defined(CONFIG_USER_ONLY)
-#define LOAD_SEG(index, sreg)\
- if (tswapl(registers[index]) != env->segs[sreg].selector)\
- cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
- LOAD_SEG(10, R_CS);
- LOAD_SEG(11, R_SS);
- LOAD_SEG(12, R_DS);
- LOAD_SEG(13, R_ES);
- LOAD_SEG(14, R_FS);
- LOAD_SEG(15, R_GS);
+#define LOAD_SEG(index, sreg) \
+ if (tswap32(regs->segm[index]) != env->segs[sreg].selector) \
+ cpu_x86_load_seg(env, sreg, tswap32(regs->segm[index]));
+
+ LOAD_SEG(0, R_CS);
+ LOAD_SEG(1, R_SS);
+ LOAD_SEG(2, R_DS);
+ LOAD_SEG(3, R_ES);
+ LOAD_SEG(4, R_FS);
+ LOAD_SEG(5, R_GS);
#endif
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2007-04-23 15:53 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-09-19 20:51 [Qemu-devel] [PATCH] x86_64 debug registers for gdb Jason Wessel
2007-04-18 20:53 ` [Qemu-devel] " Jan Kiszka
2007-04-19 15:11 ` Paul Brook
2007-04-19 21:30 ` Jan Kiszka
2007-04-20 12:55 ` Paul Brook
2007-04-20 22:15 ` Jan Kiszka
2007-04-20 23:13 ` Paul Brook
2007-04-21 17:45 ` Jan Kiszka
2007-04-23 9:13 ` Jan Kiszka
2007-04-23 15:47 ` Jan Kiszka
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.