diff --git a/dev/contributing/index.html b/dev/contributing/index.html index 58c1d289f..c140eaded 100644 --- a/dev/contributing/index.html +++ b/dev/contributing/index.html @@ -1,8 +1,8 @@ Contributing Guide - Documentation
Skip to content

Contributing Guide¤

Contributing Overview¤

Thank you for your interest in contributing to Pwndbg!

Note that while it is recommended that your pull request (PR) links to an issue (which can be used for discussing the bug / feature), you do not need to be assigned to it - just create the PR and it will be reviewed.

To start, install Pwndbg from source and set it up for development. For common tasks see:

Regardless of the contents of your PR, you will need to lint and test your code so make sure to read those sections. It is also likely you will need to update the documentation.

Read General developer notes to get more familiar with the various systems in place in Pwndbg. If you have any questions don't hesitate to ask us on our discord server!

Linting¤

The lint.sh script runs isort, ruff, shfmt, and vermin. isort and ruff (mostly) are able to automatically fix any issues they detect. You may apply all available fixes by running

./lint.sh -f
 

Note

You can find the configuration files for these tools in pyproject.toml or by checking the arguments passed inside lint.sh.

When submitting a PR, the continuous integration (CI) job defined in .github/workflows/lint.yml will verify that running ./lint.sh succeeds, otherwise the job will fail and we won't be able to merge your PR.

It is recommended to enable the pre-push git hook to run the lint if you haven't already done so. You may re-run ./setup-dev.sh to set it.

Running tests¤

Your PR will not be merged without passing the testing CI. Moreover, it is highly recommended you write a new test or update an existing test whenever adding new functionality to Pwndbg. To see how to do this, check out Writing tests.

To run the tests in the same environment as the testing CI, you can use the following docker commands.

# General (x86_64) test suite
-docker compose run --rm --build ubuntu24.04-mount ./tests.sh
+docker compose run --rm --build ubuntu24.04-mount ./tests.sh -d gdb -g gdb
 # Cross-architecture tests
-docker compose run --rm --build ubuntu24.04-mount ./crossarch-tests.sh
+docker compose run --rm --build ubuntu24.04-mount ./tests.sh -d gdb -g cross-arch-user
 # Kernel tests (x86_64 and aarch64)
 docker compose run --rm --build ubuntu24.04-mount ./kernel-tests.sh
 # Unit tests
@@ -10,9 +10,9 @@
 
This comes in handy particularly for cross-architecture tests because the docker environment has all the cross-compilers installed. The active pwndbg directory is mounted, preventing the need for a full rebuild whenever you update the codebase.

Remove the -mount if you want the tests to run from a clean slate (no files are mounted, meaning all binaries are recompiled each time).

If you wish to focus on some failing tests, you can filter the tests to run by providing an argument to the script, such as <docker..> ./tests.sh heap, which will only run tests that contain "heap" in the name. See ./tests.sh --help for more information and other options. You can also do this with the cross-arch and kernel tests.

If you want to, you may also run the tests with nix or run them bare.

Running tests with nix¤

You will need to build a nix-compatible gdbinit.py file, which you can do with

nix build .#pwndbg-dev
 
Then simply run the test by adding the --nix flag:
./tests.sh --nix [filter]
 

Running without docker¤

If you wish to improve Pwndbg support for your distribution (or the testing infrastructure) you may run the testing suite without the docker container.

The commands are analogous to the docker commands.

# General (x86_64) test suite
-./tests.sh
+./tests.sh -d gdb -g gdb
 # Cross-architecture tests
-./crossarch-tests.sh
+./tests.sh -d gdb -g cross-arch-user
 # Kernel tests (x86_64 and aarch64)
 ./kernel-tests.sh
 # Unit tests
diff --git a/dev/contributing/writing-tests/index.html b/dev/contributing/writing-tests/index.html
index a8eb14fd9..c9c2f07ae 100644
--- a/dev/contributing/writing-tests/index.html
+++ b/dev/contributing/writing-tests/index.html
@@ -1,4 +1,4 @@
- Writing Tests - Documentation      

Writing Tests¤

Overview¤

Note

This is written under the assumption you already know how to run the tests.

In Pwndbg we have four types of tests: extensive x86_64 GDB tests, cross-architecture tests, linux kernel tests and unit-tests. They are all located in subdirectories of ./tests.

The x86_64 tests encompass most of the Pwndbg testing suite. If your tests do not belong in any of the other categories, they should go here. Since we do not yet perform testing on LLDB, these are run from inside GDB and are located in the ./tests/gdb-tests directory. They can be run with ./tests.sh -t gdb (this is the default option).

The cross-architecture tests are run using qemu-user emulation. They test architecture-specific logic and are located in the ./tests/qemu-tests/tests/user directory. They can be run with ./tests.sh -t cross-arch (this is what ./qemu-tests.sh does).

The linux kernel tests are run using qemu-system emulation. They are located in the ./tests/qemu-tests/tests/system directory and run for a variety kernel configurations and architectures.

The unit tests are not run from within a debugger, but rather directly with pytest. They are located in the ./tests/unit-tests/ directory.

Here are the options supported by ./tests.sh which you can get by running ./tests.sh -h.

usage: tests.py [-h] [-t {gdb,cross-arch}] [-p] [-c] [-v] [-s] [--nix] [--collect-only] [test_name_filter]
+ Writing Tests - Documentation      

Writing Tests¤

Overview¤

Note

This is written under the assumption you already know how to run the tests.

In Pwndbg we have four types of tests: extensive x86_64 GDB tests, cross-architecture tests, linux kernel tests and unit-tests. They are all located in subdirectories of ./tests.

The x86_64 tests encompass most of the Pwndbg testing suite. If your tests do not belong in any of the other categories, they should go here. Since we do not yet perform testing on LLDB, these are run from inside GDB and are located in the ./tests/library/gdb directory. They can be run with ./tests.sh -d gdb -g gdb.

The cross-architecture tests are run using qemu-user emulation. They test architecture-specific logic and are located in the ./tests/library/qemu-user directory. They can be run with ./tests.sh -d gdb -g cross-arch-user.

The linux kernel tests are run using qemu-system emulation. They are located in the ./tests/library/qemu-system directory and run for a variety kernel configurations and architectures.

The unit tests are not run from within a debugger, but rather directly with pytest. They are located in the ./tests/unit-tests/ directory.

Here are the options supported by ./tests.sh which you can get by running ./tests.sh -h.

usage: tests.py [-h] -g {gdb,dbg,cross-arch-user} -d {gdb} [-p] [-c] [-v] [-s] [--nix] [--collect-only] [test_name_filter]
 
 Run tests.
 
@@ -7,22 +7,23 @@
 
 options:
   -h, --help            show this help message and exit
-  -t, --type {gdb,cross-arch}
-  -p, --pdb             enable pdb (Python debugger) post mortem debugger on failed tests
-  -c, --cov             enable codecov
-  -v, --verbose         display all test output instead of just failing test output
-  -s, --serial          run tests one at a time instead of in parallel
-  --nix                 run tests using built for nix environment
-  --collect-only        only show the output of test collection, don't run any tests
-

Writing tests¤

Each test is a Python function that runs inside of an isolated GDB session. Using a pytest fixture at the beginning of each test, GDB will attach to a binary or connect to a QEMU instance. Each test runs some commands and uses Python assert statements to verify correctness. We can access Pwndbg library code like pwndbg.aglib.regs.rsp as well as execute GDB commands with gdb.execute().

We can take a look at tests/gdb-tests/tests/test_symbol.py for an example of a simple test. Looking at a simplified version of the top-level code, we have this:

import gdb
+  -g {gdb,dbg,cross-arch-user}, --group {gdb,dbg,cross-arch-user}
+  -d {gdb}, --driver {gdb}
+  -p, --pdb             enable pdb (Python debugger) post mortem debugger on failed tests
+  -c, --cov             enable codecov
+  -v, --verbose         display all test output instead of just failing test output
+  -s, --serial          run tests one at a time instead of in parallel
+  --nix                 run tests using built for nix environment
+  --collect-only        only show the output of test collection, don't run any tests
+

Writing tests¤

Each test is a Python function that runs inside of an isolated GDB session. Using a pytest fixture at the beginning of each test, GDB will attach to a binary or connect to a QEMU instance. Each test runs some commands and uses Python assert statements to verify correctness. We can access Pwndbg library code like pwndbg.aglib.regs.rsp as well as execute GDB commands with gdb.execute().

We can take a look at tests/library/gdb/tests/test_symbol.py for an example of a simple test. Looking at a simplified version of the top-level code, we have this:

import gdb
 import pwndbg
 import tests
 
-BINARY = tests.binaries.get("symbol_1600_and_752.out")
+BINARY = tests.get_binary("symbol_1600_and_752.out")
 

Since these tests run inside GDB, we can import the gdb Python library. We also import the tests module, which makes it easy to get the path to the test binaries located in tests/gdb-tests/tests/binaries. You should be able to reuse the binaries in this folder for most tests, but if not feel free to add a new one.

Here's a small snippet of the actual test:

def test_hexdump(start_binary):
     start_binary(BINARY)
     pwndbg.config.hexdump_group_width.value = -1
 
     gdb.execute("set hexdump-byte-separator")
     stack_addr = pwndbg.aglib.regs.rsp - 0x100
-

pytest will run any function that starts with test_ as a new test, so there is no need to register your new test anywhere. The start_binary argument is a function that will run the binary you give it, and it will set some common options before starting the binary. Using start_binary is recommended if you don't need any additional customization to GDB settings before starting the binary, but if you do it's fine to not use it.

QEMU Tests¤

Our gdb-tests run in x86. To debug other architectures, we use QEMU for emulation and attach to its debug port. These tests are located in tests/qemu-tests/tests/user. Test creation is identical to our x86 tests - create a Python function with a Pytest fixture name as the parameter (it matches based on the name), and call the argument to start debugging a binary. The qemu_assembly_run fixture takes in a Python string of assembly code, compiles it in the appropriate architecture, and runs it - no need to create an external file or edit a Makefile.

\ No newline at end of file +

pytest will run any function that starts with test_ as a new test, so there is no need to register your new test anywhere. The start_binary argument is a function that will run the binary you give it, and it will set some common options before starting the binary. Using start_binary is recommended if you don't need any additional customization to GDB settings before starting the binary, but if you do it's fine to not use it.

QEMU Tests¤

Our gdb tests run in x86. To debug other architectures, we use QEMU for emulation and attach to its debug port. These tests are located in tests/library/qemu-user/tests. Test creation is identical to our x86 tests - create a Python function with a Pytest fixture name as the parameter (it matches based on the name), and call the argument to start debugging a binary. The qemu_assembly_run fixture takes in a Python string of assembly code, compiles it in the appropriate architecture, and runs it - no need to create an external file or edit a Makefile.

\ No newline at end of file diff --git a/dev/feed_json_updated.json b/dev/feed_json_updated.json index 487a8757c..898c6538c 100644 --- a/dev/feed_json_updated.json +++ b/dev/feed_json_updated.json @@ -1 +1 @@ -{"version": "https://jsonfeed.org/version/1", "title": "pwndbg Blog", "home_page_url": "https://pwndbg.re/pwndbg/latest/", "feed_url": "https://pwndbg.re/pwndbg/latest/feed_json_updated.json", "description": "pwndbg (/pa\u028an\u02c8di\u02ccb\u028c\u0261/) is a GDB plug-in that makes debugging with GDB suck less, with a focus on features needed by low-level software developers, hardware hackers, reverse-engineers and exploit developers.", "icon": "https://pwndbg.re/pwndbg/assets/favicon.ico", "authors": [], "language": "en", "items": [{"id": "https://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/", "url": "https://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/", "title": "Pwndbg coding sprints report", "content_html": "Report of the two coding sprints with Pwndbg\n", "image": null, "date_modified": "2025-06-13T21:57:07+00:00", "authors": [{"name": "Disconnect3d"}], "tags": []}]} \ No newline at end of file +{"version": "https://jsonfeed.org/version/1", "title": "pwndbg Blog", "home_page_url": "https://pwndbg.re/pwndbg/latest/", "feed_url": "https://pwndbg.re/pwndbg/latest/feed_json_updated.json", "description": "pwndbg (/pa\u028an\u02c8di\u02ccb\u028c\u0261/) is a GDB plug-in that makes debugging with GDB suck less, with a focus on features needed by low-level software developers, hardware hackers, reverse-engineers and exploit developers.", "icon": "https://pwndbg.re/pwndbg/assets/favicon.ico", "authors": [], "language": "en", "items": [{"id": "https://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/", "url": "https://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/", "title": "Pwndbg coding sprints report", "content_html": "Report of the two coding sprints with Pwndbg\n", "image": null, "date_modified": "2025-06-15T17:30:02+00:00", "authors": [{"name": "Disconnect3d"}], "tags": []}]} \ No newline at end of file diff --git a/dev/feed_rss_created.xml b/dev/feed_rss_created.xml index 92f92cbbe..30f6728bc 100644 --- a/dev/feed_rss_created.xml +++ b/dev/feed_rss_created.xml @@ -1 +1 @@ - pwndbg Blogpwndbg (/paʊnˈdiˌbʌɡ/) is a GDB plug-in that makes debugging with GDB suck less, with a focus on features needed by low-level software developers, hardware hackers, reverse-engineers and exploit developers.https://pwndbg.re/pwndbg/latest/https://github.com/pwndbg/pwndbg/en Fri, 13 Jun 2025 22:00:07 -0000 Fri, 13 Jun 2025 22:00:07 -0000 1440 MkDocs RSS plugin - v1.17.1 https://pwndbg.re/pwndbg/assets/favicon.ico pwndbg Bloghttps://pwndbg.re/pwndbg/latest/ Pwndbg coding sprints report Disconnect3d Report of the two coding sprints with Pwndbghttps://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/ Sun, 21 Aug 2022 00:00:00 +0000pwndbg Bloghttps://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/ \ No newline at end of file + pwndbg Blogpwndbg (/paʊnˈdiˌbʌɡ/) is a GDB plug-in that makes debugging with GDB suck less, with a focus on features needed by low-level software developers, hardware hackers, reverse-engineers and exploit developers.https://pwndbg.re/pwndbg/latest/https://github.com/pwndbg/pwndbg/en Sun, 15 Jun 2025 17:32:22 -0000 Sun, 15 Jun 2025 17:32:22 -0000 1440 MkDocs RSS plugin - v1.17.1 https://pwndbg.re/pwndbg/assets/favicon.ico pwndbg Bloghttps://pwndbg.re/pwndbg/latest/ Pwndbg coding sprints report Disconnect3d Report of the two coding sprints with Pwndbghttps://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/ Sun, 21 Aug 2022 00:00:00 +0000pwndbg Bloghttps://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/ \ No newline at end of file diff --git a/dev/feed_rss_updated.xml b/dev/feed_rss_updated.xml index 31db80957..6cb2b743f 100644 --- a/dev/feed_rss_updated.xml +++ b/dev/feed_rss_updated.xml @@ -1 +1 @@ - pwndbg Blogpwndbg (/paʊnˈdiˌbʌɡ/) is a GDB plug-in that makes debugging with GDB suck less, with a focus on features needed by low-level software developers, hardware hackers, reverse-engineers and exploit developers.https://pwndbg.re/pwndbg/latest/https://github.com/pwndbg/pwndbg/en Fri, 13 Jun 2025 22:00:07 -0000 Fri, 13 Jun 2025 22:00:07 -0000 1440 MkDocs RSS plugin - v1.17.1 https://pwndbg.re/pwndbg/assets/favicon.ico pwndbg Bloghttps://pwndbg.re/pwndbg/latest/ Pwndbg coding sprints report Disconnect3d Report of the two coding sprints with Pwndbghttps://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/ Fri, 13 Jun 2025 21:57:07 +0000pwndbg Bloghttps://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/ \ No newline at end of file + pwndbg Blogpwndbg (/paʊnˈdiˌbʌɡ/) is a GDB plug-in that makes debugging with GDB suck less, with a focus on features needed by low-level software developers, hardware hackers, reverse-engineers and exploit developers.https://pwndbg.re/pwndbg/latest/https://github.com/pwndbg/pwndbg/en Sun, 15 Jun 2025 17:32:22 -0000 Sun, 15 Jun 2025 17:32:22 -0000 1440 MkDocs RSS plugin - v1.17.1 https://pwndbg.re/pwndbg/assets/favicon.ico pwndbg Bloghttps://pwndbg.re/pwndbg/latest/ Pwndbg coding sprints report Disconnect3d Report of the two coding sprints with Pwndbghttps://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/ Sun, 15 Jun 2025 17:30:02 +0000pwndbg Bloghttps://pwndbg.re/pwndbg/latest/blog/2022/08/21/pwndbg-coding-sprints-report/ \ No newline at end of file diff --git a/dev/reference/pwndbg/aglib/disasm/arch/index.html b/dev/reference/pwndbg/aglib/disasm/arch/index.html index e0eca6df8..a95c449bd 100644 --- a/dev/reference/pwndbg/aglib/disasm/arch/index.html +++ b/dev/reference/pwndbg/aglib/disasm/arch/index.html @@ -24,9 +24,9 @@ module-attribute (pwndbg.aglib.disasm.arch.DO_NOT_EMULATE)" href=#pwndbg.aglib.disasm.arch.DO_NOT_EMULATE>DO_NOT_EMULATE

DEBUG_ENHANCEMENT module-attribute ¤

DEBUG_ENHANCEMENT = False
-

groups module-attribute ¤

groups = {v: _Afor (k, v) in items() if startswith('CS_GRP_')}
-

ops module-attribute ¤

ops = {v: _wfor (k, v) in items() if startswith('CS_OP_')}
-

access module-attribute ¤

access = {v: _ffor (k, v) in items() if startswith('CS_AC_')}
+

groups module-attribute ¤

groups = {v: _Sfor (k, v) in items() if startswith('CS_GRP_')}
+

ops module-attribute ¤

ops = {v: _Pfor (k, v) in items() if startswith('CS_OP_')}
+

access module-attribute ¤

access = {v: _3for (k, v) in items() if startswith('CS_AC_')}
 

DO_NOT_EMULATE module-attribute ¤

DO_NOT_EMULATE = {CS_GRP_INT, CS_GRP_INVALID, CS_GRP_IRET}
 

DisassemblyAssistant ¤

DisassemblyAssistant(architecture: X86_MATH_INSTRUCTIONS

groups module-attribute ¤

groups = {v: _Pfor (k, v) in items() if startswith('X86_GRP_')}
-

ops module-attribute ¤

ops = {v: _6for (k, v) in items() if startswith('X86_OP_')}
-

regs module-attribute ¤

regs = {v: _Nfor (k, v) in items() if startswith('X86_REG_')}
-

access module-attribute ¤

access = {v: _Vfor (k, v) in items() if startswith('CS_AC_')}
+   (pwndbg.aglib.disasm.x86.X86_MATH_INSTRUCTIONS)" href=#pwndbg.aglib.disasm.x86.X86_MATH_INSTRUCTIONS>X86_MATH_INSTRUCTIONS

groups module-attribute ¤

groups = {v: _ifor (k, v) in items() if startswith('X86_GRP_')}
+

ops module-attribute ¤

ops = {v: _hfor (k, v) in items() if startswith('X86_OP_')}
+

regs module-attribute ¤

regs = {v: _4for (k, v) in items() if startswith('X86_REG_')}
+

access module-attribute ¤

access = {v: _Kfor (k, v) in items() if startswith('CS_AC_')}
 

X86_MATH_INSTRUCTIONS module-attribute ¤

X86_MATH_INSTRUCTIONS = {
     X86_INS_ADD: "+",
     X86_INS_SUB: "-",
diff --git a/dev/reference/pwndbg/lib/elftypes/index.html b/dev/reference/pwndbg/lib/elftypes/index.html
index e649fc40c..f834f082a 100644
--- a/dev/reference/pwndbg/lib/elftypes/index.html
+++ b/dev/reference/pwndbg/lib/elftypes/index.html
@@ -135,7 +135,7 @@
     47: "AT_L3_CACHEGEOMETRY",
     51: "AT_MINSIGSTKSZ",
 }
-

AT_CONSTANT_NAMES module-attribute ¤

AT_CONSTANT_NAMES = {v: _ifor (k, v) in items()}
+

AT_CONSTANT_NAMES module-attribute ¤

AT_CONSTANT_NAMES = {v: _mfor (k, v) in items()}
 

constants ¤

Attributes: