]>
git.proxmox.com Git - mirror_qemu.git/blob - tests/tcg/multiarch/gdbstub/registers.py
688c0611072b26114f4bfc72a563ca5f0e639ef2
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")
48 tree
= ET
.fromstring(xml
)
49 for f
in tree
.findall("feature"):
50 name
= f
.attrib
["name"]
51 regs
= f
.findall("reg")
55 base
= int(regs
[0].attrib
["regnum"])
56 top
= int(regs
[-1].attrib
["regnum"])
58 print(f
"feature: {name} has {total} registers from {base} to {top}")
61 name
= r
.attrib
["name"]
62 regnum
= int(r
.attrib
["regnum"])
64 entry
= { "name": name
, "regnum": regnum
}
67 report(False, f
"duplicate register {entry} vs {reg_map[name]}")
73 report(total_regs
== len(reg_map
.keys()),
74 f
"counted all {total_regs} registers in XML")
78 def get_register_by_regnum(reg_map
, regnum
):
80 Helper to find a register from the map via its XML regnum
82 for regname
, entry
in reg_map
.items():
83 if entry
['regnum'] == regnum
:
87 def crosscheck_remote_xml(reg_map
):
89 Cross-check the list of remote-registers with the XML info.
92 remote
= gdb
.execute("maint print remote-registers", False, True)
93 r_regs
= remote
.split("\n")
95 total_regs
= len(reg_map
.keys())
97 total_r_elided_regs
= 0
100 r
= r
.replace("long long", "long_long")
101 r
= r
.replace("long double", "long_double")
103 # Some of the registers reported here are "pseudo" registers that
104 # gdb invents based on actual registers so we need to filter them
108 r_regnum
= int(fields
[6])
110 # Some registers are "hidden" so don't have a name
111 # although they still should have a register number
113 total_r_elided_regs
+= 1
114 x_reg
= get_register_by_regnum(reg_map
, r_regnum
)
115 if x_reg
is not None:
116 x_reg
["hidden"] = True
121 x_reg
= reg_map
[r_name
]
123 report(False, f
"{r_name} not in XML description")
127 x_regnum
= x_reg
["regnum"]
128 if r_regnum
!= x_regnum
:
129 report(False, f
"{r_name} {r_regnum} == {x_regnum} (xml)")
133 report(total_regs
== total_r_regs
+ total_r_elided_regs
,
134 "All XML Registers accounted for")
136 print(f
"xml-tdesc has {total_regs} registers")
137 print(f
"remote-registers has {total_r_regs} registers")
138 print(f
"of which {total_r_elided_regs} are hidden")
140 for x_key
in reg_map
.keys():
141 x_reg
= reg_map
[x_key
]
142 if "hidden" in x_reg
:
143 print(f
"{x_reg} elided by gdb")
144 elif "seen" not in x_reg
:
145 print(f
"{x_reg} wasn't seen in remote-registers")
147 def initial_register_read(reg_map
):
149 Do an initial read of all registers that we know gdb cares about
150 (so ignore the elided ones).
152 frame
= gdb
.selected_frame()
154 for e
in reg_map
.values():
160 value
= frame
.read_register(regnum
)
163 value
= frame
.read_register(name
)
167 report(False, f
"failed to read reg: {name}")
170 def complete_and_diff(reg_map
):
172 Let the program run to (almost) completion and then iterate
173 through all the registers we know about and report which ones have
176 # Let the program get to the end and we can check what changed
177 b
= gdb
.Breakpoint("_exit")
178 if b
.pending
: # workaround Microblaze weirdness
180 gdb
.Breakpoint("_Exit")
182 gdb
.execute("continue")
184 frame
= gdb
.selected_frame()
187 for e
in reg_map
.values():
188 if "initial" in e
and "hidden" not in e
:
190 old_val
= e
["initial"]
193 new_val
= frame
.read_register(name
)
195 report(False, f
"failed to read {name} at end of run")
198 if new_val
!= old_val
:
199 print(f
"{name} changes from {old_val} to {new_val}")
202 # as long as something changed we can be confident its working
203 report(changed
> 0, f
"{changed} registers were changed")
207 "Run through the tests"
209 reg_map
= fetch_xml_regmap()
211 if reg_map
is not None:
212 crosscheck_remote_xml(reg_map
)
213 initial_register_read(reg_map
)
214 complete_and_diff(reg_map
)
218 # This runs as the script it sourced (via -x, via run-test.py)
221 inferior
= gdb
.selected_inferior()
222 arch
= inferior
.architecture()
223 print("ATTACHED: %s" % arch
.name())
224 except (gdb
.error
, AttributeError):
225 print("SKIPPING (not connected)", file=sys
.stderr
)
228 if gdb
.parse_and_eval('$pc') == 0:
229 print("SKIP: PC not set")
235 print ("GDB Exception: %s" % (sys
.exc_info()[0]))
239 print("All tests complete: %d failures" % failcount
)