{"id":36624235,"url":"https://github.com/memfault/gdbundle","last_synced_at":"2026-01-12T09:30:04.413Z","repository":{"id":55889702,"uuid":"255177050","full_name":"memfault/gdbundle","owner":"memfault","description":"Minimalist plugin manager for GDB and LLDB","archived":false,"fork":false,"pushed_at":"2020-12-09T08:39:37.000Z","size":20,"stargazers_count":81,"open_issues_count":1,"forks_count":3,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-08-11T10:09:24.244Z","etag":null,"topics":["debug","debugger","debugging","embedded","embedded-systems","gdb","gdbundle","lldb","plugins","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/memfault.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-12T21:54:06.000Z","updated_at":"2024-07-02T08:19:39.000Z","dependencies_parsed_at":"2022-08-15T08:40:48.679Z","dependency_job_id":null,"html_url":"https://github.com/memfault/gdbundle","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/memfault/gdbundle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memfault%2Fgdbundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memfault%2Fgdbundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memfault%2Fgdbundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memfault%2Fgdbundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/memfault","download_url":"https://codeload.github.com/memfault/gdbundle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memfault%2Fgdbundle/sbom","scorecard":{"id":636194,"data":{"date":"2025-08-11","repo":{"name":"github.com/memfault/gdbundle","commit":"1289f9c1592126ca633309e6612e46c72b253bf7"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/memfault/gdbundle/main.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating buildpack-deps:buster to buildpack-deps:buster@sha256:c9285bcb198c0ae171bfc350a4af94ddfda547c4e4d2900a92c280232319341e","Warn: downloadThenRun not pinned by hash: Dockerfile:7-16","Warn: pipCommand not pinned by hash: Dockerfile:19","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T09:13:47.385Z","repository_id":55889702,"created_at":"2025-08-21T09:13:47.385Z","updated_at":"2025-08-21T09:13:47.385Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28337723,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["debug","debugger","debugging","embedded","embedded-systems","gdb","gdbundle","lldb","plugins","python"],"created_at":"2026-01-12T09:30:04.218Z","updated_at":"2026-01-12T09:30:04.376Z","avatar_url":"https://github.com/memfault.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GDBundle - Plugin Manager for GDB and LLDB\n\n[![PyPI version](https://badge.fury.io/py/gdbundle.svg)](https://badge.fury.io/py/gdbundle)\n\ngdbundle is short for GDB bundle and is a plugin manager for GDB and LLDB.\n\nFor detailed info about the origin story of gdbundle, read the announcement on Interrupt: \n[gdbundle - GDB's Missing Plugin Manager](https://interrupt.memfault.com/blog/gdbundle-plugin-manager)\n\n## Benefits\n\nThere are a handful of indisputable benefits of using gdbundle over manually modifying `.gdbinit` and `.lldbinit` files.\n\n1. Just `pip install gdbundle-\u003cplugin-name\u003e`. No more manually editing your\n   `~/.gdbinit` in specific ways depending on the extension.\n2. It enables developers to use virtual environments (and encourages it!).\n3. Personal projects and team projects can have project-specific\n   `requirements.txt` and `.gdbinit` files. With these two in place, a new\n   developer would just need to `pip install -r requirements.txt`.\n4. Discoverability. Check out this\n   [PyPi filter](https://pypi.org/search/?q=gdbundle) to find new plugins.\n5. Dependency management and version tracking is now done automatically by\n   Python's packaging infrastructure.\n\n## Published Plugins\n\nPublished ones can be found on [PyPi](https://pypi.org/search/?q=gdbundle)\n\nFor now, a list is kept here as well:\n\n- [example](https://github.com/memfault/gdbundle-example)\n- [gdb-dashboard](https://github.com/memfault/gdbundle-gdb-dashboard)\n- [PyCortexMDebug](https://github.com/memfault/gdbundle-PyCortexMDebug)\n- [voltron](https://github.com/memfault/gdbundle-voltron)\n\n## Quickstart\n\n\u003e NOTE: The Python compiled with GDB should be the same major version as \n\u003e the Python in the local virtual, Conda, or local environment that \n\u003e you are installing gdbundle and plugins into. \n\nTo check both versions of Python, you can run the following:\n\n```\n$ gdb\n(gdb) pi\n\u003e\u003e\u003e import sys; sys.version\n'3.6.9 (default, Nov  7 2019, 10:44:02) \\n[GCC 8.3.0]'\n\n$ python --version\nPython 3.6.9\n```\n\n### Install gdbundle\n\nInstall `gdbundle` from PyPi first. Using a\n[virtual environment](https://docs.python.org/3/library/venv.html) is\nrecommended.\n\n```\n$ pip install gdbundle\n```\n\nIf you'd rather not use a virtual environment, it's advised to use `--user` when\ninstalling the package.\n\n```\n$ pip install --user gdbundle\n```\n\nJust, whatever you do, don't use `sudo ...`. And don't let your friends either.\n\n### Amend Init Scripts\n\nPlacing the following in the appropriate file will load all installed gdbundle\nplugins by default. If you would like to selectively load certain ones, please\nrefer to the [Configuration](#Configuration) section.\n\n#### GDB's `.gdbinit`\n\nAppend the following to your `~/.gdbinit` or to a project-specific `.gdbinit`\nthat is loaded with `gdb --command .gdbinit`\n\n```\n# -- gdbundle_BEGIN\npython\nimport os,sys,subprocess\n# Execute a Python using the user's shell and pull out the sys.path (for site-packages)\npaths = subprocess.check_output('python -c \"import os,sys;print(os.linesep.join(sys.path).strip())\"',shell=True).decode(\"utf-8\").split()\n# Extend GDB's Python search path\nsys.path.extend(paths)\n\n# Initialize gdbundle\nimport gdbundle\ngdbundle.init()\nend\n# -- gdbundle_END\n```\n\n#### LLDB's `.lldbinit`\n\nCopy the `sample_lldbinit.py` somewhere. For now, let's assume it's at\n`/path/to/gdbundle_lldbinit.py`\n\n```\n# /path/to/gdbundle_lldbinit.py\n\n# -- gdbundle_BEGIN\nimport os,subprocess,sys\n# Execute a Python using the user's shell and pull out the sys.path (for site-packages)\npaths = subprocess.check_output('python -c \"import os,sys;print(os.linesep.join(sys.path).strip())\"',shell=True).decode(\"utf-8\").split()\n# Extend LLDB's Python search path\nsys.path.extend(paths)\n\n# Initialize gdbundle\nimport gdbundle\ngdbundle.init()\n# -- gdbundle_END\n```\n\nAppend the following to your `~/.lldbinit` or to project-specific `.lldbinit`\nfile that is loaded with `lldb -s .lldbinit`.\n\n```\n# .lldbinit\n\ncommand script import '/path/to/gdbundle_lldbinit.py'\n```\n\n## Background\n\nGDB has\n[built-in support for extensions](https://sourceware.org/gdb/current/onlinedocs/gdb/Extending-GDB.html#Extending-GDB)\nwritten in in Python, Guile, or GDB's command language. However, there is no\nconvenient way to package, distribute, and install these scripts.\n\nGDB does provide a few mechanisms:\n\n- Place scripts in /usr/local/share/gdb/auto-load or similar\n- Use `gdb --command ...` to load the scripts on invocation\n-\n\nGDB's documentation gives us the following:\n\n\u003e Python scripts used by GDB should be installed in data-directory/python, where\n\u003e data-directory is the data directory as determined at GDB startup\n\nThis leaves a lot to be desired, because a user would have to copy-paste script\nfiles to this directory. There are many drawbacks to this method, including:\n\n- Requires manual intervention to install scripts to `data-directory`\n- Scripts become out of date since they were copy-pasted\n- `data-directory` is usually in a directory next to GDB's installation path,\n  usually in `/usr/local`. Everyone should do their best not to manually edit\n  files there.\n\nThere _has_ to be a better way, and thankfully, there is! It's called\n`gdbundle`.\n\n## Installing Packages\n\nPackages are prefixed with `gdbundle-` and are installing through `pip` from\nPyPi.\n\n```\n$ pip install gdbundle-example\n```\n\n## Configuration\n\n`gdbundle` today is simple and has only a few configuration knobs. Configuration\nis passed into the `gdbundle.init(...)` function call.\n\n\u003e NOTE: The names passed into `include` and `exclude` should be the package name\n\u003e minus `gdbundle_`, and hyphens are underscores. (e.g. `gdbundle-gdb-dashboard`\n\u003e becomes `gdb_dashboard`)\n\n```py\n# .gdbinit\n\nimport gdbundle\n\n# Configure which packages to include\ninclude = [\n    # List of packages to load.\n    # e.g. \"example\"\n]\n\nexclude = [\n    # List of packages to exclude.\n    # Useful if the same virtual environment is used for multiple\n    #  projects and not all packages should be loaded\n    # e.g. \"example\"\n]\n# Load the configured packages\ngdbundle.init(include=include, exclude=exclude)\n```\n\nIf you've created a Python package that has the necessary gdbundle hooks (e.g.\n`gdbundle.gdb_loader.gdbundle_load()`), you can manually load it using\n`gdbundle.load_module()`.\n\n```\n# gdbundle will import this module and attempt to run `my_package.gdb_loader.gdbundle_load()`\ngdbundle.load_module(\"my_package\")\n```\n\n## Creating and Distributing Packages\n\nThe goal was to keep `gdbundle` packages as simple as possible. A package only\nhas a few responsibilities:\n\n1. Define dependencies in the `pyproject.toml` so they are automatically\n   installed.\n2. Provide a version so users can easily pin and upgrade to specific versions.\n3. Provide a hook `gdb_loader.gdbundle_load()` and/or\n   `lldb_loader.gdbundle_load()` which is called by gdbundle, which should\n   either:\n   - Load the script into the debugger context by calling\n     `gdb.execute(\"source \u003cfile\u003e\")` or\n     `lldb.debugger.HandleCommand(\"command script import \u003cfile\u003e\"`\n   - Import the Python module which does the sourcing itself:\n     `from mypackage import HelloWorld; HelloWorld()`\n\nTo investigate a real package that works with both GDB and LLDB, check out the\n[gdbundle-example plugin](https://github.com/memfault/gdbundle-example).\n\nLet's go over each piece quickly.\n\n### `pyproject.toml`\n\nA standard `setup.py` file. The main thing to note here is that our package\n`name` will be `gdbundle-\u003csomething\u003e`, but our Python package will be called\n`gdbundle_\u003csomething\u003e`.\n\n```python\n[tool.poetry]\nname = \"gdbundle-example\"\nversion = \"0.0.1\"\ndescription = \"\"\nauthors = [\"Tyler Hoffman \u003ctyler@memfault.com\u003e\"]\nreadme = \"README.md\"\ninclude = [\"gdbundle_example/scripts/*\"]\nlicense = \"MIT\"\nclassifiers = [\n    [...]\n]\n\n[tool.poetry.dependencies]\npython = \"*\"\n\n[build-system]\nrequires = [\"poetry\u003e=0.12\"]\nbuild-backend = \"poetry.masonry.api\"\n\n```\n\n### `gdbundle_example/gdb_loader.py`\n\n```python\nimport gdb\nimport os\n\nPACKAGE_DIR = os.path.dirname(__file__)\n\nSCRIPT_PATHS = [\n    [PACKAGE_DIR, 'scripts', 'example_gdb.gdb'],\n    [PACKAGE_DIR, 'scripts', 'example_gdb.py']\n]\n\ndef _abs_path(path):\n    return os.path.abspath(os.path.join(*path))\n\ndef gdbundle_load():\n    for script_path in SCRIPT_PATHS:\n        gdb.execute(\"source {}\".format(_abs_path(script_path)))\n```\n\n### `gdbundle_example/scripts/`\n\nPlace the script files here!\n\n## How It Works\n\nIf the GDB/LLDB executable you are using was downloaded rather than compiled\nfrom source, it's likely that it is linked against a system Python library and\n`site-packages` directory, rather than against a virtual environment, Conda\nenvironment, or another user installed version of Python.\n\nFor example, if we start `arm-none-eabi-gdb-py` downloaded from\n[ARM](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain),\nwe'll see that it is searching within the system Python's `site-packages` folder\nfor packages:\n\n```\n$ arm-none-eabi-gdb-py\n(gdb) python-interactive\n\u003e\u003e\u003e import sysconfig\n\u003e\u003e\u003e sysconfig.get_paths()['purelib']\n'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages'\n```\n\nSimilar with LLDB:\n\n```\n$ lldb\n(lldb) script\nPython Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.\n\u003e\u003e\u003e import sysconfig; sysconfig.get_paths()['purelib']\n'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/site-packages'\n\n```\n\nWhen a user installs packages with an `apt` or `brew` Python, or one from a\nConda or virtual environment, GDB will **not** automatically find those packages\nsince Python's configured `sys.path` is only looking in the system's\n`site-packages` folder.\n\nThere are three recommended (but _very bad_) ways to handle this:\n\n- Override `PYTHONPATH` on init or in the users shell.\n- Create sym-links between the virtual environment and the system python\n  installation.\n- Deal with it, as said in LLDB's\n  [Python Caveat](https://lldb.llvm.org/resources/caveats.html) docs. Install\n  the packages in the same installation anyways.\n\nWe want something that edits _only_ GDB's Python context, and only appends to\nPython's `sys.path`, not overrides it.\n\nThe best solution I've found and have been using (along with 100 other engineers\nat my previous employer) is to shell out from within GDB, ask the local shell\nenvironment what the configured Python executable is, get its `sys.path`\nentries, and then append those to our current GDB session's Python environment.\nThis allows GDB to find and use packages that are installed into a Conda or\nvirtualenv environment, as well as any other user installed Python environment.\n\n## Who uses GDB Python Scripts\n\nMany companies and projects use and include GDB scripts with their large\nopen-source projects. They are usually buried in the repo, difficult to source,\nand built and used in various ways. They usually require the developer to\ndiscover that they exist, manually source them, and then look at the source code\nto figure out how they work.\n\nCheck out the gdbundle announcement for a list of ones that are public and\nopen-source.\n\n[Neat GDB Script Repositories](https://interrupt.memfault.com/blog/gdbundle-plugin-manager#neat-gdb-script-repositories)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmemfault%2Fgdbundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmemfault%2Fgdbundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmemfault%2Fgdbundle/lists"}