total_regs = 0
reg_map = {}
- frame = gdb.selected_frame()
tree = ET.fromstring(xml)
for f in tree.findall("feature"):
for r in regs:
name = r.attrib["name"]
regnum = int(r.attrib["regnum"])
- try:
- value = frame.read_register(name)
- except ValueError:
- report(False, f"failed to read reg: {name}")
- entry = { "name": name, "initial": value, "regnum": regnum }
+ entry = { "name": name, "regnum": regnum }
if name in reg_map:
report(False, f"duplicate register {entry} vs {reg_map[name]}")
return reg_map
+def get_register_by_regnum(reg_map, regnum):
+ """
+ Helper to find a register from the map via its XML regnum
+ """
+ for regname, entry in reg_map.items():
+ if entry['regnum'] == regnum:
+ return entry
+ return None
+
def crosscheck_remote_xml(reg_map):
"""
Cross-check the list of remote-registers with the XML info.
total_regs = len(reg_map.keys())
total_r_regs = 0
+ total_r_elided_regs = 0
for r in r_regs:
+ r = r.replace("long long", "long_long")
+ r = r.replace("long double", "long_double")
fields = r.split()
# Some of the registers reported here are "pseudo" registers that
# gdb invents based on actual registers so we need to filter them
r_name = fields[0]
r_regnum = int(fields[6])
+ # Some registers are "hidden" so don't have a name
+ # although they still should have a register number
+ if r_name == "''":
+ total_r_elided_regs += 1
+ x_reg = get_register_by_regnum(reg_map, r_regnum)
+ if x_reg is not None:
+ x_reg["hidden"] = True
+ continue
+
# check in the XML
try:
x_reg = reg_map[r_name]
else:
total_r_regs += 1
- # Just print a mismatch in totals as gdb will filter out 64 bit
- # registers on a 32 bit machine. Also print what is missing to
- # help with debug.
- if total_regs != total_r_regs:
- print(f"xml-tdesc has ({total_regs}) registers")
- print(f"remote-registers has ({total_r_regs}) registers")
+ report(total_regs == total_r_regs + total_r_elided_regs,
+ "All XML Registers accounted for")
+
+ print(f"xml-tdesc has {total_regs} registers")
+ print(f"remote-registers has {total_r_regs} registers")
+ print(f"of which {total_r_elided_regs} are hidden")
+
+ for x_key in reg_map.keys():
+ x_reg = reg_map[x_key]
+ if "hidden" in x_reg:
+ print(f"{x_reg} elided by gdb")
+ elif "seen" not in x_reg:
+ print(f"{x_reg} wasn't seen in remote-registers")
+
+def initial_register_read(reg_map):
+ """
+ Do an initial read of all registers that we know gdb cares about
+ (so ignore the elided ones).
+ """
+ frame = gdb.selected_frame()
+
+ for e in reg_map.values():
+ name = e["name"]
+ regnum = e["regnum"]
+
+ try:
+ if "hidden" in e:
+ value = frame.read_register(regnum)
+ e["initial"] = value
+ elif "seen" in e:
+ value = frame.read_register(name)
+ e["initial"] = value
+
+ except ValueError:
+ report(False, f"failed to read reg: {name}")
- for x_key in reg_map.keys():
- x_reg = reg_map[x_key]
- if "seen" not in x_reg:
- print(f"{x_reg} wasn't seen in remote-registers")
def complete_and_diff(reg_map):
"""
changed = 0
for e in reg_map.values():
- name = e["name"]
- old_val = e["initial"]
+ if "initial" in e and "hidden" not in e:
+ name = e["name"]
+ old_val = e["initial"]
- try:
- new_val = frame.read_register(name)
- except:
- report(False, f"failed to read {name} at end of run")
- continue
+ try:
+ new_val = frame.read_register(name)
+ except ValueError:
+ report(False, f"failed to read {name} at end of run")
+ continue
- if new_val != old_val:
- print(f"{name} changes from {old_val} to {new_val}")
- changed += 1
+ if new_val != old_val:
+ print(f"{name} changes from {old_val} to {new_val}")
+ changed += 1
# as long as something changed we can be confident its working
report(changed > 0, f"{changed} registers were changed")
if reg_map is not None:
crosscheck_remote_xml(reg_map)
+ initial_register_read(reg_map)
complete_and_diff(reg_map)