Skip to content

Instantly share code, notes, and snippets.

@stek29
Last active June 25, 2024 05:56
Show Gist options
  • Save stek29/cdbbbe018f0aaf0b2a9a58c9173becb8 to your computer and use it in GitHub Desktop.
Save stek29/cdbbbe018f0aaf0b2a9a58c9173becb8 to your computer and use it in GitHub Desktop.
Pretty print x86 (r|e)flags register with lldb script
import lldb
import shlex
FLAGS = [
['CF', 'Carry Flag'],
[None, 'Reserved'],
['PF', 'Parity Flag'],
[None, 'Reserved'],
['AF', 'Adjust Flag'],
[None, 'Reserved'],
['ZF', 'Zero Flag'],
['SF', 'Sign Flag'],
['TF', 'Trap Flag'],
['IF', 'Interrupt Enable Flag'],
['DF', 'Direction Flag'],
['OF', 'Overflow Flag'],
['IOPL_H', 'I/O privilege level High bit'],
['IOPL_L', 'I/O privilege level Low bit'],
['NT', 'Nested Task Flag'],
[None, 'Reserved'],
# eflags
['RF', 'Resume Flag'],
['VM', 'Virtual 8086 mode flag'],
['AC', 'Alignment check'],
['VIF', 'Virtual interrupt flag'],
['VIP', 'Virtual interrupt pending'],
['ID', 'Able to use CPUID instruction'],
# 22-31 reserved
# rflags 32-63 reserved
]
def parse_flags(val):
""" Returns list of set flags """
set_flags = list()
for bit, desc in enumerate(FLAGS):
if val & (1 << bit) and desc[0] is not None:
set_flags.append(desc)
return set_flags
def flag_list_to_str(l):
return ' '.join((desc[0] for desc in l))
def get_flags_reg(frame):
grs = list()
for rs in frame.GetRegisters():
if rs.GetName().lower() == 'general purpose registers':
grs = rs
break
for reg in grs:
if 'flags' in reg.GetName():
return reg
return None
def fmt_lst(fl_reg, lst):
val = fl_reg.GetValueAsUnsigned()
lst = [x.upper() for x in lst]
found = list()
for bit, desc in enumerate(FLAGS):
if desc[0] is not None and desc[0] in lst:
lst.remove(desc[0])
found.append([desc[0], bool(val & (1 << bit))])
ret = list()
# lst must be empty at this point
# anything left wasn't found
if lst:
ret.append('ERROR: Unknown flags: [%s]' % ' '.join(lst))
for x in found:
ret.append('%s: %d'%(x[0], int(x[1])))
return '\n'.join(ret)
def fmt_short(fl_reg):
val = fl_reg.GetValueAsUnsigned()
reg_print_width = fl_reg.GetByteSize() * 2
descs = parse_flags(val)
return ('%s: 0x%.*x [%s]' % (
fl_reg.GetName(), # register name
reg_print_width, # how many hex digits to print
val, # value
flag_list_to_str(descs) # parsed value (list of set flags)
))
def pfl_cmd(debugger, command, result, internal_dict):
target = debugger.GetSelectedTarget()
process = target.GetProcess()
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
fl_reg = get_flags_reg(frame)
if fl_reg is None:
print("ERROR: Cant find flags register!")
return
lst = shlex.split(command)
ret = ''
if lst:
# dirty argparse hack
# XXX handle flags and eflags diff for fun? :)
if '-l' in lst:
lst = [desc[0] for desc in FLAGS if desc[0] is not None]
ret = fmt_lst(fl_reg, lst)
else:
ret = fmt_short(fl_reg)
print(ret)
@invokeness
Copy link

how to use it ?

@eihli
Copy link

eihli commented Aug 11, 2022

Save as rflags.py.
Run lldb then run:

(lldb) command script add -f rflags.pfl_cmd pfl
(lldb) pfl
rflags: 0x0000000000000206 [PF IF]

Reference: https://lldb.llvm.org/use/python-reference.html#create-a-new-lldb-command-using-a-python-function

@programmingkidx
Copy link

programmingkidx commented Apr 16, 2024

@eihli I see "error: unable to execute script function" when I enter pfl.
I am using lldb 900.0.64 on Mac OS 10.12.

@therealdreg
Copy link

thx for this code, added to my repo https://github.com/therealdreg/lldb_reversing/

@yuraic
Copy link

yuraic commented Jun 25, 2024

[Dendy's-MacBook-Pro] /Users/dendy/Documents/asm/sum_list >lldb hello
(lldb) target create "hello"
Current executable set to '/Users/dendy/Documents/asm/sum_list/hello' (x86_64).
(lldb) command script add -f rflags.pfl_cmd pfl
(lldb) pfl
(lldb)
__
Nothing happens... I copied the file rflags.py to local directory and the version of python installed is 3.12.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment