Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debug: Add UnavailableHaltedTest #515

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions debug/gdbserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1863,6 +1863,7 @@ def test(self):
self.gdb.p("$pc=_start")

self.exit()

class CeaseStepiTest(ProgramTest):
"""Test that we work correctly when the hart we're debugging ceases to
respond."""
Expand Down Expand Up @@ -1950,6 +1951,66 @@ def test(self):
self.gdb.interrupt()
self.gdb.p("$pc")

class UnavailableHaltedTest(ProgramTest):
"""Test behavior when the current hart becomes unavailable while halted."""
def early_applicable(self):
return self.target.support_unavailable_control

def test_resume(self, c_expect=None):
# Confirm things don't completely fall apart on `c`
self.gdb.c(wait=False)
if c_expect:
self.gdb.expect(c_expect)
else:
time.sleep(1)

# Now send a DMI command through OpenOCD to make the hart available
# again.
self.server.set_available(self.target.harts)

# The hart will show up as halted. That's just how spike behaves when we
# make a hart unavailable while it's halted.

self.gdb.expect("became available")
self.gdb.p("$minstret")

def test(self):
self.gdb.b("main")
output = self.gdb.c()
assertIn("Breakpoint", output)
assertIn("main", output)

self.server.set_available(
[h for h in self.target.harts if h != self.hart])
self.gdb.command(f"# disabled hart {self.hart.id}")
# gdb won't show that the hart became unavailable, because it thinks
# nothing can changed on a halted Linux thread.
try:
# We can't try this with something reasonable like $pc, because gdb
# has cached it, and it assumes the target can't change while it's
# halted.
self.gdb.p("$minstret")
assert False, ("Registers shouldn't be accessible when the hart is "
"unavailable.")
except testlib.CouldNotFetch:
pass

# There's a breakpoint set, so gdb will single step. You can't single
# step an unavailable target, so gdb should get a message to that
# effect.
self.test_resume(c_expect="unavailable")

# Delete breakpoints
self.gdb.command("delete")
self.server.set_available(
[h for h in self.target.harts if h != self.hart])

# Resume again. With breakpoints cleared, gdb will send vCont;c instead
# of step. There should be no error this time, since there is no
# observable difference between an unavailable thread and a running
# thread.
self.test_resume()

class FreeRtosTest(GdbTest):
def early_applicable(self):
return self.target.freertos_binary
Expand Down
Loading