Add max-decimal-number config (#3259)

* centralize max-decimal deteminration and add config

* add comments about consistency with capstone

* fix tests

* drive-by fix
pull/3268/head
k4lizen 3 months ago committed by GitHub
parent a693fc7c7d
commit 4891cceafe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -774,6 +774,24 @@ Whether to left-pad disassembly.
----------
## **max-decimal-number**
Show all numbers greater than this in hex.
For negative numbers, their absolute value is used.
Set the parameter to 'unlimited' if you want all values in decimal.
Specially, set the parameter to zero if you want all values in hex.
The assembly instruction operands come from capstone, and are thus
not controlled by this setting. For consistency with them, leave
this setting at 9 (the default).
**Default:** 9
----------
## **max-visualize-chunk-size**

@ -776,12 +776,7 @@ class DisassemblyAssistant:
# String functions assume the .before_value and .after_value have been set
def _immediate_string(self, instruction, operand) -> str:
value = operand.before_value
if abs(value) < 0x10:
return "%i" % value
return "%#x" % value
return pwndbg.lib.pretty_print.int_to_string(operand.before_value)
def _register_string(self, instruction: PwndbgInstruction, operand: EnhancedOperand):
"""
@ -863,7 +858,9 @@ class DisassemblyAssistant:
if (l_value := left.before_value_resolved) is not None and (
r_value := right.before_value_resolved
) is not None:
print_left, print_right = pwndbg.enhance.format_small_int_pair(l_value, r_value)
print_left, print_right = pwndbg.lib.pretty_print.int_pair_to_string(
l_value, r_value
)
# Ex: "0x7f - 0x12" or "0xdffffdea + 0x8"
instruction.annotation = (
f"{print_left} {char_to_separate_operands} {print_right}"
@ -1043,7 +1040,7 @@ class DisassemblyAssistant:
math_string = None
if op_one is not None and op_two is not None:
print_left, print_right = pwndbg.enhance.format_small_int_pair(op_one, op_two)
print_left, print_right = pwndbg.lib.pretty_print.int_pair_to_string(op_one, op_two)
math_string = f"{print_left} {char_to_separate_operands} {print_right}"

@ -106,10 +106,7 @@ def get(
color = lambda x: c.wx(old_color(x))
if text is None:
if address > 255:
text = f"{address:#x}"
else:
text = f"{address}"
text = pwndbg.lib.pretty_print.int_to_string(address)
if prefix:
# Replace first N characters with the provided prefix

@ -475,10 +475,9 @@ class Emulator:
intval = 0
intval0 = intval
if 0 <= intval < 10:
intval = E.integer(str(intval))
else:
intval = E.integer("%#x" % int(intval & pwndbg.aglib.arch.ptrmask))
intval = E.integer(
pwndbg.lib.pretty_print.int_to_string(intval & pwndbg.aglib.arch.ptrmask)
)
retval = []

@ -11,7 +11,6 @@ supplemental information sources (e.g. active IDA Pro connection).
from __future__ import annotations
import string
from typing import Tuple
import pwndbg
import pwndbg.aglib.arch
@ -24,31 +23,15 @@ import pwndbg.color.enhance as E
import pwndbg.color.memory
import pwndbg.integration
import pwndbg.lib.cache
import pwndbg.lib.pretty_print
from pwndbg import color
def format_small_int(value: int) -> str:
if value < 10:
return str(value)
else:
return hex(value)
def format_small_int_pair(first: int, second: int) -> Tuple[str, str]:
if first < 10 and second < 10:
return (str(first), str(second))
else:
return (
hex(first),
hex(second),
)
def int_str(value: int) -> str:
retval = format_small_int(value)
retval = pwndbg.lib.pretty_print.int_to_string(value)
# Try to unpack the value as a string
packed = pwndbg.aglib.arch.pack(int(value))
packed = pwndbg.aglib.arch.pack(value)
if all(c in string.printable.encode("utf-8") for c in packed):
if len(retval) > 4:
retval = "{} ({!r})".format(retval, str(packed.decode("ascii", "ignore")))
@ -133,10 +116,7 @@ def enhance(
if safe_linking:
intval ^= value >> 12
intval0 = intval
if 0 <= intval < 10:
intval = E.integer(str(intval))
else:
intval = E.integer("%#x" % int(intval & pwndbg.aglib.arch.ptrmask))
intval = E.integer(pwndbg.lib.pretty_print.int_to_string(intval & pwndbg.aglib.arch.ptrmask))
retval = []
@ -184,6 +164,6 @@ def enhance(
return E.unknown("???")
if len(retval) == 1:
return retval[0] # type: ignore[return-value]
return retval[0]
return retval[0] + E.comment(color.strip(f" /* {'; '.join(retval[1:])} */")) # type: ignore[arg-type]
return retval[0] + E.comment(color.strip(f" /* {'; '.join(retval[1:])} */"))

@ -5,10 +5,68 @@ from typing import Any
from typing import Callable
from typing import List
from typing import Optional
from typing import Tuple
import pwndbg
import pwndbg.color as color
from pwndbg.color import theme
max_decimal_number = pwndbg.config.add_param(
"max-decimal-number",
9,
"show all numbers greater than this in hex",
param_class=pwndbg.lib.config.PARAM_ZUINTEGER_UNLIMITED,
help_docstring="""
For negative numbers, their absolute value is used.
Set the parameter to 'unlimited' if you want all values in decimal.
Specially, set the parameter to zero if you want all values in hex.
The assembly instruction operands come from capstone, and are thus
not controlled by this setting. For consistency with them, leave
this setting at 9 (the default).
""",
# We could look into also overwriting the capstone operands string, similarly
# to what is done here: https://github.com/pwndbg/pwndbg/blob/26db4533aa08d77c4bbc359b4760a0944e0c6b23/pwndbg/aglib/disasm/arch.py#L322-L331
)
def int_to_string(num: int) -> str:
"""
Converts an integer value to string.
Decides whether to format it in decimal or
hex depending on the max-decimal-number config.
"""
if max_decimal_number == -1:
return f"{num}"
elif max_decimal_number == 0:
return f"{num:#x}"
elif abs(num) > max_decimal_number:
return f"{num:#x}"
else:
return f"{num}"
def int_pair_to_string(num1: int, num2: int) -> Tuple[str, str]:
"""
Converts an integer pair to a string pair.
Decides whether to format them in decimal or
hex depending on the max-decimal-number config.
If either value should be hex, both are hex.
"""
if max_decimal_number == -1:
return f"{num1}", f"{num2}"
elif max_decimal_number == 0:
return f"{num1:#x}", f"{num2:#x}"
elif abs(num1) > max_decimal_number or abs(num2) > max_decimal_number:
return f"{num1:#x}", f"{num2:#x}"
else:
return f"{num1}", f"{num2}"
config_property_name_color = theme.add_color_param(
"prop-name-color",
"bold",
@ -36,6 +94,7 @@ Used heavily in mallocng commands.
"""
)
@dataclass
class Property:
"""
@ -129,15 +188,10 @@ def from_properties(
# Transform prop values to string representation
for prop in properties:
if isinstance(prop.value, int):
if prop.use_hex:
prop.value = hex(prop.value)
else:
prop.value = str(prop.value)
prop.value = f"{prop.value:#x}" if prop.use_hex else f"{prop.value}"
if isinstance(prop.alt_value, int):
if prop.use_hex:
prop.alt_value = hex(prop.alt_value)
else:
prop.alt_value = str(prop.alt_value)
prop.alt_value = f"{prop.alt_value:#x}" if prop.use_hex else f"{prop.alt_value}"
indentation_str = indent_size * " "
extra_list_pad_str = (

@ -314,7 +314,7 @@ def test_aarch64_binary_operations(qemu_assembly_run):
" 0x101013c <_start+28> orr x5, x0, x1 X5 => 0x237 (0x7 | 0x233)\n"
" 0x1010140 <_start+32> eor x6, x0, x1 X6 => 0x234 (0x7 ^ 0x233)\n"
" 0x1010144 <_start+36> mul x10, x0, x1 X10 => 0xf65 (0x7 * 0x233)\n"
" 0x1010148 <_start+40> udiv x11, x1, x0 X11 => 80 (0x233 / 0x7)\n"
" 0x1010148 <_start+40> udiv x11, x1, x0 X11 => 0x50 (0x233 / 0x7)\n"
"────────────────────────────────────────────────────────────────────────────────\n"
)

@ -398,8 +398,8 @@ def test_arm_stack_pointer_check(qemu_assembly_run):
" 0x200c0 <_start+12> sub r3, r2, #2 R3 => 5 (7 - 2)\n"
f" 0x200c4 <_start+16> str r3, [sp, #-4]! [{hex(pwndbg.aglib.regs.sp - 4)}] <= 5\n"
" 0x200c8 <_start+20> pop {r4}\n"
" 0x200cc <_start+24> mul r4, r2, r1 R4 => 21 (7 * 3)\n"
" 0x200d0 <_start+28> add r4, r4, #1 R4 => 22 (0x15 + 0x1)\n"
" 0x200cc <_start+24> mul r4, r2, r1 R4 => 0x15 (7 * 3)\n"
" 0x200d0 <_start+28> add r4, r4, #1 R4 => 0x16 (0x15 + 0x1)\n"
" 0x200d4 <end> mov r0, #0 R0 => 0\n"
" 0x200d8 <end+4> mov r7, #0xf8 R7 => 0xf8\n"
" 0x200dc <end+8> svc #0 <SYS_exit_group>\n"

@ -128,7 +128,7 @@ def test_mips32_bnez_instruction(qemu_assembly_run, arch):
expected_1 = (
"LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA\n"
"───────────────────────[ DISASM / mips / set emulate on ]───────────────────────\n"
" ► 0x20150 <__start> addiu $t0, $zero, 0xa T0 => 10 (0x0 + 0xa)\n"
" ► 0x20150 <__start> addiu $t0, $zero, 0xa T0 => 0xa (0x0 + 0xa)\n"
" 0x20154 <__start+4> ✔ bnez $t0, end <end>\n"
" 0x20158 <__start+8> nop \n"
"\n"
@ -431,14 +431,14 @@ def test_mips32_binary_operations(qemu_assembly_run, arch):
expected = (
"LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA\n"
"───────────────────────[ DISASM / mips / set emulate on ]───────────────────────\n"
" ► 0x20150 <__start> addiu $t0, $zero, 0xa T0 => 10 (0x0 + 0xa)\n"
" 0x20154 <__start+4> addiu $t1, $zero, 0x14 T1 => 20 (0x0 + 0x14)\n"
" 0x20158 <__start+8> add $t2, $t0, $t1 T2 => 30 (0xa + 0x14)\n"
" 0x2015c <__start+12> sub $t3, $t1, $t0 T3 => 10 (0x14 - 0xa)\n"
" ► 0x20150 <__start> addiu $t0, $zero, 0xa T0 => 0xa (0x0 + 0xa)\n"
" 0x20154 <__start+4> addiu $t1, $zero, 0x14 T1 => 0x14 (0x0 + 0x14)\n"
" 0x20158 <__start+8> add $t2, $t0, $t1 T2 => 0x1e (0xa + 0x14)\n"
" 0x2015c <__start+12> sub $t3, $t1, $t0 T3 => 0xa (0x14 - 0xa)\n"
" 0x20160 <__start+16> and $t4, $t0, $t1 T4 => 0 (0xa & 0x14)\n"
" 0x20164 <__start+20> or $t5, $t0, $t1 T5 => 30 (0xa | 0x14)\n"
" 0x20168 <__start+24> xor $t6, $t0, $t1 T6 => 30 (0xa ^ 0x14)\n"
" 0x2016c <__start+28> sll $t7, $t0, 2 T7 => 40 (0xa << 0x2)\n"
" 0x20164 <__start+20> or $t5, $t0, $t1 T5 => 0x1e (0xa | 0x14)\n"
" 0x20168 <__start+24> xor $t6, $t0, $t1 T6 => 0x1e (0xa ^ 0x14)\n"
" 0x2016c <__start+28> sll $t7, $t0, 2 T7 => 0x28 (0xa << 0x2)\n"
" 0x20170 <__start+32> srl $t8, $t1, 2 T8 => 5 (0x14 >> 0x2)\n"
" 0x20174 <__start+36> sllv $t8, $t1, $t8 T8 => 0x280 (0x14 << 0x5)\n"
" 0x20178 <__start+40> srlv $t3, $t8, $t5 T3 => 0 (0x280 >> 0x1e)\n"
@ -489,7 +489,7 @@ def test_mips32_multiple_branches_followed(qemu_assembly_run, arch):
" 0x20154 <__start+4> ✔ beq $t1, $t0, first <first>\n"
" 0x20158 <__start+8> nop \n"
"\n"
" 0x20164 <first> addiu $t0, $zero, 0xa T0 => 10 (0x0 + 0xa)\n"
" 0x20164 <first> addiu $t0, $zero, 0xa T0 => 0xa (0x0 + 0xa)\n"
" 0x20168 <first+4> ✔ bnez $t0, second <second>\n"
" 0x2016c <first+8> nop \n"
"\n"

@ -191,10 +191,10 @@ def test_riscv64_compressed_loads(qemu_assembly_run):
" ► 0x10011b8 <store> c.sd a0, 0(a2) [data] <= 0x1234567890abcdef\n"
" 0x10011ba <store+2> c.ld a1, 0(a2) A1, [data] => 0x1234567890abcdef\n"
" 0x10011bc <store+4> c.li a1, 0x10 A1 => 0x10\n"
" 0x10011be <store+6> addi a2, zero, 0x26 A2 => 38 (0x0 + 0x26)\n"
" 0x10011c2 <store+10> add a4, a1, a2 A4 => 54 (0x10 + 0x26)\n"
" 0x10011c6 <store+14> sub a5, a1, a3 A5 => 16 (0x10 - 0x0)\n"
" 0x10011ca <store+18> xor a6, a1, a2 A6 => 54 (0x10 ^ 0x26)\n"
" 0x10011be <store+6> addi a2, zero, 0x26 A2 => 0x26 (0x0 + 0x26)\n"
" 0x10011c2 <store+10> add a4, a1, a2 A4 => 0x36 (0x10 + 0x26)\n"
" 0x10011c6 <store+14> sub a5, a1, a3 A5 => 0x10 (0x10 - 0x0)\n"
" 0x10011ca <store+18> xor a6, a1, a2 A6 => 0x36 (0x10 ^ 0x26)\n"
" 0x10011ce <store+22> and a7, a1, a2 A7 => 0 (0x10 & 0x26)\n"
" 0x10011d2 <store+26> sll a3, a1, a2 A3 => 0x40000000000 (0x10 << 0x26)\n"
" 0x10011d6 <store+30> mul a2, a1, a2 A2 => 0x260 (0x10 * 0x26)\n"
@ -271,7 +271,7 @@ def test_riscv64_jumps(qemu_assembly_run):
" 0x1001174 <fourth> ✔ blt t5, t0, 6 <end>\n"
"\n"
" 0x100117a <end> c.li a2, 0x1e A2 => 0x1e\n"
" 0x100117c <end+2> addi a7, zero, 0x5d A7 => 93 (0x0 + 0x5d)\n"
" 0x100117c <end+2> addi a7, zero, 0x5d A7 => 0x5d (0x0 + 0x5d)\n"
"────────────────────────────────────────────────────────────────────────────────\n"
)
@ -301,7 +301,7 @@ def test_riscv64_jumps(qemu_assembly_run):
" 0x1001174 <fourth> ✔ blt t5, t0, 6 <end>\n"
"\n"
" 0x100117a <end> c.li a2, 0x1e A2 => 0x1e\n"
" 0x100117c <end+2> addi a7, zero, 0x5d A7 => 93 (0x0 + 0x5d)\n"
" 0x100117c <end+2> addi a7, zero, 0x5d A7 => 0x5d (0x0 + 0x5d)\n"
" 0x1001180 <end+6> c.li a0, 0 A0 => 0\n"
"────────────────────────────────────────────────────────────────────────────────\n"
)
@ -361,7 +361,7 @@ def test_riscv64_jump_chain(qemu_assembly_run):
" 0x1001162 <e> c.j 2 <end>\n"
"\n"
" 0x1001164 <end> c.li a2, 0x1e A2 => 0x1e\n"
" 0x1001166 <end+2> addi a7, zero, 0x5d A7 => 93 (0x0 + 0x5d)\n"
" 0x1001166 <end+2> addi a7, zero, 0x5d A7 => 0x5d (0x0 + 0x5d)\n"
" 0x100116a <end+6> c.li a0, 0 A0 => 0\n"
" 0x100116c <end+8> ecall <SYS_exit>\n"
" 0x1001170 c.li s0, 0x10 S0 => 0x10\n"

Loading…
Cancel
Save