qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Edgar E. Iglesias" <edgar.iglesias@axis.com>
To: Jason Wessel <jason.wessel@windriver.com>
Cc: qemu-devel@nongnu.org
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	[thread overview]
Message-ID: <20080509083841.GC27235@edgar.se.axis.com> (raw)
In-Reply-To: <4823D56F.1010600@windriver.com>

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 )
> > <timo.keilhau.student@thomson.net> 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 <jason.wessel@windriver.com>
> 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 <jason.wessel@windriver.com>
> 
> 
> ---
>  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, &reg, sizeof reg); \
> +       p += sizeof reg; \
> +    } while (0)
> +#define PUTREG32(x) do { \
> +       uint32_t reg = tswap32(x);              \
> +       memcpy(p, &reg, 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(&reg, p, sizeof reg);     \
> +       x = tswapl(reg);               \
> +       p += sizeof reg;                 \
> +    } while (0)
> +#define GETREG32(x) do { \
> +       uint32_t reg; \
> +       memcpy(&reg, 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 <jason.wessel@windriver.com>
> 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 <jason.wessel@windriver.com>
> 
> ---
>  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:
> +@enumerate @code
> +@item maintenance packet qqemu.sstepbits
> +
> +This will display the MASK bits used to control the single stepping IE:
> +@example
> +(gdb) maintenance packet qqemu.sstepbits
> +sending: "qqemu.sstepbits"
> +received: "ENABLE=1,NOIRQ=2,NOTIMER=4"
> +@end example
> +@item maintenance packet qqemu.sstep
> +
> +This will display the current value of the mask used when single stepping IE:
> +@example
> +(gdb) maintenance packet qqemu.sstep
> +sending: "qqemu.sstep"
> +received: "0x7"
> +@end example
> +@item 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:
> +@example
> +(gdb) maintenance packet Qqemu.sstep=0x5
> +sending: "qemu.sstep=0x5"
> +received: "OK"
> +@end example
> +@end enumerate
> +
>  @node pcsys_os_specific
>  @section Target OS specific information
>  


-- 
Edgar E. Iglesias
Axis Communications AB

  parent reply	other threads:[~2008-05-09  8:38 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-08  7:53 [Qemu-devel] Debugging vmlinux with qemu and gdb. Unable to step, next, print or to get any information Keilhau Timo ( Student )
2008-05-08  8:28 ` [Qemu-devel] " Jan Kiszka
2008-05-08  9:09   ` Keilhau Timo ( Student )
2008-05-08 18:39     ` Jan Kiszka
2008-05-09  2:31 ` [Qemu-devel] " Mulyadi Santosa
2008-05-09  4:39   ` Jason Wessel
2008-05-09  7:23     ` Mulyadi Santosa
2008-05-09  8:29       ` Jan Kiszka
2008-05-09  9:03       ` Keilhau Timo ( Student )
2008-05-09 10:03         ` Mulyadi Santosa
2008-05-09  8:38     ` Edgar E. Iglesias [this message]
2008-05-09 14:40     ` Daniel Jacobowitz
2008-05-09 14:47       ` Jason Wessel
2008-05-09 16:39         ` Daniel Jacobowitz
2008-05-12  9:41       ` Edgar E. Iglesias
2008-05-12 12:51         ` Jason Wessel
2008-05-12 13:30           ` Edgar E. Iglesias
2008-05-12 14:02           ` Edgar E. Iglesias
2008-05-12 14:31             ` Jason Wessel
2008-05-12 14:33             ` Paul Brook
2008-05-12 14:47               ` Edgar E. Iglesias
2008-05-12 14:48               ` Jason Wessel
2008-05-12 12:51         ` Daniel Jacobowitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080509083841.GC27235@edgar.se.axis.com \
    --to=edgar.iglesias@axis.com \
    --cc=jason.wessel@windriver.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).