Split config.py into lib/ and gdblib/ (#1134)

This commit is contained in:
Gulshan Singh 2022-10-13 05:50:20 -07:00 committed by GitHub
parent 2be84a9b4d
commit eabab316d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 484 additions and 506 deletions

View File

@ -1,5 +1,5 @@
:mod:`pwndbg.config` --- pwndbg.config
:mod:`pwndbg.gdblib.config` --- pwndbg.gdblib.config
=============================================
.. automodule:: pwndbg.config
.. automodule:: pwndbg.gdblib.config
:members:

View File

@ -98,3 +98,7 @@ signal.signal(
# Reading Comment file
pwndbg.commands.comments.init()
from pwndbg.gdblib import config_mod
config_mod.init_params()

View File

@ -10,7 +10,7 @@ import pwndbg.gdblib.symbol
import pwndbg.gdblib.typeinfo
import pwndbg.vmmap
LIMIT = pwndbg.config.Parameter(
LIMIT = pwndbg.gdblib.config.add_param(
"dereference-limit", 5, "max number of pointers to dereference in a chain"
)
@ -69,9 +69,9 @@ def get(
return result
config_arrow_left = theme.Parameter("chain-arrow-left", "◂—", "left arrow of chain formatting")
config_arrow_right = theme.Parameter("chain-arrow-right", "—▸", "right arrow of chain formatting")
config_contiguous = theme.Parameter(
config_arrow_left = theme.add_param("chain-arrow-left", "◂—", "left arrow of chain formatting")
config_arrow_right = theme.add_param("chain-arrow-right", "—▸", "right arrow of chain formatting")
config_contiguous = theme.add_param(
"chain-contiguous-marker", "...", "contiguous marker of chain formatting"
)

View File

@ -115,7 +115,7 @@ def colorize(x, color):
return color + terminateWith(str(x), color) + NORMAL
disable_colors = theme.Parameter(
disable_colors = theme.add_param(
"disable-colors",
bool(os.environ.get("PWNDBG_DISABLE_COLORS")),
"whether to color the output or not",
@ -142,7 +142,8 @@ def generateColorFunction(config):
return function
for color in config.split(","):
function = generateColorFunctionInner(function, globals()[color.lower().replace("-", "_")])
func_name = color.lower().replace("-", "_")
function = generateColorFunctionInner(function, globals()[func_name])
return function

View File

@ -1,18 +1,18 @@
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.gdblib.config as config
from pwndbg.color import generateColorFunction
config_prefix = theme.Parameter("backtrace-prefix", "", "prefix for current backtrace label")
config_prefix_color = theme.ColoredParameter(
config_prefix = theme.add_param("backtrace-prefix", "", "prefix for current backtrace label")
config_prefix_color = theme.add_color_param(
"backtrace-prefix-color", "none", "color for prefix of current backtrace label"
)
config_address_color = theme.ColoredParameter(
config_address_color = theme.add_color_param(
"backtrace-address-color", "none", "color for backtrace (address)"
)
config_symbol_color = theme.ColoredParameter(
config_symbol_color = theme.add_color_param(
"backtrace-symbol-color", "none", "color for backtrace (symbol)"
)
config_label_color = theme.ColoredParameter(
config_label_color = theme.add_color_param(
"backtrace-frame-label-color", "none", "color for backtrace (frame label)"
)

View File

@ -1,11 +1,11 @@
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.gdblib.config as config
from pwndbg.color import generateColorFunction
config_arrow_color = theme.ColoredParameter(
config_arrow_color = theme.add_color_param(
"chain-arrow-color", "normal", "color of chain formatting (arrow)"
)
config_contiguous_color = theme.ColoredParameter(
config_contiguous_color = theme.add_color_param(
"chain-contiguous-marker-color", "normal", "color of chain formatting (contiguous marker)"
)

View File

@ -1,40 +1,40 @@
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.gdblib.config as config
from pwndbg.color import generateColorFunction
config_prefix_color = theme.ColoredParameter(
config_prefix_color = theme.add_color_param(
"code-prefix-color", "none", "color for 'context code' command (prefix marker)"
)
config_highlight_color = theme.ColoredParameter(
config_highlight_color = theme.add_color_param(
"highlight-color", "green,bold", "color added to highlights like source/pc"
)
config_register_color = theme.ColoredParameter(
config_register_color = theme.add_color_param(
"context-register-color", "bold", "color for registers label"
)
config_flag_value_color = theme.ColoredParameter(
config_flag_value_color = theme.add_color_param(
"context-flag-value-color", "none", "color for flags register (register value)"
)
config_flag_bracket_color = theme.ColoredParameter(
config_flag_bracket_color = theme.add_color_param(
"context-flag-bracket-color", "none", "color for flags register (bracket)"
)
config_flag_set_color = theme.ColoredParameter(
config_flag_set_color = theme.add_color_param(
"context-flag-set-color", "green,bold", "color for flags register (flag set)"
)
config_flag_unset_color = theme.ColoredParameter(
config_flag_unset_color = theme.add_color_param(
"context-flag-unset-color", "red", "color for flags register (flag unset)"
)
config_flag_changed_color = theme.ColoredParameter(
config_flag_changed_color = theme.add_color_param(
"context-flag-changed-color", "underline", "color for flags register (flag changed)"
)
config_banner_color = theme.ColoredParameter("banner-color", "blue", "color for banner line")
config_banner_title = theme.ColoredParameter("banner-title-color", "none", "color for banner title")
config_register_changed_color = theme.ColoredParameter(
config_banner_color = theme.add_color_param("banner-color", "blue", "color for banner line")
config_banner_title = theme.add_color_param("banner-title-color", "none", "color for banner title")
config_register_changed_color = theme.add_color_param(
"context-register-changed-color", "red", "color for registers label (change marker)"
)
config_register_changed_marker = theme.Parameter(
config_register_changed_marker = theme.add_param(
"context-register-changed-marker", "*", "change marker for registers label"
)
config_comment = theme.ColoredParameter("comment-color", "gray", "color for comment")
config_comment = theme.add_color_param("comment-color", "gray", "color for comment")
def prefix(x):

View File

@ -5,15 +5,15 @@ import pwndbg.color.context as C
import pwndbg.color.memory as M
import pwndbg.color.syntax_highlight as H
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.disasm.jump
import pwndbg.gdblib.config as config
from pwndbg.color import generateColorFunction
from pwndbg.color import ljust_colored
from pwndbg.color.message import on
capstone_branch_groups = set((capstone.CS_GRP_CALL, capstone.CS_GRP_JUMP))
config_branch = theme.ColoredParameter(
config_branch = theme.add_color_param(
"disasm-branch-color", "bold", "color for disasm (branch/call instruction)"
)
@ -28,12 +28,12 @@ def syntax_highlight(ins):
def instruction(ins):
asm = "%-06s %s" % (ins.mnemonic, ins.op_str)
if pwndbg.config.syntax_highlight:
if pwndbg.gdblib.config.syntax_highlight:
asm = syntax_highlight(asm)
is_branch = set(ins.groups) & capstone_branch_groups
# Highlight the current line if enabled
if pwndbg.config.highlight_pc and ins.address == pwndbg.gdblib.regs.pc:
if pwndbg.gdblib.config.highlight_pc and ins.address == pwndbg.gdblib.regs.pc:
asm = C.highlight(asm)
# tl;dr is a branch?

View File

@ -1,17 +1,17 @@
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.gdblib.config as config
from pwndbg.color import generateColorFunction
config_integer_color = theme.ColoredParameter(
config_integer_color = theme.add_color_param(
"enhance-integer-value-color", "none", "color of value enhance (integer)"
)
config_string_color = theme.ColoredParameter(
config_string_color = theme.add_color_param(
"enhance-string-value-color", "none", "color of value enhance (string)"
)
config_comment_color = theme.ColoredParameter(
config_comment_color = theme.add_color_param(
"enhance-comment-color", "none", "color of value enhance (comment)"
)
config_unknown_color = theme.ColoredParameter(
config_unknown_color = theme.add_color_param(
"enhance-unknown-color", "none", "color of value enhance (unknown value)"
)

View File

@ -1,29 +1,29 @@
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.gdblib.config as config
from pwndbg.color import generateColorFunction
config_normal = theme.ColoredParameter(
config_normal = theme.add_color_param(
"hexdump-normal-color", "none", "color for hexdump command (normal bytes)"
)
config_printable = theme.ColoredParameter(
config_printable = theme.add_color_param(
"hexdump-printable-color", "bold", "color for hexdump command (printable characters)"
)
config_zero = theme.ColoredParameter(
config_zero = theme.add_color_param(
"hexdump-zero-color", "red", "color for hexdump command (zero bytes)"
)
config_special = theme.ColoredParameter(
config_special = theme.add_color_param(
"hexdump-special-color", "yellow", "color for hexdump command (special bytes)"
)
config_offset = theme.ColoredParameter(
config_offset = theme.add_color_param(
"hexdump-offset-color", "none", "color for hexdump command (offset label)"
)
config_address = theme.ColoredParameter(
config_address = theme.add_color_param(
"hexdump-address-color", "none", "color for hexdump command (address label)"
)
config_separator = theme.ColoredParameter(
config_separator = theme.add_color_param(
"hexdump-separator-color", "none", "color for hexdump command (group separator)"
)
config_highlight_group_lsb = theme.Parameter(
config_highlight_group_lsb = theme.add_param(
"hexdump-highlight-group-lsb",
"underline",
"highlight LSB of each group. Applies only if hexdump-adjust-group-endianess"

View File

@ -1,21 +1,19 @@
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.gdblib.config as config
import pwndbg.vmmap
from pwndbg.color import generateColorFunction
from pwndbg.color import normal
config_stack = theme.ColoredParameter("memory-stack-color", "yellow", "color for stack memory")
config_heap = theme.ColoredParameter("memory-heap-color", "blue", "color for heap memory")
config_code = theme.ColoredParameter("memory-code-color", "red", "color for executable memory")
config_data = theme.ColoredParameter(
config_stack = theme.add_color_param("memory-stack-color", "yellow", "color for stack memory")
config_heap = theme.add_color_param("memory-heap-color", "blue", "color for heap memory")
config_code = theme.add_color_param("memory-code-color", "red", "color for executable memory")
config_data = theme.add_color_param(
"memory-data-color", "purple", "color for all other writable memory"
)
config_rodata = theme.ColoredParameter(
config_rodata = theme.add_color_param(
"memory-rodata-color", "normal", "color for all read only memory"
)
config_rwx = theme.ColoredParameter(
"memory-rwx-color", "underline", "color added to all RWX memory"
)
config_rwx = theme.add_color_param("memory-rwx-color", "underline", "color added to all RWX memory")
def stack(x):

View File

@ -1,40 +1,40 @@
from pwndbg import config
from pwndbg.color import generateColorFunction
from pwndbg.color import theme
from pwndbg.gdblib import config
config_status_on_color = theme.ColoredParameter(
config_status_on_color = theme.add_color_param(
"message-status-on-color", "green", "color of on status messages"
)
config_status_off_color = theme.ColoredParameter(
config_status_off_color = theme.add_color_param(
"message-status-off-color", "red", "color of off status messages"
)
config_notice_color = theme.ColoredParameter(
config_notice_color = theme.add_color_param(
"message-notice-color", "purple", "color of notice messages"
)
config_hint_color = theme.ColoredParameter(
config_hint_color = theme.add_color_param(
"message-hint-color", "yellow", "color of hint and marker messages"
)
config_success_color = theme.ColoredParameter(
config_success_color = theme.add_color_param(
"message-success-color", "green", "color of success messages"
)
config_warning_color = theme.ColoredParameter(
config_warning_color = theme.add_color_param(
"message-warning-color", "yellow", "color of warning messages"
)
config_error_color = theme.ColoredParameter("message-error-color", "red", "color of error messages")
config_system_color = theme.ColoredParameter(
config_error_color = theme.add_color_param("message-error-color", "red", "color of error messages")
config_system_color = theme.add_color_param(
"message-system-color", "light-red", "color of system messages"
)
config_exit_color = theme.ColoredParameter("message-exit-color", "red", "color of exit messages")
config_breakpoint_color = theme.ColoredParameter(
config_exit_color = theme.add_color_param("message-exit-color", "red", "color of exit messages")
config_breakpoint_color = theme.add_color_param(
"message-breakpoint-color", "yellow", "color of breakpoint messages"
)
config_signal_color = theme.ColoredParameter(
config_signal_color = theme.add_color_param(
"message-signal-color", "bold,red", "color of signal messages"
)
config_prompt_color = theme.ColoredParameter("prompt-color", "bold,red", "prompt color")
config_prompt_color = theme.add_color_param("prompt-color", "bold,red", "prompt color")
def on(msg):

View File

@ -1,26 +1,26 @@
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.gdblib.config as config
from pwndbg.color import generateColorFunction
config_symbol = theme.ColoredParameter(
config_symbol = theme.add_color_param(
"nearpc-symbol-color", "normal", "color for nearpc command (symbol)"
)
config_address = theme.ColoredParameter(
config_address = theme.add_color_param(
"nearpc-address-color", "normal", "color for nearpc command (address)"
)
config_prefix = theme.ColoredParameter(
config_prefix = theme.add_color_param(
"nearpc-prefix-color", "none", "color for nearpc command (prefix marker)"
)
config_syscall_name = theme.ColoredParameter(
config_syscall_name = theme.add_color_param(
"nearpc-syscall-name-color", "red", "color for nearpc command (resolved syscall name)"
)
config_argument = theme.ColoredParameter(
config_argument = theme.add_color_param(
"nearpc-argument-color", "bold", "color for nearpc command (target argument)"
)
config_ida_anterior = theme.ColoredParameter(
config_ida_anterior = theme.add_color_param(
"nearpc-ida-anterior-color", "bold", "color for nearpc command (IDA anterior)"
)
config_branch_marker = theme.ColoredParameter(
config_branch_marker = theme.add_color_param(
"nearpc-branch-marker-color", "normal", "color for nearpc command (branch marker line)"
)

View File

@ -7,14 +7,14 @@ import pygments
import pygments.formatters
import pygments.lexers
import pwndbg.config
import pwndbg.gdblib.config
from pwndbg.color import disable_colors
from pwndbg.color import message
from pwndbg.color import theme
from pwndbg.color.lexer import PwntoolsLexer
pwndbg.config.Parameter("syntax-highlight", True, "Source code / assembly syntax highlight")
style = theme.Parameter(
pwndbg.gdblib.config.add_param("syntax-highlight", True, "Source code / assembly syntax highlight")
style = theme.add_param(
"syntax-highlight-style",
"monokai",
"Source code / assembly syntax highlight stylename of pygments module",
@ -25,7 +25,7 @@ pwntools_lexer = PwntoolsLexer()
lexer_cache: Dict[str, Any] = {}
@pwndbg.config.Trigger([style])
@pwndbg.gdblib.config.trigger(style)
def check_style():
global formatter
try:

View File

@ -1,24 +1,24 @@
import pwndbg.color.theme as theme
import pwndbg.config as config
import pwndbg.gdblib.config as config
from pwndbg.color import generateColorFunction
offset_color = theme.ColoredParameter(
offset_color = theme.add_color_param(
"telescope-offset-color", "normal", "color of the telescope command (offset prefix)"
)
register_color = theme.ColoredParameter(
register_color = theme.add_color_param(
"telescope-register-color", "bold", "color of the telescope command (register)"
)
offset_separator_color = theme.ColoredParameter(
offset_separator_color = theme.add_color_param(
"telescope-offset-separator-color",
"normal",
"color of the telescope command (offset separator)",
)
offset_delimiter_color = theme.ColoredParameter(
offset_delimiter_color = theme.add_color_param(
"telescope-offset-delimiter-color",
"normal",
"color of the telescope command (offset delimiter)",
)
repeating_marker_color = theme.ColoredParameter(
repeating_marker_color = theme.add_color_param(
"telescope-repeating-marker-color",
"normal",
"color of the telescope command (repeating values marker)",

View File

@ -1,11 +1,9 @@
import pwndbg.config
import pwndbg.gdblib.config
class Parameter(pwndbg.config.Parameter):
def __init__(self, name, default, docstring):
super(Parameter, self).__init__(name, default, docstring, "theme")
def add_param(name, default, docstring):
return pwndbg.gdblib.config.add_param(name, default, docstring, "theme")
class ColoredParameter(Parameter):
def __init__(self, name, default, docstring):
super(ColoredParameter, self).__init__(name, default, docstring)
def add_color_param(name, default, docstring):
return add_param(name, default, docstring)

View File

@ -9,9 +9,9 @@ import gdb
import pwndbg.chain
import pwndbg.color
import pwndbg.color.message as message
import pwndbg.config
import pwndbg.enhance
import pwndbg.exception
import pwndbg.gdblib.config
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.gdblib.symbol
@ -285,21 +285,27 @@ def OnlyWithResolvedHeapSyms(function):
w(
f"You can try to determine the libc symbols addresses manually and set them appropriately. For this, see the `heap_config` command output and set the config about `{err.symbol}`."
)
if pwndbg.config.exception_verbose.value or pwndbg.config.exception_debugger.value:
if (
pwndbg.gdblib.config.exception_verbose.value
or pwndbg.gdblib.config.exception_debugger.value
):
raise err
except Exception as err:
e(f"{function.__name__}: An unknown error occurred when running this command.")
if pwndbg.config.resolve_heap_via_heuristic:
if pwndbg.gdblib.config.resolve_heap_via_heuristic:
w(
"Maybe you can try to determine the libc symbols addresses manually, set them appropriately and re-run this command. For this, see the `heap_config` command output and set the `main_arena`, `mp_`, `global_max_fast`, `tcache` and `thread_arena` addresses."
)
else:
w("You can try `set resolve-heap-via-heuristic on` and re-run this command.\n")
if pwndbg.config.exception_verbose or pwndbg.config.exception_debugger:
if (
pwndbg.gdblib.config.exception_verbose
or pwndbg.gdblib.config.exception_debugger
):
raise err
else:
print(message.error(f"{function.__name__}: "), end="")
if not pwndbg.config.resolve_heap_via_heuristic:
if not pwndbg.gdblib.config.resolve_heap_via_heuristic:
if _is_statically_linked():
e(
"Can't find libc symbols addresses required for this command to work since this is a statically linked binary"

View File

@ -5,7 +5,7 @@ Dumps all pwndbg-specific configuration points.
import argparse
import pwndbg.commands
import pwndbg.config
import pwndbg.gdblib.config
from pwndbg.color import ljust_colored
from pwndbg.color import strip
from pwndbg.color.message import hint
@ -29,8 +29,8 @@ def extend_value_with_default(value, default):
def get_config_parameters(scope, filter_pattern):
values = [
v
for k, v in pwndbg.config.__dict__.items()
if isinstance(v, pwndbg.config.Parameter) and v.scope == scope
for k, v in pwndbg.gdblib.config.__dict__.items()
if isinstance(v, pwndbg.lib.config.Parameter) and v.scope == scope
]
if filter_pattern:
@ -113,7 +113,7 @@ def themefile(show_all=False):
def configfile_print_scope(scope, show_all=False):
params = pwndbg.config.get_params(scope)
params = pwndbg.gdblib.config.get_params(scope)
if not show_all:
params = list(filter(lambda p: p.is_changed, params))

View File

@ -18,8 +18,8 @@ import pwndbg.color.syntax_highlight as H
import pwndbg.commands
import pwndbg.commands.nearpc
import pwndbg.commands.telescope
import pwndbg.config
import pwndbg.disasm
import pwndbg.gdblib.config
import pwndbg.gdblib.events
import pwndbg.gdblib.regs
import pwndbg.gdblib.symbol
@ -54,13 +54,13 @@ def clear_screen(out=sys.stdout):
out.write("\x1b[H\x1b[2J")
config_clear_screen = pwndbg.config.Parameter(
config_clear_screen = pwndbg.gdblib.config.add_param(
"context-clear-screen", False, "whether to clear the screen before printing the context"
)
config_output = pwndbg.config.Parameter(
config_output = pwndbg.gdblib.config.add_param(
"context-output", "stdout", 'where pwndbg should output ("stdout" or file/tty).'
)
config_context_sections = pwndbg.config.Parameter(
config_context_sections = pwndbg.gdblib.config.add_param(
"context-sections",
"regs disasm code ghidra stack backtrace expressions",
"which context sections are displayed (controls order)",
@ -71,7 +71,7 @@ outputs = {} # type: Dict[str,str]
output_settings = {}
@pwndbg.config.Trigger([config_context_sections])
@pwndbg.gdblib.config.trigger(config_context_sections)
def validate_context_sections():
valid_values = [
context.__name__.replace("context_", "") for context in context_sections.values()
@ -299,7 +299,7 @@ def context_expressions(target=sys.stdout, with_banner=True, width=None):
return banner + output if with_banner else output
config_context_ghidra = pwndbg.config.Parameter(
config_context_ghidra = pwndbg.gdblib.config.add_param(
"context-ghidra",
"never",
"when to try to decompile the current function with ghidra (slow and requires radare2/r2pipe) (valid values: always, never, if-no-source)",
@ -395,14 +395,16 @@ def context(subcontext=None):
out.flush()
pwndbg.config.Parameter(
pwndbg.gdblib.config.add_param(
"show-compact-regs", False, "whether to show a compact register view with columns"
)
pwndbg.config.Parameter(
pwndbg.gdblib.config.add_param(
"show-compact-regs-columns", 2, "the number of columns (0 for dynamic number of columns)"
)
pwndbg.config.Parameter("show-compact-regs-min-width", 20, "the minimum width of each column")
pwndbg.config.Parameter(
pwndbg.gdblib.config.add_param(
"show-compact-regs-min-width", 20, "the minimum width of each column"
)
pwndbg.gdblib.config.add_param(
"show-compact-regs-separation", 4, "the number of spaces separating columns"
)
@ -415,9 +417,9 @@ def calculate_padding_to_align(length, align):
def compact_regs(regs, width=None, target=sys.stdout):
columns = max(0, int(pwndbg.config.show_compact_regs_columns))
min_width = max(1, int(pwndbg.config.show_compact_regs_min_width))
separation = max(1, int(pwndbg.config.show_compact_regs_separation))
columns = max(0, int(pwndbg.gdblib.config.show_compact_regs_columns))
min_width = max(1, int(pwndbg.gdblib.config.show_compact_regs_min_width))
separation = max(1, int(pwndbg.gdblib.config.show_compact_regs_separation))
if width is None: # auto width. In case of stdout, it's better to use stdin (b/c GdbOutputFile)
_height, width = pwndbg.ui.get_window_size(
@ -479,12 +481,12 @@ def compact_regs(regs, width=None, target=sys.stdout):
def context_regs(target=sys.stdout, with_banner=True, width=None):
regs = get_regs()
if pwndbg.config.show_compact_regs:
if pwndbg.gdblib.config.show_compact_regs:
regs = compact_regs(regs, target=target, width=width)
info = " / show-flags %s / show-compact-regs %s" % (
"on" if pwndbg.config.show_flags else "off",
"on" if pwndbg.config.show_compact_regs else "off",
"on" if pwndbg.gdblib.config.show_flags else "off",
"on" if pwndbg.gdblib.config.show_compact_regs else "off",
)
banner = [pwndbg.ui.banner("registers", target=target, width=width, extra=info)]
return banner + regs if with_banner else regs
@ -502,14 +504,14 @@ def regs(regs=None):
print("\n".join(get_regs(*regs)))
pwndbg.config.Parameter("show-flags", False, "whether to show flags registers")
pwndbg.config.Parameter("show-retaddr-reg", False, "whether to show return address register")
pwndbg.gdblib.config.add_param("show-flags", False, "whether to show flags registers")
pwndbg.gdblib.config.add_param("show-retaddr-reg", False, "whether to show return address register")
def get_regs(*regs):
result = []
if not regs and pwndbg.config.show_retaddr_reg:
if not regs and pwndbg.gdblib.config.show_retaddr_reg:
regs = (
pwndbg.gdblib.regs.gpr
+ (pwndbg.gdblib.regs.frame, pwndbg.gdblib.regs.current.stack)
@ -523,7 +525,7 @@ def get_regs(*regs):
pwndbg.gdblib.regs.current.pc,
)
if pwndbg.config.show_flags:
if pwndbg.gdblib.config.show_flags:
regs += tuple(pwndbg.gdblib.regs.flags)
changed = pwndbg.gdblib.regs.changed
@ -559,14 +561,14 @@ def get_regs(*regs):
return result
pwndbg.config.Parameter(
pwndbg.gdblib.config.add_param(
"emulate",
True,
"""
Unicorn emulation of code near the current instruction
""",
)
code_lines = pwndbg.config.Parameter(
code_lines = pwndbg.gdblib.config.add_param(
"context-code-lines", 10, "number of additional lines to print in the code context"
)
@ -590,7 +592,7 @@ def context_disasm(target=sys.stdout, with_banner=True, width=None):
pwndbg.lib.memoize.reset()
arch = pwndbg.gdblib.arch.current
emulate = bool(pwndbg.config.emulate)
emulate = bool(pwndbg.gdblib.config.emulate)
info = " / %s / set emulate %s" % (arch, "on" if emulate else "off")
banner = [pwndbg.ui.banner("disasm", target=target, width=width, extra=info)]
@ -604,11 +606,11 @@ def context_disasm(target=sys.stdout, with_banner=True, width=None):
return banner + result if with_banner else result
theme.Parameter("highlight-source", True, "whether to highlight the closest source line")
source_code_lines = pwndbg.config.Parameter(
theme.add_param("highlight-source", True, "whether to highlight the closest source line")
source_code_lines = pwndbg.gdblib.config.add_param(
"context-source-code-lines", 10, "number of source code lines to print by the context command"
)
theme.Parameter("code-prefix", "", "prefix marker for 'context code' command")
theme.add_param("code-prefix", "", "prefix marker for 'context code' command")
@pwndbg.lib.memoize.reset_on_start
@ -617,7 +619,7 @@ def get_highlight_source(filename):
with open(filename, encoding="utf-8", errors="ignore") as f:
source = f.read()
if pwndbg.config.syntax_highlight:
if pwndbg.gdblib.config.syntax_highlight:
source = H.syntax_highlight(source, filename)
source_lines = source.split("\n")
@ -659,14 +661,14 @@ def get_filename_and_formatted_source():
source = source[start:end]
# Compute the prefix_sign length
prefix_sign = C.prefix(str(pwndbg.config.code_prefix))
prefix_sign = C.prefix(str(pwndbg.gdblib.config.code_prefix))
prefix_width = len(prefix_sign)
# Format the output
formatted_source = []
for line_number, code in enumerate(source, start=start + 1):
fmt = " {prefix_sign:{prefix_width}} {line_number:>{num_width}} {code}"
if pwndbg.config.highlight_source and line_number == closest_line:
if pwndbg.gdblib.config.highlight_source and line_number == closest_line:
fmt = C.highlight(fmt)
line = fmt.format(
@ -710,7 +712,7 @@ def context_code(target=sys.stdout, with_banner=True, width=None):
return []
stack_lines = pwndbg.config.Parameter(
stack_lines = pwndbg.gdblib.config.add_param(
"context-stack-lines", 8, "number of lines to print in the stack context"
)
@ -725,10 +727,10 @@ def context_stack(target=sys.stdout, with_banner=True, width=None):
return result
backtrace_lines = pwndbg.config.Parameter(
backtrace_lines = pwndbg.gdblib.config.add_param(
"context-backtrace-lines", 8, "number of lines to print in the backtrace context"
)
backtrace_frame_label = theme.Parameter(
backtrace_frame_label = theme.add_param(
"backtrace-frame-label", "f ", "frame number label for backtrace"
)

View File

@ -7,7 +7,7 @@ import gdb
import pwndbg.color.context as C
import pwndbg.color.memory as M
import pwndbg.commands
import pwndbg.config
import pwndbg.gdblib.config
import pwndbg.gdblib.typeinfo
import pwndbg.glibc
from pwndbg.color import generateColorFunction
@ -27,7 +27,7 @@ def read_chunk(addr):
"mchunk_size": "size",
"mchunk_prev_size": "prev_size",
}
if not pwndbg.config.resolve_heap_via_heuristic:
if not pwndbg.gdblib.config.resolve_heap_via_heuristic:
val = pwndbg.gdblib.typeinfo.read_gdbvalue("struct malloc_chunk", addr)
else:
val = pwndbg.heap.current.malloc_chunk(addr)
@ -589,7 +589,7 @@ def find_fake_fast(addr, size=None):
malloc_chunk(start + offset - psize, fake=True)
pwndbg.config.Parameter(
pwndbg.gdblib.config.add_param(
"max-visualize-chunk-size",
0,
"max display size for heap chunks visualization (0 for display all)",
@ -715,7 +715,8 @@ def vis_heap_chunks(addr=None, count=None, naive=None, display_all=None):
has_huge_chunk = False
# round up to align with 4*ptr_size and get half
half_max_size = (
pwndbg.lib.memory.round_up(pwndbg.config.max_visualize_chunk_size, ptr_size << 2) >> 1
pwndbg.lib.memory.round_up(pwndbg.gdblib.config.max_visualize_chunk_size, ptr_size << 2)
>> 1
)
for c, stop in enumerate(chunk_delims):

View File

@ -3,20 +3,20 @@ import argparse
import gdb
import pwndbg.commands
import pwndbg.config
import pwndbg.gdblib.arch
import pwndbg.gdblib.config
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.hexdump
pwndbg.config.Parameter("hexdump-width", 16, "line width of hexdump command")
pwndbg.config.Parameter("hexdump-bytes", 64, "number of bytes printed by hexdump command")
pwndbg.config.Parameter(
pwndbg.gdblib.config.add_param("hexdump-width", 16, "line width of hexdump command")
pwndbg.gdblib.config.add_param("hexdump-bytes", 64, "number of bytes printed by hexdump command")
pwndbg.gdblib.config.add_param(
"hexdump-group-width",
4,
"number of bytes grouped in hexdump command (If -1, the architecture's pointer size is used)",
)
pwndbg.config.Parameter(
pwndbg.gdblib.config.add_param(
"hexdump-group-use-big-endian",
False,
"Use big-endian within each group of bytes. Only applies to raw bytes, not the ASCII part. "
@ -51,13 +51,13 @@ parser.add_argument(
help="Address or module name to dump",
)
parser.add_argument(
"count", nargs="?", default=pwndbg.config.hexdump_bytes, help="Number of bytes to dump"
"count", nargs="?", default=pwndbg.gdblib.config.hexdump_bytes, help="Number of bytes to dump"
)
@pwndbg.commands.ArgparsedCommand(parser)
@pwndbg.commands.OnlyWhenRunning
def hexdump(address=None, count=pwndbg.config.hexdump_bytes):
def hexdump(address=None, count=pwndbg.gdblib.config.hexdump_bytes):
if hexdump.repeat:
address = hexdump.last_address
hexdump.offset += 1
@ -67,11 +67,11 @@ def hexdump(address=None, count=pwndbg.config.hexdump_bytes):
address = int(address)
address &= pwndbg.gdblib.arch.ptrmask
count = max(int(count), 0)
width = int(pwndbg.config.hexdump_width)
group_width = int(pwndbg.config.hexdump_group_width)
width = int(pwndbg.gdblib.config.hexdump_width)
group_width = int(pwndbg.gdblib.config.hexdump_group_width)
group_width = pwndbg.gdblib.typeinfo.ptrsize if group_width == -1 else group_width
flip_group_endianess = (
pwndbg.config.hexdump_group_use_big_endian and pwndbg.gdblib.arch.endian == "little"
pwndbg.gdblib.config.hexdump_group_use_big_endian and pwndbg.gdblib.arch.endian == "little"
)
if count > address > 0x10000:

View File

@ -10,8 +10,8 @@ import pwndbg.color.disasm as D
import pwndbg.color.nearpc as N
import pwndbg.color.theme
import pwndbg.commands.comments
import pwndbg.config
import pwndbg.disasm
import pwndbg.gdblib.config
import pwndbg.gdblib.regs
import pwndbg.gdblib.strings
import pwndbg.gdblib.symbol
@ -27,19 +27,19 @@ def ljust_padding(lst):
return [s.ljust(longest_len) for s in lst]
nearpc_branch_marker = pwndbg.color.theme.Parameter(
nearpc_branch_marker = pwndbg.color.theme.add_param(
"nearpc-branch-marker", "", "branch marker line for nearpc command"
)
nearpc_branch_marker_contiguous = pwndbg.color.theme.Parameter(
nearpc_branch_marker_contiguous = pwndbg.color.theme.add_param(
"nearpc-branch-marker-contiguous", " ", "contiguous branch marker line for nearpc command"
)
pwndbg.color.theme.Parameter("highlight-pc", True, "whether to highlight the current instruction")
pwndbg.color.theme.Parameter("nearpc-prefix", "", "prefix marker for nearpc command")
pwndbg.config.Parameter("left-pad-disasm", True, "whether to left-pad disassembly")
nearpc_lines = pwndbg.config.Parameter(
pwndbg.color.theme.add_param("highlight-pc", True, "whether to highlight the current instruction")
pwndbg.color.theme.add_param("nearpc-prefix", "", "prefix marker for nearpc command")
pwndbg.gdblib.config.add_param("left-pad-disasm", True, "whether to left-pad disassembly")
nearpc_lines = pwndbg.gdblib.config.add_param(
"nearpc-lines", 10, "number of additional lines to print for the nearpc command"
)
show_args = pwndbg.config.Parameter(
show_args = pwndbg.gdblib.config.add_param(
"nearpc-show-args", True, "show call arguments below instruction"
)
@ -132,7 +132,7 @@ def nearpc(pc=None, lines=None, to_string=False, emulate=False):
symbols = ["<%s> " % sym if sym else "" for sym in symbols]
# Pad out all of the symbols and addresses
if pwndbg.config.left_pad_disasm and not nearpc.repeat:
if pwndbg.gdblib.config.left_pad_disasm and not nearpc.repeat:
symbols = ljust_padding(symbols)
addresses = ljust_padding(addresses)
@ -143,7 +143,7 @@ def nearpc(pc=None, lines=None, to_string=False, emulate=False):
# Print out each instruction
for address_str, symbol, instr in zip(addresses, symbols, instructions):
asm = D.instruction(instr)
prefix_sign = pwndbg.config.nearpc_prefix
prefix_sign = pwndbg.gdblib.config.nearpc_prefix
# Show prefix only on the specified address and don't show it while in repeat-mode
# or when showing current instruction for the second time
@ -157,10 +157,10 @@ def nearpc(pc=None, lines=None, to_string=False, emulate=False):
# Colorize address and symbol if not highlighted
# symbol is fetched from gdb and it can be e.g. '<main+8>'
if instr.address != pc or not pwndbg.config.highlight_pc or nearpc.repeat:
if instr.address != pc or not pwndbg.gdblib.config.highlight_pc or nearpc.repeat:
address_str = N.address(address_str)
symbol = N.symbol(symbol)
elif pwndbg.config.highlight_pc and first_pc:
elif pwndbg.gdblib.config.highlight_pc and first_pc:
prefix = C.highlight(prefix)
address_str = C.highlight(address_str)
symbol = C.highlight(symbol)

View File

@ -7,9 +7,9 @@ from typing import Set
import pwndbg.color.memory as M
import pwndbg.commands
import pwndbg.config
import pwndbg.enhance
import pwndbg.gdblib.arch
import pwndbg.gdblib.config
import pwndbg.search
import pwndbg.vmmap
from pwndbg.color import message
@ -40,7 +40,7 @@ def print_search_hit(address):
print(region, addr, display)
auto_save = pwndbg.config.Parameter(
auto_save = pwndbg.gdblib.config.add_param(
"auto-save-search", False, 'automatically pass --save to "search" command'
)
@ -146,7 +146,7 @@ def search(type, hex, executable, writable, value, mapping_name, save, next, tru
type = {4: "dword", 8: "qword"}[pwndbg.gdblib.arch.ptrsize]
if save is None:
save = bool(pwndbg.config.auto_save_search)
save = bool(pwndbg.gdblib.config.auto_save_search)
if hex:
try:

View File

@ -12,33 +12,33 @@ import pwndbg.chain
import pwndbg.color.telescope as T
import pwndbg.color.theme as theme
import pwndbg.commands
import pwndbg.config
import pwndbg.gdblib.arch
import pwndbg.gdblib.config
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.gdblib.typeinfo
telescope_lines = pwndbg.config.Parameter(
telescope_lines = pwndbg.gdblib.config.add_param(
"telescope-lines", 8, "number of lines to printed by the telescope command"
)
skip_repeating_values = pwndbg.config.Parameter(
skip_repeating_values = pwndbg.gdblib.config.add_param(
"telescope-skip-repeating-val",
True,
"whether to skip repeating values of the telescope command",
)
skip_repeating_values_minimum = pwndbg.config.Parameter(
skip_repeating_values_minimum = pwndbg.gdblib.config.add_param(
"telescope-skip-repeating-val-minimum",
3,
"minimum amount of repeated values before skipping lines",
)
offset_separator = theme.Parameter(
offset_separator = theme.add_param(
"telescope-offset-separator", "", "offset separator of the telescope command"
)
offset_delimiter = theme.Parameter(
offset_delimiter = theme.add_param(
"telescope-offset-delimiter", ":", "offset delimiter of the telescope command"
)
repeating_marker = theme.Parameter(
repeating_marker = theme.add_param(
"telescope-repeating-marker", "... ↓", "repeating values marker of the telescope command"
)

View File

@ -6,7 +6,7 @@ import argparse
import pwndbg.color.theme
import pwndbg.commands
import pwndbg.config
import pwndbg.gdblib.config
from pwndbg.color import generateColorFunction
from pwndbg.color.message import hint
from pwndbg.commands.config import extend_value_with_default
@ -41,7 +41,7 @@ def theme(filter_pattern):
header = print_row("Name", "Value", "Def", "Documentation", longest_optname, longest_value)
print("-" * (len(header)))
for v in sorted(values):
if isinstance(v, pwndbg.color.theme.ColoredParameter):
if isinstance(v, pwndbg.color.theme.add_color_param):
value = generateColorFunction(v.value)(v.value)
default = generateColorFunction(v.default)(v.default)
elif isinstance(v.value, str):

View File

@ -2,8 +2,8 @@ import argparse
import pwndbg.color.memory as M
import pwndbg.commands
import pwndbg.config
import pwndbg.gdblib.arch
import pwndbg.gdblib.config
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.gdblib.stack

View File

@ -1,271 +0,0 @@
"""
Dynamic configuration system for pwndbg, using GDB's built-in Parameter
mechanism.
To create a new pwndbg configuration point, create an instance of
``pwndbg.config.Parameter``.
Parameters should be declared in the module in which they are primarily
used, or in this module for general-purpose parameters.
All pwndbg Parameter types are accessible via property access on this
module, for example:
>>> pwndbg.config.Parameter('example-value', 7, 'an example')
>>> int(pwndbg.config.example_value)
7
"""
import codecs
import collections
import re
import sys
import types
from functools import total_ordering
import gdb
import pwndbg.decorators
main_arena: int
thread_arena: int
mp_: int
tcache: int
debug_events: int
syntax_highlight: int
hexdump_width: int
hexdump_bytes: int
show_compact_regs_min_width: int
show_flags: bool
show_retaddr_reg: bool
left_pad_disasm: bool
ida_rpc_host: str
ida_rpc_port: int
ida_enabled: bool
ida_timeout: int
glibc: str
TYPES = collections.OrderedDict()
# The value is a plain boolean.
# The Python boolean values, True and False are the only valid values.
TYPES[bool] = gdb.PARAM_BOOLEAN
# The value is an integer.
# This is like PARAM_INTEGER, except 0 is interpreted as itself.
TYPES[int] = gdb.PARAM_ZINTEGER
# The value is a string.
# When the user modifies the string, any escape sequences,
# such as \t, \f, and octal escapes, are translated into
# corresponding characters and encoded into the current host charset.
TYPES[str] = gdb.PARAM_STRING
triggers = collections.defaultdict(lambda: [])
class Trigger:
def __init__(self, names):
if not isinstance(names, list):
names = [names]
names = list(map(lambda n: n.name if isinstance(n, Parameter) else n, names))
self.names = list(map(lambda n: n.replace("-", "_"), names))
def __call__(self, function):
global triggers
for name in self.names:
triggers[name].append(function)
return function
def get_param(value):
for k, v in TYPES.items():
if isinstance(value, k):
return v
def get_params(scope):
module_attributes = globals()["module"].__dict__.values()
return sorted(
filter(lambda p: isinstance(p, Parameter) and p.scope == scope, module_attributes)
)
def value_to_gdb_native(value):
"""Translates Python value into native GDB syntax string."""
mapping = collections.OrderedDict()
mapping[bool] = lambda value: "on" if value else "off"
for k, v in mapping.items():
if isinstance(value, k):
return v(value)
return value
member_remap = {"value": "_value", "raw_value": "value"}
@total_ordering
class Parameter(gdb.Parameter):
"""
For python2, we can not store unicode type in self.value since the implementation limitation of gdb python.
We use self._value as the converted cache and set __getattribute__() and __setattr__() to remap variables.
Since GDB will set gdb.Parameter.value to user input and call get_set_string(),
we use self.raw_value to map back to gdb.Parameter.value
That is, we remap
* Parameter.value -> gdb.Parameter._value (if it is string type, always keep unicode)
All getter return this
* Parameter.raw_value -> gdb.Parameter.value
Only used in get_set_string()
"""
def __init__(self, name, default, docstring, scope="config"):
self.docstring = docstring.strip()
self.optname = name
self.name = name.replace("-", "_")
self.default = default
self.set_doc = "Set " + docstring
self.show_doc = docstring + ":"
super(Parameter, self).__init__(name, gdb.COMMAND_SUPPORT, get_param(default))
self.value = default
self.scope = scope
setattr(module, self.name, self)
@property
def native_value(self):
return value_to_gdb_native(self.value)
@property
def native_default(self):
return value_to_gdb_native(self.default)
@property
def is_changed(self):
return self.value != self.default
def __setattr__(self, name, value):
new_name = member_remap.get(name, name)
new_name = str(new_name) # Python2 only accept str type as key
return super(Parameter, self).__setattr__(new_name, value)
def __getattribute__(self, name):
new_name = member_remap.get(name, name)
new_name = str(new_name) # Python2 only accept str type as key
return super(Parameter, self).__getattribute__(new_name)
def get_set_string(self):
value = self.raw_value
# For string value, convert utf8 byte string to unicode.
if isinstance(value, bytes):
value = codecs.decode(value, "utf-8")
# Remove surrounded ' and " characters
if isinstance(value, str):
# The first character must be ' or " and ends with the same character.
# See PR #404 for more information
pattern = r"^(?P<quote>[\"'])(?P<content>.*?)(?P=quote)$"
value = re.sub(pattern, r"\g<content>", value)
# Write back to self.value
self.value = value
for trigger in triggers[self.name]:
trigger()
if not pwndbg.decorators.first_prompt:
return ""
return "Set %s to %r" % (self.docstring, self.value)
def get_show_string(self, svalue):
return "Sets %s (currently: %r)" % (self.docstring, self.value)
def revert_default(self):
self.value = self.default
# TODO: use __getattribute__ to remapping all member function to self.value's member?
# Then, we can use param.member() just like param.value.member()
# The str type member function, used in color/__init__.py
def split(self, *args, **kargs):
return str(self).split(*args, **kargs)
# Casting
def __int__(self):
return int(self.value)
def __str__(self):
return str(self.value)
def __bool__(self):
return bool(self.value)
# Compare operators
# Ref: http://portingguide.readthedocs.io/en/latest/comparisons.html
# If other is Parameter, comparing by optname. Used in `sorted` in `config` command.
# Otherwise, compare `self.value` with `other`
def __eq__(self, other):
if isinstance(other, gdb.Parameter):
return self.optname == other.optname
else:
return self.value == other
def __lt__(self, other):
if isinstance(other, gdb.Parameter):
return self.optname < other.optname
else:
return self.value < other
# Operators
def __add__(self, other):
return self.value + other
def __radd__(self, other):
return other + self.value
def __sub__(self, other):
return self.value - other
def __rsub__(self, other):
return other - self.value
def __mul__(self, other):
return self.value * other
def __rmul__(self, other):
return other * self.value
def __div__(self, other):
return self.value / other
def __floordiv__(self, other):
return self.value // other
def __pow__(self, other):
return self.value**other
def __mod__(self, other):
return self.value % other
def __len__(self):
return len(self.value)
# Python2 compatibility
__nonzero__ = __bool__
class ConfigModule(types.ModuleType):
def __init__(self, name, module):
super(ConfigModule, self).__init__(name)
self.__dict__.update(module.__dict__)
Parameter = Parameter
# To prevent garbage collection
tether = sys.modules[__name__]
# Create the module structure
module = ConfigModule(__name__, tether)
sys.modules[__name__] = module

View File

@ -11,9 +11,9 @@ import string
import pwndbg.color as color
import pwndbg.color.enhance as E
import pwndbg.config
import pwndbg.disasm
import pwndbg.gdblib.arch
import pwndbg.gdblib.config
import pwndbg.gdblib.memory
import pwndbg.gdblib.strings
import pwndbg.gdblib.symbol
@ -90,7 +90,7 @@ def enhance(value, code=True, safe_linking=False):
instr = pwndbg.disasm.one(value)
if instr:
instr = "%-6s %s" % (instr.mnemonic, instr.op_str)
if pwndbg.config.syntax_highlight:
if pwndbg.gdblib.config.syntax_highlight:
instr = syntax_highlight(instr)
szval = pwndbg.gdblib.strings.get(value) or None

View File

@ -5,7 +5,7 @@ import traceback
import gdb
import pwndbg.color.message as message
import pwndbg.config
import pwndbg.gdblib.config
import pwndbg.lib.memoize
import pwndbg.lib.stdio
@ -15,12 +15,12 @@ with pwndbg.lib.stdio.stdio:
except ImportError:
import pdb
verbose = pwndbg.config.Parameter(
verbose = pwndbg.gdblib.config.add_param(
"exception-verbose",
False,
"whether to print a full stacktrace for exceptions raised in Pwndbg commands",
)
debug = pwndbg.config.Parameter(
debug = pwndbg.gdblib.config.add_param(
"exception-debugger", False, "whether to debug exceptions raised in Pwndbg commands"
)
@ -95,7 +95,7 @@ def set_trace():
pdb.set_trace = set_trace
@pwndbg.config.Trigger([verbose, debug])
@pwndbg.gdblib.config.trigger(verbose, debug)
def update():
if verbose or debug:
command = "set python print-stack full"

View File

@ -1,7 +1,9 @@
# The `arch` module can be accessed with `from pwndbg.gdblib.arch import arch_mod`,
# while `pwndbg.gdblib.arch` will represent the `Arch` object
from pwndbg.gdblib import arch as arch_mod
from pwndbg.gdblib import config as config_mod
from pwndbg.gdblib.arch import arch
from pwndbg.gdblib.config import config
__all__ = ["ctypes", "memory", "typeinfo"]

92
pwndbg/gdblib/config.py Normal file
View File

@ -0,0 +1,92 @@
"""
Dynamic configuration system for pwndbg, using GDB's built-in Parameter
mechanism.
To create a new pwndbg configuration point, call ``pwndbg.gdblib.config.add_param``.
Parameters should be declared in the module in which they are primarily
used, or in this module for general-purpose parameters.
All pwndbg Parameter types are accessible via property access on this
module, for example:
>>> pwndbg.gdblib.config.add_param('example-value', 7, 'an example')
>>> int(pwndbg.gdblib.config.example_value)
7
"""
import gdb
import pwndbg.decorators
import pwndbg.lib.config
config = pwndbg.lib.config.Config()
PARAM_CLASSES = {
# The Python boolean values, True and False are the only valid values.
bool: gdb.PARAM_BOOLEAN,
# This is like PARAM_INTEGER, except 0 is interpreted as itself.
int: gdb.PARAM_ZINTEGER,
# When the user modifies the string, any escape sequences,
# such as \t, \f, and octal escapes, are translated into
# corresponding characters and encoded into the current host charset.
str: gdb.PARAM_STRING,
}
# See this for details about the API of `gdb.Parameter`:
# https://sourceware.org/gdb/onlinedocs/gdb/Parameters-In-Python.html
class Parameter(gdb.Parameter):
def __init__(self, param: pwndbg.lib.config.Parameter):
self.param = param
# `set_doc` and `show_doc` must be set before `gdb.Parameter.__init__`.
# They will be used for `help set <param>` and `help show <param>`,
# respectively
self.set_doc = "Set " + self.param.docstring
self.show_doc = "Show " + self.param.docstring
super().__init__(self.param.name, gdb.COMMAND_SUPPORT, self._param_class())
def _param_class(self):
for k, v in PARAM_CLASSES.items():
if isinstance(self.param.value, k):
return v
@property
def native_value(self):
return Parameter._value_to_gdb_native(self.param.value)
@property
def native_default(self):
return Parameter._value_to_gdb_native(self.param.default)
def get_set_string(self):
"""Handles the GDB `set <param>` command"""
# GDB will set `self.value` to the user's input
self.param.value = self.value
for trigger in config.triggers[self.param.name]:
trigger()
# No need to print anything if this is set before we get to a prompt,
# like if we're setting options in .gdbinit
if not pwndbg.decorators.first_prompt:
return ""
return "Set %s to %r" % (self.param.docstring, self.param.value)
@staticmethod
def _value_to_gdb_native(value):
"""Translates Python value into native GDB syntax string."""
# Convert booleans to "on" or "off". Other types pass through normally
if isinstance(value, bool):
return "on" if value else "off"
return value
def init_params():
# Create a gdb.Parameter for each parameter
for p in pwndbg.gdblib.config.params.values():
# We don't need to store this anywhere, GDB will handle this
Parameter(p)

View File

@ -15,9 +15,9 @@ from typing import Set
import gdb
import pwndbg.config
from pwndbg.gdblib.config import config
debug = pwndbg.config.Parameter("debug-events", False, "display internal event debugging info")
debug = config.add_param("debug-events", False, "display internal event debugging info")
# There is no GDB way to get a notification when the binary itself

View File

@ -24,7 +24,7 @@ for line in hint_lines:
print(message.prompt("pwndbg: ") + message.system(line))
# noinspection PyPackageRequirements
show_tip = pwndbg.config.Parameter(
show_tip = pwndbg.gdblib.config.add_param(
"show-tips", True, "whether to display the tip of the day on startup"
)
@ -71,7 +71,7 @@ def reset_context_shown(*a):
context_shown = False
@pwndbg.config.Trigger([message.config_prompt_color, disable_colors])
@pwndbg.gdblib.config.trigger(message.config_prompt_color, disable_colors)
def set_prompt():
prompt = "pwndbg> "

View File

@ -228,5 +228,5 @@ def update_last():
M = sys.modules[__name__]
M.previous = M.last
M.last = {k: M[k] for k in M.common}
if pwndbg.config.show_retaddr_reg:
if pwndbg.gdblib.config.show_retaddr_reg:
M.last.update({k: M[k] for k in M.retaddr})

View File

@ -60,11 +60,11 @@ def decompile(func=None):
source = source.split("\n")
line = source[curline]
if line.startswith(" "):
line = line[min(4, len(pwndbg.config.code_prefix) + 1) :]
line = line[min(4, len(pwndbg.gdblib.config.code_prefix) + 1) :]
source[curline] = current_line_marker + " " + line
source = "\n".join(source)
if pwndbg.config.syntax_highlight:
if pwndbg.gdblib.config.syntax_highlight:
# highlighting depends on the file extension to guess the language, so try to get one...
src_filename = pwndbg.gdblib.symbol.selected_frame_source_absolute_filename()
if not src_filename:
@ -73,5 +73,5 @@ def decompile(func=None):
source = H.syntax_highlight(source, src_filename)
# Replace code prefix marker after syntax highlighting
source = source.replace(current_line_marker, C.prefix(pwndbg.config.code_prefix), 1)
source = source.replace(current_line_marker, C.prefix(pwndbg.gdblib.config.code_prefix), 1)
return source

View File

@ -7,7 +7,7 @@ import re
import gdb
import pwndbg.config
import pwndbg.gdblib.config
import pwndbg.gdblib.memory
import pwndbg.gdblib.proc
import pwndbg.gdblib.symbol
@ -15,11 +15,13 @@ import pwndbg.heap
import pwndbg.lib.memoize
import pwndbg.search
safe_lnk = pwndbg.config.Parameter(
safe_lnk = pwndbg.gdblib.config.add_param(
"safe-linking", "auto", "whether glibc use safe-linking (on/off/auto)"
)
glibc_version = pwndbg.config.Parameter("glibc", "", "GLIBC version for heuristics", scope="heap")
glibc_version = pwndbg.gdblib.config.add_param(
"glibc", "", "GLIBC version for heuristics", scope="heap"
)
@pwndbg.gdblib.proc.OnlyWhenRunning

View File

@ -1,29 +1,31 @@
import pwndbg.color.message as message
import pwndbg.config
import pwndbg.gdblib.config
import pwndbg.gdblib.symbol
import pwndbg.heap.heap
current = None
main_arena = pwndbg.config.Parameter("main_arena", "0", "&main_arena for heuristics", "heap")
main_arena = pwndbg.gdblib.config.add_param("main-arena", "0", "&main_arena for heuristics", "heap")
thread_arena = pwndbg.config.Parameter("thread_arena", "0", "*thread_arena for heuristics", "heap")
thread_arena = pwndbg.gdblib.config.add_param(
"thread-arena", "0", "*thread_arena for heuristics", "heap"
)
mp_ = pwndbg.config.Parameter("mp_", "0", "&mp_ for heuristics", "heap")
mp_ = pwndbg.gdblib.config.add_param("mp", "0", "&mp_ for heuristics", "heap")
tcache = pwndbg.config.Parameter("tcache", "0", "*tcache for heuristics", "heap")
tcache = pwndbg.gdblib.config.add_param("tcache", "0", "*tcache for heuristics", "heap")
global_max_fast = pwndbg.config.Parameter(
"global_max_fast", "0", "&global_max_fast for heuristics", "heap"
global_max_fast = pwndbg.gdblib.config.add_param(
"global-max-fast", "0", "&global_max_fast for heuristics", "heap"
)
symbol_list = [main_arena, thread_arena, mp_, tcache, global_max_fast]
heap_chain_limit = pwndbg.config.Parameter(
heap_chain_limit = pwndbg.gdblib.config.add_param(
"heap-dereference-limit", 8, "number of bins to dereference", "heap"
)
resolve_heap_via_heuristic = pwndbg.config.Parameter(
resolve_heap_via_heuristic = pwndbg.gdblib.config.add_param(
"resolve-heap-via-heuristic",
False,
"Resolve missing heap related symbols via heuristics",
@ -46,7 +48,7 @@ def reset():
symbol.value = "0"
@pwndbg.config.Trigger([resolve_heap_via_heuristic])
@pwndbg.gdblib.config.trigger(resolve_heap_via_heuristic)
def resolve_heap(is_first_run=False):
import pwndbg.heap.ptmalloc

View File

@ -4,8 +4,8 @@ from collections import OrderedDict
import gdb
import pwndbg.color.memory as M
import pwndbg.config
import pwndbg.disasm
import pwndbg.gdblib.config
import pwndbg.gdblib.events
import pwndbg.gdblib.symbol
import pwndbg.gdblib.tls
@ -981,7 +981,7 @@ class HeuristicHeap(Heap):
@property
def main_arena(self):
main_arena_via_config = int(str(pwndbg.config.main_arena), 0)
main_arena_via_config = int(str(pwndbg.gdblib.config.main_arena), 0)
main_arena_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"main_arena"
) or pwndbg.gdblib.symbol.address("main_arena")
@ -1114,7 +1114,7 @@ class HeuristicHeap(Heap):
@property
def thread_arena(self):
thread_arena_via_config = int(str(pwndbg.config.thread_arena), 0)
thread_arena_via_config = int(str(pwndbg.gdblib.config.thread_arena), 0)
thread_arena_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"thread_arena"
) or pwndbg.gdblib.symbol.address("thread_arena")
@ -1274,7 +1274,7 @@ class HeuristicHeap(Heap):
"""Locate a thread's tcache struct. We try to find its address in Thread Local Storage (TLS) first,
and if that fails, we guess it's at the first chunk of the heap.
"""
thread_cache_via_config = int(str(pwndbg.config.tcache), 0)
thread_cache_via_config = int(str(pwndbg.gdblib.config.tcache), 0)
thread_cache_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"tcache"
) or pwndbg.gdblib.symbol.address("tcache")
@ -1509,7 +1509,7 @@ class HeuristicHeap(Heap):
@property
def mp(self):
mp_via_config = int(str(pwndbg.config.mp_), 0)
mp_via_config = int(str(pwndbg.gdblib.config.mp_), 0)
mp_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"mp_"
) or pwndbg.gdblib.symbol.address("mp_")
@ -1656,7 +1656,7 @@ class HeuristicHeap(Heap):
@property
def global_max_fast(self):
global_max_fast_via_config = int(str(pwndbg.config.global_max_fast), 0)
global_max_fast_via_config = int(str(pwndbg.gdblib.config.global_max_fast), 0)
global_max_fast_via_symbol = pwndbg.gdblib.symbol.static_linkage_symbol_address(
"global_max_fast"
) or pwndbg.gdblib.symbol.address("global_max_fast")

View File

@ -7,7 +7,7 @@ import string
import pwndbg.color.hexdump as H
import pwndbg.color.theme as theme
import pwndbg.config
import pwndbg.gdblib.config
color_scheme = None
printable = None
@ -21,21 +21,21 @@ def groupby(array, count, fill=None):
yield array[i : i + count]
config_colorize_ascii = theme.Parameter(
config_colorize_ascii = theme.add_param(
"hexdump-colorize-ascii", True, "whether to colorize the hexdump command ascii section"
)
config_separator = theme.Parameter(
config_separator = theme.add_param(
"hexdump-ascii-block-separator", "", "block separator char of the hexdump command"
)
config_byte_separator = theme.Parameter(
config_byte_separator = theme.add_param(
"hexdump-byte-separator",
" ",
"separator of single bytes in hexdump (does NOT affect group separator)",
)
@pwndbg.config.Trigger(
[H.config_normal, H.config_zero, H.config_special, H.config_printable, config_colorize_ascii]
@pwndbg.gdblib.config.trigger(
H.config_normal, H.config_zero, H.config_special, H.config_printable, config_colorize_ascii
)
def load_color_scheme():
global color_scheme, printable
@ -51,16 +51,18 @@ def load_color_scheme():
):
color_scheme[c] = H.printable("%02x" % c)
printable[c] = (
H.printable("%s" % chr(c)) if pwndbg.config.hexdump_colorize_ascii else "%s" % chr(c)
H.printable("%s" % chr(c))
if pwndbg.gdblib.config.hexdump_colorize_ascii
else "%s" % chr(c)
)
for c in bytearray(b"\x00"):
color_scheme[c] = H.zero("%02x" % c)
printable[c] = H.zero(".") if pwndbg.config.hexdump_colorize_ascii else "."
printable[c] = H.zero(".") if pwndbg.gdblib.config.hexdump_colorize_ascii else "."
for c in bytearray(b"\xff\x7f\x80"):
color_scheme[c] = H.special("%02x" % c)
printable[c] = H.special(".") if pwndbg.config.hexdump_colorize_ascii else "."
printable[c] = H.special(".") if pwndbg.gdblib.config.hexdump_colorize_ascii else "."
color_scheme[-1] = " "
printable[-1] = " "

View File

@ -13,9 +13,9 @@ import xmlrpc.client
import gdb
import pwndbg.config
import pwndbg.decorators
import pwndbg.gdblib.arch
import pwndbg.gdblib.config
import pwndbg.gdblib.elf
import pwndbg.gdblib.events
import pwndbg.gdblib.memory
@ -23,10 +23,16 @@ import pwndbg.gdblib.regs
import pwndbg.lib.memoize
from pwndbg.color import message
ida_rpc_host = pwndbg.config.Parameter("ida-rpc-host", "127.0.0.1", "ida xmlrpc server address")
ida_rpc_port = pwndbg.config.Parameter("ida-rpc-port", 31337, "ida xmlrpc server port")
ida_enabled = pwndbg.config.Parameter("ida-enabled", True, "whether to enable ida integration")
ida_timeout = pwndbg.config.Parameter("ida-timeout", 2, "time to wait for ida xmlrpc in seconds")
ida_rpc_host = pwndbg.gdblib.config.add_param(
"ida-rpc-host", "127.0.0.1", "ida xmlrpc server address"
)
ida_rpc_port = pwndbg.gdblib.config.add_param("ida-rpc-port", 31337, "ida xmlrpc server port")
ida_enabled = pwndbg.gdblib.config.add_param(
"ida-enabled", True, "whether to enable ida integration"
)
ida_timeout = pwndbg.gdblib.config.add_param(
"ida-timeout", 2, "time to wait for ida xmlrpc in seconds"
)
xmlrpc.client.Marshaller.dispatch[int] = lambda _, v, w: w("<value><i8>%d</i8></value>" % v)
@ -42,7 +48,7 @@ _ida_last_connection_check = 0
@pwndbg.decorators.only_after_first_prompt()
@pwndbg.config.Trigger([ida_rpc_host, ida_rpc_port, ida_enabled, ida_timeout])
@pwndbg.gdblib.config.trigger(ida_rpc_host, ida_rpc_port, ida_enabled, ida_timeout)
def init_ida_rpc_client():
global _ida, _ida_last_exception, _ida_last_connection_check
@ -78,7 +84,10 @@ def init_ida_rpc_client():
not isinstance(_ida_last_exception, exception[0])
or _ida_last_exception.args != exception[1].args
):
if hasattr(pwndbg.config, "exception_verbose") and pwndbg.config.exception_verbose:
if (
hasattr(pwndbg.gdblib.config, "exception_verbose")
and pwndbg.gdblib.config.exception_verbose
):
print(message.error("[!] Ida Pro xmlrpc error"))
traceback.print_exception(*exception)
else:

130
pwndbg/lib/config.py Normal file
View File

@ -0,0 +1,130 @@
import collections
from functools import total_ordering
from typing import List
# @total_ordering allows us to implement `__eq__` and `__lt__` and have all the
# other comparison operators handled for us
@total_ordering
class Parameter:
def __init__(self, name, default, docstring, scope="config"):
self.docstring = docstring.strip()
self.name = name
self.default = default
self.value = default
self.scope = scope
@property
def is_changed(self):
return self.value != self.default
def revert_default(self):
self.value = self.default
def attr_name(self):
"""Returns the attribute name associated with this config option,
i.e. `my-config` has the attribute name `my_config`"""
return self.name.replace("-", "_")
def __getattr__(self, name):
return getattr(self.value, name)
# Casting
def __int__(self):
return int(self.value)
def __str__(self):
return str(self.value)
def __bool__(self):
return bool(self.value)
# Compare operators
# Ref: http://portingguide.readthedocs.io/en/latest/comparisons.html
# If comparing with another `Parameter`, the `Parameter` objects are equal
# if they refer to the same GDB parameter. For any other type of object, the
# `Parameter` is equal to the object if `self.value` is equal to the object
def __eq__(self, other):
if isinstance(other, Parameter):
return self.name == other.name
return self.value == other
def __lt__(self, other):
if isinstance(other, Parameter):
return self.name < other.name
return self.value < other
# Operators
def __add__(self, other):
return self.value + other
def __radd__(self, other):
return other + self.value
def __sub__(self, other):
return self.value - other
def __rsub__(self, other):
return other - self.value
def __mul__(self, other):
return self.value * other
def __rmul__(self, other):
return other * self.value
def __div__(self, other):
return self.value / other
def __floordiv__(self, other):
return self.value // other
def __pow__(self, other):
return self.value**other
def __mod__(self, other):
return self.value % other
def __len__(self):
return len(self.value)
class Config:
def __init__(self):
self.params = {}
self.triggers = collections.defaultdict(lambda: [])
def add_param(self, name, default, docstring, scope="config"):
# Dictionary keys are going to have underscores, so we can't allow them here
assert "_" not in name
p = Parameter(name, default, docstring, scope)
attr_name = p.attr_name()
# Make sure this isn't a duplicate parameter
assert attr_name not in self.params
self.params[attr_name] = p
return p
def trigger(self, *params: List[Parameter]):
names = [p.name for p in params]
def wrapper(func):
for name in names:
self.triggers[name].append(func)
return func
return wrapper
def get_params(self, scope) -> List[Parameter]:
return sorted(filter(lambda p: p.scope == scope, self.params.values()))
def __getattr__(self, name):
if name in self.params:
return self.params[name]
else:
raise AttributeError("'Config' object has no attribute '%s'" % name)

View File

@ -10,22 +10,22 @@ import termios
import pwndbg.color.context as C
import pwndbg.gdblib.arch
from pwndbg import config
from pwndbg.color import ljust_colored
from pwndbg.color import message
from pwndbg.color import rjust_colored
from pwndbg.color import strip
from pwndbg.color import theme
from pwndbg.gdblib import config
theme.Parameter("banner-separator", "", "repeated banner separator character")
theme.Parameter("banner-title-surrounding-left", "[ ", "banner title surrounding char (left side)")
theme.Parameter(
theme.add_param("banner-separator", "", "repeated banner separator character")
theme.add_param("banner-title-surrounding-left", "[ ", "banner title surrounding char (left side)")
theme.add_param(
"banner-title-surrounding-right", " ]", "banner title surrounding char (right side)"
)
title_position = theme.Parameter("banner-title-position", "center", "banner title position")
title_position = theme.add_param("banner-title-position", "center", "banner title position")
@pwndbg.config.Trigger([title_position])
@pwndbg.gdblib.config.trigger(title_position)
def check_title_position():
valid_values = ["center", "left", "right"]
if title_position not in valid_values:

View File

@ -31,7 +31,7 @@ explored_pages = []
custom_pages = []
kernel_vmmap_via_pt = pwndbg.config.Parameter(
kernel_vmmap_via_pt = pwndbg.gdblib.config.add_param(
"kernel-vmmap-via-page-tables",
True,
"When on, it reads vmmap for kernels via page tables, otherwise uses QEMU kernel's `monitor info mem` command",

View File

@ -1,7 +1,7 @@
import gdb
from pwnlib.util.cyclic import cyclic
import pwndbg.config
import pwndbg.gdblib.config
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.vmmap
@ -11,7 +11,7 @@ BINARY = tests.binaries.get("reference-binary.out")
def run_tests(stack, use_big_endian, expected):
pwndbg.config.hexdump_group_use_big_endian = use_big_endian
pwndbg.gdblib.config.hexdump_group_use_big_endian = use_big_endian
# Put some data onto the stack
pwndbg.gdblib.memory.write(stack, cyclic(0x100))
@ -33,7 +33,7 @@ def run_tests(stack, use_big_endian, expected):
def test_hexdump(start_binary):
start_binary(BINARY)
pwndbg.config.hexdump_group_width = -1
pwndbg.gdblib.config.hexdump_group_width = -1
# TODO: Setting theme options with Python isn't working
gdb.execute("set hexdump-byte-separator")