lldb: port version and bugreport commands + refactor (#2708)

* lldb: port version and bugreport commands + refactor

Port `version` and `bugreport` commands to LLDB.

Additionally, refactor them to provide better information and be less
bloated.

* fix lint

* fix lint

* fix lint
pull/2714/head
Disconnect3d 11 months ago committed by GitHub
parent 3fef9a1556
commit 1ce7ee36e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -696,7 +696,6 @@ def load_commands() -> None:
import pwndbg.commands.ropper
import pwndbg.commands.segments
import pwndbg.commands.shell
import pwndbg.commands.version
import pwndbg.commands.argv
import pwndbg.commands.aslr
@ -763,6 +762,7 @@ def load_commands() -> None:
import pwndbg.commands.tips
import pwndbg.commands.tls
import pwndbg.commands.valist
import pwndbg.commands.version
import pwndbg.commands.vmmap
import pwndbg.commands.windbg
import pwndbg.commands.xinfo

@ -1,5 +1,5 @@
"""
Displays gdb, python and pwndbg versions.
Implements version and bugreport commands.
"""
from __future__ import annotations
@ -14,8 +14,6 @@ from subprocess import check_output
from tempfile import NamedTemporaryFile
from urllib.parse import quote
import gdb
import pwndbg
import pwndbg.commands
import pwndbg.integration
@ -23,53 +21,81 @@ from pwndbg.color import message
from pwndbg.commands import CommandCategory
def _gdb_version() -> str:
return gdb.VERSION
def os_info():
os_info = platform.system()
if os_info.lower() == "linux" and os.path.isfile("/etc/os-release"):
with open("/etc/os-release") as os_release:
contents = os_release.read()
match = re.search('PRETTY_NAME="?([^",\n]+)', contents)
if match:
os_info = match.group(1)
def _py_version():
return sys.version.replace("\n", " ")
return os_info
def capstone_version():
def module_version(module):
try:
import capstone
return ".".join(map(str, capstone.cs_version()))
return __import__(module).__version__
except ImportError:
return "not found"
def unicorn_version():
try:
import unicorn
def debugger_version():
if pwndbg.dbg.is_gdblib_available():
import gdb
return unicorn.__version__
except ImportError:
return "not found"
return f"GDB: {gdb.VERSION}"
else:
return f"LLDB: {'.'.join(map(str, pwndbg.dbg_mod.lldb.LLDB_VERSION))}"
def all_versions():
gdb_str = f"Gdb: {_gdb_version()}"
py_str = f"Python: {_py_version()}"
pwndbg_str = f"Pwndbg: {pwndbg.__version__}"
return (
f"Pwndbg: {pwndbg.__version__}",
f"Python: {sys.version.replace('\n', ' ')}",
debugger_version(),
f"Capstone: {module_version('capstone')}",
f"Unicorn: {module_version('unicorn')}",
f"Pwnlib: {module_version('pwnlib')}",
) + pwndbg.integration.provider.get_versions()
def get_target_arch():
arch_info = pwndbg.aglib.arch.current
target = f"Target Arch: {arch_info}\n"
if pwndbg.dbg.is_gdblib_available():
import gdb
# Note: this are only available if given arch is supported by GDB
# (e.g., `gdb-multiarch` on Ubuntu)
if arch_info in ("arm", "armcm", "aarch64"):
arm_info = gdb.execute("show arm", to_string=True)
target += f"ARM: {arm_info}\n"
elif arch_info in ("mips", "mips64"):
mips_info = gdb.execute("show mips", to_string=True)
target += f"MIPS: {mips_info}\n"
return target
capstone_str = f"Capstone: {capstone_version()}"
unicorn_str = f"Unicorn: {unicorn_version()}"
all_versions = (gdb_str, py_str, pwndbg_str, capstone_str, unicorn_str)
def get_terminal_size():
try:
width_info = os.get_terminal_size().columns
height_info = os.get_terminal_size().lines
except OSError:
# Terminal size may not be available in non-interactive environments (e.g., scripts, IDEs)
width_info = height_info = "<unavailable>"
all_versions += pwndbg.integration.provider.get_versions()
return all_versions
return f"Terminal width: {width_info}, height: {height_info}\n"
@pwndbg.commands.ArgparsedCommand(
"Displays GDB, Python, and pwndbg versions.", category=CommandCategory.PWNDBG
"Displays Pwndbg and its important deps versions.", category=CommandCategory.PWNDBG
)
def version() -> None:
"""
Displays GDB, Python, and pwndbg versions.
"""
print("\n".join(map(message.system, all_versions())))
@ -87,20 +113,19 @@ bugreport_group.add_argument(
def bugreport(run_browser=False, use_gh=False):
ISSUE_TEMPLATE = """
<!--
Before reporting a new issue, make sure that we do not have any duplicates already open.
If there is one it might be good to take part in the discussion there.
Please see if the bug isn't reported already on: https://github.com/pwndbg/pwndbg/issues
and take part in discussion if it was.
Please make sure you have checked that the issue persists on LATEST pwndbg version.
Before reporting a new issue, make sure it happens on latest Pwndbg version.
Below is a template for BUG REPORTS.
Don't include it if this is a FEATURE REQUEST.
Use the template below.
-->
### Description
<!--
Briefly describe the problem you are having in a few paragraphs.
Describe the problem you are having in a few paragraphs.
-->
### Steps to reproduce
@ -111,84 +136,73 @@ If this is connected to particular C/asm code or a binary,
please provide the binary or if possible, a smallest C code that reproduces the issue.
-->
Gdb session history:
Session history:
```
{gdb_history}
{session_history}
```
### My setup
<!--
Show us your gdb/python/pwndbg/OS/IDA Pro version (depending on your case).
NOTE: We are currently testing Pwndbg only on Ubuntu installations but it should work fine on other distros as well.
This can be displayed in pwndbg through `version` command.
If it is somehow unavailable, use:
* `show version` - for gdb
* `py import sys; print(sys.version)` - for python
* pwndbg version/git commit id
Show us your Pwndbg and any other relevant versions.
-->
```
{setup}
```"""
setup = "\n".join(all_versions()) + "\n"
setup += f"OS: {os_info()} ({platform.platform()}, {sys.byteorder} endian)\n"
setup += f"OS ABI: {platform.uname().version}\n"
setup += f"Charset: {sys.getdefaultencoding()}\n"
setup += get_terminal_size()
setup += get_target_arch()
gdb_config = gdb.execute("show configuration", to_string=True).split("\n")
all_info = all_versions()
os_info = platform.system()
# Commented out for now: do we need this? It seems to be a bloat for GDB.
# People rarely build custom GDB with fancy options...?
# setup += get_debugger_configuration()
current_setup = f"Platform: {platform.platform()}\n"
session_history = get_debugger_session_history()
if os_info.lower() == "linux" and os.path.isfile("/etc/os-release"):
with open("/etc/os-release") as os_release:
contents = os_release.read()
match = re.search('PRETTY_NAME="?([^",\n]+)', contents)
if match:
os_info = match.group(1)
current_setup += f"OS: {os_info}\n"
# 1. showing osabi
osabi_info = platform.uname().version
current_setup += f"OS ABI: {osabi_info}\n"
issue_bugreport = ISSUE_TEMPLATE.format(setup=setup, session_history=session_history)
print(issue_bugreport)
# 2. showing architecture
arch_info = platform.machine()
current_setup += f"Architecture: {arch_info}\n"
please_please_submit = "Please submit the bugreport generated above at "
github_issue_url = "https://github.com/pwndbg/pwndbg/issues/new"
github_issue_body = "?body=" + quote(issue_bugreport)
# 3. showing endian
endian_info = sys.byteorder
current_setup += f"Endian: {endian_info}\n"
if use_gh:
try:
with NamedTemporaryFile("w", delete=True) as f:
f.write(issue_bugreport)
f.flush()
check_call([os.environ.get("EDITOR", "vi"), f.name])
check_call(["gh", "issue", "create", "--body-file", f.name])
except Exception:
print(please_please_submit + github_issue_url)
elif run_browser:
try:
check_output(["xdg-open", github_issue_url + github_issue_body])
except Exception:
print(please_please_submit + github_issue_url)
else:
print(please_please_submit + github_issue_url)
# 4. Depending on current arch -- note that those are only available if given arch is supported by current GDB, like gdb-multiarch
if arch_info in ["armv7l", "aarch64"]:
arm_info = gdb.execute("show arm", to_string=True)
current_setup += f"ARM: {arm_info}\n"
elif arch_info in ["mips", "mips64"]:
mips_info = gdb.execute("show mips", to_string=True)
current_setup += f"MIPS: {mips_info}\n"
def get_debugger_configuration():
if pwndbg.dbg.is_gdblib_available():
import gdb
# 7. showing charset
charset_info = sys.getdefaultencoding()
current_setup += f"Charset: {charset_info}\n"
gdb_config = gdb.execute("show configuration", to_string=True).split("\n")
return "\n" + "\n".join(gdb_config)
# 8. showing width, height
try:
width_info = os.get_terminal_size().columns
height_info = os.get_terminal_size().lines
except OSError:
# Terminal size may not be available in non-interactive environments (e.g., scripts, IDEs)
width_info = "no terminal size"
height_info = "no terminal size"
# LLDB: TODO/FIXME: Do we need this?
else:
return ""
current_setup += f"Width: {width_info}\n"
current_setup += f"Height: {height_info}\n"
current_setup += "\n".join(all_info)
current_setup += "\n" + "\n".join(gdb_config)
def get_debugger_session_history():
if pwndbg.dbg.is_gdblib_available():
import gdb
# get saved history size (not including current gdb session)
gdb_history_file = gdb.execute("show history filename", to_string=True)
@ -232,30 +246,8 @@ If it is somehow unavailable, use:
current_command_no += 1
gdb_current_session_history = (v for (k, v) in sorted(gdb_current_session_history.items()))
gdb_current_session_history = "\n".join(gdb_current_session_history)
return "\n".join(gdb_current_session_history)
issue_bugreport = ISSUE_TEMPLATE.format(
gdb_history=gdb_current_session_history, setup=current_setup
)
print(issue_bugreport)
please_please_submit = "Please submit the bugreport generated above at "
github_issue_url = "https://github.com/pwndbg/pwndbg/issues/new"
github_issue_body = "?body=" + quote(issue_bugreport)
if use_gh:
try:
with NamedTemporaryFile("w", delete=True) as f:
f.write(issue_bugreport)
f.flush()
check_call([os.environ.get("EDITOR", "vi"), f.name])
check_call(["gh", "issue", "create", "--body-file", f.name])
except Exception:
print(please_please_submit + github_issue_url)
elif run_browser:
try:
check_output(["xdg-open", github_issue_url + github_issue_body])
except Exception:
print(please_please_submit + github_issue_url)
# LLDB: TODO/FIXME: Not yet supported
else:
print(please_please_submit + github_issue_url)
return "<session history not supported on lldb yet>"

Loading…
Cancel
Save