[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH V2] [SPARC] Gdbstub: Fix back-trace on SPARC32
From: |
Blue Swirl |
Subject: |
Re: [Qemu-devel] [PATCH V2] [SPARC] Gdbstub: Fix back-trace on SPARC32 |
Date: |
Sat, 10 Sep 2011 18:38:15 +0000 |
Thanks, applied.
On Thu, Sep 8, 2011 at 10:48 AM, Fabien Chouteau <address@hidden> wrote:
> Gdb expects all registers windows to be flushed in ram, which is not the case
> in Qemu. Therefore the back-trace generation doesn't work. This patch adds a
> function to handle reads (and only read) in stack frames as if windows were
> flushed.
>
> Signed-off-by: Fabien Chouteau <address@hidden>
> ---
>
> V2:
> * only handle reads in stack frames
>
> gdbstub.c | 16 +++++++--
> target-sparc/cpu.h | 7 ++++
> target-sparc/helper.c | 84
> +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 104 insertions(+), 3 deletions(-)
>
> diff --git a/gdbstub.c b/gdbstub.c
> index 3b87c27..7802c5f 100644
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -41,6 +41,15 @@
> #include "qemu_socket.h"
> #include "kvm.h"
>
> +#ifndef TARGET_CPU_MEMORY_RW_DEBUG
> +static inline int target_memory_rw_debug(CPUState *env, target_ulong addr,
> + uint8_t *buf, int len, int is_write)
> +{
> + return cpu_memory_rw_debug(env, addr, buf, len, is_write);
> +}
> +#else
> +/* target_memory_rw_debug() defined in cpu.h */
> +#endif
>
> enum {
> GDB_SIGNAL_0 = 0,
> @@ -2013,7 +2022,7 @@ static int gdb_handle_packet(GDBState *s, const char
> *line_buf)
> if (*p == ',')
> p++;
> len = strtoull(p, NULL, 16);
> - if (cpu_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 0) != 0) {
> + if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 0) != 0) {
> put_packet (s, "E14");
> } else {
> memtohex(buf, mem_buf, len);
> @@ -2028,10 +2037,11 @@ static int gdb_handle_packet(GDBState *s, const char
> *line_buf)
> if (*p == ':')
> p++;
> hextomem(mem_buf, p, len);
> - if (cpu_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 1) != 0)
> + if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 1) != 0) {
> put_packet(s, "E14");
> - else
> + } else {
> put_packet(s, "OK");
> + }
> break;
> case 'p':
> /* Older gdb are really dumb, and don't use 'g' if 'p' is avaialable.
> diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
> index 8654f26..19de5ba 100644
> --- a/target-sparc/cpu.h
> +++ b/target-sparc/cpu.h
> @@ -495,6 +495,13 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1,
> target_ulong address, int rw
> target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
> void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
>
> +#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
> +int target_memory_rw_debug(CPUState *env, target_ulong addr,
> + uint8_t *buf, int len, int is_write);
> +#define TARGET_CPU_MEMORY_RW_DEBUG
> +#endif
> +
> +
> /* translate.c */
> void gen_intermediate_code_init(CPUSPARCState *env);
>
> diff --git a/target-sparc/helper.c b/target-sparc/helper.c
> index 1fe1f07..c80531a 100644
> --- a/target-sparc/helper.c
> +++ b/target-sparc/helper.c
> @@ -358,6 +358,90 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf,
> CPUState *env)
> }
> }
>
> +#if !defined(CONFIG_USER_ONLY)
> +
> +/* Gdb expects all registers windows to be flushed in ram. This function
> handles
> + * reads (and only reads) in stack frames as if windows were flushed. We
> assume
> + * that the sparc ABI is followed.
> + */
> +int target_memory_rw_debug(CPUState *env, target_ulong addr,
> + uint8_t *buf, int len, int is_write)
> +{
> + int i;
> + int len1;
> + int cwp = env->cwp;
> +
> + if (!is_write) {
> + for (i = 0; i < env->nwindows; i++) {
> + int off;
> + target_ulong fp = env->regbase[cwp * 16 + 22];
> +
> + /* Assume fp == 0 means end of frame. */
> + if (fp == 0) {
> + break;
> + }
> +
> + cwp = cpu_cwp_inc(env, cwp + 1);
> +
> + /* Invalid window ? */
> + if (env->wim & (1 << cwp)) {
> + break;
> + }
> +
> + /* According to the ABI, the stack is growing downward. */
> + if (addr + len < fp) {
> + break;
> + }
> +
> + /* Not in this frame. */
> + if (addr > fp + 64) {
> + continue;
> + }
> +
> + /* Handle access before this window. */
> + if (addr < fp) {
> + len1 = fp - addr;
> + if (cpu_memory_rw_debug(env, addr, buf, len1, is_write) !=
> 0) {
> + return -1;
> + }
> + addr += len1;
> + len -= len1;
> + buf += len1;
> + }
> +
> + /* Access byte per byte to registers. Not very efficient but
> speed
> + * is not critical.
> + */
> + off = addr - fp;
> + len1 = 64 - off;
> +
> + if (len1 > len) {
> + len1 = len;
> + }
> +
> + for (; len1; len1--) {
> + int reg = cwp * 16 + 8 + (off >> 2);
> + union {
> + uint32_t v;
> + uint8_t c[4];
> + } u;
> + u.v = cpu_to_be32(env->regbase[reg]);
> + *buf++ = u.c[off & 3];
> + addr++;
> + len--;
> + off++;
> + }
> +
> + if (len == 0) {
> + return 0;
> + }
> + }
> + }
> + return cpu_memory_rw_debug(env, addr, buf, len, is_write);
> +}
> +
> +#endif /* !defined(CONFIG_USER_ONLY) */
> +
> #else /* !TARGET_SPARC64 */
>
> // 41 bit physical address space
> --
> 1.7.4.1
>
>