diff options
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | riscv/gdbserver.cc | 6 | ||||
-rw-r--r-- | tests/debug.c | 27 | ||||
-rwxr-xr-x | tests/gdbserver-smoke.py | 49 | ||||
-rw-r--r-- | tests/testlib.py | 46 |
5 files changed, 126 insertions, 4 deletions
diff --git a/Makefile.in b/Makefile.in index 1e353ab..a0f119a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -335,7 +335,7 @@ deps : $(deps) bintest_outs = $(bintests:=.out) junk += $(bintest_outs) %.out: % all - ./$^ < /dev/null 2>&1 | tee $@ + ./$* < /dev/null 2>&1 | tee $@ check-cpp : $(test_outs) echo; grep -h -e'Unit Tests' -e'FAILED' -e'Segmentation' $^ < /dev/null; echo diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc index 70dac13..39bfdf8 100644 --- a/riscv/gdbserver.cc +++ b/riscv/gdbserver.cc @@ -529,7 +529,8 @@ void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet) return send_packet("E53"); } - mmu_t* mmu = sim->debug_mmu; + processor_t *p = sim->get_core(0); + mmu_t* mmu = p->mmu; if (insert) { bp.insert(mmu); breakpoints[bp.address] = bp; @@ -540,8 +541,7 @@ void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet) breakpoints.erase(bp.address); } mmu->flush_icache(); - processor_t *p = sim->get_core(0); - p->mmu->flush_icache(); + sim->debug_mmu->flush_icache(); return send_packet("OK"); } diff --git a/tests/debug.c b/tests/debug.c new file mode 100644 index 0000000..2cad88f --- /dev/null +++ b/tests/debug.c @@ -0,0 +1,27 @@ +#include <stdio.h> + +char c = 'x'; + +void print_row(int length) +{ + for (int x=0; x<length; x++) { + printf("%c", c); + } + printf("\n"); +} + +int main() +{ + volatile int i = 42; + const char *text = "constant\n"; + int threshold = 7; + + // Wait for the debugger to get us out of this loop. + while (i) + ; + + printf("%s", text); + for (int y=0; y < 10; y++) { + print_row(y); + } +} diff --git a/tests/gdbserver-smoke.py b/tests/gdbserver-smoke.py new file mode 100755 index 0000000..d9eae92 --- /dev/null +++ b/tests/gdbserver-smoke.py @@ -0,0 +1,49 @@ +#!/usr/bin/python + +import os +import testlib +import unittest +import tempfile +import time + +class SmokeTest(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.gdb = testlib.Gdb() + self.gdb.command("file %s" % self.tmpf.name) + self.gdb.command("target extended-remote localhost:9824") + self.gdb.command("p i"); + self.gdb.command("p i=0"); + + def cleanUp(self): + self.spike.kill() + + def test_turbostep(self): + """Single step until the program exits. TODO""" + last_pc = None + for _ in range(100): + self.gdb.command("stepi") + pc = self.gdb.command("p $pc") + self.assertNotEqual(last_pc, pc) + last_pc = pc + + def test_exit(self): + output = self.gdb.command("c") + self.assertIn("Continuing", output) + self.assertIn("Remote connection closed", output) + + def test_breakpoint(self): + self.gdb.command("b print_row") + # The breakpoint should be hit exactly 10 times. + for _ in range(10): + output = self.gdb.command("c") + self.assertIn("Continuing", output) + self.assertIn("Breakpoint 1", output) + output = self.gdb.command("c") + self.assertIn("Continuing", output) + self.assertIn("Remote connection closed", output) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/testlib.py b/tests/testlib.py new file mode 100644 index 0000000..274ba6c --- /dev/null +++ b/tests/testlib.py @@ -0,0 +1,46 @@ +import os.path +import pexpect +import subprocess +import tempfile +import testlib +import unittest + +# Note that gdb comes with its own testsuite. I was unable to figure out how to +# run that testsuite against the spike simulator. + +def find_file(path): + for directory in (os.getcwd(), os.path.dirname(testlib.__file__)): + fullpath = os.path.join(directory, path) + if os.path.exists(fullpath): + return fullpath + raise ValueError("Couldn't find %r." % path) + +def compile(src, dst): + """Compile a single .c file into a binary.""" + cc = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gcc") + return os.system("%s -g -o %s %s" % (cc, dst, find_file(src))) + +def spike(binary, halted=False): + cmd = [find_file("spike")] + if halted: + cmd.append('-H') + cmd += ['pk', binary] + logfile = open("spike.log", "w") + return subprocess.Popen(cmd, stdout=logfile, stderr=logfile) + +class Gdb(object): + def __init__(self): + path = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gdb") + self.child = pexpect.spawn(path) + self.child.logfile = file("gdb.log", "w") + self.wait() + + def wait(self): + """Wait for prompt.""" + self.child.expect("\(gdb\)") + + def command(self, command): + self.child.sendline(command) + self.child.expect("\n") + self.child.expect("\(gdb\)") + return self.child.before.strip() |