Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3e564f7
Key decompilation results by DWARF address, not short name
sjkim1127 Sep 17, 2026
b5ac906
Add C++ function identity regression tests
sjkim1127 Sep 17, 2026
6bbac5c
Make the artifact identity contract hold on the way back in
sjkim1127 Sep 17, 2026
d9361f4
Merge main into C++ identity PR
sjkim1127 Sep 28, 2026
aa305e0
Fix DWARF reference forms in type ground truth
sjkim1127 Oct 12, 2026
8eeceb8
Align type-match cache generation assertion
sjkim1127 Oct 12, 2026
b82502d
Merge remote-tracking branch 'origin/main' into codex/cpp-native-debug
sjkim1127 Oct 13, 2026
a8a4ae7
Read UUID-matched Mach-O dSYM ground truth and native function ranges
sjkim1127 Oct 13, 2026
e216d9c
Prepare native debug review evidence and prerequisite submission notes
sjkim1127 Oct 13, 2026
80c8be4
Connect bounded PDB ground truth and qualified C++ definition discovery
sjkim1127 Oct 13, 2026
bb5ccfb
Abstain from legacy PDB symbols without explicit formal classification
sjkim1127 Oct 13, 2026
f68f60a
Record native PDB corpus evidence and scoring limits
sjkim1127 Oct 13, 2026
0b4a2de
Prototype separate C++ type views and native Fission provenance
sjkim1127 Oct 13, 2026
120f44d
Record C++ policy coverage and native address validation
sjkim1127 Oct 13, 2026
cfcc485
[AUTOMATED] Add C++ type graphs and scoped provenance contracts
sjkim1127 Oct 13, 2026
fbb9775
[AUTOMATED] Fix C++ evaluator abstention and scoped provenance
sjkim1127 Oct 18, 2026
6307dc0
[AUTOMATED] Add opt-in C++ GED identity diagnostics
sjkim1127 Oct 18, 2026
ea2b461
[AUTOMATED] Expose pinned Rust Joern library to CFG regression tests
sjkim1127 Oct 18, 2026
9f50ebf
[AUTOMATED] Retain native-proven C++ origins and validate recompiler …
sjkim1127 Oct 18, 2026
c88e6c1
[AUTOMATED] Fix C++ population integrity and reference recovery
sjkim1127 Oct 18, 2026
12a199c
[AUTOMATED] Add bounded C++ producer-output inspection
sjkim1127 Oct 19, 2026
ad8ceaf
[AUTOMATED] Guard C++ oracle reuse and document qualification gates
sjkim1127 Oct 19, 2026
81efc86
[AUTOMATED] Preserve all first-PC PDB source locations for exact CFG …
sjkim1127 Oct 22, 2026
5d3dfb6
[AUTOMATED] Classify erroneous source definitions before identity dia…
sjkim1127 Oct 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .github/workflows/cpp-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: C++ evaluation contracts
on:
pull_request:
push:
branches: [main, 'codex/cpp-type-policy']
workflow_dispatch:
permissions:
contents: read
jobs:
contracts:
runs-on: ubuntu-24.04
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: pip
- name: Native debug fixture compilers
run: sudo apt-get update && sudo apt-get install -y clang lld
- uses: dtolnay/rust-toolchain@stable
- name: Pinned existing CFG dependency
run: |
git clone https://github.com/Noelo-Lab/rust-joern.git ../rust-joern
git -C ../rust-joern checkout 9fd97f50885202596b125ebd2504e64910874bcb
cargo build --release --manifest-path ../rust-joern/Cargo.toml
python -m pip install ../rust-joern
test -f ../rust-joern/target/release/librust_joern.so
- name: Development dependencies
run: python -m pip install -e '.[dev]'
- name: Evaluation and provenance regressions
env:
DECBENCH_NO_CACHE: '1'
RUST_JOERN_LIBRARY: ${{ github.workspace }}/../rust-joern/target/release/librust_joern.so
run: |
python -m pytest --no-cov tests/test_cpp_first_pc_locations.py tests/test_cpp_native_inputs.py tests/test_cpp_toolchain_probe.py tests/test_producer_validation.py tests/test_cpp_type_graph.py tests/test_cpp_review_contracts.py \
tests/test_cpp_ged_identity.py tests/test_cpp_ged_compilation_units.py \
tests/test_recompiler_arch.py tests/test_byte_match_fixup_policy.py \
tests/test_metric_function_identity.py \
tests/test_cpp_support.py tests/test_cpp_identity_backends.py \
tests/test_cpp_identity_deep_validation.py tests/test_cpp_identity_end_to_end.py \
tests/test_cpp_identity_optimized_dwarf.py tests/test_cpp_identity_progress.py \
tests/test_cpp_identity_thumb.py tests/test_function_identity.py \
tests/test_cpp_identity_icf.py tests/test_cpp_identity_slice_invariance.py \
tests/test_type_match_correspondence.py tests/test_provenance_sanitizer.py \
tests/test_raw_line_provenance.py
- name: New policy code style
run: |
black --check tests/test_cpp_first_pc_locations.py
ruff check tests/test_cpp_first_pc_locations.py
black --check scripts/audit_cpp_toolchains.py tests/test_cpp_native_inputs.py tests/test_cpp_toolchain_probe.py decbench/models/decompilation.py decbench/decompilers/raw/angr_raw.py decbench/decompilers/raw/ghidra_raw.py decbench/decompilers/raw/kuna_raw.py decbench/utils/producer_validation.py tests/test_producer_validation.py decbench/utils/cfg_identity.py decbench/pipeline/cpp_ged.py \
scripts/evaluate_cpp_ged.py tests/test_cpp_ged_identity.py \
decbench/utils/compilation_units.py tests/test_cpp_ged_compilation_units.py \
decbench/metrics/variable_features.py \
decbench/utils/binfmt.py decbench/metrics/byte_match.py tests/test_recompiler_arch.py \
decbench/metrics/cpp_type_graph.py decbench/metrics/cpp_recovered_types.py \
decbench/metrics/cpp_types.py decbench/metrics/cpp_type_match.py \
decbench/utils/pdb_info.py decbench/decompilers/raw/fission_raw.py \
tests/test_cpp_type_graph.py tests/test_cpp_review_contracts.py
ruff check scripts/audit_cpp_toolchains.py tests/test_cpp_native_inputs.py tests/test_cpp_toolchain_probe.py decbench/models/decompilation.py decbench/decompilers/raw/angr_raw.py decbench/decompilers/raw/ghidra_raw.py decbench/decompilers/raw/kuna_raw.py decbench/utils/producer_validation.py tests/test_producer_validation.py decbench/utils/cfg_identity.py decbench/pipeline/cpp_ged.py \
scripts/evaluate_cpp_ged.py tests/test_cpp_ged_identity.py \
decbench/utils/compilation_units.py tests/test_cpp_ged_compilation_units.py \
decbench/metrics/variable_features.py \
decbench/utils/binfmt.py decbench/metrics/byte_match.py tests/test_recompiler_arch.py \
decbench/metrics/cpp_type_graph.py decbench/metrics/cpp_recovered_types.py \
decbench/metrics/cpp_types.py decbench/metrics/cpp_type_match.py \
decbench/utils/pdb_info.py decbench/decompilers/raw/fission_raw.py \
tests/test_cpp_type_graph.py tests/test_cpp_review_contracts.py
- name: New policy type contracts
run: |
mypy --follow-imports=silent scripts/audit_cpp_toolchains.py decbench/models/decompilation.py decbench/utils/producer_validation.py decbench/utils/cfg_identity.py \
decbench/utils/compilation_units.py \
decbench/pipeline/cpp_ged.py decbench/metrics/cpp_type_graph.py \
decbench/metrics/cpp_recovered_types.py decbench/metrics/cpp_types.py \
decbench/metrics/cpp_type_match.py
6 changes: 0 additions & 6 deletions decbench/decompilers/external.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,6 @@ def decompile_binary(


EXTERNAL_DECOMPILERS: tuple[ExternalSpec, ...] = (
ExternalSpec(
id="fission",
display_name="Fission",
url="https://github.com/fission-systems/Fission",
version="0.2.3",
),
ExternalSpec(
id="ventris",
display_name="Ventris",
Expand Down
10 changes: 10 additions & 0 deletions decbench/decompilers/provenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ def _hydrate_additive_provenance(
) -> None:
"""Hydrate additive fields absent from legacy pickled model instances."""
for mapping in function.line_mappings:
if not hasattr(mapping, "defined_variables"):
mapping.defined_variables = None
report.increment("legacy_additive_fields_hydrated")
if not isinstance(getattr(mapping, "addresses", None), list):
mapping.addresses = []
report.increment("legacy_additive_fields_hydrated")
Expand Down Expand Up @@ -179,6 +182,13 @@ def _sanitize_function(
sanitized_mappings = []
report.increment("line_mapping_rows_seen", len(function.line_mappings))
for mapping in function.line_mappings:
if mapping.defined_variables is not None and not 1 <= mapping.line_number <= len(
function.decompiled_code.splitlines()
):
modified = True
report.increment("line_mapping_rows_dropped")
report.record_address_drop("line_outside_output")
continue
addresses = _filter_addresses(
mapping.addresses,
code=code,
Expand Down
2 changes: 2 additions & 0 deletions decbench/decompilers/raw/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
angr_raw, # noqa: F401
binja_raw, # noqa: F401
dewolf_raw, # noqa: F401
fission_raw, # noqa: F401
ghidra_raw, # noqa: F401
glaurung_raw, # noqa: F401
ida_raw, # noqa: F401
Expand All @@ -35,4 +36,5 @@
"dewolf_raw",
"manifold_raw",
"glaurung_raw",
"fission_raw",
]
7 changes: 6 additions & 1 deletion decbench/decompilers/raw/angr_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
DecompilerMetadata,
FunctionDecompilation,
LineMapping,
ProducerLanguageContract,
VariableInfo,
)
from decbench.utils.function_identity import insert_function

_l = logging.getLogger(__name__)

Expand Down Expand Up @@ -141,7 +143,7 @@ def _dump() -> None:
_l.debug("angr-raw: failed to decompile %s: %s", func_name, e)

if func_result is not None:
decompiled_functions[func_name] = func_result
insert_function(decompiled_functions, func_result)
else:
failed_functions.append(func_name)
_dump()
Expand Down Expand Up @@ -264,6 +266,9 @@ def _decompile_one(
function_name=func_name,
)
metadata = common.extract_metrics(code)
metadata["output_contract"] = ProducerLanguageContract(
surface="c-like-pseudocode", declarations="partial", dialect="angr-c"
).model_dump()

return FunctionDecompilation(
name=func_name,
Expand Down
7 changes: 4 additions & 3 deletions decbench/decompilers/raw/binja_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
LineMapping,
VariableInfo,
)
from decbench.utils.function_identity import insert_function

_l = logging.getLogger(__name__)

Expand Down Expand Up @@ -149,8 +150,8 @@ def _dump() -> None:
bv = self._load(binary_path)
enumerated = self._enumerate(bv, elf_base, text_range, addr_targets)
if functions is not None:
requested = {n for (n, _a) in functions}
enumerated = [(n, a) for (n, a) in enumerated if n in requested]
requested_addrs = {a for (_n, a) in functions}
enumerated = [(n, a) for (n, a) in enumerated if a in requested_addrs]
enumerated = common.narrow_to_source(
enumerated,
function_names,
Expand All @@ -170,7 +171,7 @@ def _dump() -> None:
except Exception as e: # noqa: BLE001
_l.debug("binja-raw: failed to decompile %s: %s", func_name, e)
if func_result is not None:
decompiled_functions[func_name] = func_result
insert_function(decompiled_functions, func_result)
else:
failed_functions.append(func_name)
_dump()
Expand Down
6 changes: 6 additions & 0 deletions decbench/decompilers/raw/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ def elf_min_vaddr(binary_path: Path) -> int:
if base is not None:
return base
return 0
from decbench.utils import binfmt

info = binfmt.detect(binary_path)
if info is not None and info.fmt == "macho":
base = binfmt.mach_o_image_base(binary_path)
return base if base is not None else 0
with open(binary_path, "rb") as f:
elf = ELFFile(f)
vaddrs = [seg["p_vaddr"] for seg in elf.iter_segments() if seg["p_type"] == "PT_LOAD"]
Expand Down
3 changes: 2 additions & 1 deletion decbench/decompilers/raw/dewolf_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
FunctionDecompilation,
VariableInfo,
)
from decbench.utils.function_identity import insert_function

_l = logging.getLogger(__name__)

Expand Down Expand Up @@ -291,7 +292,7 @@ def _consume(addrs_arg: str) -> None:
metadata=common.extract_metrics(code),
)
with lock:
decompiled_functions[name] = fd
insert_function(decompiled_functions, fd)
_dump()
elif kind == "fail":
with lock:
Expand Down
Loading