From patchwork Tue Sep 2 01:37:47 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Green X-Patchwork-Id: 2623 Received: (qmail 7487 invoked by alias); 2 Sep 2014 01:38:01 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 7449 invoked by uid 89); 2 Sep 2014 01:37:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-qg0-f45.google.com Received: from mail-qg0-f45.google.com (HELO mail-qg0-f45.google.com) (209.85.192.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 02 Sep 2014 01:37:52 +0000 Received: by mail-qg0-f45.google.com with SMTP id e89so5882435qgf.32 for ; Mon, 01 Sep 2014 18:37:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:cc:date:message-id:user-agent :mime-version:content-type; bh=6Nz7rnd25EDJM06Mi4tSaEvKk55yOCtT26EdJSgkzPs=; b=WklIPur1nn/oyFVS0/y8BZUEnNqGizquiTGGv02BMt+fLyxpkoV7AI9JCjiJm4tKYy 640EkYhZltyfCgAH5ohpKTQDxKzNC9cc3yg4Il/ioxGIskb+GQZFdC5waaLUSHaoQa/g BL74/GFxLOXRpAClJVG7Sa8+BLFw8Ioqeay3Z7po9rnlHt0W+uh5oP+akh3jXgraOAhU 2hUNaWzFBdwFYEW49yR6rSQ7JkENe2FUHCO8BGkAZdFJnoOgo2mpf/sI0UgQGpWjFIlU eVqOG3iEVsrK+FOgPSlB5rDAJuj/jBDiXuThsi/6ArKA60sWD7p4nybom+z8WPJNZxeV UtXA== X-Gm-Message-State: ALoCoQlUUMiXjnmyqmGwmrZhnSaZ0bPprlX9gKf8gdCCbKRcsaRuMTrrTzfkuBS4F5C8syS2fwob X-Received: by 10.224.65.196 with SMTP id k4mr52448130qai.56.1409621869504; Mon, 01 Sep 2014 18:37:49 -0700 (PDT) Received: from localhost (CPE687f74122463-CM84948c2e0610.cpe.net.cable.rogers.com. [99.226.94.59]) by mx.google.com with ESMTPSA id e9sm6205657qar.44.2014.09.01.18.37.48 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 01 Sep 2014 18:37:48 -0700 (PDT) From: Anthony Green To: gdb-patches@sourceware.org Subject: [RFC][PATCH] Process record support for ppc CC: Ulrich Weigand Date: Mon, 01 Sep 2014 21:37:47 -0400 Message-ID: <8738cax0no.fsf@moxielogic.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Hello, This patch isn't quite ready for prime-time. I just wanted to put it out there for comment, should there be any. The current status is that none of the gdb.reverse tests FAIL due to unrecognized instructions (on powerpc64-unknown-linux-gnu (Fedora)). There are just some oddities to sort out around reverse next, etc. Anthony Green gdb/rs6000-tdep.c | 554 ++++++++++++++++++++++++++++++++++++++++++++++ gdb/testsuite/lib/gdb.exp | 4 +- 2 files changed, 556 insertions(+), 2 deletions(-) diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 730afe7..2f41767 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -61,6 +61,10 @@ #include "frame-unwind.h" #include "frame-base.h" +#include "record.h" +#include "record-full.h" +#include "opcode/ppc.h" + #include "features/rs6000/powerpc-32.c" #include "features/rs6000/powerpc-altivec32.c" #include "features/rs6000/powerpc-vsx32.c" @@ -148,6 +152,9 @@ struct rs6000_framedata int vrsave_offset; /* offset of saved vrsave register */ }; +static int +rs6000_process_record (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr); /* Is REGNO a VSX register? Return 1 if so, 0 otherwise. */ int @@ -4206,6 +4213,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) else register_ppc_ravenscar_ops (gdbarch); + /* Support reverse debugging. */ + set_gdbarch_process_record (gdbarch, rs6000_process_record); + return gdbarch; } @@ -4425,3 +4435,547 @@ of its first byte."), NULL, show_powerpc_exact_watchpoints, &setpowerpccmdlist, &showpowerpccmdlist); } + +/* Parse the current instruction and record the values of the registers and + memory that will be changed in current instruction to "record_arch_list". + Return -1 if something wrong. */ + +static int +rs6000_process_record (struct gdbarch *gdbarch, struct regcache *regcache, + CORE_ADDR addr) +{ + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + uint32_t op; + + if (record_debug > 1) + fprintf_unfiltered (gdb_stdlog, "Process record: rs6000_process_record " + "addr = 0x%s\n", + paddress (target_gdbarch (), addr)); + + op = rs6000_fetch_instruction (gdbarch, addr); + + switch (PPC_OP (op)) + { + case 0x7: /* mulli */ + case 0xe: /* addi */ + case 0xf: /* addis */ + case 0x20: /* lwz */ + case 0x2a: /* lha */ + { + int reg = (op >> 21) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + } + break; + + case 0x8: /* subfic */ + { + int reg = (op >> 21) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM)) + return -1; + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + } + break; + + case 0xa: /* cmpli */ + case 0xb: /* cmpi */ + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + break; + + case 0xd: /* addic. */ + { + int reg = (op >> 21) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM)) + return -1; + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + } + break; + + case 0x10: /* bc */ + if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM)) + return -1; + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + break; + + case 0x11: /* sc */ + if (record_full_arch_list_add_reg (regcache, PPC_MSR_REGNUM)) + return -1; + /* Also SRR0 and SRR1, but not implementing supervisory instructions here */ + break; + + case 0x12: /* b */ + { + if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM)) + return -1; + } + break; + + case 0x13: + { + switch ((op >> 1) & ((1<<10)-1)) + { + case 0x0: /* mcrf */ + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + break; + + case 0x10: /* bclr */ + if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM)) + return -1; + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + break; + + case 0xc1: /* crxor */ + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + break; + + case 0x96: /* isync */ + break; + + case 0x210: /* bcctr */ + if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM)) + return -1; + break; + default: + printf_unfiltered (_("Process record: unrecognized instruction " + "0x13 opcode 0x%x at addr 0x%s.\n"), + ((op >> 1) & ((1<<10)-1)), + paddress (target_gdbarch (), addr)); + return -1; + } + } + break; + + case 0x14: /* rlwimi */ + case 0x15: /* rlwinm */ + case 0x1c: /* andi. */ + case 0x1e: /* rldicl, rldicr */ + { + int reg = (op >> 16) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + } + break; + + case 0x18: /* ori */ + case 0x19: /* oris */ + case 0x1a: /* xori */ + case 0x1b: /* xoris */ + { + int reg = (op >> 16) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + break; + } + + case 0x1f: + { + int reg; + switch ((op >> 1) & ((1<<10)-1)) + { + case 0x0: /* cmp */ + case 0x20: /* cmpl */ + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + break; + + case 0x9: /* mulhdu */ + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + reg = (op >> 21) & ((1<<5)-1); + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + break; + + case 0x13: /* mfcr */ + case 0x14: /* lwarx */ + case 0x15: /* ldx */ + case 0x17: /* lwzx */ + case 0x54: /* ldarx */ + case 0x57: /* lbzx */ + case 0x117: /* lhzx */ + case 0x155: /* lwax */ + reg = (op >> 21) & ((1<<5)-1); + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + break; + + case 0x90: /* mtcrf */ + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + break; + + case 0x28: /* subf */ + case 0x68: /* neg */ + case 0x88: /* subfe */ + case 0x8a: /* adde */ + case 0xe9: /* mulld */ + case 0xeb: /* mullw */ + case 0x10a: /* add */ + case 0x1c9: /* divdu */ + if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM)) + return -1; + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + reg = (op >> 21) & ((1<<5)-1); + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + break; + + case 0x36: /* dcbst */ + case 0x56: /* dcbf */ + case 0x116: /* dcbt */ + case 0x256: /* sync */ + case 0x3f6: /* sync */ + break; + + case 0x318: /* sraw */ + case 0x33a: /* sradi */ + case 0x33b: /* sradi */ + if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM)) + return -1; + /* fall through... */ + case 0x8: /* rldcl */ + case 0x18: /* slw */ + case 0x1a: /* cntlzw */ + case 0x1c: /* and */ + case 0x3a: /* cntlzd */ + case 0x3c: /* andc */ + case 0x7c: /* nor */ + case 0x11c: /* eqv */ + case 0x13c: /* xor */ + case 0x1bc: /* or */ + case 0x19c: /* orc */ + case 0x21b: /* srd */ + case 0x39a: /* extsh */ + case 0x3da: /* extsw */ + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + /* fall through... */ + case 0x153: /* mfspr */ + reg = (op >> 16) & ((1<<5)-1); + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + break; + + case 0x95: /* stdx */ + { + CORE_ADDR rAa, rBa; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int regB = (op >> 11) & ((1<<5)-1); + + if (regA) + regcache_raw_read_unsigned (regcache, regA, &rAa); + else + rAa = 0; + regcache_raw_read_unsigned (regcache, regB, &rBa); + + if (record_full_arch_list_add_mem (rAa + rBa, 8)) + return -1; + } + break; + + case 0xb5: /* stdux */ + { + CORE_ADDR rAa, rBa; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int regB = (op >> 11) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, regA)) + return -1; + + regcache_raw_read_unsigned (regcache, regA, &rAa); + regcache_raw_read_unsigned (regcache, regB, &rBa); + + if (record_full_arch_list_add_mem (rAa + rBa, 8)) + return -1; + } + break; + + case 0xd7: /* stbx */ + { + CORE_ADDR rAa, rBa; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int regB = (op >> 11) & ((1<<5)-1); + + if (regA) + regcache_raw_read_unsigned (regcache, regA, &rAa); + else + rAa = 0; + regcache_raw_read_unsigned (regcache, regB, &rBa); + + if (record_full_arch_list_add_mem (rAa + rBa, 1)) + return -1; + } + break; + + case 0x197: /* sthx */ + { + CORE_ADDR rAa, rBa; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int regB = (op >> 11) & ((1<<5)-1); + + if (regA) + regcache_raw_read_unsigned (regcache, regA, &rAa); + else + rAa = 0; + regcache_raw_read_unsigned (regcache, regB, &rBa); + + if (record_full_arch_list_add_mem (rAa + rBa, 2)) + return -1; + } + break; + + case 0x1d3: /* mtspr */ + reg = (op >> 11) & ((1<<10)-1); + switch (reg) + { + case 0x100: /* lr */ + if (record_full_arch_list_add_reg (regcache, PPC_LR_REGNUM)) + return -1; + break; + + case 0x120: /* ctr */ + if (record_full_arch_list_add_reg (regcache, PPC_CTR_REGNUM)) + return -1; + break; + + default: + printf_unfiltered (_("Process record: unrecognized mtspr SPR 0x%x" + " at addr 0x%s.\n"), + reg, paddress (target_gdbarch (), addr)); + return -1; + } + break; + + case 0x338: /* srawi */ + if (record_full_arch_list_add_reg (regcache, PPC_XER_REGNUM)) + return -1; + if (record_full_arch_list_add_reg (regcache, PPC_CR_REGNUM)) + return -1; + reg = (op >> 16) & ((1<<5)-1); + if (record_full_arch_list_add_reg (regcache, reg)) + return -1; + break; + + default: + printf_unfiltered (_("Process record: unrecognized instruction 0x1F opcode 0x%x" + " at addr 0x%s.\n"), + ((op >> 1) & ((1<<10)-1)), paddress (target_gdbarch (), addr)); + return -1; + } + break; + } + + case 0x21: /* lwzu */ + case 0x23: /* lbzu */ + case 0x29: /* lhzu */ + { + int regT = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, regA)) + return -1; + if (record_full_arch_list_add_reg (regcache, regT)) + return -1; + } + break; + + case 0x22: /* lbz */ + case 0x28: /* lhz */ + case 0x3a: /* ld */ + { + int regT = (op >> 21) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, regT)) + return -1; + } + break; + + case 0x24: /* stw */ + case 0x34: /* stfs */ + { + CORE_ADDR addr; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16; + + if (regA == 0) + addr = 0; + else + regcache_raw_read_unsigned (regcache, regA, &addr); + + if (record_full_arch_list_add_mem (addr + offset, 4)) + return -1; + } + break; + + case 0x25: /* stwu */ + { + CORE_ADDR addr; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16; + + if (record_full_arch_list_add_reg (regcache, regA)) + return -1; + + regcache_raw_read_unsigned (regcache, regA, &addr); + + if (record_full_arch_list_add_mem (addr + offset, 4)) + return -1; + } + break; + + case 0x26: /* stb */ + { + CORE_ADDR addr; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16; + + if (regA == 0) + addr = 0; + else + regcache_raw_read_unsigned (regcache, regA, &addr); + + if (record_full_arch_list_add_mem (addr + offset, 1)) + return -1; + } + break; + + case 0x27: /* stbu */ + { + CORE_ADDR addr; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16; + + if (record_full_arch_list_add_reg (regcache, regA)) + return -1; + + regcache_raw_read_unsigned (regcache, regA, &addr); + + if (record_full_arch_list_add_mem (addr + offset, 1)) + return -1; + } + break; + + case 0x2c: /* sth */ + { + CORE_ADDR addr; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16; + + if (regA == 0) + addr = 0; + else + regcache_raw_read_unsigned (regcache, regA, &addr); + + if (record_full_arch_list_add_mem (addr + offset, 2)) + return -1; + } + break; + + case 0x2d: /* sthu */ + { + CORE_ADDR addr; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16; + + if (record_full_arch_list_add_reg (regcache, regA)) + return -1; + + regcache_raw_read_unsigned (regcache, regA, &addr); + + if (record_full_arch_list_add_mem (addr + offset, 2)) + return -1; + } + break; + + case 0x30: /* lfs */ + case 0x32: /* lfd */ + { + int regT = (op >> 21) & ((1<<5)-1); + + if (record_full_arch_list_add_reg (regcache, PPC_F0_REGNUM + regT)) + return -1; + } + break; + + case 0x36: /* stfd */ + case 0x3e: /* std */ + { + CORE_ADDR addr; + int regS = (op >> 21) & ((1<<5)-1); + int regA = (op >> 16) & ((1<<5)-1); + int32_t offset = (((int32_t)op & 0xFFFF) << 16) >> 16; + + if (regA == 0) + addr = 0; + else + regcache_raw_read_unsigned (regcache, regA, &addr); + + if (record_full_arch_list_add_mem (addr + offset, 8)) + return -1; + } + break; + + case 0x3f: + { + int reg; + + switch ((op >> 1) & ((1<<10)-1)) + { + case 0x48: /* fmr */ + { + int regT = (op >> 21) & ((1<<5)-1); + if (record_full_arch_list_add_reg (regcache, PPC_F0_REGNUM + regT)) + return -1; + } + break; + + default: + printf_unfiltered (_("Process record: unrecognized instruction 0x3F opcode 0x%x" + " at addr 0x%s.\n"), + ((op >> 1) & ((1<<10)-1)), paddress (target_gdbarch (), addr)); + return -1; + } + } + break; + + default: + printf_unfiltered (_("Process record: unrecognized instruction opcode 0x%x" + " at addr 0x%s.\n"), + PPC_OP (op), paddress (target_gdbarch (), addr)); + return -1; + } + + if (record_full_arch_list_add_reg (regcache, PPC_PC_REGNUM)) + return -1; + if (record_full_arch_list_add_end ()) + return -1; + + return 0; +} diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 1019ecd..9e03d87 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -1869,7 +1869,7 @@ proc supports_process_record {} { } if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"] - || [istarget "i\[34567\]86-*-linux*"] } { + || [istarget "i\[34567\]86-*-linux*"] || [istarget "powerpc*-*-*"] } { return 1 } @@ -1885,7 +1885,7 @@ proc supports_reverse {} { } if { [istarget "arm*-*-linux*"] || [istarget "x86_64-*-linux*"] - || [istarget "i\[34567\]86-*-linux*"] } { + || [istarget "i\[34567\]86-*-linux*"] || [istarget "powerpc*-*-*"] } { return 1 }