demangle 0.5.2__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {demangle-0.5.2 → demangle-0.7.0}/.gitignore +3 -0
- {demangle-0.5.2 → demangle-0.7.0}/ARCHITECTURE.md +3 -1
- {demangle-0.5.2 → demangle-0.7.0}/CHANGELOG.md +127 -1
- {demangle-0.5.2 → demangle-0.7.0}/CITATION.cff +1 -1
- {demangle-0.5.2 → demangle-0.7.0}/CONFORMANCE.md +1 -1
- {demangle-0.5.2 → demangle-0.7.0}/CONTRIBUTING.md +54 -7
- {demangle-0.5.2 → demangle-0.7.0}/PKG-INFO +17 -2
- {demangle-0.5.2 → demangle-0.7.0}/README.md +16 -1
- {demangle-0.5.2 → demangle-0.7.0}/SECURITY.md +2 -2
- demangle-0.7.0/benchmarks/audit_signature.py +106 -0
- demangle-0.7.0/benchmarks/baseline.json +68 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/bench.py +79 -8
- demangle-0.7.0/benchmarks/bench_playground_bridge.py +179 -0
- demangle-0.7.0/benchmarks/bench_playground_browser.py +461 -0
- demangle-0.7.0/benchmarks/compare.py +536 -0
- demangle-0.7.0/benchmarks/end_to_end.py +182 -0
- demangle-0.7.0/benchmarks/performance.md +156 -0
- demangle-0.7.0/benchmarks/results/library-after.json +184 -0
- demangle-0.7.0/benchmarks/results/library-before.json +184 -0
- demangle-0.7.0/benchmarks/results/playground-bridge-after.json +79 -0
- demangle-0.7.0/benchmarks/results/playground-browser-after-0.26.4.json +211 -0
- demangle-0.7.0/benchmarks/results/playground-browser-current-dom-cleanup.json +125 -0
- demangle-0.7.0/benchmarks/results/playground-browser-pristine-0.26.4.json +211 -0
- demangle-0.7.0/benchmarks/results/playground-browser-pristine-dom-cleanup.json +125 -0
- demangle-0.7.0/benchmarks/results/playground-browser-trial-0.29.3.json +211 -0
- demangle-0.7.0/benchmarks/results/signature-paired.json +223 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/adding-a-scheme.md +7 -6
- demangle-0.7.0/docs/comparison.md +294 -0
- demangle-0.7.0/docs/hooks.py +80 -0
- demangle-0.7.0/docs/integrations.md +372 -0
- demangle-0.7.0/docs/playground.md +37 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/reference/core.md +1 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/reference/schemes.md +1 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/testing.md +76 -2
- demangle-0.7.0/integrations/demangle_binja.py +210 -0
- demangle-0.7.0/integrations/demangle_ghidra.py +191 -0
- demangle-0.7.0/integrations/demangle_ida.py +210 -0
- demangle-0.7.0/integrations/demangle_labels.py +245 -0
- {demangle-0.5.2 → demangle-0.7.0}/mkdocs.yml +6 -0
- demangle-0.7.0/playground/README.md +62 -0
- demangle-0.7.0/playground/index.html +284 -0
- demangle-0.7.0/playground/playground-worker.js +49 -0
- demangle-0.7.0/playground/playground.js +773 -0
- demangle-0.7.0/playground/playground_bridge.py +179 -0
- demangle-0.7.0/playground/style.css +1030 -0
- {demangle-0.5.2 → demangle-0.7.0}/pyproject.toml +24 -4
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/__init__.py +1 -1
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/_signature.py +19 -6
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/cache.py +2 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/decorations.py +7 -1
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/errors.py +10 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/limits.py +2 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/plugin.py +6 -2
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/reader.py +8 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/registry.py +26 -8
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/spelling.py +10 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/style.py +8 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/go/__init__.py +10 -1
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/itanium/options.py +2 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/msvc/__init__.py +17 -17
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/msvc/_parser.py +320 -136
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/msvc/nodes.py +35 -6
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/nim/__init__.py +3 -1
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/nim/_parser.py +10 -1
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/pascal/__init__.py +4 -1
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/pascal/_parser.py +11 -2
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/rust/__init__.py +11 -1
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/__init__.py +1 -1
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/_demangler.py +173 -71
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/_node.py +17 -24
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/_printer.py +149 -61
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/nodes.py +3 -2
- demangle-0.7.0/tests/browser/test_playground_browser.py +801 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/swift-upstream.txt +16 -12
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_benchmarks.py +16 -0
- demangle-0.7.0/tests/test_compare.py +185 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_conformance.py +7 -8
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_core.py +30 -1
- demangle-0.7.0/tests/test_integrations.py +455 -0
- demangle-0.7.0/tests/test_integrations_ghidra_live.py +136 -0
- demangle-0.7.0/tests/test_integrations_hosts.py +854 -0
- demangle-0.7.0/tests/test_llvm_oracle.py +240 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_msvc.py +116 -1
- demangle-0.7.0/tests/test_msvc_instantiations.py +426 -0
- demangle-0.7.0/tests/test_playground.py +273 -0
- demangle-0.7.0/tests/test_prepare_release.py +109 -0
- demangle-0.7.0/tests/test_release_publish.py +155 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_signature.py +31 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_swift.py +81 -8
- demangle-0.7.0/tests/test_swift_fast_paths.py +718 -0
- demangle-0.7.0/tests/test_upstream_drift.py +409 -0
- demangle-0.7.0/tests/test_upstream_workflow.py +470 -0
- demangle-0.7.0/tools/ensure_release_publish.py +81 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/enumerate.py +8 -0
- demangle-0.7.0/tools/llvm-oracle-requirements.txt +18 -0
- demangle-0.7.0/tools/llvm_oracle.py +307 -0
- demangle-0.7.0/tools/prepare_release.py +149 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/swift-demangle-reference/README.md +17 -11
- {demangle-0.5.2 → demangle-0.7.0}/tools/swift-demangle-reference/build.sh +1 -1
- {demangle-0.5.2 → demangle-0.7.0}/tools/upstream_drift.py +126 -12
- demangle-0.5.2/benchmarks/baseline.json +0 -38
- demangle-0.5.2/tests/test_upstream_drift.py +0 -205
- {demangle-0.5.2 → demangle-0.7.0}/CODE_OF_CONDUCT.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/LICENSE +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/NOTICE +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_api.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_api_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_ast_optimization_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_cli_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_core.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_followup_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_graph.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_integrated_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_jni.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_nim.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_nim_optimization_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_objc.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_rust.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_rust_optimization_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_stream.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_swift.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/benchmarks/audit_swift_unicode_results.json +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/ARCHITECTURE.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/CHANGELOG.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/CONFORMANCE.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/CONTRIBUTING.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/SECURITY.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/analysing-a-binary.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/index.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/labelling-a-symbol-table.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/reference/api.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/docs/specs/itanium-grammar.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/__main__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/api.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/cli.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/ast.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/core/builder.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/filter.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/py.typed +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/ada/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/ada/_parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/ada/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/codewarrior/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/codewarrior/_parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/codewarrior/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/codewarrior/options.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/d/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/d/_parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/d/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/delphi/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/delphi/_parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/delphi/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/gnuv2/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/gnuv2/_parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/gnuv2/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/gnuv2/options.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/go/_parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/go/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/itanium/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/itanium/parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/itanium/substitutions.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/itanium/tables.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/jni/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/jni/_parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/jni/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/msvc/options.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/nim/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/objc/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/objc/_parser.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/objc/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/pascal/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/rust/_dispatch.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/rust/_legacy.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/rust/_v0.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/rust/nodes.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/rust/options.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/_old_demangler.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/_punycode.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/options.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/resolve.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/src/demangle/schemes/swift/symbolic.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/__init__.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/ada-libiberty.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/ada-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/codewarrior-cwdemangle.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/d-libiberty.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/d-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/delphi-constructs.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/delphi-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/delphi-refusals.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/delphi-tdump.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/gnuv2-libiberty.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/gnuv2-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/go-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/itanium-libcxxabi.txt.gz +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/itanium-libstdcxx.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/itanium-real-world-gnu.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/itanium-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/itanium-reference-defects.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/itanium-types-llvm.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/itanium-types.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/jni-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-arm64ec.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-boost.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-clang.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-dbghelp.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-llvm-corpus.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-name-only.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-reference-defects.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-suppressions.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/msvc-type-descriptors.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/nim-lossy.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/nim-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/objc-lossy.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/objc-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/objc-refusals.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/pascal-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/pascal-refusals.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/reported/d-gnu.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/reported/gnuv2-gnu.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/reported/itanium-gnu.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/reported/itanium.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/reported/rust.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/reported/swift.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/rust-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/rust-toolchain.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/rustc-upstream.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/swift-real-world.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/swift-reference-defects.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/swift-refusals.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/swift-simplified.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conformance/swift-symbolic.txt +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/conftest.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_ada.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_address_of.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_api.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_api_surface.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_architecture.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_cli.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_codewarrior.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_concurrency.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_d.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_delphi.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_differential.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_docs.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_expressions.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_gnu_expressions.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_gnuv2.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_go.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_invariants.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_itanium_apple_auto.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_itanium_closure_prefix.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_itanium_import_thunk.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_itanium_utf8.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_jni.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_limits.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_local_names.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_msvc_arm64ec.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_msvc_ast.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_msvc_descriptors.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_msvc_options.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_nim.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_objc.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_parity.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_pascal.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_readme.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_repro.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_robustness.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_rust.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_rust_ast.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_rust_consts.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_special_names.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_substitution_parameters.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_swift_simplified.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_swift_symbolic.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tests/test_types.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/features.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/go/go.mod +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/go/main.go +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/go/plain/lib.go +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/go/v2.5/lib.go +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/go/weird.pkg.name/lib.go +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/modern.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/modern23.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/msvc/modern.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/msvc/msvc.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/README.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/auto_marshall.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/closure_prefix.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/division.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/generic_lambda.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/inheriting_constructor.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/insort.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/insort_composite.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/member_template_lambda.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/prepare_execution.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/template_template_param.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/reference_defects/value_init_new.cpp +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/rust/consts.rs +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/rust/features.rs +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/rust/library.rs +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/corpus_sources/rust/types.rs +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/cplus-dem-reference/README.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/cplus-dem-reference/SHA256SUMS +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/cplus-dem-reference/build.sh +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/cplus-dem-reference/main.c +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/differential.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/generate_ada_corpus.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/generate_corpus.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/generate_d_corpus.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/generate_delphi_corpus.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/generate_go_corpus.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/generate_msvc_dbghelp_corpus.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/generate_rust_corpus.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/invariants.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/mutate.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/probe_substitutions.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/repro.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/rustc-demangle-reference/Cargo.lock +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/rustc-demangle-reference/Cargo.toml +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/rustc-demangle-reference/README.md +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/rustc-demangle-reference/src/main.rs +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/sweep_rust_chars.py +0 -0
- {demangle-0.5.2 → demangle-0.7.0}/tools/swift-demangle-reference/main.cpp +0 -0
|
@@ -169,7 +169,9 @@ scheme with a fixed first character declares it (`first_characters`), and a name
|
|
|
169
169
|
starting with anything else never reaches it. A scheme whose names are ordinary C
|
|
170
170
|
identifiers has none, so it declares a `DETECT_SCREEN`: the markers and openings that a
|
|
171
171
|
name must hold for its `detect` to say yes, and a name with none of them is not offered
|
|
172
|
-
to it.
|
|
172
|
+
to it. Both can apply: Nim and Free Pascal names are identifiers, so they also declare
|
|
173
|
+
the letters and `_` as first characters, which keeps them off MSVC's `?` and Swift's
|
|
174
|
+
`$s` names even though those hold the `__` and `$` they screen on. The schemes whose names carry no marker at all -- Ada and the two pre-Itanium
|
|
173
175
|
C++ manglings, whose `detect` has to parse -- are offered last, behind everything a
|
|
174
176
|
prefix settles.
|
|
175
177
|
|
|
@@ -8,6 +8,130 @@ the reference demanglers, and a **Performance** section.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.7.0] - 2026-11-12
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **The IDA, Binary Ninja and Ghidra scripts read Mach-O names without their leading
|
|
16
|
+
underscore.** Mach-O puts one underscore in front of every symbol, and the tools keep
|
|
17
|
+
it, so Nim's `_area__mymod_u10` came out as `mymod._area`, JNI's `_Java_...` was not
|
|
18
|
+
read, and Free Pascal, Ada and GCC 2 names were read with the underscore as part of the
|
|
19
|
+
name. On a Mach-O file a name is now read without it, except where C++, Swift, Rust, D
|
|
20
|
+
or Objective-C reads it as it stands (`__Z`, `_$s`, `__D`, ...), which those schemes do
|
|
21
|
+
already and which keeps Apple's C++ rules. `demangle_labels.Options` has a
|
|
22
|
+
`leading_underscore` field for it, and each script a `LEADING_UNDERSCORE` setting that
|
|
23
|
+
overrides the file type. Checked in IDA 9.5, Binary Ninja 6.0 and Ghidra 12.2 on a
|
|
24
|
+
Mach-O arm64 dylib.
|
|
25
|
+
- **The Binary Ninja plugin leaves alone an address holding several user symbols.**
|
|
26
|
+
Binary Ninja's DWARF import defines a user symbol for each function the linker
|
|
27
|
+
discarded, all at the image base beside `__elf_header`. With
|
|
28
|
+
`ONLY_LEFT_MANGLED = False` on a Rust program the plugin relabelled one of them, which
|
|
29
|
+
dropped `__elf_header`, and Undo did not bring it back. Such an address is now skipped
|
|
30
|
+
and counted in the summary line. Found running the plugin live in Binary Ninja 6.0 on
|
|
31
|
+
Linux; the IDA script was run live in IDA 9.5, through idalib and `idat -S`, with
|
|
32
|
+
nothing to fix. Both were then run from their windows, the Plugins menu of Binary Ninja
|
|
33
|
+
6.0.10905 and File > Script file in IDA 9.5, with Cancel, Undo and Redo behaving as
|
|
34
|
+
documented.
|
|
35
|
+
- **An MSVC name holding `_$$_` or a `/` is no longer read as Free Pascal or Go.**
|
|
36
|
+
`?A_$$_B@@3HA` read as a Free Pascal routine `B@@3HA` in a unit `?A`, where it is
|
|
37
|
+
MSVC's `int A_$$_B`, and an MSVC string literal with a `/` in it was claimed by Go and
|
|
38
|
+
left as it was. Neither scheme writes a name opening `?`.
|
|
39
|
+
- **Swift follows upstream's renames (weekly drift report #70).** The called-once
|
|
40
|
+
function conventions are `@once` (`XO`) and `@callable(once)` (`XOo`), where they were
|
|
41
|
+
`@called(exactlyOnce)` and `@called(atMostOnce)`, and `Twa` after a type metadata
|
|
42
|
+
accessor reads as `back deployment copy of type metadata accessor for ...`, where it
|
|
43
|
+
was refused. The Swift reference build moves to swiftlang/swift `main` @ `4f010677`
|
|
44
|
+
(2026-11-12), which reproduces the corpora: 531 / 531, 217 / 217, 71 / 71. Rust's
|
|
45
|
+
`#[rustc_splat]` is not followed yet: it is on rustc-demangle's `main` only, and the
|
|
46
|
+
released 0.1.28 that the reference builds still prints `#[splat]`.
|
|
47
|
+
- **MSVC: a conversion operator used as an alias template's argument is declined
|
|
48
|
+
cleanly.** `?f@@YAXV?$A@$$Y?$?BH@@@@V?$A@$$Y?$?BH@@@@@Z` failed on an internal
|
|
49
|
+
`ValueError`, because the placeholder for a conversion operator's name and the mark
|
|
50
|
+
for a function type's calling convention shared a delimiter. They are now distinct,
|
|
51
|
+
and the name is refused as `llvm-undname` refuses it.
|
|
52
|
+
- **Swift reads a propagated `@differentiable` function argument.** A function
|
|
53
|
+
signature specialization parameter `a` (`...Tf1na_n`) carries the original function
|
|
54
|
+
and its JVP and VJP, each as a name and a type, and prints as `[Differentiable
|
|
55
|
+
Function Propagated, Components : [...]]`; it was refused. That was the last vector of
|
|
56
|
+
the drift report this library did not read. `swift-upstream.txt` now holds it and the
|
|
57
|
+
three `Twa` rows: 535 / 535 against the reference build at `4f010677`.
|
|
58
|
+
- Playground navigation, presets, and cards share centered page gutters and a bounded
|
|
59
|
+
content width. Inner padding, control sizing, and responsive option rows stay aligned
|
|
60
|
+
on desktop, narrow screens, and with enlarged text; overflow is contained locally.
|
|
61
|
+
- Release recovery resumes publishing when a tag and release already exist. Active
|
|
62
|
+
or successful publishing runs are preserved; failed runs retry only failed jobs.
|
|
63
|
+
- Playground theme settings no longer prevent startup when browser storage is blocked.
|
|
64
|
+
The theme toggle follows the system preference until the user selects a theme.
|
|
65
|
+
- Automatic and manual release runs require successful push CI for the commit being tagged.
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
- Playground batch results preserve line order and blank lines, show individual errors,
|
|
70
|
+
cache duplicate symbols, and support copying or downloading the selected output view.
|
|
71
|
+
- Share links restore batch mode and validate options, with a size limit and explicit
|
|
72
|
+
clipboard feedback. Result states distinguish unrecognized, invalid, and unchanged
|
|
73
|
+
symbols; keyboard focus and live announcements cover batch controls and results.
|
|
74
|
+
- A release-preparation command updates package and citation versions, release notes,
|
|
75
|
+
and comparison links together, with metadata checks and rollback on failure.
|
|
76
|
+
- Browser checks for theme persistence, keyboard shortcuts, and stalled-worker recovery.
|
|
77
|
+
- IDA Pro, Binary Ninja and Ghidra scripts that label the symbols each tool leaves
|
|
78
|
+
mangled, in `integrations/`, with a "Disassembler integrations" page. They stay out of
|
|
79
|
+
the wheel.
|
|
80
|
+
- `benchmarks/compare.py` and a "Comparison with other demanglers" page that measure this
|
|
81
|
+
package against LLVM's demangler, `cpp-demangle`, `itanium_demangler` and the `c++filt`
|
|
82
|
+
tools on the same names.
|
|
83
|
+
- The weekly upstream drift job also reads every checked-in corpus with the newest LLVM,
|
|
84
|
+
through `llvm-demangle-fxti` pinned by hash, in a job that holds no token
|
|
85
|
+
(`tools/llvm_oracle.py`; `tools/upstream_drift.py --source llvm-*`, `--llvm-version`,
|
|
86
|
+
`--require-llvm` and `--no-llvm`).
|
|
87
|
+
|
|
88
|
+
### Changed
|
|
89
|
+
|
|
90
|
+
- An MSVC name nested deep enough to reach Python's own recursion limit before
|
|
91
|
+
`max_depth` can now be read, where 0.6.0 reported `LimitExceeded`. `max_depth` itself is
|
|
92
|
+
unchanged.
|
|
93
|
+
|
|
94
|
+
### Performance
|
|
95
|
+
|
|
96
|
+
- MSVC names read about 7% faster cold, Swift names about 5% and Delphi names about
|
|
97
|
+
12%. Go, Nim and Free Pascal are asked about a name before these schemes, and the
|
|
98
|
+
`$`, `__` and `/` they look for are in most such names. Nim and Free Pascal names
|
|
99
|
+
open with a letter or `_`, which both now declare as their first characters, and Go's
|
|
100
|
+
`detect` turns away a name opening `?` or `$` before looking for a path: no import
|
|
101
|
+
path holds either, and Go's own `$` constants were never claimed. Output over every
|
|
102
|
+
corpus is unchanged.
|
|
103
|
+
- Swift names read about 1.3 times as fast cold: identifiers are split into words only
|
|
104
|
+
when a substitution needs them, and the commonest parser and printer steps make about
|
|
105
|
+
40% fewer calls.
|
|
106
|
+
- Template-heavy MSVC names read about 1.5 times as fast cold: each template
|
|
107
|
+
instantiation is read once per name, and the control-character scan runs once.
|
|
108
|
+
|
|
109
|
+
## [0.6.0] - 2026-10-11
|
|
110
|
+
|
|
111
|
+
### Fixed
|
|
112
|
+
|
|
113
|
+
- Preserve playground input and selected settings while its runtime loads. Scheme
|
|
114
|
+
selectors and output controls stay inside their columns on narrow screens and with
|
|
115
|
+
enlarged text. AST references reveal collapsed ancestors and support keyboard use.
|
|
116
|
+
|
|
117
|
+
### Added
|
|
118
|
+
|
|
119
|
+
- MSVC C++20 three-way comparison (`operator<=>`) and ARM64e pointer authentication
|
|
120
|
+
qualifiers, including their structured AST representation.
|
|
121
|
+
- Swift inverse conformance to `~Deinitable`, with module-name display options respected.
|
|
122
|
+
- A standalone browser playground with theme switching and keyboard shortcuts.
|
|
123
|
+
- Shareable playground links and the loaded library version, runtime retry controls,
|
|
124
|
+
and browser regression tests including a real Pyodide smoke test in CI.
|
|
125
|
+
- Bounded Swift and cross-scheme signature benchmarks with successful-work checks.
|
|
126
|
+
|
|
127
|
+
### Performance
|
|
128
|
+
|
|
129
|
+
- Run playground parsing in a worker and derive signature and AST data from one parse.
|
|
130
|
+
Output view changes reuse the result; AST expansion is lazy and paged with a display
|
|
131
|
+
budget while raw JSON remains complete.
|
|
132
|
+
- Deliver a deterministic, zipimportable source archive instead of a synthetic wheel
|
|
133
|
+
and duplicate base64 bundle.
|
|
134
|
+
|
|
11
135
|
## [0.5.2] - 2026-10-10
|
|
12
136
|
|
|
13
137
|
### Fixed
|
|
@@ -4037,7 +4161,9 @@ substitution table contents, pinned by name.
|
|
|
4037
4161
|
faster by doing less work.
|
|
4038
4162
|
- API reference published from docstrings at <https://r0ny123.github.io/demangle/>.
|
|
4039
4163
|
|
|
4040
|
-
[Unreleased]: https://github.com/r0ny123/demangle/compare/v0.
|
|
4164
|
+
[Unreleased]: https://github.com/r0ny123/demangle/compare/v0.7.0...HEAD
|
|
4165
|
+
[0.7.0]: https://github.com/r0ny123/demangle/compare/v0.6.0...v0.7.0
|
|
4166
|
+
[0.6.0]: https://github.com/r0ny123/demangle/compare/v0.5.2...v0.6.0
|
|
4041
4167
|
[0.5.2]: https://github.com/r0ny123/demangle/compare/v0.5.1...v0.5.2
|
|
4042
4168
|
[0.5.1]: https://github.com/r0ny123/demangle/compare/v0.5.0...v0.5.1
|
|
4043
4169
|
[0.5.0]: https://github.com/r0ny123/demangle/compare/v0.4.0...v0.5.0
|
|
@@ -37,7 +37,7 @@ Replayed by the test suite. No compiler and no reference demangler needed.
|
|
|
37
37
|
| Bare `<type>` encodings, llvm style | `llvm-cxxfilt --types` 18.1.3 | **1076 / 1076** |
|
|
38
38
|
| Bare `<type>` encodings, gnu style | GNU `c++filt -t` 2.42 | **1076 / 1076** <sup>[3](#3-bare-types-under-both-references)</sup> |
|
|
39
39
|
| Swift runtime + the compiler's own test corpus | `swift-demangle`, built from source <sup>[6](#6-the-swift-reference-is-built-here)</sup> | **8494 / 8494** |
|
|
40
|
-
| Swift — the compiler's own demangler vectors | `swift-demangle`, built from source <sup>[6](#6-the-swift-reference-is-built-here)</sup> | **
|
|
40
|
+
| Swift — the compiler's own demangler vectors | `swift-demangle`, built from source <sup>[6](#6-the-swift-reference-is-built-here)</sup> | **535 / 535** |
|
|
41
41
|
| Nim 1.6 and 2.2, against the compiler's own record <sup>[14](#14-nim)</sup> | `.ndi` debug mapping | **2115 / 2115** |
|
|
42
42
|
| Free Pascal 3.2.2 runtime and packages <sup>[5](#5-free-pascal)</sup> | re-assembly + `ppudump` | **3899 / 3899** |
|
|
43
43
|
| Go, from the shipped toolchain | round trip <sup>[16](#16-go)</sup> | **1517 / 1517** |
|
|
@@ -40,7 +40,35 @@ Development requirements are [dependency groups](https://peps.python.org/pep-073
|
|
|
40
40
|
not extras. An extra is a *published* feature of the distribution -- `pip install
|
|
41
41
|
demangle[dev]` would appear on PyPI as something users are invited to install -- and a
|
|
42
42
|
linter is not a feature of a demangler. The groups are `test`, `format`, `lint`, `docs`,
|
|
43
|
-
and `dev`, which includes the first three.
|
|
43
|
+
`browser`, and `dev`, which includes the first three.
|
|
44
|
+
|
|
45
|
+
The browser suite is opt-in: it needs the browser dependency group, a built docs site,
|
|
46
|
+
and Chromium. It uses a deterministic fake worker for UI regressions; the real Pyodide
|
|
47
|
+
CDN smoke test is separately opt-in.
|
|
48
|
+
|
|
49
|
+
```console
|
|
50
|
+
uv pip install -e . --group browser --group docs --group test
|
|
51
|
+
python -m playwright install chromium
|
|
52
|
+
mkdocs build --strict
|
|
53
|
+
DEMANGLE_BROWSER_TESTS=1 python -m pytest -q tests/browser/test_playground_browser.py
|
|
54
|
+
|
|
55
|
+
# Also exercise Pyodide from its CDN, as the browser CI job does.
|
|
56
|
+
DEMANGLE_BROWSER_TESTS=1 DEMANGLE_PYODIDE_SMOKE=1 \
|
|
57
|
+
python -m pytest -q tests/browser/test_playground_browser.py
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
So is the Ghidra test, which runs `integrations/demangle_ghidra.py` in a real headless
|
|
61
|
+
Ghidra: it compiles a small C++ program, imports it with analysis off, runs the script
|
|
62
|
+
twice, and checks the symbol table after each run. It needs Ghidra 11.3 or later with a
|
|
63
|
+
JDK it runs on, the `pyghidra` package for that Ghidra in the same environment as
|
|
64
|
+
`demangle`, and `g++`, `c++` or `clang++` on PATH; without any of them, or without both
|
|
65
|
+
variables below, it is skipped.
|
|
66
|
+
|
|
67
|
+
```console
|
|
68
|
+
pip install pyghidra
|
|
69
|
+
GHIDRA_INSTALL_DIR=/path/to/ghidra DEMANGLE_GHIDRA_TESTS=1 \
|
|
70
|
+
python -m pytest -q tests/test_integrations_ghidra_live.py
|
|
71
|
+
```
|
|
44
72
|
|
|
45
73
|
The toolchain is deliberately the fast one: **ruff** for linting and formatting (it
|
|
46
74
|
replaces black, isort, flake8 and pyupgrade), **ty** for type checking (it replaces
|
|
@@ -152,6 +180,23 @@ it accepts -- has been through `tools/enumerate.py`, `tools/mutate.py` and
|
|
|
152
180
|
has why, what each asks, and how to build the references for Rust, Swift and
|
|
153
181
|
pre-Itanium C++ that no distribution ships.
|
|
154
182
|
|
|
183
|
+
## Preparing a release
|
|
184
|
+
|
|
185
|
+
After the Unreleased section has notes ready to publish, prepare the release metadata with
|
|
186
|
+
its stable semantic version. The command defaults the date to today; pass `--date` for a
|
|
187
|
+
specific `YYYY-MM-DD` date. It updates the package and citation versions, moves the notes
|
|
188
|
+
under the dated changelog heading, refreshes comparison links, then runs the documentation
|
|
189
|
+
metadata checks. If those checks fail, it restores the original files. Commit and push
|
|
190
|
+
that change to `main`; `tag-release.yml` creates the tag and release only after push CI
|
|
191
|
+
passes for that exact commit. It then starts the PyPI publishing workflow. If starting
|
|
192
|
+
publishing fails, rerun the tag-release job: an existing release no longer stops recovery.
|
|
193
|
+
Active or successful publishing runs are left alone; failed runs retry only failed jobs.
|
|
194
|
+
Cancelled runs require an explicit manual restart.
|
|
195
|
+
|
|
196
|
+
```console
|
|
197
|
+
python tools/prepare_release.py 0.7.0 --date 2026-10-12
|
|
198
|
+
```
|
|
199
|
+
|
|
155
200
|
## How changes get merged
|
|
156
201
|
|
|
157
202
|
Leave `CHANGELOG.md` alone: the maintainer writes the entry when merging. A first-time
|
|
@@ -163,13 +208,15 @@ while before any checks appear. The easiest first contribution is a
|
|
|
163
208
|
## CI and workflows
|
|
164
209
|
|
|
165
210
|
Workflows run with `permissions: contents: read` and grant more only where a job needs
|
|
166
|
-
it: the weekly `upstream.yml`
|
|
167
|
-
that says a reference's vectors moved ahead of a scheme
|
|
211
|
+
it: the weekly `upstream.yml` gives `issues: write` to its `drift` job alone, because that
|
|
212
|
+
job files the issue that says a reference's vectors moved ahead of a scheme; its `llvm`
|
|
213
|
+
job, which runs a third party's native wheel, has `contents: read` and no secret, and its
|
|
214
|
+
wheel is pinned by hash. Checkout uses
|
|
168
215
|
`persist-credentials: false`, because nothing in CI pushes and a token left in
|
|
169
|
-
`.git/config` is readable by every later step.
|
|
170
|
-
|
|
171
|
-
`actions: write` on that one job; it starts `release.yml`, which publishes through
|
|
172
|
-
Trusted Publishing, so there is no long-lived API token in repository secrets. The
|
|
216
|
+
`.git/config` is readable by every later step. `tag-release.yml` cuts a release after
|
|
217
|
+
push CI succeeds on `main` for the exact commit, through the API with `contents: write`
|
|
218
|
+
and `actions: write` on that one job; it starts `release.yml`, which publishes through
|
|
219
|
+
PyPI Trusted Publishing, so there is no long-lived API token in repository secrets. The
|
|
173
220
|
`pypi` environment still waits for a maintainer to approve.
|
|
174
221
|
|
|
175
222
|
The test matrix is deliberately not a cross product. Every supported version runs on
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: demangle
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Read mangled symbol names -- Itanium C++, MSVC, Rust, Swift, Objective-C, Go, D, Nim, Free Pascal, Delphi, Ada/GNAT, JNI and pre-Itanium C++ (g++ 2.x, cfront/ARM, Lucid, HP aCC, CodeWarrior) -- in pure Python, with no dependencies.
|
|
5
5
|
Project-URL: Homepage, https://github.com/r0ny123/demangle
|
|
6
6
|
Project-URL: Documentation, https://r0ny123.github.io/demangle/
|
|
@@ -37,6 +37,7 @@ Description-Content-Type: text/markdown
|
|
|
37
37
|
[](https://www.python.org/downloads/)
|
|
38
38
|
[](https://github.com/r0ny123/demangle/blob/main/LICENSE)
|
|
39
39
|
[](https://r0ny123.github.io/demangle/)
|
|
40
|
+
[](https://r0ny123.github.io/demangle/playground/)
|
|
40
41
|
|
|
41
42
|
**Read mangled symbol names in pure Python** — Itanium C++ (GCC/Clang), MSVC, Rust,
|
|
42
43
|
Swift, Objective-C, Go, D, Nim, Free Pascal, Delphi, Ada/GNAT, JNI, and the pre-Itanium
|
|
@@ -89,7 +90,8 @@ pip install demangle
|
|
|
89
90
|
Python 3.11 or newer, on CPython or PyPy. That is the whole dependency list.
|
|
90
91
|
|
|
91
92
|
The documentation, API reference included, is published at
|
|
92
|
-
<https://r0ny123.github.io/demangle/>.
|
|
93
|
+
<https://r0ny123.github.io/demangle/>. An interactive in-browser playground is available
|
|
94
|
+
at <https://r0ny123.github.io/demangle/playground/>.
|
|
93
95
|
|
|
94
96
|
## Use
|
|
95
97
|
|
|
@@ -320,6 +322,9 @@ Swift's own 217 vectors:
|
|
|
320
322
|
```console
|
|
321
323
|
$ nm -a libfoo.so | demangle
|
|
322
324
|
$ demangle _ZNSt6vectorIiSaIiEE9push_backERKi
|
|
325
|
+
$ demangle -b _ZN3foo3barEv # `mangled ==> demangled`
|
|
326
|
+
$ demangle -m _ZN3foo3barEv # only print successfully demangled symbols
|
|
327
|
+
$ demangle -s gnu _ZNSt6vectorIiSaIiEE9push_backERKi # choose output style (llvm, gnu)
|
|
323
328
|
$ demangle --tree _Z1fPKc
|
|
324
329
|
$ demangle --detect _RNvC6_123foo3bar
|
|
325
330
|
$ demangle --detect --strict _ZN3Foo # the scheme that reads it, or an error
|
|
@@ -338,6 +343,7 @@ $ demangle --json _Z1fPi # the parse tree as JSON
|
|
|
338
343
|
$ nm -a libfoo.so | demangle --json-lines # a JSON object per symbol
|
|
339
344
|
$ demangle --json-lines --signature _Z1fPi # ... with the parts of the name
|
|
340
345
|
$ printf '%s\0' "$name" | demangle -0 # whole names ended by NUL, in and out
|
|
346
|
+
$ demangle --list-languages # list supported schemes and aliases
|
|
341
347
|
```
|
|
342
348
|
|
|
343
349
|
`--json-lines` writes one object per name, `{"mangled": ..., "demangled": ...,
|
|
@@ -396,6 +402,15 @@ Taken from `benchmarks/baseline.json`; treat them as ratios rather than absolute
|
|
|
396
402
|
gap between cold and warm is the point: symbol tables repeat themselves relentlessly, and
|
|
397
403
|
results are cached.
|
|
398
404
|
|
|
405
|
+
On names it has not seen, a native demangler is faster than this one by an order of
|
|
406
|
+
magnitude or more: LLVM's, through its Python binding `llvm-demangle-fxti`, reads the
|
|
407
|
+
Itanium names libstdc++ exports about 50 times as fast as this package does cold. This
|
|
408
|
+
package is fast enough in practice because a symbol table repeats its names, and a name
|
|
409
|
+
read once costs a dictionary lookup afterwards. [Comparison with other
|
|
410
|
+
demanglers](https://r0ny123.github.io/demangle/comparison/) has the measurements against it
|
|
411
|
+
and other tools, what each one covers, and what this one offers instead;
|
|
412
|
+
`benchmarks/compare.py` reproduces them.
|
|
413
|
+
|
|
399
414
|
`bench.py --check` gates CI against the committed baseline. It compares figures
|
|
400
415
|
normalised against a calibration workload measured in the same run, so the gate reports
|
|
401
416
|
a slower *demangler* rather than a slower *machine*.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
[](https://www.python.org/downloads/)
|
|
5
5
|
[](https://github.com/r0ny123/demangle/blob/main/LICENSE)
|
|
6
6
|
[](https://r0ny123.github.io/demangle/)
|
|
7
|
+
[](https://r0ny123.github.io/demangle/playground/)
|
|
7
8
|
|
|
8
9
|
**Read mangled symbol names in pure Python** — Itanium C++ (GCC/Clang), MSVC, Rust,
|
|
9
10
|
Swift, Objective-C, Go, D, Nim, Free Pascal, Delphi, Ada/GNAT, JNI, and the pre-Itanium
|
|
@@ -56,7 +57,8 @@ pip install demangle
|
|
|
56
57
|
Python 3.11 or newer, on CPython or PyPy. That is the whole dependency list.
|
|
57
58
|
|
|
58
59
|
The documentation, API reference included, is published at
|
|
59
|
-
<https://r0ny123.github.io/demangle/>.
|
|
60
|
+
<https://r0ny123.github.io/demangle/>. An interactive in-browser playground is available
|
|
61
|
+
at <https://r0ny123.github.io/demangle/playground/>.
|
|
60
62
|
|
|
61
63
|
## Use
|
|
62
64
|
|
|
@@ -287,6 +289,9 @@ Swift's own 217 vectors:
|
|
|
287
289
|
```console
|
|
288
290
|
$ nm -a libfoo.so | demangle
|
|
289
291
|
$ demangle _ZNSt6vectorIiSaIiEE9push_backERKi
|
|
292
|
+
$ demangle -b _ZN3foo3barEv # `mangled ==> demangled`
|
|
293
|
+
$ demangle -m _ZN3foo3barEv # only print successfully demangled symbols
|
|
294
|
+
$ demangle -s gnu _ZNSt6vectorIiSaIiEE9push_backERKi # choose output style (llvm, gnu)
|
|
290
295
|
$ demangle --tree _Z1fPKc
|
|
291
296
|
$ demangle --detect _RNvC6_123foo3bar
|
|
292
297
|
$ demangle --detect --strict _ZN3Foo # the scheme that reads it, or an error
|
|
@@ -305,6 +310,7 @@ $ demangle --json _Z1fPi # the parse tree as JSON
|
|
|
305
310
|
$ nm -a libfoo.so | demangle --json-lines # a JSON object per symbol
|
|
306
311
|
$ demangle --json-lines --signature _Z1fPi # ... with the parts of the name
|
|
307
312
|
$ printf '%s\0' "$name" | demangle -0 # whole names ended by NUL, in and out
|
|
313
|
+
$ demangle --list-languages # list supported schemes and aliases
|
|
308
314
|
```
|
|
309
315
|
|
|
310
316
|
`--json-lines` writes one object per name, `{"mangled": ..., "demangled": ...,
|
|
@@ -363,6 +369,15 @@ Taken from `benchmarks/baseline.json`; treat them as ratios rather than absolute
|
|
|
363
369
|
gap between cold and warm is the point: symbol tables repeat themselves relentlessly, and
|
|
364
370
|
results are cached.
|
|
365
371
|
|
|
372
|
+
On names it has not seen, a native demangler is faster than this one by an order of
|
|
373
|
+
magnitude or more: LLVM's, through its Python binding `llvm-demangle-fxti`, reads the
|
|
374
|
+
Itanium names libstdc++ exports about 50 times as fast as this package does cold. This
|
|
375
|
+
package is fast enough in practice because a symbol table repeats its names, and a name
|
|
376
|
+
read once costs a dictionary lookup afterwards. [Comparison with other
|
|
377
|
+
demanglers](https://r0ny123.github.io/demangle/comparison/) has the measurements against it
|
|
378
|
+
and other tools, what each one covers, and what this one offers instead;
|
|
379
|
+
`benchmarks/compare.py` reproduces them.
|
|
380
|
+
|
|
366
381
|
`bench.py --check` gates CI against the committed baseline. It compares figures
|
|
367
382
|
normalised against a calibration workload measured in the same run, so the gate reports
|
|
368
383
|
a slower *demangler* rather than a slower *machine*.
|
|
@@ -91,8 +91,8 @@ name that caused it rather than being killed.
|
|
|
91
91
|
|
|
92
92
|
| Version | Supported |
|
|
93
93
|
| --- | --- |
|
|
94
|
-
| 0.
|
|
95
|
-
| < 0.
|
|
94
|
+
| 0.7.x | yes |
|
|
95
|
+
| < 0.7 | no |
|
|
96
96
|
|
|
97
97
|
Until 1.0, security fixes land on the latest released minor version only. There is no
|
|
98
98
|
long-term support branch and no backporting; upgrading to the current minor version is
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Paired signature audit using the same parser and corpus in both versions.
|
|
2
|
+
|
|
3
|
+
Uses the source-module comparison protocol of audit_api.py/audit_core.py. Alternating
|
|
4
|
+
trials reduce process/runner drift; full field parity gates every retained result.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import dataclasses
|
|
9
|
+
import gc
|
|
10
|
+
import json
|
|
11
|
+
import statistics
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
import time
|
|
15
|
+
import tracemalloc
|
|
16
|
+
import types
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
import bench
|
|
20
|
+
|
|
21
|
+
from demangle import _signature
|
|
22
|
+
from demangle.core.ast import Function, Name, Pointer
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main():
|
|
26
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
27
|
+
parser.add_argument("--before", default="03bd234e6684a7b42672bd962da3f21cfa3e1adb")
|
|
28
|
+
parser.add_argument("--trials", type=int, default=9)
|
|
29
|
+
parser.add_argument("--output", type=Path, required=True)
|
|
30
|
+
args = parser.parse_args()
|
|
31
|
+
if args.trials < 3:
|
|
32
|
+
parser.error("at least three trials are required")
|
|
33
|
+
source = subprocess.check_output(
|
|
34
|
+
["git", "show", f"{args.before}:src/demangle/_signature.py"], cwd=bench.ROOT, text=True
|
|
35
|
+
)
|
|
36
|
+
old = types.ModuleType("demangle._signature")
|
|
37
|
+
old.__package__ = "demangle"
|
|
38
|
+
exec(compile(source, "baseline_signature.py", "exec"), old.__dict__)
|
|
39
|
+
groups = {
|
|
40
|
+
language: [(language, name) for name in bench.corpus_sample(corpus, 256)]
|
|
41
|
+
for language, corpus in (
|
|
42
|
+
("itanium", "itanium-real-world.txt"),
|
|
43
|
+
("msvc", "msvc-llvm-corpus.txt"),
|
|
44
|
+
("rust", "rust-real-world.txt"),
|
|
45
|
+
("go", "go-real-world.txt"),
|
|
46
|
+
("swift", "swift-real-world.txt"),
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
groups["mixed"] = [item for group in groups.values() for item in group]
|
|
50
|
+
results = {}
|
|
51
|
+
for group, inputs in groups.items():
|
|
52
|
+
assert [dataclasses.asdict(old.signature(name, language=language)) for language, name in inputs] == [
|
|
53
|
+
dataclasses.asdict(_signature.signature(name, language=language)) for language, name in inputs
|
|
54
|
+
], group
|
|
55
|
+
samples = {"before": [], "after": []}
|
|
56
|
+
functions = [("before", old.signature), ("after", _signature.signature)]
|
|
57
|
+
for trial in range(args.trials):
|
|
58
|
+
for label, function in functions if trial % 2 else reversed(functions):
|
|
59
|
+
gc.collect()
|
|
60
|
+
start = time.perf_counter()
|
|
61
|
+
for language, name in inputs:
|
|
62
|
+
function(name, language=language)
|
|
63
|
+
samples[label].append((time.perf_counter() - start) * 1000)
|
|
64
|
+
medians = {label: statistics.median(values) for label, values in samples.items()}
|
|
65
|
+
results[group] = {
|
|
66
|
+
"names": len(inputs),
|
|
67
|
+
"samples_ms": samples,
|
|
68
|
+
"medians_ms": medians,
|
|
69
|
+
"change_percent": 100 * (medians["after"] / medians["before"] - 1),
|
|
70
|
+
}
|
|
71
|
+
graphs = {}
|
|
72
|
+
for depth in (40, 120, 400):
|
|
73
|
+
parameter = Name("item")
|
|
74
|
+
for _ in range(depth):
|
|
75
|
+
parameter = Pointer(parameter)
|
|
76
|
+
tree = Function(None, (parameter,) * 32, name=Name("f"))
|
|
77
|
+
peaks = {}
|
|
78
|
+
fields = []
|
|
79
|
+
for label, module in (("before", old), ("after", _signature)):
|
|
80
|
+
gc.collect()
|
|
81
|
+
tracemalloc.start()
|
|
82
|
+
result = module._extract(module._Reading("itanium", "::", "gnu"), tree)
|
|
83
|
+
peaks[label] = tracemalloc.get_traced_memory()[1]
|
|
84
|
+
tracemalloc.stop()
|
|
85
|
+
fields.append(dataclasses.asdict(result))
|
|
86
|
+
assert fields[0] == fields[1], depth
|
|
87
|
+
graphs[depth] = {"shared_parameters": 32, "peak_bytes": peaks}
|
|
88
|
+
args.output.write_text(
|
|
89
|
+
json.dumps(
|
|
90
|
+
{
|
|
91
|
+
"baseline": args.before,
|
|
92
|
+
"python": sys.version,
|
|
93
|
+
"trials": args.trials,
|
|
94
|
+
"shared_current_parsers": True,
|
|
95
|
+
"groups": results,
|
|
96
|
+
"constructed_graphs": graphs,
|
|
97
|
+
},
|
|
98
|
+
indent=2,
|
|
99
|
+
)
|
|
100
|
+
+ "\n"
|
|
101
|
+
)
|
|
102
|
+
print(args.output)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
main()
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cold": {
|
|
3
|
+
"names": 14101,
|
|
4
|
+
"seconds": 0.648513,
|
|
5
|
+
"per_second": 21744,
|
|
6
|
+
"microseconds_each": 45.991,
|
|
7
|
+
"normalised": 1329.407,
|
|
8
|
+
"relative_to_pivot": 123.19
|
|
9
|
+
},
|
|
10
|
+
"warm": {
|
|
11
|
+
"names": 42303,
|
|
12
|
+
"seconds": 0.015793,
|
|
13
|
+
"per_second": 2678592,
|
|
14
|
+
"microseconds_each": 0.373,
|
|
15
|
+
"normalised": 10.792
|
|
16
|
+
},
|
|
17
|
+
"negative": {
|
|
18
|
+
"names": 14101,
|
|
19
|
+
"seconds": 0.011647,
|
|
20
|
+
"per_second": 1210698,
|
|
21
|
+
"microseconds_each": 0.826,
|
|
22
|
+
"normalised": 23.876,
|
|
23
|
+
"relative_to_pivot": 2.2124
|
|
24
|
+
},
|
|
25
|
+
"structured": {
|
|
26
|
+
"names": 636,
|
|
27
|
+
"seconds": 0.035171,
|
|
28
|
+
"per_second": 18083,
|
|
29
|
+
"microseconds_each": 55.3,
|
|
30
|
+
"parsed": 636,
|
|
31
|
+
"normalised": 1598.062,
|
|
32
|
+
"relative_to_pivot": 148.0849
|
|
33
|
+
},
|
|
34
|
+
"calibration": {
|
|
35
|
+
"seconds": 0.034605,
|
|
36
|
+
"rounds": 200000
|
|
37
|
+
},
|
|
38
|
+
"swift": {
|
|
39
|
+
"names": 256,
|
|
40
|
+
"seconds": 0.0181,
|
|
41
|
+
"per_second": 14174,
|
|
42
|
+
"microseconds_each": 70.55,
|
|
43
|
+
"succeeded": 256,
|
|
44
|
+
"normalised": 2303.46,
|
|
45
|
+
"relative_to_pivot": 336.776,
|
|
46
|
+
"recorded_on": "GitHub Actions ubuntu-24.04, CPython 3.13.16; run 38108232827"
|
|
47
|
+
},
|
|
48
|
+
"swift_parse": {
|
|
49
|
+
"names": 256,
|
|
50
|
+
"seconds": 0.0213,
|
|
51
|
+
"per_second": 12046,
|
|
52
|
+
"microseconds_each": 83.02,
|
|
53
|
+
"succeeded": 256,
|
|
54
|
+
"normalised": 2710.43,
|
|
55
|
+
"relative_to_pivot": 396.277,
|
|
56
|
+
"recorded_on": "GitHub Actions ubuntu-24.04, CPython 3.13.16; run 38108232827"
|
|
57
|
+
},
|
|
58
|
+
"signature": {
|
|
59
|
+
"names": 1280,
|
|
60
|
+
"seconds": 0.0963,
|
|
61
|
+
"per_second": 13289,
|
|
62
|
+
"microseconds_each": 75.25,
|
|
63
|
+
"succeeded": 1280,
|
|
64
|
+
"normalised": 2456.81,
|
|
65
|
+
"relative_to_pivot": 359.197,
|
|
66
|
+
"recorded_on": "GitHub Actions ubuntu-24.04, CPython 3.13.16; run 38108232827"
|
|
67
|
+
}
|
|
68
|
+
}
|