From 082b28c7029d7c786f0351db93db48caaf1fda69 Mon Sep 17 00:00:00 2001 From: jens Date: Tue, 30 Apr 2024 12:56:08 +0200 Subject: [PATCH] segment and mxcsr --- .../lldbdash/modules/register_module.py | 159 +++++++++++++----- .../lldbdash/register_lookup/__init__.py | 8 +- .../lldbdash/register_lookup/register.py | 53 +++++- .../register_lookup/register_lookup.py | 46 +++-- 4 files changed, 214 insertions(+), 52 deletions(-) diff --git a/unix/.config/lldbdash/modules/register_module.py b/unix/.config/lldbdash/modules/register_module.py index 5a749cd..8eb0209 100644 --- a/unix/.config/lldbdash/modules/register_module.py +++ b/unix/.config/lldbdash/modules/register_module.py @@ -7,9 +7,11 @@ from lldbdash.dashboard import Dashboard as D from lldbdash.register_lookup import ( AvxRegister, - GpRegister, + GeneralPurposeRegister, + MxcsrRegister, RegisterLookup, RflagsRegister, + SegmentRegister, get_avx_reg_set, get_fp_reg_set, get_gp_reg_set, @@ -65,54 +67,77 @@ class RegisterModule: def render(size: os.terminal_size, exe_ctx: lldb.SBExecutionContext, out: Output): frame: lldb.SBFrame = exe_ctx.GetFrame() lookup = RegisterLookup.new_or_cached(frame) + gp_reg_set = get_gp_reg_set(frame) + fp_reg_set = get_fp_reg_set(frame) avx_reg_set = get_avx_reg_set(frame) - fp_ret_set = get_fp_reg_set(frame) - gp_regs = filter( - not_none, - [ - lookup.read_gp(gp_reg_set, "rax"), - lookup.read_gp(gp_reg_set, "rbx"), - lookup.read_gp(gp_reg_set, "rcx"), - lookup.read_gp(gp_reg_set, "rdx"), - lookup.read_gp(gp_reg_set, "rdi"), - lookup.read_gp(gp_reg_set, "rsi"), - lookup.read_gp(gp_reg_set, "rbp"), - lookup.read_gp(gp_reg_set, "rsp"), - lookup.read_gp(gp_reg_set, "r8"), - lookup.read_gp(gp_reg_set, "r9"), - lookup.read_gp(gp_reg_set, "r10"), - lookup.read_gp(gp_reg_set, "r11"), - lookup.read_gp(gp_reg_set, "r12"), - lookup.read_gp(gp_reg_set, "r13"), - lookup.read_gp(gp_reg_set, "r14"), - lookup.read_gp(gp_reg_set, "r15"), - ], + + write_gp( + out, + filter( + not_none, + [ + lookup.read_gp(gp_reg_set, "rax"), + lookup.read_gp(gp_reg_set, "rbx"), + lookup.read_gp(gp_reg_set, "rcx"), + lookup.read_gp(gp_reg_set, "rdx"), + lookup.read_gp(gp_reg_set, "rdi"), + lookup.read_gp(gp_reg_set, "rsi"), + lookup.read_gp(gp_reg_set, "rbp"), + lookup.read_gp(gp_reg_set, "rsp"), + lookup.read_gp(gp_reg_set, "r8"), + lookup.read_gp(gp_reg_set, "r9"), + lookup.read_gp(gp_reg_set, "r10"), + lookup.read_gp(gp_reg_set, "r11"), + lookup.read_gp(gp_reg_set, "r12"), + lookup.read_gp(gp_reg_set, "r13"), + lookup.read_gp(gp_reg_set, "r14"), + lookup.read_gp(gp_reg_set, "r15"), + ], + ), + size.columns // 40, ) - per_row = size.columns // 40 - write_gp(out, gp_regs, per_row) + if RegisterModule.settings["show-segment"]: + write_segment( + out, + filter( + not_none, + [ + lookup.read_segment(gp_reg_set, "cs"), + lookup.read_segment(gp_reg_set, "ss"), + lookup.read_segment(gp_reg_set, "ds"), + lookup.read_segment(gp_reg_set, "es"), + lookup.read_segment(gp_reg_set, "fs"), + lookup.read_segment(gp_reg_set, "gs"), + ], + ), + ) - if RegisterModule.settings["show-rflags"] and ( - rflags := lookup.read_rflags(gp_reg_set) - ): - write_rflags(out, rflags) + if RegisterModule.settings["show-rflags"]: + rflags = lookup.read_rflags(gp_reg_set) + if rflags: + write_rflags(out, rflags) - if RegisterModule.settings["show-vector"] and ( - ymms := list( + if RegisterModule.settings["show-vector"]: + write_avx( + out, filter( not_none, [ - lookup.read_avx(avx_reg_set, fp_ret_set, f"ymm{i}") + lookup.read_avx(avx_reg_set, fp_reg_set, f"ymm{i}") for i in range(16) ], - ) + ), ) - ): - write_avx(out, ymms) + + if RegisterModule.settings["show-mxcsr"]: + mxcsr = lookup.read_mxcsr(fp_reg_set) + if mxcsr: + write_mxcsr(out, mxcsr) -def write_gp(out: Output, regs: typing.Iterable[GpRegister], per_row: int): +def write_gp(out: Output, regs: typing.Iterable[GeneralPurposeRegister], per_row: int): for batch in batched(regs, per_row): for i in range(len(batch) - 1): write_gp_hex(out, batch[i]) @@ -127,7 +152,7 @@ def write_gp(out: Output, regs: typing.Iterable[GpRegister], per_row: int): out.write("\n") -def write_gp_hex(out: Output, reg: GpRegister): +def write_gp_hex(out: Output, reg: GeneralPurposeRegister): out.write( D.settings["text-highlight"].value if reg.changed @@ -139,7 +164,7 @@ def write_gp_hex(out: Output, reg: GpRegister): out.write(reg.hex_str) -def write_gp_decimal(out: Output, reg: GpRegister): +def write_gp_decimal(out: Output, reg: GeneralPurposeRegister): out.write(f"{reg.value_int:>{len(reg.hex_str)+19}}") @@ -190,6 +215,49 @@ def write_rflags(out: Output, flags: RflagsRegister): out.write(f" {close_bracket}\n") +def write_mxcsr(out: Output, flags: MxcsrRegister): + open_bracket = f"{D.settings['text-secondary']}{{{RESET_COLOR}" + close_bracket = f"{D.settings['text-secondary']}}}{RESET_COLOR}" + out.write( + D.settings["text-highlight"].value + if flags.changed + else D.settings["text-secondary"].value + ) + out.write(flags.name) + out.write(RESET_COLOR) + out.write(f" {open_bracket} ") + write_flag(out, "FTZ", flags.ftz, flags.ftz_changed) + out.write(" ") + write_flag(out, "RC", flags.rc, flags.rc_changed) + out.write(f" {close_bracket} {open_bracket} ") + write_flag(out, "PM", flags.pm, flags.pm_changed) + out.write(" ") + write_flag(out, "UM", flags.um, flags.um_changed) + out.write(" ") + write_flag(out, "OM", flags.om, flags.om_changed) + out.write(" ") + write_flag(out, "ZM", flags.zm, flags.zm_changed) + out.write(" ") + write_flag(out, "DM", flags.dm, flags.dm_changed) + out.write(" ") + write_flag(out, "IM", flags.im, flags.im_changed) + out.write(f" {close_bracket} {open_bracket} ") + write_flag(out, "DAZ", flags.daz, flags.daz_changed) + out.write(f" {close_bracket} {open_bracket} ") + write_flag(out, "PE", flags.pe, flags.pe_changed) + out.write(" ") + write_flag(out, "UE", flags.ue, flags.ue_changed) + out.write(" ") + write_flag(out, "OE", flags.oe, flags.oe_changed) + out.write(" ") + write_flag(out, "ZE", flags.ze, flags.ze_changed) + out.write(" ") + write_flag(out, "DE", flags.de, flags.de_changed) + out.write(" ") + write_flag(out, "IE", flags.ie, flags.ie_changed) + out.write(f" {close_bracket}\n") + + def write_flag(out: Output, name: str, value: int, changed: bool): if changed: out.write(FONT_UNDERLINE) @@ -199,7 +267,7 @@ def write_flag(out: Output, name: str, value: int, changed: bool): out.write(RESET_COLOR) -def write_avx(out: Output, regs: list[AvxRegister]): +def write_avx(out: Output, regs: typing.Iterable[AvxRegister]): for reg in regs: out.write( D.settings["text-highlight"].value @@ -220,3 +288,18 @@ def write_avx(out: Output, regs: list[AvxRegister]): for i in reversed(range(16)): out.write(f" {reg.values[i]:>3}") out.write("\n") + + +def write_segment(out: Output, regs: typing.Iterable[SegmentRegister]): + for i, reg in enumerate(regs): + if i: + out.write(" ") + out.write( + D.settings["text-highlight"].value + if reg.changed + else D.settings["text-secondary"].value + ) + out.write(reg.name) + out.write(RESET_COLOR) + out.write(f" {reg.hex_str}") + out.write("\n") diff --git a/unix/.config/lldbdash/register_lookup/__init__.py b/unix/.config/lldbdash/register_lookup/__init__.py index 4e29e03..dca09d6 100644 --- a/unix/.config/lldbdash/register_lookup/__init__.py +++ b/unix/.config/lldbdash/register_lookup/__init__.py @@ -1,3 +1,9 @@ -from .register import AvxRegister, GpRegister, RflagsRegister +from .register import ( + AvxRegister, + GeneralPurposeRegister, + MxcsrRegister, + RflagsRegister, + SegmentRegister, +) from .register_lookup import RegisterLookup from .register_set import get_avx_reg_set, get_fp_reg_set, get_gp_reg_set diff --git a/unix/.config/lldbdash/register_lookup/register.py b/unix/.config/lldbdash/register_lookup/register.py index de8378e..d42b5b8 100644 --- a/unix/.config/lldbdash/register_lookup/register.py +++ b/unix/.config/lldbdash/register_lookup/register.py @@ -1,7 +1,7 @@ import lldb -class GpRegister: +class GeneralPurposeRegister: def __init__(self, values: list[lldb.SBValue], prev_value: int): self.name: str = "'".join([value.GetName() for value in values]) self.value_int: int = values[0].GetValueAsSigned() @@ -15,6 +15,15 @@ def __init__(self, values: list[lldb.SBValue], prev_value: int): ) +class SegmentRegister: + def __init__(self, value: lldb.SBValue, prev_value: int): + self.name: str = value.GetName() + self.value_int: int = value.GetValueAsSigned() + self.value_uint: int = value.GetValueAsUnsigned() + self.changed: bool = prev_value != self.value_uint + self.hex_str: str = f"{self.value_uint:04x}" + + class RflagsRegister: def __init__(self, value: lldb.SBValue, prev_value: int): self.name: str = value.GetName() @@ -60,14 +69,52 @@ def __init__(self, value: lldb.SBValue, prev_value: int): self.of_changed = (prev_value >> 11) & 1 != self.of +class MxcsrRegister: + def __init__(self, value: lldb.SBValue, prev_value: int): + self.name: str = value.GetName() + self.value_int: int = value.GetValueAsSigned() + self.value_uint: int = value.GetValueAsUnsigned() + self.changed: bool = prev_value != self.value_uint + self.ie = self.value_uint & 1 # Invalid operation flags + self.ie_changed = prev_value & 1 != self.ie + self.de = (self.value_uint >> 1) & 1 # Denormal flag + self.de_changed = (prev_value >> 1) & 1 != self.de + self.ze = (self.value_uint >> 2) & 1 # Divide-by-zero flag + self.ze_changed = (prev_value >> 2) & 1 != self.ze + self.oe = (self.value_uint >> 3) & 1 # Overflow flag + self.oe_changed = (prev_value >> 3) & 1 != self.oe + self.ue = (self.value_uint >> 4) & 1 # Underflow flag + self.ue_changed = (prev_value >> 4) & 1 != self.ue + self.pe = (self.value_uint >> 5) & 1 # Precision flag + self.pe_changed = (prev_value >> 5) & 1 != self.pe + self.daz = (self.value_uint >> 6) & 1 # Denormals are zero + self.daz_changed = (prev_value >> 6) & 1 != self.daz + self.im = (self.value_uint >> 7) & 1 # Invalid operation mask + self.im_changed = (prev_value >> 7) & 1 != self.im + self.dm = (self.value_uint >> 8) & 1 # Denormal mask + self.dm_changed = (prev_value >> 8) & 1 != self.dm + self.zm = (self.value_uint >> 9) & 1 # Divide-by-zero mask + self.zm_changed = (prev_value >> 9) & 1 != self.zm + self.om = (self.value_uint >> 10) & 1 # Overflow mask + self.om_changed = (prev_value >> 10) & 1 != self.om + self.um = (self.value_uint >> 11) & 1 # Underflow mask + self.um_changed = (prev_value >> 11) & 1 != self.um + self.pm = (self.value_uint >> 12) & 1 # Precision mask + self.pm_changed = (prev_value >> 12) & 1 != self.pm + self.rc = (self.value_uint >> 13) & 3 # Rounding control + self.rc_changed = (prev_value >> 13) & 3 != self.rc + self.ftz = (self.value_uint >> 15) & 1 # Flush to zero + self.ftz_changed = (prev_value >> 15) & 1 != self.ftz + + class AvxRegister: def __init__(self, ymm: lldb.SBValue, xmm: lldb.SBValue, prev_values: list[int]): self.name_ymm: str = ymm.GetName() self.name_xmm: str = xmm.GetName() self.values: list[int] = [child.GetValueAsUnsigned() for child in ymm] self.changed_xmm: bool = any( - prev_values[i] != self.values[i] for i in range(15) + prev_values[i] != self.values[i] for i in range(16) ) self.changed_ymm: bool = any( - prev_values[i] != self.values[i] for i in range(15, 32) + prev_values[i] != self.values[i] for i in range(16, 32) ) diff --git a/unix/.config/lldbdash/register_lookup/register_lookup.py b/unix/.config/lldbdash/register_lookup/register_lookup.py index 518940b..4da5ab0 100644 --- a/unix/.config/lldbdash/register_lookup/register_lookup.py +++ b/unix/.config/lldbdash/register_lookup/register_lookup.py @@ -4,7 +4,13 @@ import lldb from lldbdash.common import not_none -from .register import AvxRegister, GpRegister, RflagsRegister +from .register import ( + AvxRegister, + GeneralPurposeRegister, + MxcsrRegister, + RflagsRegister, + SegmentRegister, +) from .register_set import get_avx_reg_set, get_fp_reg_set, get_gp_reg_set Entries = dict[str, "RegisterLookup.Entry"] @@ -36,7 +42,16 @@ def read_gp(self, reg_set: lldb.SBValue, name: str): if entry is None: return values: list[lldb.SBValue] = [reg_set.GetChildAtIndex(i) for i in entry.indices] - register = GpRegister(values, entry.prev_values[0]) + register = GeneralPurposeRegister(values, entry.prev_values[0]) + entry.prev_values[0] = register.value_uint + return register + + def read_segment(self, reg_set: lldb.SBValue, name: str): + entry = self.entries.get(name, None) + if entry is None: + return + value: lldb.SBValue = reg_set.GetChildAtIndex(entry.indices[0]) + register = SegmentRegister(value, entry.prev_values[0]) entry.prev_values[0] = register.value_uint return register @@ -49,6 +64,15 @@ def read_rflags(self, reg_set: lldb.SBValue): entry.prev_values[0] = register.value_uint return register + def read_mxcsr(self, reg_set: lldb.SBValue): + entry = self.entries.get("mxcsr", None) + if entry is None: + return + value: lldb.SBValue = reg_set.GetChildAtIndex(entry.indices[0]) + register = MxcsrRegister(value, entry.prev_values[0]) + entry.prev_values[0] = register.value_uint + return register + def read_avx(self, avx_reg_set: lldb.SBValue, fp_reg_set: lldb.SBValue, name: str): entry = self.entries.get(name, None) if entry is None: @@ -87,10 +111,11 @@ def init_gp(entries: Entries, frame: lldb.SBFrame): indices, [gp_reg_set.GetChildAtIndex(indices[0]).GetValueAsUnsigned()] ) - if (index := gp_index.get("rflags", None)) is not None: - entries["rflags"] = RegisterLookup.Entry( - [index], [gp_reg_set.GetChildAtIndex(index).GetValueAsUnsigned()] - ) + for reg in ["cs", "ds", "ss", "es", "fs", "gs", "rflags"]: + if (index := gp_index.get(reg, None)) is not None: + entries[reg] = RegisterLookup.Entry( + [index], [gp_reg_set.GetChildAtIndex(index).GetValueAsUnsigned()] + ) def init_avx(entries: Entries, frame: lldb.SBFrame): @@ -127,7 +152,8 @@ def init_fp(entries: Entries, frame: lldb.SBFrame): [child.GetValueAsUnsigned() for child in fp_reg_set.GetChildAtIndex(index)], ) - if (index := fp_index.get("mxcsr", None)) is not None: - entries["mxcsr"] = RegisterLookup.Entry( - [index], [fp_reg_set.GetChildAtIndex(index).GetValueAsUnsigned()] - ) + for reg in ["mxcsr"]: + if (index := fp_index.get(reg, None)) is not None: + entries[reg] = RegisterLookup.Entry( + [index], [fp_reg_set.GetChildAtIndex(index).GetValueAsUnsigned()] + )