[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, ne
From: |
Edgar E. Iglesias |
Subject: |
Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.. |
Date: |
Fri, 9 May 2008 10:38:41 +0200 |
User-agent: |
Mutt/1.5.16 (2007-06-09) |
On Thu, May 08, 2008 at 11:39:11PM -0500, Jason Wessel wrote:
> Mulyadi Santosa wrote:
> > Hi...
> >
> > On Thu, May 8, 2008 at 2:53 PM, Keilhau Timo ( Student )
> > <address@hidden> wrote:
> >
> >> Ive compiled the 2.6.25 kernel on guest with:
> >> [*] Compile the kernel with frame pointers
> >> [*] Compile the kernel with debug info
> >> additionally CFLAGS="-g3 -ggdb"
> >>
> >
> > You meant -O3? well, IMO, you don't need -O at all. AFAIK mixing -g or
> > -ggdb with -O{1,2,3} is a bad thing, since it will render the DWARF
> > information inside the ELF file (in this case, the vmlinux)
> > inconsistent with the runtime context (line number, current EIP
> > correlated with break points).
> >
> > Of course, this assume that there is no bugs while Qemu inspect and
> > found that it must pause at certain address... I believe Jasson Wessel
> > had squashed all that kind of bugs in the past.
> >
> > regards,
> >
> > Mulyadi.
> >
> >
> I believe that Mulyadi is talking about the following two patches which
> are attached here, assuming you are able to hit breakpoints.
>
> Jason.
>
Hi,
Tested the singlestepping w/o interrupts, it works very nice thanks.
Best regards
> From: Jason Wessel <address@hidden>
> Subject: [PATCH] Add x86_64 gdb stub for qemu
>
> This patch comes from the kvm sources and allows debugging the back
> end with gdb connected to qemu for the qemu-system-x86_64 machine.
>
>
> Signed-off-by: Jason Wessel <address@hidden>
>
>
> ---
> gdbstub.c | 134
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 133 insertions(+), 1 deletion(-)
>
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -238,9 +238,141 @@ static int put_packet(GDBState *s, char
> }
> return 0;
> }
> +#if defined(TARGET_X86_64)
>
> -#if defined(TARGET_I386)
> +static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
> +{
> + uint8_t *p = mem_buf;
> + int i, fpus;
> +
> +#define PUTREG(x) do { \
> + target_ulong reg = tswapl(x); \
> + memcpy(p, ®, sizeof reg); \
> + p += sizeof reg; \
> + } while (0)
> +#define PUTREG32(x) do { \
> + uint32_t reg = tswap32(x); \
> + memcpy(p, ®, sizeof reg); \
> + p += sizeof reg; \
> + } while (0)
> +#define PUTREGF(x) do { \
> + memcpy(p, &(x), 10); \
> + p += sizeof (x); \
> + } while (0)
> +
> + PUTREG(env->regs[R_EAX]);
> + PUTREG(env->regs[R_EBX]);
> + PUTREG(env->regs[R_ECX]);
> + PUTREG(env->regs[R_EDX]);
> + PUTREG(env->regs[R_ESI]);
> + PUTREG(env->regs[R_EDI]);
> + PUTREG(env->regs[R_EBP]);
> + PUTREG(env->regs[R_ESP]);
> + PUTREG(env->regs[8]);
> + PUTREG(env->regs[9]);
> + PUTREG(env->regs[10]);
> + PUTREG(env->regs[11]);
> + PUTREG(env->regs[12]);
> + PUTREG(env->regs[13]);
> + PUTREG(env->regs[14]);
> + PUTREG(env->regs[15]);
> +
> + PUTREG(env->eip);
> + PUTREG32(env->eflags);
> + PUTREG32(env->segs[R_CS].selector);
> + PUTREG32(env->segs[R_SS].selector);
> + PUTREG32(env->segs[R_DS].selector);
> + PUTREG32(env->segs[R_ES].selector);
> + PUTREG32(env->segs[R_FS].selector);
> + PUTREG32(env->segs[R_GS].selector);
> + /* XXX: convert floats */
> + for(i = 0; i < 8; i++) {
> + PUTREGF(env->fpregs[i]);
> + }
> + PUTREG32(env->fpuc);
> + fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
> + PUTREG32(fpus);
> + PUTREG32(0); /* XXX: convert tags */
> + PUTREG32(0); /* fiseg */
> + PUTREG32(0); /* fioff */
> + PUTREG32(0); /* foseg */
> + PUTREG32(0); /* fooff */
> + PUTREG32(0); /* fop */
> +
> +#undef PUTREG
> +#undef PUTREG32
> +#undef PUTREGF
> +
> + return p - mem_buf;
> +}
> +
> +static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int
> size)
> +{
> + uint8_t *p = mem_buf;
> + uint32_t junk;
> + int i, fpus;
> +
> +#define GETREG(x) do { \
> + target_ulong reg; \
> + memcpy(®, p, sizeof reg); \
> + x = tswapl(reg); \
> + p += sizeof reg; \
> + } while (0)
> +#define GETREG32(x) do { \
> + uint32_t reg; \
> + memcpy(®, p, sizeof reg); \
> + x = tswap32(reg); \
> + p += sizeof reg; \
> + } while (0)
> +#define GETREGF(x) do { \
> + memcpy(&(x), p, 10); \
> + p += 10; \
> + } while (0)
> +
> + GETREG(env->regs[R_EAX]);
> + GETREG(env->regs[R_EBX]);
> + GETREG(env->regs[R_ECX]);
> + GETREG(env->regs[R_EDX]);
> + GETREG(env->regs[R_ESI]);
> + GETREG(env->regs[R_EDI]);
> + GETREG(env->regs[R_EBP]);
> + GETREG(env->regs[R_ESP]);
> + GETREG(env->regs[8]);
> + GETREG(env->regs[9]);
> + GETREG(env->regs[10]);
> + GETREG(env->regs[11]);
> + GETREG(env->regs[12]);
> + GETREG(env->regs[13]);
> + GETREG(env->regs[14]);
> + GETREG(env->regs[15]);
> +
> + GETREG(env->eip);
> + GETREG32(env->eflags);
> + GETREG32(env->segs[R_CS].selector);
> + GETREG32(env->segs[R_SS].selector);
> + GETREG32(env->segs[R_DS].selector);
> + GETREG32(env->segs[R_ES].selector);
> + GETREG32(env->segs[R_FS].selector);
> + GETREG32(env->segs[R_GS].selector);
> + /* XXX: convert floats */
> + for(i = 0; i < 8; i++) {
> + GETREGF(env->fpregs[i]);
> + }
> + GETREG32(env->fpuc);
> + GETREG32(fpus); /* XXX: convert fpus */
> + GETREG32(junk); /* XXX: convert tags */
> + GETREG32(junk); /* fiseg */
> + GETREG32(junk); /* fioff */
> + GETREG32(junk); /* foseg */
> + GETREG32(junk); /* fooff */
> + GETREG32(junk); /* fop */
> +
> +#undef GETREG
> +#undef GETREG32
> +#undef GETREGF
> +}
>
> +#elif defined(TARGET_I386)
> static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
> {
> int i, fpus;
> From: Jason Wessel <address@hidden>
> Subject: [PATCH] debugger single step without interrupts
>
> This patch allows the qemu backend debugger to single step an
> instruction without running the hardware interrupts.
>
>
> Signed-off-by: Jason Wessel <address@hidden>
>
> ---
> cpu-all.h | 5 +++++
> cpu-exec.c | 2 +-
> gdbstub.c | 39 ++++++++++++++++++++++++++++++++++-----
> qemu-doc.texi | 30 ++++++++++++++++++++++++++++++
> vl.c | 2 ++
> 5 files changed, 72 insertions(+), 6 deletions(-)
>
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -422,7 +422,7 @@ int cpu_exec(CPUState *env1)
> #if defined(TARGET_I386)
> && env->hflags & HF_GIF_MASK
> #endif
> - ) {
> + && !(env->singlestep_enabled & SSTEP_NOIRQ)) {
> if (interrupt_request & CPU_INTERRUPT_DEBUG) {
> env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
> env->exception_index = EXCP_DEBUG;
> --- a/vl.c
> +++ b/vl.c
> @@ -7508,6 +7508,7 @@ void main_loop_wait(int timeout)
> qemu_aio_poll();
>
> if (vm_running) {
> + if (!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER))
> qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
> qemu_get_clock(vm_clock));
> /* run dma transfers, if any */
> @@ -7515,6 +7516,7 @@ void main_loop_wait(int timeout)
> }
>
> /* real time timers */
> + if (!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER))
> qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
> qemu_get_clock(rt_clock));
>
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -73,6 +73,11 @@ typedef struct GDBState {
> #endif
> } GDBState;
>
> +/* By default use no IRQs and no timers while single stepping so as to
> + * make single stepping like an ICE HW step.
> + */
> +static int sstep_flags = SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER;
> +
> #ifdef CONFIG_USER_ONLY
> /* XXX: This is not thread safe. Do we care? */
> static int gdbserver_fd = -1;
> @@ -940,7 +945,7 @@ static int gdb_handle_packet(GDBState *s
> env->pc = addr;
> #endif
> }
> - cpu_single_step(env, 1);
> + cpu_single_step(env, sstep_flags);
> gdb_continue(s);
> return RS_IDLE;
> case 'F':
> @@ -1047,9 +1052,34 @@ static int gdb_handle_packet(GDBState *s
> goto breakpoint_error;
> }
> break;
> -#ifdef CONFIG_LINUX_USER
> case 'q':
> - if (strncmp(p, "Offsets", 7) == 0) {
> + case 'Q':
> + /* parse any 'q' packets here */
> + if (!strcmp(p,"qemu.sstepbits")) {
> + /* Query Breakpoint bit definitions */
> + sprintf(buf,"ENABLE=%x,NOIRQ=%x,NOTIMER=%x",
> + SSTEP_ENABLE,
> + SSTEP_NOIRQ,
> + SSTEP_NOTIMER);
> + put_packet(s, buf);
> + break;
> + } else if (strncmp(p,"qemu.sstep",10) == 0) {
> + /* Display or change the sstep_flags */
> + p += 10;
> + if (*p != '=') {
> + /* Display current setting */
> + sprintf(buf,"0x%x", sstep_flags);
> + put_packet(s, buf);
> + break;
> + }
> + p++;
> + type = strtoul(p, (char **)&p, 16);
> + sstep_flags = type;
> + put_packet(s, "OK");
> + break;
> + }
> +#ifdef CONFIG_LINUX_USER
> + else if (strncmp(p, "Offsets", 7) == 0) {
> TaskState *ts = env->opaque;
>
> sprintf(buf,
> @@ -1061,10 +1091,9 @@ static int gdb_handle_packet(GDBState *s
> put_packet(s, buf);
> break;
> }
> - /* Fall through. */
> #endif
> + /* Fall through. */
> default:
> - // unknown_command:
> /* put empty packet */
> buf[0] = '\0';
> put_packet(s, buf);
> --- a/cpu-all.h
> +++ b/cpu-all.h
> @@ -761,6 +761,11 @@ int cpu_watchpoint_insert(CPUState *env,
> int cpu_watchpoint_remove(CPUState *env, target_ulong addr);
> int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
> int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
> +
> +#define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
> +#define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
> +#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
> +
> void cpu_single_step(CPUState *env, int enabled);
> void cpu_reset(CPUState *s);
>
> --- a/qemu-doc.texi
> +++ b/qemu-doc.texi
> @@ -1924,6 +1924,36 @@ Use @code{set architecture i8086} to dum
> @code{x/10i $cs*16+$eip} to dump the code at the PC position.
> @end enumerate
>
> +Advanced debugging options:
> +
> +The default single stepping behavior is step with the IRQs and timer service
> routines off. It is set this way because when gdb executes a single step it
> expects to advance beyond the current instruction. With the IRQs and and
> timer service routines on, a single step might jump into the one of the
> interrupt or exception vectors instead of executing the current instruction.
> This means you may hit the same breakpoint a number of times before executing
> the instruction gdb wants to have executed. Because there are rare
> circumstances where you want to single step into an interrupt vector the
> behavior can be controlled from GDB. There are three commands you can query
> and set the single step behavior:
> address@hidden @code
> address@hidden maintenance packet qqemu.sstepbits
> +
> +This will display the MASK bits used to control the single stepping IE:
> address@hidden
> +(gdb) maintenance packet qqemu.sstepbits
> +sending: "qqemu.sstepbits"
> +received: "ENABLE=1,NOIRQ=2,NOTIMER=4"
> address@hidden example
> address@hidden maintenance packet qqemu.sstep
> +
> +This will display the current value of the mask used when single stepping IE:
> address@hidden
> +(gdb) maintenance packet qqemu.sstep
> +sending: "qqemu.sstep"
> +received: "0x7"
> address@hidden example
> address@hidden maintenance packet Qqemu.sstep=HEX_VALUE
> +
> +This will change the single step mask, so if wanted to enable IRQs on the
> single step, but not timers, you would use:
> address@hidden
> +(gdb) maintenance packet Qqemu.sstep=0x5
> +sending: "qemu.sstep=0x5"
> +received: "OK"
> address@hidden example
> address@hidden enumerate
> +
> @node pcsys_os_specific
> @section Target OS specific information
>
--
Edgar E. Iglesias
Axis Communications AB
- [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Keilhau Timo ( Student ), 2008/05/08
- [Qemu-devel] Re: Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Jan Kiszka, 2008/05/08
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Mulyadi Santosa, 2008/05/08
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Jason Wessel, 2008/05/09
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Mulyadi Santosa, 2008/05/09
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Jan Kiszka, 2008/05/09
- RE: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Keilhau Timo ( Student ), 2008/05/09
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Mulyadi Santosa, 2008/05/09
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information..,
Edgar E. Iglesias <=
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Daniel Jacobowitz, 2008/05/09
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Jason Wessel, 2008/05/09
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Daniel Jacobowitz, 2008/05/09
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Edgar E. Iglesias, 2008/05/12
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Jason Wessel, 2008/05/12
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Edgar E. Iglesias, 2008/05/12
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Edgar E. Iglesias, 2008/05/12
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Jason Wessel, 2008/05/12
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Paul Brook, 2008/05/12
- Re: [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information.., Edgar E. Iglesias, 2008/05/12