]>
git.proxmox.com Git - mirror_qemu.git/blob - tests/tcg/multiarch/gdbstub/registers.py
1 # Exercise the register functionality by exhaustively iterating
2 # through all supported registers on the system.
4 # This is launched via tests/guest-debug/run-test.py but you can also
5 # call it directly if using it for debugging/introspection:
7 # SPDX-License-Identifier: GPL-2.0-or-later
11 import xml
.etree
.ElementTree
as ET
16 def report(cond
, msg
):
17 "Report success/fail of test."
19 print("PASS: %s" % (msg
))
21 print("FAIL: %s" % (msg
))
26 def fetch_xml_regmap():
28 Iterate through the XML descriptions and validate.
30 We check for any duplicate registers and report them. Return a
31 reg_map hash containing the names, regnums and initial values of
35 # First check the XML descriptions we have sent. Most arches
36 # support XML but a few of the ancient ones don't in which case we
37 # need to gracefully fail.
40 xml
= gdb
.execute("maint print xml-tdesc", False, True)
42 print("SKIP: target does not support XML")
47 frame
= gdb
.selected_frame()
49 tree
= ET
.fromstring(xml
)
50 for f
in tree
.findall("feature"):
51 name
= f
.attrib
["name"]
52 regs
= f
.findall("reg")
56 base
= int(regs
[0].attrib
["regnum"])
57 top
= int(regs
[-1].attrib
["regnum"])
59 print(f
"feature: {name} has {total} registers from {base} to {top}")
62 name
= r
.attrib
["name"]
63 regnum
= int(r
.attrib
["regnum"])
65 value
= frame
.read_register(name
)
67 report(False, f
"failed to read reg: {name}")
69 entry
= { "name": name
, "initial": value
, "regnum": regnum
}
72 report(False, f
"duplicate register {entry} vs {reg_map[name]}")
78 report(total_regs
== len(reg_map
.keys()),
79 f
"counted all {total_regs} registers in XML")
83 def crosscheck_remote_xml(reg_map
):
85 Cross-check the list of remote-registers with the XML info.
88 remote
= gdb
.execute("maint print remote-registers", False, True)
89 r_regs
= remote
.split("\n")
91 total_regs
= len(reg_map
.keys())
96 # Some of the registers reported here are "pseudo" registers that
97 # gdb invents based on actual registers so we need to filter them
101 r_regnum
= int(fields
[6])
105 x_reg
= reg_map
[r_name
]
107 report(False, f
"{r_name} not in XML description")
111 x_regnum
= x_reg
["regnum"]
112 if r_regnum
!= x_regnum
:
113 report(False, f
"{r_name} {r_regnum} == {x_regnum} (xml)")
117 # Just print a mismatch in totals as gdb will filter out 64 bit
118 # registers on a 32 bit machine. Also print what is missing to
120 if total_regs
!= total_r_regs
:
121 print(f
"xml-tdesc has ({total_regs}) registers")
122 print(f
"remote-registers has ({total_r_regs}) registers")
124 for x_key
in reg_map
.keys():
125 x_reg
= reg_map
[x_key
]
126 if "seen" not in x_reg
:
127 print(f
"{x_reg} wasn't seen in remote-registers")
129 def complete_and_diff(reg_map
):
131 Let the program run to (almost) completion and then iterate
132 through all the registers we know about and report which ones have
135 # Let the program get to the end and we can check what changed
136 b
= gdb
.Breakpoint("_exit")
137 if b
.pending
: # workaround Microblaze weirdness
139 gdb
.Breakpoint("_Exit")
141 gdb
.execute("continue")
143 frame
= gdb
.selected_frame()
146 for e
in reg_map
.values():
148 old_val
= e
["initial"]
151 new_val
= frame
.read_register(name
)
153 report(False, f
"failed to read {name} at end of run")
156 if new_val
!= old_val
:
157 print(f
"{name} changes from {old_val} to {new_val}")
160 # as long as something changed we can be confident its working
161 report(changed
> 0, f
"{changed} registers were changed")
165 "Run through the tests"
167 reg_map
= fetch_xml_regmap()
169 if reg_map
is not None:
170 crosscheck_remote_xml(reg_map
)
171 complete_and_diff(reg_map
)
175 # This runs as the script it sourced (via -x, via run-test.py)
178 inferior
= gdb
.selected_inferior()
179 arch
= inferior
.architecture()
180 print("ATTACHED: %s" % arch
.name())
181 except (gdb
.error
, AttributeError):
182 print("SKIPPING (not connected)", file=sys
.stderr
)
185 if gdb
.parse_and_eval('$pc') == 0:
186 print("SKIP: PC not set")
192 print ("GDB Exception: %s" % (sys
.exc_info()[0]))
196 print("All tests complete: %d failures" % failcount
)