From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31295 invoked by alias); 9 Aug 2013 03:56:05 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 31250 invoked by uid 89); 9 Aug 2013 03:56:04 -0000 X-Spam-SWARE-Status: No, score=-5.9 required=5.0 tests=AWL,BAYES_00,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,RDNS_NONE,SPF_HELO_PASS,SPF_PASS autolearn=no version=3.3.1 Received: from Unknown (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Fri, 09 Aug 2013 03:56:03 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r793tuBt010346 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 8 Aug 2013 23:55:56 -0400 Received: from localhost.localdomain (ovpn-113-102.phx2.redhat.com [10.3.113.102]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r793ttJp020990 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO) for ; Thu, 8 Aug 2013 23:55:55 -0400 Date: Fri, 09 Aug 2013 03:56:00 -0000 From: Kevin Buettner To: gdb-patches@sourceware.org Subject: [RFC] rl78-tdep.c: Make PC a pseudo-register Message-ID: <20130808205554.070f72ce@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-SW-Source: 2013-08/txt/msg00261.txt.bz2 I investigated a segfault for the rl78 target recently in which the program counter was being set incorrectly when executing a return command. The return address is stored in a 32-bit container on the stack, but when storing the return address, the simulator only writes three of the four bytes due to the fact that the rl78 PC is only 20 bits wide. The other byte is not touched and will have whatever value was there either at initialization or whatever other value was last written to the location as the stack grows and shrinks during program execution. To the best of my knowledge, actual hardware behaves the same way. When DWARF unwinding is used, the entire 32-bit container is read including the high byte which may in fact contain random garbage. I have spent some time examining the unwinding code, but have not been able to locate a point at which it makes sense to add a call to gdbarch_addr_bits_remove(). I'm not tremendously fond of my patch below because I feel that there should be a simpler way of doing things. This patch changes PC to be a pseudo register in which three bytes are read and written to/from the corresponding raw register. Comments? Can anyone think of a better way to do this? * rl78-tdep.c (RL78_RAW_PC_REGNUM): New enum. (RL78_PC_REGNUM): Move to list of pseudo-register enums. (rl78_register_type, rl78_register_name, rl78_register_reggroup_p): Update to account for fact that PC is now a pseudo-register. (rl78_pseudo_register_write, rl78_pseudo_register_read): Add cases for RL78_PC_REGNUM. Index: gdb/rl78-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rl78-tdep.c,v retrieving revision 1.9 diff -u -p -r1.9 rl78-tdep.c --- gdb/rl78-tdep.c 4 May 2013 06:14:53 -0000 1.9 +++ gdb/rl78-tdep.c 8 Aug 2013 00:02:28 -0000 @@ -94,7 +94,7 @@ enum RL78_PSW_REGNUM, /* 8 bits */ RL78_ES_REGNUM, /* 8 bits */ RL78_CS_REGNUM, /* 8 bits */ - RL78_PC_REGNUM, /* 20 bits; we'll use 32 bits for it. */ + RL78_RAW_PC_REGNUM, /* 20 bits; we'll use 32 bits for it. */ /* Fixed address SFRs (some of those above are SFRs too.) */ RL78_SPL_REGNUM, /* 8 bits; lower half of SP */ @@ -105,7 +105,8 @@ enum RL78_NUM_REGS, /* Pseudo registers. */ - RL78_SP_REGNUM = RL78_NUM_REGS, + RL78_PC_REGNUM = RL78_NUM_REGS, + RL78_SP_REGNUM, RL78_X_REGNUM, RL78_A_REGNUM, @@ -243,6 +244,8 @@ rl78_register_type (struct gdbarch *gdba if (reg_nr == RL78_PC_REGNUM) return tdep->rl78_code_pointer; + else if (reg_nr == RL78_RAW_PC_REGNUM) + return tdep->rl78_uint32; else if (reg_nr <= RL78_MEM_REGNUM || (RL78_X_REGNUM <= reg_nr && reg_nr <= RL78_H_REGNUM) || (RL78_BANK0_R0_REGNUM <= reg_nr @@ -298,13 +301,14 @@ rl78_register_name (struct gdbarch *gdba "psw", "es", "cs", - "pc", + "", "", /* spl */ "", /* sph */ "pmc", "mem", + "pc", "sp", "x", @@ -395,8 +399,10 @@ rl78_register_reggroup_p (struct gdbarch { if ((regnum < RL78_NUM_REGS && regnum != RL78_SPL_REGNUM - && regnum != RL78_SPH_REGNUM) - || regnum == RL78_SP_REGNUM) + && regnum != RL78_SPH_REGNUM + && regnum != RL78_RAW_PC_REGNUM) + || regnum == RL78_SP_REGNUM + || regnum == RL78_PC_REGNUM) return 1; else return 0; @@ -409,6 +415,7 @@ rl78_register_reggroup_p (struct gdbarch || regnum == RL78_SPH_REGNUM || regnum == RL78_PMC_REGNUM || regnum == RL78_MEM_REGNUM + || regnum == RL78_RAW_PC_REGNUM || (RL78_BANK0_RP0_REGNUM <= regnum && regnum <= RL78_BANK3_RP3_REGNUM)) return group == system_reggroup; @@ -464,6 +471,12 @@ rl78_pseudo_register_read (struct gdbarc if (status == REG_VALID) status = regcache_raw_read (regcache, RL78_SPH_REGNUM, buffer + 1); } + else if (reg == RL78_PC_REGNUM) + { + gdb_byte rawbuf[4]; + status = regcache_raw_read (regcache, RL78_RAW_PC_REGNUM, rawbuf); + memcpy (buffer, rawbuf, 3); + } else if (RL78_X_REGNUM <= reg && reg <= RL78_H_REGNUM) { ULONGEST psw; @@ -527,6 +540,13 @@ rl78_pseudo_register_write (struct gdbar regcache_raw_write (regcache, RL78_SPL_REGNUM, buffer); regcache_raw_write (regcache, RL78_SPH_REGNUM, buffer + 1); } + else if (reg == RL78_PC_REGNUM) + { + gdb_byte rawbuf[4]; + memcpy (rawbuf, buffer, 3); + rawbuf[3] = 0; + regcache_raw_write (regcache, RL78_RAW_PC_REGNUM, rawbuf); + } else if (RL78_X_REGNUM <= reg && reg <= RL78_H_REGNUM) { ULONGEST psw;