Browse Source

Implement register writes.

pull/39/head
Tim Newsome 11 years ago
parent
commit
daa39a2204
  1. 74
      riscv/gdbserver.cc
  2. 1
      riscv/gdbserver.h
  3. 41
      tests/gdbserver-smoke.py
  4. 14
      tests/testlib.py

74
riscv/gdbserver.cc

@ -299,11 +299,6 @@ void gdbserver_t::handle_general_registers_read(const std::vector<uint8_t> &pack
// "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
// "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
// "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
// "pc",
// "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
// "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
// "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
// "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
// Each byte of register data is described by two hex digits. The bytes with
// the register are transmitted in target byte order. The size of each
@ -321,6 +316,8 @@ void gdbserver_t::handle_general_registers_read(const std::vector<uint8_t> &pack
expect_ack = true;
}
// First byte is the most-significant one.
// Eg. "08675309" becomes 0x08675309.
uint64_t consume_hex_number(std::vector<uint8_t>::const_iterator &iter,
std::vector<uint8_t>::const_iterator end)
{
@ -338,6 +335,29 @@ uint64_t consume_hex_number(std::vector<uint8_t>::const_iterator &iter,
return value;
}
// First byte is the least-significant one.
// Eg. "08675309" becomes 0x09536708
uint64_t consume_hex_number_le(std::vector<uint8_t>::const_iterator &iter,
std::vector<uint8_t>::const_iterator end)
{
uint64_t value = 0;
unsigned int shift = 4;
while (iter != end) {
uint8_t c = *iter;
uint64_t c_value = character_hex_value(c);
if (c_value > 15)
break;
iter++;
value |= c_value << shift;
if ((shift % 8) == 0)
shift += 12;
else
shift -= 4;
}
return value;
}
void consume_string(std::string &str, std::vector<uint8_t>::const_iterator &iter,
std::vector<uint8_t>::const_iterator end, uint8_t separator)
{
@ -473,6 +493,48 @@ void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
expect_ack = true;
}
void gdbserver_t::handle_register_write(const std::vector<uint8_t> &packet)
{
// P n...=r...
std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
unsigned int n = consume_hex_number(iter, packet.end());
if (*iter != '=')
return send_packet("E05");
iter++;
if (n >= sizeof(register_access) / sizeof(*register_access))
return send_packet("E07");
reg_t value = consume_hex_number_le(iter, packet.end());
if (*iter != '#')
return send_packet("E06");
processor_t *p = sim->get_core(0);
register_access_t access = register_access[n];
switch (access.clss) {
case RC_XPR:
p->state.XPR.write(access.index, value);
break;
case RC_PC:
p->state.pc = value;
break;
case RC_FPR:
p->state.FPR.write(access.index, value);
break;
case RC_CSR:
try {
p->set_csr(access.index, value);
} catch(trap_t& t) {
return send_packet("EFF");
}
break;
}
return send_packet("OK");
}
void gdbserver_t::handle_memory_read(const std::vector<uint8_t> &packet)
{
// m addr,length
@ -693,6 +755,8 @@ void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
return handle_memory_binary_write(packet);
case 'p':
return handle_register_read(packet);
case 'P':
return handle_register_write(packet);
case 'c':
return handle_continue(packet);
case 's':

1
riscv/gdbserver.h

@ -77,6 +77,7 @@ public:
void handle_memory_read(const std::vector<uint8_t> &packet);
void handle_query(const std::vector<uint8_t> &packet);
void handle_register_read(const std::vector<uint8_t> &packet);
void handle_register_write(const std::vector<uint8_t> &packet);
void handle_step(const std::vector<uint8_t> &packet);
private:

41
tests/gdbserver-smoke.py

@ -6,13 +6,12 @@ import unittest
import tempfile
import time
class SmokeTest(unittest.TestCase):
class DebugTest(unittest.TestCase):
def setUp(self):
self.tmpf = tempfile.NamedTemporaryFile()
testlib.compile("debug.c", self.tmpf.name)
self.spike = testlib.spike(self.tmpf.name, halted=False)
self.binary = testlib.compile("debug.c")
self.spike = testlib.spike(self.binary, halted=False)
self.gdb = testlib.Gdb()
self.gdb.command("file %s" % self.tmpf.name)
self.gdb.command("file %s" % self.binary)
self.gdb.command("target extended-remote localhost:9824")
self.gdb.command("p i=0");
@ -62,5 +61,37 @@ class SmokeTest(unittest.TestCase):
last_time = time
self.gdb.command("stepi")
class RegsTest(unittest.TestCase):
def setUp(self):
self.binary = testlib.compile("regs.s")
self.spike = testlib.spike(self.binary, halted=False)
self.gdb = testlib.Gdb()
self.gdb.command("file %s" % self.binary)
self.gdb.command("target extended-remote localhost:9824")
def tearDown(self):
self.spike.kill()
self.spike.wait()
def test_write_gprs(self):
# Note a0 is missing from this list since it's used to hold the
# address.
regs = ("ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1",
"a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4",
"s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5",
"t6")
self.gdb.command("p $pc=write_regs")
for i, r in enumerate(regs):
self.gdb.command("p $%s=%d" % (r, i*0xdeadbeef+17))
self.gdb.command("p $a0=data")
self.gdb.command("b all_done")
output = self.gdb.command("c")
self.assertIn("Breakpoint 1", output)
for n in range(len(regs)):
self.assertEqual(self.gdb.x("data+%d" % (8*n), 'g'),
n*0xdeadbeef+17)
if __name__ == '__main__':
unittest.main()

14
tests/testlib.py

@ -15,10 +15,15 @@ def find_file(path):
return fullpath
raise ValueError("Couldn't find %r." % path)
def compile(src, dst):
def compile(src):
"""Compile a single .c file into a binary."""
src = find_file(src)
dst = os.path.splitext(src)[0]
cc = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gcc")
return os.system("%s -g -o %s %s" % (cc, dst, find_file(src)))
cmd = "%s -g -o %s %s" % (cc, dst, src)
result = os.system(cmd)
assert result == 0, "%r failed" % cmd
return dst
def spike(binary, halted=False):
cmd = [find_file("spike")]
@ -46,3 +51,8 @@ class Gdb(object):
self.child.expect("\n")
self.child.expect("\(gdb\)")
return self.child.before.strip()
def x(self, address, size='w'):
output = self.command("x/%s %s" % (size, address))
value = int(output.split(':')[1].strip())
return value

Loading…
Cancel
Save