Skip to content

Commit

Permalink
segment and mxcsr
Browse files Browse the repository at this point in the history
  • Loading branch information
JensDll committed Apr 30, 2024
1 parent 2e49d5d commit 082b28c
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 52 deletions.
159 changes: 121 additions & 38 deletions unix/.config/lldbdash/modules/register_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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])
Expand All @@ -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
Expand All @@ -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}}")


Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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")
8 changes: 7 additions & 1 deletion unix/.config/lldbdash/register_lookup/__init__.py
Original file line number Diff line number Diff line change
@@ -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
53 changes: 50 additions & 3 deletions unix/.config/lldbdash/register_lookup/register.py
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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()
Expand Down Expand Up @@ -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)
)
46 changes: 36 additions & 10 deletions unix/.config/lldbdash/register_lookup/register_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down Expand Up @@ -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

Expand All @@ -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:
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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()]
)

0 comments on commit 082b28c

Please sign in to comment.