]>
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
10 import xml
.etree
.ElementTree
as ET
11 from test_gdbstub
import main
, report
17 def fetch_xml_regmap():
19 Iterate through the XML descriptions and validate.
21 We check for any duplicate registers and report them. Return a
22 reg_map hash containing the names, regnums and initial values of
26 # First check the XML descriptions we have sent. Most arches
27 # support XML but a few of the ancient ones don't in which case we
28 # need to gracefully fail.
31 xml
= gdb
.execute("maint print xml-tdesc", False, True)
33 print("SKIP: target does not support XML")
39 tree
= ET
.fromstring(xml
)
40 for f
in tree
.findall("feature"):
41 name
= f
.attrib
["name"]
42 regs
= f
.findall("reg")
46 base
= int(regs
[0].attrib
["regnum"])
47 top
= int(regs
[-1].attrib
["regnum"])
49 print(f
"feature: {name} has {total} registers from {base} to {top}")
52 name
= r
.attrib
["name"]
53 regnum
= int(r
.attrib
["regnum"])
55 entry
= { "name": name
, "regnum": regnum
}
58 report(False, f
"duplicate register {entry} vs {reg_map[name]}")
64 report(total_regs
== len(reg_map
.keys()),
65 f
"counted all {total_regs} registers in XML")
70 def get_register_by_regnum(reg_map
, regnum
):
72 Helper to find a register from the map via its XML regnum
74 for regname
, entry
in reg_map
.items():
75 if entry
['regnum'] == regnum
:
80 def crosscheck_remote_xml(reg_map
):
82 Cross-check the list of remote-registers with the XML info.
85 remote
= gdb
.execute("maint print remote-registers", False, True)
86 r_regs
= remote
.split("\n")
88 total_regs
= len(reg_map
.keys())
90 total_r_elided_regs
= 0
93 r
= r
.replace("long long", "long_long")
94 r
= r
.replace("long double", "long_double")
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])
103 # Some registers are "hidden" so don't have a name
104 # although they still should have a register number
106 total_r_elided_regs
+= 1
107 x_reg
= get_register_by_regnum(reg_map
, r_regnum
)
108 if x_reg
is not None:
109 x_reg
["hidden"] = True
114 x_reg
= reg_map
[r_name
]
116 report(False, f
"{r_name} not in XML description")
120 x_regnum
= x_reg
["regnum"]
121 if r_regnum
!= x_regnum
:
122 report(False, f
"{r_name} {r_regnum} == {x_regnum} (xml)")
126 report(total_regs
== total_r_regs
+ total_r_elided_regs
,
127 "All XML Registers accounted for")
129 print(f
"xml-tdesc has {total_regs} registers")
130 print(f
"remote-registers has {total_r_regs} registers")
131 print(f
"of which {total_r_elided_regs} are hidden")
133 for x_key
in reg_map
.keys():
134 x_reg
= reg_map
[x_key
]
135 if "hidden" in x_reg
:
136 print(f
"{x_reg} elided by gdb")
137 elif "seen" not in x_reg
:
138 print(f
"{x_reg} wasn't seen in remote-registers")
141 def initial_register_read(reg_map
):
143 Do an initial read of all registers that we know gdb cares about
144 (so ignore the elided ones).
146 frame
= gdb
.selected_frame()
148 for e
in reg_map
.values():
154 value
= frame
.read_register(regnum
)
157 value
= frame
.read_register(name
)
161 report(False, f
"failed to read reg: {name}")
164 def complete_and_diff(reg_map
):
166 Let the program run to (almost) completion and then iterate
167 through all the registers we know about and report which ones have
170 # Let the program get to the end and we can check what changed
171 b
= gdb
.Breakpoint("_exit")
172 if b
.pending
: # workaround Microblaze weirdness
174 gdb
.Breakpoint("_Exit")
176 gdb
.execute("continue")
178 frame
= gdb
.selected_frame()
181 for e
in reg_map
.values():
182 if "initial" in e
and "hidden" not in e
:
184 old_val
= e
["initial"]
187 new_val
= frame
.read_register(name
)
189 report(False, f
"failed to read {name} at end of run")
192 if new_val
!= old_val
:
193 print(f
"{name} changes from {old_val} to {new_val}")
196 # as long as something changed we can be confident its working
197 report(changed
> 0, f
"{changed} registers were changed")
201 "Run through the tests"
203 reg_map
= fetch_xml_regmap()
205 if reg_map
is not None:
206 crosscheck_remote_xml(reg_map
)
207 initial_register_read(reg_map
)
208 complete_and_diff(reg_map
)