From: Kevin Buettner <kevinb@redhat.com>
To: gdb-patches@sourceware.org
Subject: [RFC] rl78-tdep.c: Make PC a pseudo-register
Date: Fri, 09 Aug 2013 03:56:00 -0000 [thread overview]
Message-ID: <20130808205554.070f72ce@redhat.com> (raw)
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;
next reply other threads:[~2013-08-09 3:56 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-09 3:56 Kevin Buettner [this message]
2013-08-14 14:04 ` Joel Brobecker
2013-08-15 4:34 ` Kevin Buettner
2013-08-16 4:31 ` Kevin Buettner
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=20130808205554.070f72ce@redhat.com \
--to=kevinb@redhat.com \
--cc=gdb-patches@sourceware.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