From 17658dfceb6e838e8c8b6b1443ee1f375179fe9c Mon Sep 17 00:00:00 2001 From: Bogdan-Alexandru Stoica Date: Wed, 18 Feb 2026 16:17:20 -0600 Subject: [PATCH 1/7] [arteval-bench] feat: adding a static copy of DepSurf (EuroSys'25) --- .../eurosys25_depsurf/_agent_eval/main.py | 184 ++ .../eurosys25_depsurf/depsurf/00_deps.ipynb | 180 ++ .../eurosys25_depsurf/depsurf/10_links.ipynb | 338 +++ .../depsurf/11_download.ipynb | 262 ++ .../depsurf/20_dataset.ipynb | 610 +++++ .../eurosys25_depsurf/depsurf/30_diff.ipynb | 2217 +++++++++++++++++ .../eurosys25_depsurf/depsurf/35_src.ipynb | 583 +++++ .../depsurf/36_breakdown.ipynb | 294 +++ .../eurosys25_depsurf/depsurf/39_config.ipynb | 298 +++ .../eurosys25_depsurf/depsurf/40_inline.ipynb | 782 ++++++ .../depsurf/41_transform.ipynb | 533 ++++ .../eurosys25_depsurf/depsurf/42_dup.ipynb | 322 +++ .../depsurf/50_programs.ipynb | 177 ++ .../eurosys25_depsurf/depsurf/51_plot.ipynb | 375 +++ .../depsurf/52_summary.ipynb | 1795 +++++++++++++ .../depsurf/60_website.ipynb | 300 +++ .../eurosys25_depsurf/depsurf/LICENSE | 21 + .../eurosys25_depsurf/depsurf/README.md | 129 + .../depsurf/archive/.clang-format | 2 + .../depsurf/archive/55_category.ipynb | 206 ++ .../depsurf/archive/91_test_diff.ipynb | 966 +++++++ .../depsurf/archive/92_test_sections.ipynb | 1029 ++++++++ .../depsurf/archive/93_test_funcs.ipynb | 2025 +++++++++++++++ .../depsurf/archive/95_test_relo.ipynb | 93 + .../depsurf/archive/README.md | 3 + .../depsurf/archive/depsurf/bpftool.py | 18 + .../depsurf/archive/depsurf/relo.py | 299 +++ .../depsurf/archive/test-bpf/.gitignore | 3 + .../depsurf/archive/test-bpf/CMakeLists.txt | 78 + .../depsurf/archive/test-bpf/Makefile | 15 + .../depsurf/archive/test-bpf/README.md | 44 + .../depsurf/archive/test-bpf/ebpf.bpf.c | 106 + .../depsurf/archive/test-bpf/ebpf.cpp | 104 + .../archive/test-bpf/tests/count.bpf.c | 35 + .../archive/test-bpf/tests/dents.bpf.c | 65 + .../archive/test-bpf/tests/fault.bpf.c | 145 ++ .../archive/test-bpf/tests/helper.bpf.c | 34 + .../depsurf/archive/test-bpf/tests/hex_dump.h | 12 + .../archive/test-bpf/tests/relocation.bpf.c | 16 + .../depsurf/archive/vm/.gitignore | 2 + .../depsurf/archive/vm/Makefile | 24 + .../depsurf/archive/vm/distro/README.md | 13 + .../depsurf/archive/vm/distro/prep.py | 155 ++ .../depsurf/archive/vm/distro/run.py | 74 + .../depsurf/archive/vm/distro/ssh.py | 21 + .../depsurf/archive/vm/init.c | 67 + .../eurosys25_depsurf/depsurf/data/.gitignore | 3 + .../depsurf/depsurf/__init__.py | 22 + .../depsurf/depsurf/bpf_program.py | 611 +++++ .../depsurf/depsurf/btf/__init__.py | 4 + .../depsurf/depsurf/btf/bpftool.patch | 13 + .../depsurf/depsurf/btf/bpftool.py | 30 + .../depsurf/depsurf/btf/dump.py | 207 ++ .../depsurf/depsurf/btf/kind.py | 24 + .../depsurf/depsurf/btf/types.py | 47 + .../eurosys25_depsurf/depsurf/depsurf/dep.py | 152 ++ .../depsurf/depsurf/diff/__init__.py | 7 + .../depsurf/depsurf/diff/change.py | 148 ++ .../depsurf/depsurf/diff/diff_common.py | 14 + .../depsurf/depsurf/diff/diff_config.py | 7 + .../depsurf/depsurf/diff/diff_enum.py | 34 + .../depsurf/depsurf/diff/diff_func.py | 56 + .../depsurf/depsurf/diff/diff_struct.py | 52 + .../depsurf/depsurf/diff/diff_tracepoint.py | 32 + .../depsurf/depsurf/funcs/__init__.py | 6 + .../depsurf/depsurf/funcs/dwarf.py | 156 ++ .../depsurf/depsurf/funcs/dwarf_dump.py | 220 ++ .../depsurf/depsurf/funcs/entry.py | 59 + .../depsurf/depsurf/funcs/group.py | 176 ++ .../depsurf/depsurf/funcs/groups.py | 73 + .../depsurf/depsurf/funcs/symbol.py | 68 + .../depsurf/depsurf/issues.py | 90 + .../depsurf/depsurf/linux/__init__.py | 8 + .../depsurf/depsurf/linux/comment.py | 20 + .../depsurf/depsurf/linux/config.py | 32 + .../depsurf/depsurf/linux/extract.py | 48 + .../depsurf/depsurf/linux/filebytes.py | 122 + .../depsurf/depsurf/linux/struct.py | 55 + .../depsurf/depsurf/linux/symtab.py | 66 + .../depsurf/depsurf/linux/syscalls.py | 72 + .../depsurf/depsurf/linux/tracepoint.py | 143 ++ .../depsurf/depsurf/linux_image.py | 164 ++ .../depsurf/depsurf/paths.py | 9 + .../eurosys25_depsurf/depsurf/depsurf/prep.py | 118 + .../depsurf/depsurf/report.py | 347 +++ .../depsurf/depsurf/utils/__init__.py | 4 + .../depsurf/depsurf/utils/color.py | 13 + .../depsurf/depsurf/utils/decorator.py | 39 + .../depsurf/depsurf/utils/enum.py | 34 + .../depsurf/depsurf/utils/system.py | 19 + .../depsurf/depsurf/version.py | 179 ++ .../depsurf/depsurf/version_group.py | 119 + .../depsurf/depsurf/version_pair.py | 110 + .../eurosys25_depsurf/depsurf/pyproject.toml | 15 + .../depsurf/utils/__init__.py | 6 + .../eurosys25_depsurf/depsurf/utils/consts.py | 17 + .../Inconsolata_ExtraCondensed-Medium.ttf | Bin 0 -> 101928 bytes .../eurosys25_depsurf/depsurf/utils/paths.py | 16 + .../depsurf/utils/utils_latex.py | 118 + .../depsurf/utils/utils_matplotlib.py | 86 + .../depsurf/utils/utils_pandas.py | 17 + .../depsurf/utils/utils_pickle.py | 20 + 102 files changed, 19381 insertions(+) create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/main.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/00_deps.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/10_links.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/11_download.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/20_dataset.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/30_diff.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/35_src.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/36_breakdown.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/39_config.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/40_inline.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/41_transform.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/42_dup.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/50_programs.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/51_plot.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/52_summary.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/60_website.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/LICENSE create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/README.md create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/.clang-format create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/55_category.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/91_test_diff.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/92_test_sections.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/93_test_funcs.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/95_test_relo.ipynb create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/README.md create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/depsurf/bpftool.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/depsurf/relo.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/.gitignore create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/CMakeLists.txt create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/Makefile create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/README.md create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/ebpf.bpf.c create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/ebpf.cpp create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/count.bpf.c create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/dents.bpf.c create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/fault.bpf.c create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/helper.bpf.c create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/hex_dump.h create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/relocation.bpf.c create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/.gitignore create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/Makefile create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/README.md create mode 100755 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/prep.py create mode 100755 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/run.py create mode 100755 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/ssh.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/init.c create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/data/.gitignore create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/__init__.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/bpf_program.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/__init__.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/bpftool.patch create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/bpftool.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/dump.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/kind.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/types.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/dep.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/__init__.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/change.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_common.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_config.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_enum.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_func.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_struct.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_tracepoint.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/__init__.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/dwarf.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/dwarf_dump.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/entry.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/group.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/groups.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/symbol.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/issues.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/__init__.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/comment.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/config.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/extract.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/filebytes.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/struct.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/symtab.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/syscalls.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/tracepoint.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux_image.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/paths.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/prep.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/report.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/__init__.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/color.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/decorator.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/enum.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/system.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version_group.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version_pair.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/pyproject.toml create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/__init__.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/consts.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/fonts/Inconsolata_ExtraCondensed-Medium.ttf create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/paths.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_latex.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_matplotlib.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_pandas.py create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_pickle.py diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/main.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/main.py new file mode 100644 index 00000000..e36644af --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/main.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +"""Runs environment setup, build, benchmark prep, and experiment runs checks for DepSurf.""" + +from __future__ import annotations + +from pathlib import Path +from typing import Dict +import os +import sys + +from evaluator.utils import ( + EntryConfig, + LoggerConfig, + get_logger, + record_result, +) +from oracle_artifact_build import OracleArtifactBuild +from oracle_env_setup import OracleEnvSetup +from oracle_benchmark_prep import OracleBenchmarkPrep +from oracle_experiment_runs import OracleExperimentRuns + + +def _resolve_workspace_paths() -> tuple[Path, Path]: + """Resolve and validate _agent_eval/ and DepSurf/ locations. + This expectes that either: + (1) _agent_eval/ and DepSurf/ are located in the same root directory; or + (2) _AGENT_EVAL_DIR and _DEPSURF_HOME are set by the user + """ + try: + env_agent_eval = os.environ.get("_AGENT_EVAL_DIR") + env_depsurf_home = os.environ.get("_DEPSURF_HOME") + + if env_agent_eval: + agent_eval_dir = Path(env_agent_eval).expanduser().resolve() + else: + agent_eval_dir = Path(__file__).resolve().parent + + if env_depsurf_home: + depsurf_home = Path(env_depsurf_home).expanduser().resolve() + else: + depsurf_home = agent_eval_dir.parent.resolve() + + if not agent_eval_dir.exists() or not agent_eval_dir.is_dir(): + raise RuntimeError( + f"Invalid _agent_eval dir: {agent_eval_dir}\n" + f"This runner expects _agent_eval/ and DepSurf/ to be located in the same root directory.\n" + f"Set _AGENT_EVAL_DIR to the directory containing main.py if needed.") + + depsurf_repo_root = depsurf_home / "DepSurf" + if not depsurf_repo_root.exists() or not depsurf_repo_root.is_dir(): + raise RuntimeError( + f"Invalid DepSurf workspace: {depsurf_home}\n" + f"Expected to find a 'DepSurf/' directory at: {depsurf_repo_root}\n" + f"This runner expects _agent_eval/ and DepSurf/ to be located in the same root directory.\n" + f"Set _DEPSURF_HOME to the workspace root if needed.") + + workspace_root = depsurf_home + return agent_eval_dir, workspace_root + + except OSError as exc: + raise RuntimeError(f"Failed to resolve workspace paths: {exc}") from exc + + +def _build_depsurf_config(*, agent_eval_dir: Path, + workspace_root: Path) -> EntryConfig: + """Constructs EntryConfig for the DepSurf evaluation bundle from resolved paths.""" + depsurf_repo = (workspace_root / "DepSurf").resolve() + depsurf_agent_eval = agent_eval_dir.resolve() + depsurf_refs = (depsurf_agent_eval / "refs").resolve() + depsurf_results = (depsurf_repo / "results").resolve() + + return EntryConfig( + name="depsurf", + home_dir=workspace_root, + repository_paths={ + "depsurf": depsurf_repo, + }, + results_paths={ + "39_config": depsurf_results / "39_config.csv", + "50_programs": depsurf_results / "50_programs.csv", + "52_summary_table7": depsurf_results / "52_summary_table7.csv", + "52_summary_table8": depsurf_results / "52_summary_table8.csv", + }, + ground_truth_paths={ + "39_config": depsurf_refs / "39_config.csv", + "50_programs": depsurf_refs / "50_programs.csv", + "52_summary_table7": depsurf_refs / "52_summary_table7.csv", + "52_summary_table8": depsurf_refs / "52_summary_table8.csv", + }, + metadata={ + # Dataset main directory, relative to the DepSurf root + "dataset_relpath": "data/dataset", + # Required subdirectories in the dataset main directory + "dataset_subdirs": [ + "comment", + "config", + "func_groups", + "symtab", + "syscalls", + "tracepoints", + "types_enum", + "types_func", + "types_int", + "types_struct", + "types_union", + ], + # Required files in the dataset (base names only) + "dataset_basenames": [ + "4.10.0-19-generic-amd64", + "4.13.0-16-generic-amd64", + "4.15.0-20-generic-amd64", + "4.18.0-10-generic-amd64", + "4.4.0-21-generic-amd64", + "4.8.0-22-generic-amd64", + "5.0.0-13-generic-amd64", + "5.11.0-16-generic-amd64", + "5.13.0-19-generic-amd64", + "5.15.0-25-generic-amd64", + "5.19.0-21-generic-amd64", + "5.3.0-18-generic-amd64", + "5.4.0-1009-aws-amd64", + "5.4.0-1009-gcp-amd64", + "5.4.0-1010-azure-amd64", + "5.4.0-24-generic-riscv64", + "5.4.0-26-generic-amd64", + "5.4.0-26-generic-arm64", + "5.4.0-26-generic-armhf", + "5.4.0-26-generic-ppc64el", + "5.4.0-26-lowlatency-amd64", + "5.8.0-25-generic-amd64", + "6.2.0-20-generic-amd64", + "6.5.0-9-generic-amd64", + "6.8.0-31-generic-amd64", + ], + # Optional. Leave empty to use " OR .*" existence policy. + # If later you confirm each subdir has a fixed extension, populate this mapping. + "dataset_subdir_suffixes": {}, + }, + similarity_ratio=0.75, + ) + + +def main(argv: list[str]) -> int: + verbose = "--verbose" in argv + + results: Dict[str, int] = {} + score = 0 + + logger_name = os.environ.get("EVAL_LOGGER_NAME", "DEPSURF-AGENT-EVALUATOR") + logger = get_logger(LoggerConfig(root_name=logger_name)) + + try: + agent_eval_dir, workspace_root = _resolve_workspace_paths() + DEPSURF_CONFIG = _build_depsurf_config(agent_eval_dir=agent_eval_dir, + workspace_root=workspace_root) + except RuntimeError as exc: + raise SystemExit(str(exc)) from exc + + env_checker = OracleEnvSetup(config=DEPSURF_CONFIG, logger=logger) + score += record_result(results, + type(env_checker).__name__, + env_checker.run(verbose=verbose)) + + build_checker = OracleArtifactBuild(config=DEPSURF_CONFIG, logger=logger) + score += record_result(results, + type(build_checker).__name__, + build_checker.run(verbose=verbose)) + + prep_checker = OracleBenchmarkPrep(config=DEPSURF_CONFIG, logger=logger) + score += record_result(results, + type(prep_checker).__name__, + prep_checker.run(verbose=verbose)) + + runs_checker = OracleExperimentRuns(config=DEPSURF_CONFIG, logger=logger) + score += record_result(results, + type(runs_checker).__name__, + runs_checker.run(verbose=verbose)) + + logger.info("Agent scores: %s", results) + return score + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/00_deps.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/00_deps.ipynb new file mode 100644 index 00000000..1921133f --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/00_deps.ipynb @@ -0,0 +1,180 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Install Dependencies" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook is used to install the dependencies for DepSurf." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hit:1 http://ports.ubuntu.com/ubuntu-ports jammy InRelease\n", + "Hit:2 http://ports.ubuntu.com/ubuntu-ports jammy-updates InRelease\n", + "Hit:3 http://ports.ubuntu.com/ubuntu-ports jammy-security InRelease\n", + "Reading package lists... Done\n", + "Building dependency tree... Done\n", + "Reading state information... Done\n", + "7 packages can be upgraded. Run 'apt list --upgradable' to see them.\n", + "Reading package lists... Done\n", + "Building dependency tree... Done\n", + "Reading state information... Done\n", + "Note, selecting 'binutils-dev' instead of 'libbfd-dev'\n", + "build-essential is already the newest version (12.9ubuntu3).\n", + "libelf-dev is already the newest version (0.186-1build1).\n", + "make is already the newest version (4.3-4.1build1).\n", + "patch is already the newest version (2.7.6-7build2).\n", + "pkg-config is already the newest version (0.29.2-1ubuntu3).\n", + "clang is already the newest version (1:14.0-55~exp2).\n", + "llvm is already the newest version (1:14.0-55~exp2).\n", + "binutils-dev is already the newest version (2.38-4ubuntu2.6).\n", + "libcap-dev is already the newest version (1:2.44-1ubuntu0.22.04.1).\n", + "pahole is already the newest version (1.25-0ubuntu1~22.04.2).\n", + "0 upgraded, 0 newly installed, 0 to remove and 7 not upgraded.\n" + ] + } + ], + "source": [ + "!sudo apt update\n", + "!sudo apt install make patch libelf-dev libbfd-dev libcap-dev clang llvm pkg-config pahole build-essential -y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following commands are used to patch, build, and install bpftool." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from depsurf import BPFTOOL_SRC_PATH, BPFTOOL_PATCH_PATH, BPFTOOL_BIN_PATH" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "patching file gen.c\n" + ] + } + ], + "source": [ + "!patch --forward --directory={BPFTOOL_SRC_PATH} < {BPFTOOL_PATCH_PATH}" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "make: Entering directory '/Users/szhong/Code/DepSurf/depsurf/btf/bpftool/src'\n", + "... libbfd: [ \u001b[32mon\u001b[m ]\n", + "... clang-bpf-co-re: [ \u001b[32mon\u001b[m ]\n", + "... llvm: [ \u001b[32mon\u001b[m ]\n", + "... libcap: [ \u001b[32mon\u001b[m ]\n", + " CC gen.o\n", + " CC /Users/szhong/Code/DepSurf/depsurf/btf/bpftool/src/bootstrap/gen.o\n", + " LINK /Users/szhong/Code/DepSurf/depsurf/btf/bpftool/src/bootstrap/bpftool\n", + " GEN vmlinux.h\n", + " CLANG pid_iter.bpf.o\n", + " GEN pid_iter.skel.h\n", + " CC pids.o\n", + " CLANG profiler.bpf.o\n", + " GEN profiler.skel.h\n", + " CC prog.o\n", + " LINK bpftool\n", + "make: Leaving directory '/Users/szhong/Code/DepSurf/depsurf/btf/bpftool/src'\n" + ] + } + ], + "source": [ + "!make -C {BPFTOOL_SRC_PATH} bpftool" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HEAD is now at c428db1 sync: Pull latest bpftool changes from kernel\n" + ] + } + ], + "source": [ + "!git -C {BPFTOOL_SRC_PATH} reset --hard" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bpftool v7.5.0\n", + "using libbpf v1.5\n", + "features: llvm, skeletons\n" + ] + } + ], + "source": [ + "!{BPFTOOL_BIN_PATH} --version" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/10_links.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/10_links.ipynb new file mode 100644 index 00000000..6a03c4a5 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/10_links.ipynb @@ -0,0 +1,338 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Gather Links\n", + "\n", + "This notebook collects the links to the Linux kernel packages for different Ubuntu versions.\n", + "\n", + "Note: You can safely **skip this notebook**, and refer to the output for links." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first use launchpadlib to get the API endpoints for Ubuntu 16.04 to 24.04. See https://api.launchpad.net/1.0/ for API reference." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "metadata": {} + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "24.04 https://api.launchpad.net/1.0/ubuntu/noble\n", + "23.10 https://api.launchpad.net/1.0/ubuntu/mantic\n", + "23.04 https://api.launchpad.net/1.0/ubuntu/lunar\n", + "22.10 https://api.launchpad.net/1.0/ubuntu/kinetic\n", + "22.04 https://api.launchpad.net/1.0/ubuntu/jammy\n", + "21.10 https://api.launchpad.net/1.0/ubuntu/impish\n", + "21.04 https://api.launchpad.net/1.0/ubuntu/hirsute\n", + "20.10 https://api.launchpad.net/1.0/ubuntu/groovy\n", + "20.04 https://api.launchpad.net/1.0/ubuntu/focal\n", + "19.10 https://api.launchpad.net/1.0/ubuntu/eoan\n", + "19.04 https://api.launchpad.net/1.0/ubuntu/disco\n", + "18.10 https://api.launchpad.net/1.0/ubuntu/cosmic\n", + "18.04 https://api.launchpad.net/1.0/ubuntu/bionic\n", + "17.10 https://api.launchpad.net/1.0/ubuntu/artful\n", + "17.04 https://api.launchpad.net/1.0/ubuntu/zesty\n", + "16.10 https://api.launchpad.net/1.0/ubuntu/yakkety\n", + "16.04 https://api.launchpad.net/1.0/ubuntu/xenial\n" + ] + } + ], + "source": [ + "from launchpadlib.launchpad import Launchpad \n", + "\n", + "lp = Launchpad.login_anonymously(\"ubuntu-build-list\", \"production\")\n", + "ubuntu = lp.distributions[\"ubuntu\"] # type: ignore\n", + "archive = ubuntu.main_archive\n", + "\n", + "series = {\n", + " s.version: s\n", + " for s in ubuntu.series\n", + " if (16, 4) <= tuple(int(part) for part in s.version.split(\".\")) <= (24, 4)\n", + "}\n", + "for v, s in series.items():\n", + " print(v, s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following function is defined to gather the source URL and the binary URLs for a given Ubuntu series." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "metadata": {} + }, + "outputs": [], + "source": [ + "import re\n", + "from pathlib import Path\n", + "from typing import Optional, List\n", + "from dataclasses import dataclass\n", + "\n", + "\n", + "@dataclass(frozen=True)\n", + "class SourceInfo:\n", + " source_url: str\n", + " binary_urls: List[str]\n", + "\n", + "\n", + "def get_source_info(\n", + " distro_series,\n", + " source_name: str = \"linux\",\n", + " pocket: str = \"Release\",\n", + " arch: Optional[str] = None,\n", + " flavor: Optional[str] = None,\n", + ") -> SourceInfo:\n", + " published_sources = archive.getPublishedSources(\n", + " exact_match=True,\n", + " source_name=source_name,\n", + " distro_series=distro_series,\n", + " pocket=pocket,\n", + " order_by_date=True,\n", + " )\n", + "\n", + " source_url_prefix = f\"https://launchpad.net/ubuntu/+source/{source_name}\"\n", + "\n", + " if len(published_sources) == 0:\n", + " return SourceInfo(source_url=source_url_prefix, binary_urls=[])\n", + "\n", + " versions = [\n", + " tuple(int(part) for part in re.split(r\"-|\\.|\\+\", s.source_package_version))\n", + " for s in published_sources\n", + " ]\n", + " if max(versions) != versions[0]:\n", + " raise ValueError(f\"The latest version is not the first: {versions}\")\n", + "\n", + " source = published_sources[0]\n", + " binary_urls = []\n", + " for url in source.binaryFileUrls():\n", + " path = Path(url)\n", + " if path.suffix != \".ddeb\":\n", + " continue\n", + " if not path.stem.startswith(\"linux-image\"):\n", + " continue\n", + " if arch is not None and not path.stem.endswith(arch):\n", + " continue\n", + " if flavor is not None and flavor not in path.stem:\n", + " continue\n", + " binary_urls.append(url)\n", + " return SourceInfo(\n", + " source_url=f\"{source_url_prefix}/{source.source_package_version}\",\n", + " binary_urls=binary_urls,\n", + " )\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first list the binary URLs for x86 generic kernels.\n", + "\n", + "Ref: https://launchpad.net/ubuntu/+source/linux/[version]\n", + "\n", + "For example, https://launchpad.net/ubuntu/+source/linux/5.4.0-26.30 is the kernel package for Ubuntu 20.04." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "metadata": {} + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "24.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-generic-dbgsym_6.8.0-31.31_amd64.ddeb\n", + "23.10 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.5.0-9-generic-dbgsym_6.5.0-9.9_amd64.ddeb\n", + "23.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.2.0-20-generic-dbgsym_6.2.0-20.20_amd64.ddeb\n", + "22.10 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.19.0-21-generic-dbgsym_5.19.0-21.21_amd64.ddeb\n", + "22.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.15.0-25-generic-dbgsym_5.15.0-25.25_amd64.ddeb\n", + "21.10 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.13.0-19-generic-dbgsym_5.13.0-19.19_amd64.ddeb\n", + "21.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.11.0-16-generic-dbgsym_5.11.0-16.17_amd64.ddeb\n", + "20.10 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.8.0-25-generic-dbgsym_5.8.0-25.26_amd64.ddeb\n", + "20.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_amd64.ddeb\n", + "19.10 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.3.0-18-generic-dbgsym_5.3.0-18.19_amd64.ddeb\n", + "19.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.0.0-13-generic-dbgsym_5.0.0-13.14_amd64.ddeb\n", + "18.10 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-4.18.0-10-generic-dbgsym_4.18.0-10.11_amd64.ddeb\n", + "18.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-4.15.0-20-generic-dbgsym_4.15.0-20.21_amd64.ddeb\n", + "17.10 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.13.0-16-generic-dbgsym_4.13.0-16.19_amd64.ddeb\n", + "17.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.10.0-19-generic-dbgsym_4.10.0-19.21_amd64.ddeb\n", + "16.10 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.8.0-22-generic-dbgsym_4.8.0-22.24_amd64.ddeb\n", + "16.04 https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.4.0-21-generic-dbgsym_4.4.0-21.37_amd64.ddeb\n" + ] + } + ], + "source": [ + "for s in series.values():\n", + " info = get_source_info(s, arch=\"amd64\", flavor=\"generic\")\n", + " assert len(info.binary_urls) == 1, info.binary_urls\n", + " print(s.version, info.binary_urls[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following list different [kernel variants](https://ubuntu.com/kernel/variants) for different Ubuntu 20.04 and 24.04.\n", + "\n", + "Ref: https://launchpad.net/ubuntu/+source/[source_name]\n", + "\n", + "For example, https://launchpad.net/ubuntu/+source/linux-aws is the kernel package for AWS." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "metadata": {} + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-------------------------------------20.04--------------------------------------\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "linux https://launchpad.net/ubuntu/+source/linux/5.4.0-26.30\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_s390x.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_ppc64el.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-lowlatency-dbgsym_5.4.0-26.30_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_arm64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-26-generic-dbgsym_5.4.0-26.30_armhf.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-26-generic-lpae-dbgsym_5.4.0-26.30_armhf.ddeb\n", + "linux-aws https://launchpad.net/ubuntu/+source/linux-aws/5.4.0-1009.9\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-1009-aws-dbgsym_5.4.0-1009.9_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-1009-aws-dbgsym_5.4.0-1009.9_arm64.ddeb\n", + "linux-azure https://launchpad.net/ubuntu/+source/linux-azure/5.4.0-1010.10\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-1010-azure-dbgsym_5.4.0-1010.10_amd64.ddeb\n", + "linux-gcp https://launchpad.net/ubuntu/+source/linux-gcp/5.4.0-1009.9\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-1009-gcp-dbgsym_5.4.0-1009.9_amd64.ddeb\n", + "linux-oracle https://launchpad.net/ubuntu/+source/linux-oracle/5.4.0-1009.9\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-1009-oracle-dbgsym_5.4.0-1009.9_amd64.ddeb\n", + "linux-gke https://launchpad.net/ubuntu/+source/linux-gke\n", + "linux-ibm https://launchpad.net/ubuntu/+source/linux-ibm\n", + "linux-riscv https://launchpad.net/ubuntu/+source/linux-riscv/5.4.0-24.28\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-24-generic-dbgsym_5.4.0-24.28_riscv64.ddeb\n", + "linux-raspi https://launchpad.net/ubuntu/+source/linux-raspi/5.4.0-1008.8\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-1008-raspi-dbgsym_5.4.0-1008.8_armhf.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-1008-raspi-dbgsym_5.4.0-1008.8_arm64.ddeb\n", + "linux-lowlatency https://launchpad.net/ubuntu/+source/linux-lowlatency\n", + "linux-kvm https://launchpad.net/ubuntu/+source/linux-kvm/5.4.0-1009.9\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-1009-kvm-dbgsym_5.4.0-1009.9_amd64.ddeb\n", + "linux-laptop https://launchpad.net/ubuntu/+source/linux-laptop\n", + "linux-nvidia https://launchpad.net/ubuntu/+source/linux-nvidia\n", + "-------------------------------------24.04--------------------------------------\n", + "linux https://launchpad.net/ubuntu/+source/linux/6.8.0-31.31\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-generic-dbgsym_6.8.0-31.31_s390x.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-6.8.0-31-generic-dbgsym_6.8.0-31.31_ppc64el.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-6.8.0-31-generic-dbgsym_6.8.0-31.31_armhf.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-generic-dbgsym_6.8.0-31.31_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-generic-64k-dbgsym_6.8.0-31.31_arm64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-generic-dbgsym_6.8.0-31.31_arm64.ddeb\n", + "linux-aws https://launchpad.net/ubuntu/+source/linux-aws/6.8.0-1008.8\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1008-aws-dbgsym_6.8.0-1008.8_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1008-aws-dbgsym_6.8.0-1008.8_arm64.ddeb\n", + "linux-azure https://launchpad.net/ubuntu/+source/linux-azure/6.8.0-1007.7\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1007-azure-dbgsym_6.8.0-1007.7_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1007-azure-dbgsym_6.8.0-1007.7_arm64.ddeb\n", + "linux-gcp https://launchpad.net/ubuntu/+source/linux-gcp/6.8.0-1007.7\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1007-gcp-dbgsym_6.8.0-1007.7_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1007-gcp-dbgsym_6.8.0-1007.7_arm64.ddeb\n", + "linux-oracle https://launchpad.net/ubuntu/+source/linux-oracle/6.8.0-1005.5\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1005-oracle-dbgsym_6.8.0-1005.5_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1005-oracle-64k-dbgsym_6.8.0-1005.5_arm64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1005-oracle-dbgsym_6.8.0-1005.5_arm64.ddeb\n", + "linux-gke https://launchpad.net/ubuntu/+source/linux-gke/6.8.0-1003.5\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1003-gke-dbgsym_6.8.0-1003.5_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1003-gke-dbgsym_6.8.0-1003.5_arm64.ddeb\n", + "linux-ibm https://launchpad.net/ubuntu/+source/linux-ibm/6.8.0-1005.5\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1005-ibm-dbgsym_6.8.0-1005.5_amd64.ddeb\n", + "linux-riscv https://launchpad.net/ubuntu/+source/linux-riscv/6.8.0-31.31.1\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-6.8.0-31-generic-dbgsym_6.8.0-31.31.1_riscv64.ddeb\n", + "linux-raspi https://launchpad.net/ubuntu/+source/linux-raspi/6.8.0-1004.4\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-6.8.0-1004-raspi-dbgsym_6.8.0-1004.4_arm64.ddeb\n", + "linux-lowlatency https://launchpad.net/ubuntu/+source/linux-lowlatency/6.8.0-31.31.1\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-lowlatency-dbgsym_6.8.0-31.31.1_amd64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-lowlatency-64k-dbgsym_6.8.0-31.31.1_arm64.ddeb\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-lowlatency-dbgsym_6.8.0-31.31.1_arm64.ddeb\n", + "linux-kvm https://launchpad.net/ubuntu/+source/linux-kvm\n", + "linux-laptop https://launchpad.net/ubuntu/+source/linux-laptop/6.5.0-1004.7\n", + " - https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-6.5.0-1004-laptop-dbgsym_6.5.0-1004.7_arm64.ddeb\n", + "linux-nvidia https://launchpad.net/ubuntu/+source/linux-nvidia\n" + ] + } + ], + "source": [ + "for s in [\"20.04\", \"24.04\"]:\n", + " print(f\"{s:-^80}\")\n", + " for source in [\n", + " # The default linux\n", + " \"linux\",\n", + " # Cloud-optimized kernels: https://ubuntu.com/blog/cloud-optimized-linux-kernels\n", + " \"linux-aws\",\n", + " \"linux-azure\",\n", + " \"linux-gcp\",\n", + " \"linux-oracle\",\n", + " \"linux-gke\",\n", + " \"linux-ibm\",\n", + " # Other flavors\n", + " \"linux-riscv\",\n", + " \"linux-raspi\",\n", + " \"linux-lowlatency\", # Used to be part of `linux`\n", + " \"linux-kvm\", # No debug symbols, discontinued after 22.04\n", + " \"linux-laptop\", # New in 24.04, arm64 only\n", + " \"linux-nvidia\", # New in 22.04\n", + " ]:\n", + " info = get_source_info(series[s], source_name=source)\n", + " print(f\"{source:20}{info.source_url}\")\n", + " for url in info.binary_urls:\n", + " print(f\"{'':20} - {url}\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.1" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/11_download.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/11_download.ipynb new file mode 100644 index 00000000..a84ab333 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/11_download.ipynb @@ -0,0 +1,262 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Download Packages\n", + "\n", + "This notebook downloads Linux kernel packages using links gathered in the previous notebook.\n", + "\n", + "Note: Skip this notebook if you already have the dataset. \n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following cell downloads approximately 23GB of data. The download time will vary based on your network connection speed and could take several minutes to complete." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "metadata": {} + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/4.4.0-21-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/4.4.0-21-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/4.8.0-22-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/4.8.0-22-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/4.10.0-19-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/4.10.0-19-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/4.13.0-16-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/4.13.0-16-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/4.15.0-20-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/4.15.0-20-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/4.15.0-20-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/4.18.0-10-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/4.18.0-10-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/4.18.0-10-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.0.0-13-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.0.0-13-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.0.0-13-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.0.0-13-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.3.0-18-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.3.0-18-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.3.0-18-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.3.0-18-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-26-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-26-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-26-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-26-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.8.0-25-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.8.0-25-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.8.0-25-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.8.0-25-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.11.0-16-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.11.0-16-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.11.0-16-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.11.0-16-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.13.0-19-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.13.0-19-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.13.0-19-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.13.0-19-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.15.0-25-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.15.0-25-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.15.0-25-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.15.0-25-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.19.0-21-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.19.0-21-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.19.0-21-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.19.0-21-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/6.2.0-20-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/6.2.0-20-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/6.2.0-20-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/6.2.0-20-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/6.5.0-9-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/6.5.0-9-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/6.5.0-9-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/6.5.0-9-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/6.8.0-31-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/6.8.0-31-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/6.8.0-31-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/6.8.0-31-generic-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-26-generic-arm64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-26-generic-arm64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-26-generic-arm64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-26-generic-arm64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-26-generic-armhf.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-26-generic-armhf.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-26-generic-armhf.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-26-generic-armhf.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-24-generic-riscv64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-24-generic-riscv64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-24-generic-riscv64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-24-generic-riscv64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-26-generic-ppc64el.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-26-generic-ppc64el.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-26-generic-ppc64el.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-26-generic-ppc64el.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-26-lowlatency-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-26-lowlatency-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-26-lowlatency-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-26-lowlatency-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-1010-azure-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-1010-azure-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-1010-azure-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-1010-azure-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-1009-aws-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-1009-aws-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-1009-aws-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-1009-aws-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/dbgsym/5.4.0-1009-gcp-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/image/5.4.0-1009-gcp-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/modules/5.4.0-1009-gcp-amd64.deb\n", + "[ decorator.py:14 ] INFO: download \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/download/buildinfo/5.4.0-1009-gcp-amd64.deb\n" + ] + } + ], + "source": [ + "from pathlib import Path\n", + "\n", + "from depsurf import Version, manage_result_path, system\n", + "\n", + "\n", + "urls = [\n", + " # Generic, amd64, first revision for 16.04 - 24.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.4.0-21-generic-dbgsym_4.4.0-21.37_amd64.ddeb\", # 16.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.8.0-22-generic-dbgsym_4.8.0-22.24_amd64.ddeb\", # 16.10\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.10.0-19-generic-dbgsym_4.10.0-19.21_amd64.ddeb\", # 17.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.13.0-16-generic-dbgsym_4.13.0-16.19_amd64.ddeb\", # 17.10\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-4.15.0-20-generic-dbgsym_4.15.0-20.21_amd64.ddeb\", # 18.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-4.18.0-10-generic-dbgsym_4.18.0-10.11_amd64.ddeb\", # 18.10\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.0.0-13-generic-dbgsym_5.0.0-13.14_amd64.ddeb\", # 19.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.3.0-18-generic-dbgsym_5.3.0-18.19_amd64.ddeb\", # 19.10\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_amd64.ddeb\", # 20.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.8.0-25-generic-dbgsym_5.8.0-25.26_amd64.ddeb\", # 20.10\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.11.0-16-generic-dbgsym_5.11.0-16.17_amd64.ddeb\", # 21.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.13.0-19-generic-dbgsym_5.13.0-19.19_amd64.ddeb\", # 21.10\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.15.0-25-generic-dbgsym_5.15.0-25.25_amd64.ddeb\", # 22.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.19.0-21-generic-dbgsym_5.19.0-21.21_amd64.ddeb\", # 22.10\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.2.0-20-generic-dbgsym_6.2.0-20.20_amd64.ddeb\", # 23.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.5.0-9-generic-dbgsym_6.5.0-9.9_amd64.ddeb\", # 23.10\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-generic-dbgsym_6.8.0-31.31_amd64.ddeb\", # 24.04\n", + " # Revisions for 20.04\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-51-generic-dbgsym_5.4.0-51.56_amd64.ddeb\", # 51\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-75-generic-dbgsym_5.4.0-75.84_amd64.ddeb\", # 75\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-100-generic-dbgsym_5.4.0-100.113_amd64.ddeb\", # 100\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-125-generic-dbgsym_5.4.0-125.141_amd64.ddeb\", # 125\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-175-generic-dbgsym_5.4.0-175.195_amd64.ddeb\", # 175\n", + " # Architectures for 20.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_arm64.ddeb\", # arm64\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-26-generic-dbgsym_5.4.0-26.30_armhf.ddeb\", # armhf\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-24-generic-dbgsym_5.4.0-24.28_riscv64.ddeb\", # riscv64\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_ppc64el.ddeb\", # ppc64el\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-generic-dbgsym_5.4.0-26.30_s390x.ddeb\", # s390x\n", + " # Flavors for 20.04\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-26-lowlatency-dbgsym_5.4.0-26.30_amd64.ddeb\", # lowlatency\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-1010-azure-dbgsym_5.4.0-1010.10_amd64.ddeb\", # azure\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-5.4.0-1009-aws-dbgsym_5.4.0-1009.9_amd64.ddeb\", # aws\n", + " \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-1009-gcp-dbgsym_5.4.0-1009.9_amd64.ddeb\", # gcp\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-5.4.0-1009-oracle-dbgsym_5.4.0-1009.9_amd64.ddeb\", # oracle\n", + " # Architectures for 24.04\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-generic-dbgsym_6.8.0-31.31_arm64.ddeb\", # arm64\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-6.8.0-31-generic-dbgsym_6.8.0-31.31_armhf.ddeb\", # armhf\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-6.8.0-31-generic-dbgsym_6.8.0-31.31_ppc64el.ddeb\", # ppc64el\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-generic-dbgsym_6.8.0-31.31_s390x.ddeb\", # s390x\n", + " # Flavors for 24.04\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-31-lowlatency-dbgsym_6.8.0-31.31.1_amd64.ddeb\", # lowlatency\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1007-azure-dbgsym_6.8.0-1007.7_amd64.ddeb\", # azure\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1008-aws-dbgsym_6.8.0-1008.8_amd64.ddeb\", # aws\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1007-gcp-dbgsym_6.8.0-1007.7_amd64.ddeb\", # gcp\n", + " # \"https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-unsigned-6.8.0-1005-oracle-dbgsym_6.8.0-1005.5_amd64.ddeb\", # oracle\n", + "]\n", + "\n", + "\n", + "@manage_result_path\n", + "def download(url: str, result_path: Path):\n", + " system(f\"wget -O {result_path} {url}\")\n", + "\n", + "\n", + "for dbgsym_url in urls:\n", + " v = Version.from_path(dbgsym_url)\n", + "\n", + " # download the dbgsym package\n", + " download(dbgsym_url, result_path=v.dbgsym_download_path)\n", + "\n", + " # download the image package\n", + " vmlinuz_url = dbgsym_url.replace(\"-dbgsym\", \"\").replace(\".ddeb\", \".deb\")\n", + " download(vmlinuz_url, result_path=v.image_download_path)\n", + "\n", + " url = vmlinuz_url.replace(\"unsigned-\", \"\")\n", + " # download the modules package\n", + " if v.version_tuple >= (4, 15, 0):\n", + " modules_url = url.replace(\"image-\", \"modules-\")\n", + " download(modules_url, result_path=v.modules_download_path)\n", + "\n", + " # download the buildinfo package\n", + " if v.version_tuple >= (5, 0, 0):\n", + " buildinfo_url = url.replace(\"image-\", \"buildinfo-\")\n", + " download(buildinfo_url, result_path=v.buildinfo_download_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "22G\tdata/download/dbgsym\n", + "279M\tdata/download/image\n", + "452M\tdata/download/modules\n", + "6.7M\tdata/download/buildinfo\n", + "22G\tdata/download\n" + ] + } + ], + "source": [ + "!du -h data/download" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/20_dataset.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/20_dataset.ipynb new file mode 100644 index 00000000..9f6d7b00 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/20_dataset.ipynb @@ -0,0 +1,610 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generate Dataset\n", + "\n", + "This notebook extracts relevant data from a Linux kernel package.\n", + "\n", + "Note: Skip this notebook if you already have the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "metadata": {} + }, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following code is used to extract from a single kernel." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-26-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-26-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-26-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-26-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-26-generic-amd64.txt\n" + ] + } + ], + "source": [ + "from depsurf import VERSION_DEFAULT, prep\n", + "\n", + "prep(VERSION_DEFAULT)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following cell batch processes all the kernels. \n", + "\n", + "Please have more than 20GB free space. Depending on the number of cores, it will take about 10 minutes to finish." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "metadata": {} + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/4.4.0-21-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/4.4.0-21-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/4.4.0-21-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.4.0-21-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.4.0-21-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.4.0-21-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.4.0-21-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/4.4.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/4.4.0-21-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/4.4.0-21-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/4.8.0-22-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/4.8.0-22-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/4.8.0-22-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.8.0-22-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.8.0-22-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.8.0-22-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.8.0-22-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/4.8.0-22-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/4.8.0-22-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/4.8.0-22-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/4.10.0-19-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/4.10.0-19-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/4.10.0-19-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.10.0-19-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.10.0-19-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.10.0-19-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.10.0-19-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/4.10.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/4.10.0-19-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/4.10.0-19-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/4.13.0-16-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/4.13.0-16-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/4.13.0-16-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.13.0-16-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.13.0-16-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.13.0-16-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.13.0-16-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/4.13.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/4.13.0-16-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/4.13.0-16-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/4.15.0-20-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/4.15.0-20-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/4.15.0-20-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.15.0-20-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.15.0-20-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.15.0-20-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.15.0-20-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/4.15.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/4.15.0-20-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/4.15.0-20-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/4.18.0-10-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/4.18.0-10-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/4.18.0-10-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.18.0-10-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.18.0-10-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.18.0-10-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/4.18.0-10-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/4.18.0-10-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/4.18.0-10-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/4.18.0-10-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.0.0-13-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.0.0-13-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.0.0-13-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.0.0-13-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.0.0-13-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.0.0-13-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.0.0-13-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.0.0-13-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.0.0-13-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.0.0-13-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.3.0-18-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.3.0-18-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.3.0-18-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.3.0-18-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.3.0-18-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.3.0-18-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.3.0-18-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.3.0-18-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.3.0-18-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.3.0-18-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-1009-aws-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-1009-aws-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-1009-aws-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1009-aws-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1009-aws-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1009-aws-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1009-aws-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-1009-aws-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-1009-aws-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-1009-aws-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-1010-azure-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-1010-azure-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-1010-azure-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1010-azure-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1010-azure-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1010-azure-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1010-azure-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-1010-azure-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-1010-azure-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-1010-azure-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-1009-gcp-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-1009-gcp-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-1009-gcp-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1009-gcp-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1009-gcp-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1009-gcp-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-1009-gcp-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-1009-gcp-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-1009-gcp-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-1009-gcp-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-26-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-26-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-26-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-26-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-26-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-26-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-26-generic-arm64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-26-generic-arm64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-26-generic-arm64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-arm64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-arm64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-arm64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-arm64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-26-generic-arm64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-26-generic-arm64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-26-generic-arm64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-26-generic-armhf\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-26-generic-armhf\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-26-generic-armhf.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-armhf\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-armhf.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-armhf.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-armhf.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-26-generic-armhf.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-26-generic-armhf.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-26-generic-armhf.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-26-generic-ppc64el\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-26-generic-ppc64el\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-26-generic-ppc64el.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-ppc64el\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-ppc64el.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-ppc64el.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-generic-ppc64el.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-26-generic-ppc64el.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-26-generic-ppc64el.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-26-generic-ppc64el.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-24-generic-riscv64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-24-generic-riscv64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-24-generic-riscv64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-24-generic-riscv64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-24-generic-riscv64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-24-generic-riscv64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-24-generic-riscv64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-24-generic-riscv64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-24-generic-riscv64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-24-generic-riscv64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-26-lowlatency-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.4.0-26-lowlatency-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.4.0-26-lowlatency-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-lowlatency-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-lowlatency-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-lowlatency-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.4.0-26-lowlatency-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.4.0-26-lowlatency-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.4.0-26-lowlatency-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.8.0-25-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.8.0-25-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.8.0-25-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.8.0-25-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.8.0-25-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.8.0-25-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.8.0-25-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.8.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.8.0-25-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.8.0-25-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.11.0-16-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.11.0-16-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.11.0-16-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.11.0-16-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.11.0-16-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.11.0-16-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.11.0-16-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.11.0-16-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.11.0-16-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.11.0-16-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.13.0-19-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.13.0-19-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.13.0-19-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.13.0-19-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.13.0-19-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.13.0-19-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.13.0-19-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.13.0-19-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.13.0-19-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.13.0-19-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.15.0-25-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.15.0-25-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.15.0-25-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.15.0-25-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.15.0-25-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.15.0-25-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.15.0-25-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.15.0-25-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.15.0-25-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.15.0-25-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.19.0-21-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/5.19.0-21-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/5.19.0-21-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.19.0-21-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.19.0-21-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.19.0-21-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/5.19.0-21-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/5.19.0-21-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/5.19.0-21-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/5.19.0-21-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/6.2.0-20-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/6.2.0-20-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/6.2.0-20-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.2.0-20-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.2.0-20-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.2.0-20-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.2.0-20-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/6.2.0-20-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/6.2.0-20-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/6.2.0-20-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/6.5.0-9-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/6.5.0-9-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/6.5.0-9-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.5.0-9-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.5.0-9-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.5.0-9-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.5.0-9-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/6.5.0-9-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/6.5.0-9-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/6.5.0-9-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinux/6.8.0-31-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/vmlinuz/6.8.0-31-generic-amd64\n", + "[ decorator.py:14 ] INFO: extract_deb \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/config/6.8.0-31-generic-amd64.config\n", + "[ decorator.py:14 ] INFO: extract_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.8.0-31-generic-amd64\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.8.0-31-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.8.0-31-generic-amd64.txt\n", + "[ decorator.py:14 ] INFO: dump_btf \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/btf/6.8.0-31-generic-amd64.h\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_func/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_struct/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_union/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_enum/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_types \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/types_int/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_symtab \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/symtab/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_entries \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/intermediate/func_entries/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_func_groups \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/func_groups/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_tracepoints \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/tracepoints/6.8.0-31-generic-amd64.jsonl\n", + "[ decorator.py:14 ] INFO: dump_syscalls \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/syscalls/6.8.0-31-generic-amd64.json\n", + "[ decorator.py:14 ] INFO: dump_comment \u001b[93mSkipped\u001b[0m /Users/szhong/Code/DepSurf/data/dataset/comment/6.8.0-31-generic-amd64.txt\n" + ] + } + ], + "source": [ + "import multiprocessing as mp\n", + "\n", + "from depsurf import VersionGroup, prep\n", + "\n", + "versions = VersionGroup.ALL.versions\n", + "num_cores = min(mp.cpu_count(), len(versions))\n", + "# num_cores = 1\n", + "\n", + "with mp.Pool(num_cores, maxtasksperchild=1) as pool:\n", + " pool.map(prep, versions)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.8G\tdata/dataset\n", + "104K\tdata/dataset/comment\n", + "5.8M\tdata/dataset/config\n", + "1.7G\tdata/dataset/func_groups\n", + "608M\tdata/dataset/symtab\n", + "304K\tdata/dataset/syscalls\n", + "28M\tdata/dataset/tracepoints\n", + "20M\tdata/dataset/types_enum\n", + "381M\tdata/dataset/types_func\n", + "104K\tdata/dataset/types_int\n", + "169M\tdata/dataset/types_struct\n", + "3.8M\tdata/dataset/types_union\n", + "17G\tdata/intermediate\n", + "770M\tdata/intermediate/btf\n", + "1.3G\tdata/intermediate/func_entries\n", + "15G\tdata/intermediate/vmlinux\n", + "277M\tdata/intermediate/vmlinuz\n" + ] + } + ], + "source": [ + "!du -h data/dataset data/intermediate | sort -k2" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/30_diff.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/30_diff.ipynb new file mode 100644 index 00000000..2b744b8b --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/30_diff.ipynb @@ -0,0 +1,2217 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Diff Dependency Surface\n", + "\n", + "This notebook diffs the dependency surface for Linux kernels with different versions and configurations." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from depsurf import (\n", + " DepKind,\n", + " DiffResult,\n", + " VersionGroup,\n", + " VersionPair,\n", + " VERSION_DEFAULT,\n", + " DiffKindResult,\n", + ")\n", + "from utils import OUTPUT_PATH, save_pkl\n", + "from typing import List\n", + "import pandas as pd\n", + "\n", + "\n", + "def get_pairs(group: VersionGroup) -> List[VersionPair]:\n", + " if group in (VersionGroup.REGULAR, VersionGroup.LTS, VersionGroup.REV):\n", + " return [VersionPair(*p) for p in zip(group.versions, group.versions[1:])]\n", + "\n", + " assert VERSION_DEFAULT not in group.versions\n", + " return [VersionPair(VERSION_DEFAULT, v) for v in group.versions]\n", + "\n", + "\n", + "def print_diff_kind_result(result: DiffKindResult, file=None):\n", + " def print_header(name, items):\n", + " title = f\" {name} ({len(items)}) \"\n", + " print(f\"{title:*^80}\", file=file)\n", + "\n", + " print_header(\"Changed\", result.changed)\n", + " for name, changes in result.changed.items():\n", + " print(name, file=file)\n", + " for change in changes:\n", + " print(f\"\\t{change}\", file=file)\n", + "\n", + " print_header(\"Added\", result.added)\n", + " for name in result.added:\n", + " print(f\"\\t{name}\", file=file)\n", + "\n", + " print_header(\"Removed\", result.removed)\n", + " for name in result.removed:\n", + " print(f\"\\t{name}\", file=file)\n", + "\n", + "\n", + "def diff(name: str, groups: List[VersionGroup], kinds: List[DepKind]):\n", + " results: DiffResult = {}\n", + " results_path = OUTPUT_PATH / name\n", + "\n", + " # diff each group\n", + " for group in groups:\n", + " group_result = {}\n", + " group_path = results_path / group.name\n", + "\n", + " # diff each pair\n", + " for pair in get_pairs(group):\n", + " pair_path = group_path / f\"{group.to_str(pair.v1)}_{group.to_str(pair.v2)}\"\n", + " pair_path.mkdir(parents=True, exist_ok=True)\n", + " print(f\"Saving to {pair_path}\", flush=True)\n", + "\n", + " # actual diff\n", + " pair_result = pair.diff(kinds)\n", + "\n", + " # save summary\n", + " with open(pair_path / \"Summary.txt\", \"w\") as f:\n", + " for kind, result in pair_result.iter_kinds():\n", + " for issue, count in result.iter_issues():\n", + " if count != 0:\n", + " print(f\"{kind} {issue}: {count}\", file=f)\n", + "\n", + " # save log for each individual kind\n", + " for kind, result in pair_result.iter_kinds():\n", + " kind_path = pair_path / f\"{kind}.log\"\n", + " with open(kind_path, \"w\") as f:\n", + " print_diff_kind_result(result, f)\n", + " group_result[pair] = pair_result\n", + " results[group] = group_result\n", + "\n", + " save_pkl(results, name)\n", + "\n", + " df = pd.DataFrame(\n", + " {\n", + " (group, group.to_str(pair.v1), group.to_str(pair.v2)): {\n", + " (kind, issue): count\n", + " for kind, kind_result in pair_result.iter_kinds()\n", + " for issue, count in kind_result.iter_issues()\n", + " }\n", + " for group, group_result in results.items()\n", + " for pair, pair_result in group_result.items()\n", + " }\n", + " )\n", + " df = df.loc[(df != 0).any(axis=1)]\n", + " return df\n", + "\n", + "\n", + "# diff(\"test\", [VersionGroup.LTS], [DepKind.FUNC])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following cell diffs the dependency surface for LTS and regular releases." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/LTS/4.4_4.15\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/4.4.0-21-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/4.15.0-20-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.4.0-21-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.15.0-20-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/4.4.0-21-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/4.15.0-20-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/LTS/4.15_5.4\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/5.4.0-26-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/LTS/5.4_5.15\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.15.0-25-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.15.0-25-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/5.15.0-25-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/LTS/5.15_6.8\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/6.8.0-31-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/6.8.0-31-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/6.8.0-31-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/4.4_4.8\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/4.8.0-22-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.8.0-22-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/4.8.0-22-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/4.8_4.10\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/4.10.0-19-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.10.0-19-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/4.10.0-19-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/4.10_4.13\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/4.13.0-16-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.13.0-16-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/4.13.0-16-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/4.13_4.15\n", + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/4.15_4.18\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/4.18.0-10-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/4.18.0-10-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/4.18.0-10-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/4.18_5.0\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.0.0-13-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.0.0-13-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/5.0.0-13-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/5.0_5.3\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.3.0-18-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.3.0-18-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/5.3.0-18-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/5.3_5.4\n", + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/5.4_5.8\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.8.0-25-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.8.0-25-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/5.8.0-25-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/5.8_5.11\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.11.0-16-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.11.0-16-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/5.11.0-16-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/5.11_5.13\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.13.0-19-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.13.0-19-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/5.13.0-19-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/5.13_5.15\n", + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/5.15_5.19\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.19.0-21-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.19.0-21-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/5.19.0-21-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/5.19_6.2\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/6.2.0-20-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/6.2.0-20-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/6.2.0-20-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/6.2_6.5\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/6.5.0-9-generic-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/6.5.0-9-generic-amd64.jsonl\n", + "[ symtab.py:50 ] INFO: Loading symtab from /Users/szhong/Code/DepSurf/data/dataset/symtab/6.5.0-9-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/src/Regular/6.5_6.8\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ utils_pickle.py:13 ] INFO: Saved src to /Users/szhong/Code/DepSurf/output/src.pkl\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
LTSRegular
4.44.155.45.154.44.84.104.134.154.185.05.35.45.85.115.135.155.196.26.5
4.155.45.156.84.84.104.134.154.185.05.35.45.85.115.135.155.196.26.56.8
FunctionOld3630942299480185395636309382113914840741422994448845277469924801851936543025319353956558435697859365
New4229948018539566198338211391484074142299444884527746992480185193654302531935395655843569785936561983
Added8600892910771121562849157426622118363519802516138267853518146917533525262231963626
Removed2610321048334129947637106956014461191801356286711522578990163814878091008
Changed19561807218729967683868305348216985105138718766025739369031058801
Param added111596313161534404221513300410342277446540530454264556449579352
Param removed8006599671424292178343206194303210384433485189172486347588302
Param reordered3753495565551734218387203841012713818927910124121714898
Param type changed5084215727512121071661592161751012817326071193141253199288
Return type changed29238028850711454114591791407523120915294127146158151
StructOld616073428422932961606599675270517342762378078209842286108954917893299551976710022
New73428422932910474659967527051734276237807820984228610895491789329955197671002210474
Added1449136414101504536227371362393301467273480495323232384337318500
Removed26728450335997747271112117656029215199811621216348
Changed1116113013081519554365608378511542524260678614397437697569585569
Field added8008369791120406248395259359374386183482443268334507400403405
Field removed45845252363422010120013915617319298240230144130280187211194
Field type changed41238442251314311721810916716812557199169110114203176135167
TracepointOld502675752818502539559635675683704737752785813805818843871917
New675752818932539559635675683704737752785813805818843871917932
Added1979810215037288254252434154533111753315116
Removed24213636086141731012519428351
Changed39541191152717131710222425321155049364015
Param added1319183410151710401446325616
Param removed810293140323361151450121319
Param reordered4820204030224071343161013
Param type changed3621601202220200541506
Field added283950432524159141611261032251256
Field removed26301955191471421117211413124355
Field type changed31412801300010300115181302
Event changed374410210626171216914212479115043254012
Func changed18293859112729121012117783322215
LSM HookOld168177189203168168171176177182182186189198199203203207212214
New177189203219168171176177182182186189198199203203207212214219
Added1514162033635243101505529
Removed62243012020010101004
Changed1917272716030138101454594914
Param added34201700301500134409397
Param removed16151600103410132019297
Param reordered10410010220000400100
Param type changed1711711160101010021040207
kfuncOld0002900000000001229294377107
New00291380000000001229294377107138
Added00291140000000001217016345731
Removed000500000000000020270
\n", + "
" + ], + "text/plain": [ + " LTS Regular \n", + " 4.4 4.15 5.4 5.15 4.4 4.8 4.10 4.13 4.15 4.18 5.0 5.3 5.4 5.8 5.11 5.13 5.15 5.19 6.2 6.5\n", + " 4.15 5.4 5.15 6.8 4.8 4.10 4.13 4.15 4.18 5.0 5.3 5.4 5.8 5.11 5.13 5.15 5.19 6.2 6.5 6.8\n", + "Function Old 36309 42299 48018 53956 36309 38211 39148 40741 42299 44488 45277 46992 48018 51936 54302 53193 53956 55843 56978 59365\n", + " New 42299 48018 53956 61983 38211 39148 40741 42299 44488 45277 46992 48018 51936 54302 53193 53956 55843 56978 59365 61983\n", + " Added 8600 8929 10771 12156 2849 1574 2662 2118 3635 1980 2516 1382 6785 3518 1469 1753 3525 2622 3196 3626\n", + " Removed 2610 3210 4833 4129 947 637 1069 560 1446 1191 801 356 2867 1152 2578 990 1638 1487 809 1008\n", + " Changed 1956 1807 2187 2996 768 386 830 534 821 698 510 513 871 876 602 573 936 903 1058 801\n", + " Param added 1115 963 1316 1534 404 221 513 300 410 342 277 446 540 530 454 264 556 449 579 352\n", + " Param removed 800 659 967 1424 292 178 343 206 194 303 210 384 433 485 189 172 486 347 588 302\n", + " Param reordered 375 349 556 555 173 42 183 87 203 84 101 27 138 189 279 101 241 217 148 98\n", + " Param type changed 508 421 572 751 212 107 166 159 216 175 101 28 173 260 71 193 141 253 199 288\n", + " Return type changed 292 380 288 507 114 54 114 59 179 140 75 23 120 91 52 94 127 146 158 151\n", + "Struct Old 6160 7342 8422 9329 6160 6599 6752 7051 7342 7623 7807 8209 8422 8610 8954 9178 9329 9551 9767 10022\n", + " New 7342 8422 9329 10474 6599 6752 7051 7342 7623 7807 8209 8422 8610 8954 9178 9329 9551 9767 10022 10474\n", + " Added 1449 1364 1410 1504 536 227 371 362 393 301 467 273 480 495 323 232 384 337 318 500\n", + " Removed 267 284 503 359 97 74 72 71 112 117 65 60 292 151 99 81 162 121 63 48\n", + " Changed 1116 1130 1308 1519 554 365 608 378 511 542 524 260 678 614 397 437 697 569 585 569\n", + " Field added 800 836 979 1120 406 248 395 259 359 374 386 183 482 443 268 334 507 400 403 405\n", + " Field removed 458 452 523 634 220 101 200 139 156 173 192 98 240 230 144 130 280 187 211 194\n", + " Field type changed 412 384 422 513 143 117 218 109 167 168 125 57 199 169 110 114 203 176 135 167\n", + "Tracepoint Old 502 675 752 818 502 539 559 635 675 683 704 737 752 785 813 805 818 843 871 917\n", + " New 675 752 818 932 539 559 635 675 683 704 737 752 785 813 805 818 843 871 917 932\n", + " Added 197 98 102 150 37 28 82 54 25 24 34 15 45 33 11 17 53 31 51 16\n", + " Removed 24 21 36 36 0 8 6 14 17 3 1 0 12 5 19 4 28 3 5 1\n", + " Changed 39 54 119 115 27 17 13 17 10 22 24 2 53 21 15 50 49 36 40 15\n", + " Param added 13 19 18 34 10 1 5 1 7 10 4 0 14 4 6 3 25 6 1 6\n", + " Param removed 8 10 29 31 4 0 3 2 3 3 6 1 15 14 5 0 12 13 1 9\n", + " Param reordered 4 8 20 20 4 0 3 0 2 2 4 0 7 13 4 3 16 10 1 3\n", + " Param type changed 3 6 2 16 0 1 2 0 2 2 2 0 2 0 0 5 4 15 0 6\n", + " Field added 28 39 50 43 25 2 4 15 9 14 16 1 12 6 10 32 25 12 5 6\n", + " Field removed 26 30 19 55 19 14 7 14 2 11 17 2 11 4 1 3 12 4 35 5\n", + " Field type changed 3 1 41 28 0 1 3 0 0 0 1 0 30 0 1 15 18 13 0 2\n", + " Event changed 37 44 102 106 26 17 12 16 9 14 21 2 47 9 11 50 43 25 40 12\n", + " Func changed 18 29 38 59 11 2 7 2 9 12 10 1 21 17 7 8 33 22 2 15\n", + "LSM Hook Old 168 177 189 203 168 168 171 176 177 182 182 186 189 198 199 203 203 207 212 214\n", + " New 177 189 203 219 168 171 176 177 182 182 186 189 198 199 203 203 207 212 214 219\n", + " Added 15 14 16 20 3 3 6 3 5 2 4 3 10 1 5 0 5 5 2 9\n", + " Removed 6 2 2 4 3 0 1 2 0 2 0 0 1 0 1 0 1 0 0 4\n", + " Changed 19 17 27 27 16 0 3 0 13 8 1 0 14 5 4 5 9 4 9 14\n", + " Param added 3 4 20 17 0 0 3 0 1 5 0 0 13 4 4 0 9 3 9 7\n", + " Param removed 1 6 15 16 0 0 1 0 3 4 1 0 13 2 0 1 9 2 9 7\n", + " Param reordered 1 0 4 1 0 0 1 0 2 2 0 0 0 0 4 0 0 1 0 0\n", + " Param type changed 17 11 7 11 16 0 1 0 10 1 0 0 2 1 0 4 0 2 0 7\n", + "kfunc Old 0 0 0 29 0 0 0 0 0 0 0 0 0 0 12 29 29 43 77 107\n", + " New 0 0 29 138 0 0 0 0 0 0 0 0 0 12 29 29 43 77 107 138\n", + " Added 0 0 29 114 0 0 0 0 0 0 0 0 0 12 17 0 16 34 57 31\n", + " Removed 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 2 0 27 0" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "diff(\n", + " \"src\",\n", + " [VersionGroup.LTS, VersionGroup.REGULAR],\n", + " [\n", + " DepKind.FUNC,\n", + " DepKind.STRUCT,\n", + " DepKind.TRACEPOINT,\n", + " DepKind.LSM,\n", + " DepKind.KFUNC,\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following cell diffs the dependency surface for different architectures and flavors." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/config/Arch/amd64_arm64\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-arm64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-arm64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/config/Arch/amd64_armhf\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-armhf.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-armhf.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/config/Arch/amd64_ppc64el\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-generic-ppc64el.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-generic-ppc64el.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/config/Arch/amd64_riscv64\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-24-generic-riscv64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-24-generic-riscv64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/config/Flavor/generic_aws\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-1009-aws-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-1009-aws-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/config/Flavor/generic_azure\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-1010-azure-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-1010-azure-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/config/Flavor/generic_gcp\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-1009-gcp-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-1009-gcp-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saving to /Users/szhong/Code/DepSurf/output/config/Flavor/generic_lowlatency\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_func/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ types.py:44 ] INFO: Loading types from /Users/szhong/Code/DepSurf/data/dataset/types_struct/5.4.0-26-lowlatency-amd64.jsonl\n", + "[ utils_pickle.py:13 ] INFO: Saved config to /Users/szhong/Code/DepSurf/output/config.pkl\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ArchFlavor
amd64generic
arm64armhfppc64elriscv64awsazuregcplowlatency
ConfigOld87768776877687768776877687768776
New95949607809876266413530685868779
Added1933219465748081109
Removed1115136313351630237134811906
Changed418551442528712499
Config changed418551442528712499
FunctionOld4801848018480184801848018480184801848018
New4936248845428263658646523454834814948034
Added9216126025444207932899245057
Removed78721177510636135111823352731941
Changed12010613710121010
Param added635079552910
Param removed6350805821010
Param reordered381270200
Param type changed575561481300
Return type changed9102450100
StructOld84228422842284228422842284228422
New90758551736865788022784683678425
Added1659198057015783257684
Removed10061851162420014838331231
Changed81154116981928145
Field added334232226722
Field removed396650721320113
Field type changed378975291620
TracepointOld752752752752752752752752
New685690648625747739752752
Added457025042600
Removed11213212912793900
SyscallOld333333333333333333333333
New291378347280333333333333
Added2742320000
Removed44299550000
\n", + "
" + ], + "text/plain": [ + " Arch Flavor \n", + " amd64 generic \n", + " arm64 armhf ppc64el riscv64 aws azure gcp lowlatency\n", + "Config Old 8776 8776 8776 8776 8776 8776 8776 8776\n", + " New 9594 9607 8098 7626 6413 5306 8586 8779\n", + " Added 1933 2194 657 480 8 11 0 9\n", + " Removed 1115 1363 1335 1630 2371 3481 190 6\n", + " Changed 41 85 51 44 252 871 249 9\n", + " Config changed 41 85 51 44 252 871 249 9\n", + "Function Old 48018 48018 48018 48018 48018 48018 48018 48018\n", + " New 49362 48845 42826 36586 46523 45483 48149 48034\n", + " Added 9216 12602 5444 2079 328 992 450 57\n", + " Removed 7872 11775 10636 13511 1823 3527 319 41\n", + " Changed 120 106 137 101 2 10 1 0\n", + " Param added 63 50 79 55 2 9 1 0\n", + " Param removed 63 50 80 58 2 10 1 0\n", + " Param reordered 3 8 12 7 0 2 0 0\n", + " Param type changed 57 55 61 48 1 3 0 0\n", + " Return type changed 9 10 24 5 0 1 0 0\n", + "Struct Old 8422 8422 8422 8422 8422 8422 8422 8422\n", + " New 9075 8551 7368 6578 8022 7846 8367 8425\n", + " Added 1659 1980 570 157 83 257 68 4\n", + " Removed 1006 1851 1624 2001 483 833 123 1\n", + " Changed 81 154 116 98 19 28 14 5\n", + " Field added 33 42 32 22 6 7 2 2\n", + " Field removed 39 66 50 72 13 20 11 3\n", + " Field type changed 37 89 75 29 1 6 2 0\n", + "Tracepoint Old 752 752 752 752 752 752 752 752\n", + " New 685 690 648 625 747 739 752 752\n", + " Added 45 70 25 0 4 26 0 0\n", + " Removed 112 132 129 127 9 39 0 0\n", + "Syscall Old 333 333 333 333 333 333 333 333\n", + " New 291 378 347 280 333 333 333 333\n", + " Added 2 74 23 2 0 0 0 0\n", + " Removed 44 29 9 55 0 0 0 0" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "diff(\n", + " \"config\",\n", + " [VersionGroup.ARCH, VersionGroup.FLAVOR],\n", + " [\n", + " DepKind.CONFIG,\n", + " DepKind.FUNC,\n", + " DepKind.STRUCT,\n", + " DepKind.TRACEPOINT,\n", + " DepKind.SYSCALL,\n", + " ],\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/35_src.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/35_src.ipynb new file mode 100644 index 00000000..456fa1d8 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/35_src.ipynb @@ -0,0 +1,583 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Source Code Changes\n", + "\n", + "This notebook generates the table for source code changes.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "metadata": {} + }, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ utils_pickle.py:18 ] INFO: Loding src from /Users/szhong/Code/DepSurf/output/src.pkl\n", + "[ utils_latex.py:118] INFO: Saved src to /Users/szhong/Code/DepSurf/paper/tabs/src.tex\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
FunctionStructTracepoint
\\ \\ \\ # \\ \\$+$%$-$%$\\Delta$%\\ \\ \\ # \\ \\$+$%$-$%$\\Delta$%\\ \\ \\ # \\ \\$+$%$-$%$\\Delta$%
LTS (2 yr)4.436k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.55cm}][r]{24}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.39cm}][r]{7}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.53cm}][r]{5}}}6.2k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.55cm}][r]{24}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.40cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.55cm}][r]{18}}}502\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.55cm}][r]{39}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.55cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.27cm}][r]{8}}}
4.1542k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.49cm}][r]{21}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.41cm}][r]{8}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.42cm}][r]{4}}}7.3k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.43cm}][r]{19}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.36cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.47cm}][r]{15}}}675\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.20cm}][r]{15}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.36cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.28cm}][r]{8}}}
5.448k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.52cm}][r]{22}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.55cm}][r]{10}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.45cm}][r]{5}}}8.4k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.39cm}][r]{17}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.55cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.47cm}][r]{16}}}752\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.19cm}][r]{14}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.55cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.55cm}][r]{16}}}
5.1554k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.52cm}][r]{23}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.42cm}][r]{8}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.55cm}][r]{6}}}9.3k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.38cm}][r]{16}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.35cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.49cm}][r]{16}}}818\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.26cm}][r]{18}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.51cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.49cm}][r]{14}}}
6.862k10.5k932
Regular Releases (6 mo)4.436k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.18cm}][r]{8}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.14cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.21cm}][r]{2}}}6.2k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.20cm}][r]{9}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.15cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.27cm}][r]{9}}}502\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.10cm}][r]{7}}}\\multirow[c]{2}{*}{\\color{lightgray}{-}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.19cm}][r]{5}}}
4.838k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.10cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.09cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.10cm}][r]{1}}}6.6k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.17cm}][r]{6}}}539\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.07cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.17cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{3}}}
4.1039k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.16cm}][r]{7}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.15cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.21cm}][r]{2}}}6.8k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.27cm}][r]{9}}}559\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.21cm}][r]{15}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.12cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.08cm}][r]{2}}}
4.1341k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.12cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.08cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.13cm}][r]{1}}}7.1k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.12cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.09cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.16cm}][r]{5}}}635\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.12cm}][r]{9}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.25cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.09cm}][r]{3}}}
4.1542k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.20cm}][r]{9}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.19cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.19cm}][r]{2}}}7.3k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.14cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.21cm}][r]{7}}}675\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.05cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.29cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.05cm}][r]{1}}}
4.1844k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.10cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.15cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.16cm}][r]{2}}}7.6k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.09cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.14cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.22cm}][r]{7}}}683\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.05cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.05cm}][r]{0.4}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{3}}}
5.045k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{1}}}7.8k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.14cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.08cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.20cm}][r]{7}}}704\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.07cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.02cm}][r]{0.1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.12cm}][r]{3}}}
5.347k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.07cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.04cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{1}}}8.2k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.07cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.10cm}][r]{3}}}737\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.03cm}][r]{2}}}\\multirow[c]{2}{*}{\\color{lightgray}{-}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.01cm}][r]{0.3}}}
5.448k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.33cm}][r]{14}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.33cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.18cm}][r]{2}}}8.4k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.32cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.24cm}][r]{8}}}752\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.18cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.24cm}][r]{7}}}
5.852k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.16cm}][r]{7}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.12cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.17cm}][r]{2}}}8.6k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.16cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.22cm}][r]{7}}}785\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.06cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.07cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.09cm}][r]{3}}}
5.1154k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.06cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.26cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{1}}}9.0k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.13cm}][r]{4}}}813\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.02cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.27cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.06cm}][r]{2}}}
5.1353k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{1}}}9.2k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.06cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.08cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.14cm}][r]{5}}}805\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.03cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.06cm}][r]{0.5}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.22cm}][r]{6}}}
5.1554k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.15cm}][r]{7}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.17cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.17cm}][r]{2}}}9.3k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.10cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.16cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.23cm}][r]{7}}}818\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.09cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.39cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.21cm}][r]{6}}}
5.1956k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.11cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.15cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.16cm}][r]{2}}}9.6k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.12cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.18cm}][r]{6}}}843\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.05cm}][r]{4}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.04cm}][r]{0.4}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.15cm}][r]{4}}}
6.257k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.08cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.18cm}][r]{2}}}9.8k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{3}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.06cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.18cm}][r]{6}}}871\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.07cm}][r]{1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.16cm}][r]{5}}}
6.559k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.14cm}][r]{6}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.09cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.13cm}][r]{1}}}10.0k\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.12cm}][r]{5}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.04cm}][r]{0.5}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.17cm}][r]{6}}}917\\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.02cm}][r]{2}}}\\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.01cm}][r]{0.1}}}\\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.06cm}][r]{2}}}
6.862k10.5k932
\n", + "
" + ], + "text/plain": [ + " Function Struct Tracepoint \n", + " \\ \\ \\ # \\ \\ $+$% $-$% $\\Delta$% \\ \\ \\ # \\ \\ $+$% $-$% $\\Delta$% \\ \\ \\ # \\ \\ $+$% $-$% $\\Delta$%\n", + "LTS (2 yr) 4.4 36k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.55cm}][r]{24}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.39cm}][r]{7}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.53cm}][r]{5}}} 6.2k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.55cm}][r]{24}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.40cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.55cm}][r]{18}}} 502 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.55cm}][r]{39}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.55cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.27cm}][r]{8}}}\n", + " 4.15 42k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.49cm}][r]{21}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.41cm}][r]{8}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.42cm}][r]{4}}} 7.3k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.43cm}][r]{19}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.36cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.47cm}][r]{15}}} 675 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.20cm}][r]{15}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.36cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.28cm}][r]{8}}}\n", + " 5.4 48k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.52cm}][r]{22}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.55cm}][r]{10}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.45cm}][r]{5}}} 8.4k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.39cm}][r]{17}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.55cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.47cm}][r]{16}}} 752 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.19cm}][r]{14}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.55cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.55cm}][r]{16}}}\n", + " 5.15 54k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.52cm}][r]{23}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.42cm}][r]{8}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.55cm}][r]{6}}} 9.3k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.38cm}][r]{16}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.35cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.49cm}][r]{16}}} 818 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.26cm}][r]{18}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.51cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.49cm}][r]{14}}}\n", + " 6.8 62k 10.5k 932 \n", + "Regular Releases (6 mo) 4.4 36k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.18cm}][r]{8}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.14cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.21cm}][r]{2}}} 6.2k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.20cm}][r]{9}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.15cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.27cm}][r]{9}}} 502 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.10cm}][r]{7}}} \\multirow[c]{2}{*}{\\color{lightgray}{-}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.19cm}][r]{5}}}\n", + " 4.8 38k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.10cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.09cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.10cm}][r]{1}}} 6.6k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.17cm}][r]{6}}} 539 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.07cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.17cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{3}}}\n", + " 4.10 39k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.16cm}][r]{7}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.15cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.21cm}][r]{2}}} 6.8k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.27cm}][r]{9}}} 559 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.21cm}][r]{15}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.12cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.08cm}][r]{2}}}\n", + " 4.13 41k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.12cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.08cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.13cm}][r]{1}}} 7.1k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.12cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.09cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.16cm}][r]{5}}} 635 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.12cm}][r]{9}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.25cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.09cm}][r]{3}}}\n", + " 4.15 42k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.20cm}][r]{9}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.19cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.19cm}][r]{2}}} 7.3k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.14cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.21cm}][r]{7}}} 675 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.05cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.29cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.05cm}][r]{1}}}\n", + " 4.18 44k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.10cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.15cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.16cm}][r]{2}}} 7.6k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.09cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.14cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.22cm}][r]{7}}} 683 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.05cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.05cm}][r]{0.4}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{3}}}\n", + " 5.0 45k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{1}}} 7.8k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.14cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.08cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.20cm}][r]{7}}} 704 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.07cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.02cm}][r]{0.1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.12cm}][r]{3}}}\n", + " 5.3 47k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.07cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.04cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{1}}} 8.2k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.07cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.10cm}][r]{3}}} 737 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.03cm}][r]{2}}} \\multirow[c]{2}{*}{\\color{lightgray}{-}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.01cm}][r]{0.3}}}\n", + " 5.4 48k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.33cm}][r]{14}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.33cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.18cm}][r]{2}}} 8.4k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.32cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.24cm}][r]{8}}} 752 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.18cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.24cm}][r]{7}}}\n", + " 5.8 52k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.16cm}][r]{7}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.12cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.17cm}][r]{2}}} 8.6k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.16cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.22cm}][r]{7}}} 785 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.06cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.07cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.09cm}][r]{3}}}\n", + " 5.11 54k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.06cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.26cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{1}}} 9.0k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.13cm}][r]{4}}} 813 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.02cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.27cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.06cm}][r]{2}}}\n", + " 5.13 53k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.10cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.11cm}][r]{1}}} 9.2k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.06cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.08cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.14cm}][r]{5}}} 805 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.03cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.06cm}][r]{0.5}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.22cm}][r]{6}}}\n", + " 5.15 54k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.15cm}][r]{7}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.17cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.17cm}][r]{2}}} 9.3k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.10cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.16cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.23cm}][r]{7}}} 818 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.09cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.39cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.21cm}][r]{6}}}\n", + " 5.19 56k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.11cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.15cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.16cm}][r]{2}}} 9.6k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.12cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.18cm}][r]{6}}} 843 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.05cm}][r]{4}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.04cm}][r]{0.4}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.15cm}][r]{4}}}\n", + " 6.2 57k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.13cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.08cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.18cm}][r]{2}}} 9.8k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{3}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.06cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.18cm}][r]{6}}} 871 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.08cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.07cm}][r]{1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.16cm}][r]{5}}}\n", + " 6.5 59k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.14cm}][r]{6}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.09cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.13cm}][r]{1}}} 10.0k \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.12cm}][r]{5}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.04cm}][r]{0.5}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.17cm}][r]{6}}} 917 \\multirow[c]{2}{*}{\\colorbox{add}{\\makebox[{0.02cm}][r]{2}}} \\multirow[c]{2}{*}{\\colorbox{remove}{\\makebox[{0.01cm}][r]{0.1}}} \\multirow[c]{2}{*}{\\colorbox{change}{\\makebox[{0.06cm}][r]{2}}}\n", + " 6.8 62k 10.5k 932 " + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "from depsurf import DepKind, DiffResult, IssueEnum, VersionGroup\n", + "from utils import GRAY_DASH, load_pkl, save_latex, mini_bar, multirow\n", + "\n", + "data: DiffResult = load_pkl(\"src\")\n", + "\n", + "KINDS = [\n", + " DepKind.FUNC,\n", + " # DepKind.LSM,\n", + " DepKind.STRUCT,\n", + " DepKind.TRACEPOINT,\n", + "]\n", + "\n", + "ISSUES = {\n", + " IssueEnum.OLD: r\"\\ \\ \\ # \\ \\ \",\n", + " IssueEnum.ADD: r\"$+$%\",\n", + " IssueEnum.REMOVE: r\"$-$%\",\n", + " IssueEnum.CHANGE: r\"$\\Delta$%\",\n", + "}\n", + "\n", + "COLORS = {\n", + " IssueEnum.ADD: \"add\",\n", + " IssueEnum.REMOVE: \"remove\",\n", + " IssueEnum.CHANGE: \"change\",\n", + "}\n", + "\n", + "GROUPS = {\n", + " VersionGroup.LTS: \"LTS (2 yr)\",\n", + " VersionGroup.REGULAR: \"Regular Releases (6 mo)\",\n", + "}\n", + "\n", + "\n", + "table = {}\n", + "\n", + "\n", + "def format_val(kind, val) -> str:\n", + " if kind == DepKind.FUNC:\n", + " return f\"{val / 1000:.0f}k\"\n", + " elif kind == DepKind.STRUCT:\n", + " return f\"{val / 1000:.1f}k\"\n", + " return str(val)\n", + "\n", + "def format_percent(num):\n", + " pct = num * 100\n", + " if pct < 0.5:\n", + " return f\"{pct:.1f}\"\n", + " return f\"{pct:.0f}\"\n", + "\n", + "max_percent = {\n", + " (kind, issue): max(\n", + " pair_result.kind_results[kind].issues[issue]\n", + " / pair_result.kind_results[kind].issues[IssueEnum.OLD]\n", + " for group, group_result in data.items()\n", + " for pair, pair_result in group_result.items()\n", + " )\n", + " for kind in KINDS\n", + " for issue in ISSUES\n", + "}\n", + "\n", + "\n", + "for group, group_result in data.items():\n", + " if group not in GROUPS:\n", + " continue\n", + "\n", + " for pair, pair_result in group_result.items():\n", + " col = {}\n", + " for kind, kind_result in pair_result.iter_kinds():\n", + " if kind not in KINDS:\n", + " continue\n", + " old = kind_result.issues[IssueEnum.OLD]\n", + " for issue, count in kind_result.iter_issues():\n", + " if issue not in ISSUES:\n", + " continue\n", + "\n", + " if issue == IssueEnum.OLD:\n", + " text = format_val(kind, count)\n", + " else:\n", + " if count == 0:\n", + " text = GRAY_DASH\n", + " else:\n", + " text = mini_bar(\n", + " text=format_percent(count / old),\n", + " percent=count / old / max_percent[(kind, issue)],\n", + " total_width=0.55,\n", + " color=COLORS[issue],\n", + " )\n", + " text = multirow(text)\n", + " col[(kind, ISSUES[issue])] = text\n", + "\n", + " v1 = group.to_str(pair.v1)\n", + " v2 = group.to_str(pair.v2)\n", + "\n", + " group_name = GROUPS[group]\n", + " table[(group_name, v1)] = col\n", + " if pair.v2 == list(group)[-1]:\n", + " col = {k: \"\" for k in col.keys()}\n", + " for kind, key in col.keys():\n", + " if key == ISSUES[IssueEnum.OLD]:\n", + " count = pair_result.kind_results[kind].issues[IssueEnum.NEW]\n", + " col[(kind, key)] = format_val(kind, count)\n", + " table[(group_name, v2)] = col\n", + "\n", + "\n", + "df = pd.DataFrame(table).T\n", + "latex = df.to_latex(multicolumn_format=\"c|\", column_format=r\"cc|rrrr|rrrr|rrrr\")\n", + "save_latex(latex, \"src\")\n", + "df" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/36_breakdown.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/36_breakdown.ipynb new file mode 100644 index 00000000..28c9b437 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/36_breakdown.ipynb @@ -0,0 +1,294 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Breakdown of Source Code Changes\n", + "\n", + "This notebook generates the table for a breakdown of source code changes.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ utils_pickle.py:18 ] INFO: Loding src from /Users/szhong/Code/DepSurf/output/src.pkl\n", + "[ utils_latex.py:118] INFO: Saved breakdown to /Users/szhong/Code/DepSurf/paper/tabs/breakdown.tex\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Linux Kernel Version
\\multicolumn{1}{c}{4.4 - 4.15}\\multicolumn{1}{c}{4.15 - 5.4}\\multicolumn{1}{c}{5.4 - 5.15}\\multicolumn{1}{c}{5.15 - 6.8}
FunctionNo. changed2.0k1.8k2.2k3.0k
- Param added\\colorbox{bg}{\\makebox[{0.49cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.66cm}][r]{57%}}\\colorbox{bg}{\\makebox[{0.54cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.61cm}][r]{53%}}\\colorbox{bg}{\\makebox[{0.46cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.69cm}][r]{60%}}\\colorbox{bg}{\\makebox[{0.56cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.59cm}][r]{51%}}
- Param removed\\colorbox{bg}{\\makebox[{0.68cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.47cm}][r]{41%}}\\colorbox{bg}{\\makebox[{0.73cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.42cm}][r]{36%}}\\colorbox{bg}{\\makebox[{0.64cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.51cm}][r]{44%}}\\colorbox{bg}{\\makebox[{0.60cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.55cm}][r]{48%}}
- Param reordered\\colorbox{bg}{\\makebox[{0.93cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.22cm}][r]{19%}}\\colorbox{bg}{\\makebox[{0.93cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.22cm}][r]{19%}}\\colorbox{bg}{\\makebox[{0.86cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.29cm}][r]{25%}}\\colorbox{bg}{\\makebox[{0.94cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.21cm}][r]{19%}}
- Param type changed\\colorbox{bg}{\\makebox[{0.85cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.30cm}][r]{26%}}\\colorbox{bg}{\\makebox[{0.88cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.27cm}][r]{23%}}\\colorbox{bg}{\\makebox[{0.85cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.30cm}][r]{26%}}\\colorbox{bg}{\\makebox[{0.86cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.29cm}][r]{25%}}
- Return type changed\\colorbox{bg}{\\makebox[{0.98cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.17cm}][r]{15%}}\\colorbox{bg}{\\makebox[{0.91cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.24cm}][r]{21%}}\\colorbox{bg}{\\makebox[{1.00cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.15cm}][r]{13%}}\\colorbox{bg}{\\makebox[{0.96cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.19cm}][r]{17%}}
StructNo. changed1.1k1.1k1.3k1.5k
- Field added\\colorbox{bg}{\\makebox[{0.33cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.82cm}][r]{72%}}\\colorbox{bg}{\\makebox[{0.30cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.85cm}][r]{74%}}\\colorbox{bg}{\\makebox[{0.29cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.86cm}][r]{75%}}\\colorbox{bg}{\\makebox[{0.30cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.85cm}][r]{74%}}
- Field removed\\colorbox{bg}{\\makebox[{0.68cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.47cm}][r]{41%}}\\colorbox{bg}{\\makebox[{0.69cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.46cm}][r]{40%}}\\colorbox{bg}{\\makebox[{0.69cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.46cm}][r]{40%}}\\colorbox{bg}{\\makebox[{0.67cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.48cm}][r]{42%}}
- Field type changed\\colorbox{bg}{\\makebox[{0.73cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.42cm}][r]{37%}}\\colorbox{bg}{\\makebox[{0.76cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.39cm}][r]{34%}}\\colorbox{bg}{\\makebox[{0.78cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.37cm}][r]{32%}}\\colorbox{bg}{\\makebox[{0.76cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.39cm}][r]{34%}}
TraceptNo. changed3954119115
- Event changed\\colorbox{bg}{\\makebox[{0.06cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{1.09cm}][r]{95%}}\\colorbox{bg}{\\makebox[{0.21cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.94cm}][r]{81%}}\\colorbox{bg}{\\makebox[{0.16cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.99cm}][r]{86%}}\\colorbox{bg}{\\makebox[{0.09cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{1.06cm}][r]{92%}}
- Func changed\\colorbox{bg}{\\makebox[{0.62cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.53cm}][r]{46%}}\\colorbox{bg}{\\makebox[{0.53cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.62cm}][r]{54%}}\\colorbox{bg}{\\makebox[{0.78cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.37cm}][r]{32%}}\\colorbox{bg}{\\makebox[{0.56cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.59cm}][r]{51%}}
\n", + "
" + ], + "text/plain": [ + " Linux Kernel Version \n", + " \\multicolumn{1}{c}{4.4 - 4.15} \\multicolumn{1}{c}{4.15 - 5.4} \\multicolumn{1}{c}{5.4 - 5.15} \\multicolumn{1}{c}{5.15 - 6.8}\n", + "Function No. changed 2.0k 1.8k 2.2k 3.0k\n", + " - Param added \\colorbox{bg}{\\makebox[{0.49cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.66cm}][r]{57%}} \\colorbox{bg}{\\makebox[{0.54cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.61cm}][r]{53%}} \\colorbox{bg}{\\makebox[{0.46cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.69cm}][r]{60%}} \\colorbox{bg}{\\makebox[{0.56cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.59cm}][r]{51%}}\n", + " - Param removed \\colorbox{bg}{\\makebox[{0.68cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.47cm}][r]{41%}} \\colorbox{bg}{\\makebox[{0.73cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.42cm}][r]{36%}} \\colorbox{bg}{\\makebox[{0.64cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.51cm}][r]{44%}} \\colorbox{bg}{\\makebox[{0.60cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.55cm}][r]{48%}}\n", + " - Param reordered \\colorbox{bg}{\\makebox[{0.93cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.22cm}][r]{19%}} \\colorbox{bg}{\\makebox[{0.93cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.22cm}][r]{19%}} \\colorbox{bg}{\\makebox[{0.86cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.29cm}][r]{25%}} \\colorbox{bg}{\\makebox[{0.94cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.21cm}][r]{19%}}\n", + " - Param type changed \\colorbox{bg}{\\makebox[{0.85cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.30cm}][r]{26%}} \\colorbox{bg}{\\makebox[{0.88cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.27cm}][r]{23%}} \\colorbox{bg}{\\makebox[{0.85cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.30cm}][r]{26%}} \\colorbox{bg}{\\makebox[{0.86cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.29cm}][r]{25%}}\n", + " - Return type changed \\colorbox{bg}{\\makebox[{0.98cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.17cm}][r]{15%}} \\colorbox{bg}{\\makebox[{0.91cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.24cm}][r]{21%}} \\colorbox{bg}{\\makebox[{1.00cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.15cm}][r]{13%}} \\colorbox{bg}{\\makebox[{0.96cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.19cm}][r]{17%}}\n", + "Struct No. changed 1.1k 1.1k 1.3k 1.5k\n", + " - Field added \\colorbox{bg}{\\makebox[{0.33cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.82cm}][r]{72%}} \\colorbox{bg}{\\makebox[{0.30cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.85cm}][r]{74%}} \\colorbox{bg}{\\makebox[{0.29cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.86cm}][r]{75%}} \\colorbox{bg}{\\makebox[{0.30cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.85cm}][r]{74%}}\n", + " - Field removed \\colorbox{bg}{\\makebox[{0.68cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.47cm}][r]{41%}} \\colorbox{bg}{\\makebox[{0.69cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.46cm}][r]{40%}} \\colorbox{bg}{\\makebox[{0.69cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.46cm}][r]{40%}} \\colorbox{bg}{\\makebox[{0.67cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.48cm}][r]{42%}}\n", + " - Field type changed \\colorbox{bg}{\\makebox[{0.73cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.42cm}][r]{37%}} \\colorbox{bg}{\\makebox[{0.76cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.39cm}][r]{34%}} \\colorbox{bg}{\\makebox[{0.78cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.37cm}][r]{32%}} \\colorbox{bg}{\\makebox[{0.76cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.39cm}][r]{34%}}\n", + "Tracept No. changed 39 54 119 115\n", + " - Event changed \\colorbox{bg}{\\makebox[{0.06cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{1.09cm}][r]{95%}} \\colorbox{bg}{\\makebox[{0.21cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.94cm}][r]{81%}} \\colorbox{bg}{\\makebox[{0.16cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.99cm}][r]{86%}} \\colorbox{bg}{\\makebox[{0.09cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{1.06cm}][r]{92%}}\n", + " - Func changed \\colorbox{bg}{\\makebox[{0.62cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.53cm}][r]{46%}} \\colorbox{bg}{\\makebox[{0.53cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.62cm}][r]{54%}} \\colorbox{bg}{\\makebox[{0.78cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.37cm}][r]{32%}} \\colorbox{bg}{\\makebox[{0.56cm}][r]{\\phantom{0}}}\\colorbox{change}{\\makebox[{0.59cm}][r]{51%}}" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "from typing import Dict, Tuple\n", + "from depsurf import DepKind, DiffResult, IssueEnum, VersionGroup\n", + "from utils import load_pkl, save_latex, mini_bar, center_cell\n", + "\n", + "data: DiffResult = load_pkl(\"src\")\n", + "\n", + "KINDS = {\n", + " DepKind.FUNC: DepKind.FUNC,\n", + " DepKind.STRUCT: DepKind.STRUCT,\n", + " DepKind.TRACEPOINT: \"Tracept\",\n", + "}\n", + "\n", + "GROUPS = {VersionGroup.LTS}\n", + "\n", + "ISSUES_IGNORE = [\n", + " IssueEnum.ADD,\n", + " IssueEnum.REMOVE,\n", + " IssueEnum.OLD,\n", + " IssueEnum.NEW,\n", + "]\n", + "\n", + "\n", + "table: Dict[Tuple[str, str], Dict[Tuple[DepKind, str], str]] = {}\n", + "for group, group_result in data.items():\n", + " if group not in GROUPS:\n", + " continue\n", + "\n", + " for pair, pair_result in group_result.items():\n", + " col = {}\n", + "\n", + " for kind, kind_result in pair_result.iter_kinds():\n", + " if kind not in KINDS:\n", + " continue\n", + " change = kind_result.issues[IssueEnum.CHANGE]\n", + " for issue, count in kind_result.iter_issues():\n", + " if issue in ISSUES_IGNORE:\n", + " continue\n", + " if count == 0:\n", + " continue\n", + " if kind == DepKind.TRACEPOINT:\n", + " if issue not in (\n", + " IssueEnum.CHANGE,\n", + " IssueEnum.TRACE_EVENT_CHANGE,\n", + " IssueEnum.TRACE_FUNC_CHANGE,\n", + " ):\n", + " continue\n", + "\n", + " if issue == IssueEnum.CHANGE:\n", + " issue = \"No. changed\"\n", + " text = f\"{count}\"\n", + " text = f\"{count / 1000:.1f}k\" if count > 1000 else str(count)\n", + " else:\n", + " issue = f\" - {issue}\"\n", + " text = mini_bar(\n", + " text=f\"{count / change * 100:.0f}%\",\n", + " percent=count / change,\n", + " total_width=1.15,\n", + " color=\"change\",\n", + " bg_color=\"bg\",\n", + " )\n", + "\n", + " col[(kind, issue)] = text\n", + "\n", + " table[(group.to_str(pair.v1), group.to_str(pair.v2))] = col\n", + "\n", + "df = pd.DataFrame(\n", + " {\n", + " (\n", + " \"Linux Kernel Version\",\n", + " center_cell(f\"{v1} - {v2}\"),\n", + " ): {(KINDS[kind], issue): text for (kind, issue), text in col.items()}\n", + " for (v1, v2), col in table.items()\n", + " }\n", + ")\n", + "latex = df.to_latex(multicolumn_format=\"c\", column_format=\"cl|rrrr\")\n", + "save_latex(latex, \"breakdown\")\n", + "df" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/39_config.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/39_config.ipynb new file mode 100644 index 00000000..73bd9c72 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/39_config.ipynb @@ -0,0 +1,298 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Configuration\n", + "\n", + "This notebook generates the table for differences by configuration." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "from typing import Dict, Tuple\n", + "from depsurf import DepKind, DiffResult, IssueEnum, VersionGroup\n", + "from utils import (\n", + " load_pkl,\n", + " GRAY_DASH,\n", + " save_latex,\n", + " FLAVOR_NAMES,\n", + " ARCH_NAMES,\n", + " mini_bar,\n", + ")\n", + "\n", + "data: DiffResult = load_pkl(\"config\")\n", + "\n", + "ISSUES = {\n", + " IssueEnum.NEW: \"#\",\n", + " IssueEnum.ADD: \"$+$\",\n", + " IssueEnum.REMOVE: \"$-$\",\n", + " IssueEnum.CHANGE: r\"$\\\\Delta$\",\n", + "}\n", + "\n", + "KINDS = {\n", + " DepKind.STRUCT: \"Struct\",\n", + " DepKind.CONFIG: \"Config\",\n", + " DepKind.FUNC: \"Func\",\n", + " DepKind.TRACEPOINT: \"Tracept\",\n", + " # DepKind.TRACEPOINT: r\"\\\\shortstack{Tracept\\\\\\\\($\\\\Delta=0$)}\",\n", + " DepKind.SYSCALL: r\"\\\\shortstack{Native\\\\\\\\Syscall}\",\n", + " DepKind.REGISTER: \"Register\",\n", + "}\n", + "\n", + "ROWS = [\n", + " (DepKind.CONFIG, IssueEnum.NEW),\n", + " *(\n", + " (kind, issue)\n", + " for kind in (DepKind.FUNC, DepKind.STRUCT, DepKind.TRACEPOINT)\n", + " for issue in ISSUES\n", + " ),\n", + " *(\n", + " (DepKind.SYSCALL, issue)\n", + " for issue in [i for i in ISSUES if i != IssueEnum.CHANGE]\n", + " ),\n", + " (DepKind.REGISTER, IssueEnum.CHANGE),\n", + "]\n", + "\n", + "GROUPS = {\n", + " VersionGroup.ARCH: \"Architecture\",\n", + " VersionGroup.FLAVOR: \"Flavor\",\n", + "}\n", + "\n", + "DEFAULT = (r\"\\\\multicolumn{1}{c|}{def-}\", r\"\\\\multicolumn{1}{c|}{ault}\")\n", + "\n", + "COLORS = {\n", + " DepKind.FUNC: \"func\",\n", + " DepKind.STRUCT: \"struct\",\n", + " DepKind.TRACEPOINT: \"tp\",\n", + " DepKind.SYSCALL: \"syscall\",\n", + "}\n", + "\n", + "\n", + "def format_val(v) -> str:\n", + " if v > 1000:\n", + " return f\"{v / 1000:.1f}k\"\n", + " if v == 0:\n", + " return GRAY_DASH\n", + " return str(v)\n", + "\n", + "\n", + "table: Dict[Tuple[str, str], Dict[Tuple[DepKind, IssueEnum], str]] = {}\n", + "\n", + "def_pair_result = list(data[VersionGroup.ARCH].values())[0]\n", + "col = {(kind, issue): GRAY_DASH for kind, issue in ROWS}\n", + "for kind, kind_result in def_pair_result.iter_kinds():\n", + " for issue, count in kind_result.iter_issues():\n", + " if issue == IssueEnum.OLD:\n", + " col[(kind, IssueEnum.NEW)] = format_val(count)\n", + " continue\n", + "table[DEFAULT] = col\n", + "\n", + "max_counts = {\n", + " kind: max(\n", + " count\n", + " for group, group_result in data.items()\n", + " for pair, pair_result in group_result.items()\n", + " for issue, count in pair_result.kind_results[kind].iter_issues()\n", + " if issue not in (IssueEnum.OLD, IssueEnum.NEW)\n", + " )\n", + " for kind in [DepKind.FUNC, DepKind.STRUCT, DepKind.TRACEPOINT, DepKind.SYSCALL]\n", + "}\n", + "\n", + "for group, group_result in data.items():\n", + " if group not in GROUPS:\n", + " continue\n", + " for pair, pair_result in group_result.items():\n", + " col = {(kind, issue): GRAY_DASH for kind, issue in ROWS}\n", + " for kind, kind_result in pair_result.iter_kinds():\n", + " for issue, count in kind_result.iter_issues():\n", + " if (kind, issue) not in ROWS:\n", + " continue\n", + " text = format_val(count)\n", + " if issue != IssueEnum.NEW:\n", + " text = mini_bar(\n", + " text,\n", + " count / max_counts[kind],\n", + " 0.8,\n", + " COLORS[kind],\n", + " )\n", + " col[(kind, issue)] = text\n", + " if group == VersionGroup.ARCH:\n", + " name = ARCH_NAMES[pair.v2.arch]\n", + " col[(DepKind.REGISTER, IssueEnum.CHANGE)] = \"Yes\"\n", + " elif group == VersionGroup.FLAVOR:\n", + " name = FLAVOR_NAMES[pair.v2.flavor]\n", + " table[(GROUPS[group], name)] = col\n", + "\n", + "\n", + "df = pd.DataFrame(\n", + " {\n", + " (group, name): {\n", + " (KINDS[kind], ISSUES[issue]): text for (kind, issue), text in col.items()\n", + " }\n", + " for (group, name), col in table.items()\n", + " }\n", + ")\n", + "\n", + "latex = df.to_latex(\n", + " multicolumn_format=\"c|\", column_format=r\"p{7ex}p{1.5ex}|r|rrrr|rrrr\", multirow=True\n", + ")\n", + "\n", + "save_latex(latex, \"cfg\", rotate=False)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "import csv\n", + "import json\n", + "\n", + "results_dir = Path(\"./results\")\n", + "results_dir.mkdir(parents=True, exist_ok=True)\n", + "\n", + "table_counts: Dict[Tuple[str, str], Dict[Tuple[DepKind, IssueEnum], int | None]] = {}\n", + "\n", + "def_pair_result = list(data[VersionGroup.ARCH].values())[0]\n", + "baseline = {(kind, issue): None for (kind, issue) in ROWS}\n", + "for kind, kind_result in def_pair_result.iter_kinds():\n", + " for issue, count in kind_result.iter_issues():\n", + " if issue == IssueEnum.OLD and (kind, IssueEnum.NEW) in baseline:\n", + " baseline[(kind, IssueEnum.NEW)] = int(count)\n", + "table_counts[DEFAULT] = baseline\n", + "\n", + "for group, group_result in data.items():\n", + " if group not in GROUPS:\n", + " continue\n", + " for pair, pair_result in group_result.items():\n", + " col = {(kind, issue): None for (kind, issue) in ROWS}\n", + " for kind, kind_result in pair_result.iter_kinds():\n", + " for issue, count in kind_result.iter_issues():\n", + " if (kind, issue) not in col:\n", + " continue\n", + " col[(kind, issue)] = int(count)\n", + " if group == VersionGroup.ARCH:\n", + " name = ARCH_NAMES[pair.v2.arch]\n", + " else:\n", + " name = FLAVOR_NAMES[pair.v2.flavor]\n", + " if (DepKind.REGISTER, IssueEnum.CHANGE) in col:\n", + " col[(DepKind.REGISTER, IssueEnum.CHANGE)] = None\n", + " table_counts[(GROUPS[group], name)] = col\n", + "\n", + "row_labels = [(KINDS[k], ISSUES[i]) for (k, i) in ROWS]\n", + "col_labels = list(table_counts.keys())\n", + "with (results_dir / \"39_config.labels.json\").open(\"w\") as f:\n", + " json.dump({\"rows\": [list(x) for x in row_labels], \"cols\": [list(x) for x in col_labels]}, f, indent=2)\n", + "\n", + "import re\n", + "\n", + "def _sanitize_token(s: str) -> str:\n", + " s = str(s)\n", + " s = s.replace(\"\\\\\", \" \")\n", + " s = re.sub(r\"\\\\[A-Za-z]+\", \"\", s)\n", + " s = s.replace(\"{\", \"\").replace(\"}\", \"\")\n", + " s = s.replace(\"$\", \"\")\n", + " s = s.strip()\n", + " s = re.sub(r\"\\s+\", \"_\", s)\n", + " s = re.sub(r\"[^0-9A-Za-z_]+\", \"_\", s)\n", + " s = re.sub(r\"_+\", \"_\", s)\n", + " return s.strip(\"_\").lower()\n", + "\n", + "_KIND_PLAIN = {\n", + " DepKind.CONFIG: \"config\",\n", + " DepKind.FUNC: \"func\",\n", + " DepKind.STRUCT: \"struct\",\n", + " DepKind.TRACEPOINT: \"tracept\",\n", + " DepKind.SYSCALL: \"native_syscall\",\n", + " DepKind.REGISTER: \"register\",\n", + "}\n", + "\n", + "_ISSUE_PLAIN = {\n", + " IssueEnum.NEW: \"no\",\n", + " IssueEnum.ADD: \"plus\",\n", + " IssueEnum.REMOVE: \"minus\",\n", + " IssueEnum.CHANGE: \"delta\"\n", + "}\n", + "\n", + "def _row_id(kind: DepKind, issue: IssueEnum) -> str:\n", + " k = _KIND_PLAIN.get(kind, _sanitize_token(KINDS[kind]))\n", + " i = _ISSUE_PLAIN.get(issue, _sanitize_token(ISSUES[issue]))\n", + " return f\"{k}_{i}\"\n", + "\n", + "def _col_id(k: Tuple[str, str]) -> str:\n", + " if k == DEFAULT:\n", + " return \"default\"\n", + " g, n = k\n", + " g = _sanitize_token(g)\n", + " n = _sanitize_token(n)\n", + " if g and n:\n", + " return f\"{g}_{n}\"\n", + " return g or n or \"col\"\n", + "\n", + "flat_col_headers = [_col_id(k) for k in col_labels]\n", + "flat_row_labels = [_row_id(kind, issue) for (kind, issue) in ROWS]\n", + "\n", + "csv_path = results_dir / \"39_config.csv\"\n", + "with csv_path.open(\"w\", newline=\"\") as f:\n", + " w = csv.writer(f)\n", + " w.writerow([\"row\"] + flat_col_headers)\n", + " for (kind, issue), row_name in zip(ROWS, flat_row_labels):\n", + " row = [row_name]\n", + " for col_key in col_labels:\n", + " v = table_counts[col_key].get((kind, issue), None)\n", + " if v is None or v == 0:\n", + " row.append(\"\")\n", + " else:\n", + " row.append(str(int(v)))\n", + " w.writerow(row)\n", + "\n", + "print(\"Column headers (flattened, plain):\")\n", + "print(flat_col_headers)\n", + "print(\"Row labels (flattened, plain):\")\n", + "print(flat_row_labels)\n", + "print(f\"Wrote {csv_path} and {results_dir / '39_config.labels.json'}\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/40_inline.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/40_inline.ipynb new file mode 100644 index 00000000..304e9bb1 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/40_inline.ipynb @@ -0,0 +1,782 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Function Inlining\n", + "\n", + "This notebook generates the table for function inlining." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Dict\n", + "\n", + "from depsurf import FuncGroup, FuncGroups, InlineType, Version\n", + "from utils import OUTPUT_PATH\n", + "\n", + "\n", + "def count_inline(v: Version):\n", + " groups = FuncGroups.from_dump(v.func_groups_path)\n", + " results: Dict[InlineType, Dict[str, FuncGroup]] = {t: {} for t in InlineType}\n", + "\n", + " for group in groups.iter_groups():\n", + " results[group.inline_type][group.name] = group\n", + "\n", + " output_path = OUTPUT_PATH / \"inline\" / v.name\n", + " output_path.mkdir(parents=True, exist_ok=True)\n", + " for t, group in results.items():\n", + " path = output_path / f\"{t.name.lower()}.txt\"\n", + " with open(path, \"w\") as f:\n", + " for group in results[t].values():\n", + " for func in group.funcs:\n", + " lines = (\n", + " f\"{func.name}\",\n", + " f\"\\tLoc: {func.loc}\",\n", + " f\"\\tFile: {func.file}\",\n", + " f\"\\tInline: {func.inline}\",\n", + " f\"\\tExternal: {func.external}\",\n", + " f\"\\tCaller Inline ({len(func.caller_inline)})\",\n", + " *(f\"\\t\\t{caller}\" for caller in func.caller_inline),\n", + " f\"\\tCaller Func ({len(func.caller_func)})\",\n", + " *(f\"\\t\\t{caller}\" for caller in func.caller_func),\n", + " )\n", + " print(\"\\n\".join(lines), file=f)\n", + " print(f\"Saved {len(results[t]):5} groups to {path}\", flush=True)\n", + "\n", + " return {t: len(d) / groups.num_groups for t, d in results.items()}\n", + "\n", + "\n", + "# count_inline(VERSION_LAST)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.4.0-21-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 31197 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.4.0-21-generic-amd64/no.txt\n", + "Saved 19900 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.4.0-21-generic-amd64/full.txt\n", + "Saved 6306 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.4.0-21-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.8.0-22-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 32826 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.8.0-22-generic-amd64/no.txt\n", + "Saved 20945 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.8.0-22-generic-amd64/full.txt\n", + "Saved 6610 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.8.0-22-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.10.0-19-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 33643 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.10.0-19-generic-amd64/no.txt\n", + "Saved 21649 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.10.0-19-generic-amd64/full.txt\n", + "Saved 6744 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.10.0-19-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.13.0-16-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 34636 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.13.0-16-generic-amd64/no.txt\n", + "Saved 22717 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.13.0-16-generic-amd64/full.txt\n", + "Saved 7445 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.13.0-16-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.15.0-20-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 35977 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.15.0-20-generic-amd64/no.txt\n", + "Saved 23382 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.15.0-20-generic-amd64/full.txt\n", + "Saved 7712 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.15.0-20-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.18.0-10-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 38703 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.18.0-10-generic-amd64/no.txt\n", + "Saved 24765 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.18.0-10-generic-amd64/full.txt\n", + "Saved 7181 groups to /Users/szhong/Code/DepSurf/data/output/inline/4.18.0-10-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.0.0-13-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 39450 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.0.0-13-generic-amd64/no.txt\n", + "Saved 25599 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.0.0-13-generic-amd64/full.txt\n", + "Saved 7259 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.0.0-13-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.3.0-18-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 41203 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.3.0-18-generic-amd64/no.txt\n", + "Saved 26520 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.3.0-18-generic-amd64/full.txt\n", + "Saved 7350 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.3.0-18-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 42040 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-amd64/no.txt\n", + "Saved 27224 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-amd64/full.txt\n", + "Saved 7541 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.8.0-25-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 45295 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.8.0-25-generic-amd64/no.txt\n", + "Saved 26090 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.8.0-25-generic-amd64/full.txt\n", + "Saved 8291 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.8.0-25-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.11.0-16-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 48400 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.11.0-16-generic-amd64/no.txt\n", + "Saved 27074 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.11.0-16-generic-amd64/full.txt\n", + "Saved 8416 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.11.0-16-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.13.0-19-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 47352 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.13.0-19-generic-amd64/no.txt\n", + "Saved 29570 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.13.0-19-generic-amd64/full.txt\n", + "Saved 8270 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.13.0-19-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.15.0-25-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 48216 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.15.0-25-generic-amd64/no.txt\n", + "Saved 30203 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.15.0-25-generic-amd64/full.txt\n", + "Saved 8186 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.15.0-25-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.19.0-21-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 50330 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.19.0-21-generic-amd64/no.txt\n", + "Saved 31313 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.19.0-21-generic-amd64/full.txt\n", + "Saved 7957 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.19.0-21-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/6.2.0-20-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 51429 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.2.0-20-generic-amd64/no.txt\n", + "Saved 32516 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.2.0-20-generic-amd64/full.txt\n", + "Saved 8103 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.2.0-20-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/6.5.0-9-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 53587 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.5.0-9-generic-amd64/no.txt\n", + "Saved 33495 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.5.0-9-generic-amd64/full.txt\n", + "Saved 8461 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.5.0-9-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/6.8.0-31-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 55840 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.8.0-31-generic-amd64/no.txt\n", + "Saved 34916 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.8.0-31-generic-amd64/full.txt\n", + "Saved 8917 groups to /Users/szhong/Code/DepSurf/data/output/inline/6.8.0-31-generic-amd64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-arm64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 43427 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-arm64/no.txt\n", + "Saved 27547 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-arm64/full.txt\n", + "Saved 7676 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-arm64/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-armhf.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 43148 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-armhf/no.txt\n", + "Saved 26198 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-armhf/full.txt\n", + "Saved 6671 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-armhf/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-ppc64el.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 37962 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-ppc64el/no.txt\n", + "Saved 24310 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-ppc64el/full.txt\n", + "Saved 6146 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-26-generic-ppc64el/selective.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-24-generic-riscv64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 31869 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-24-generic-riscv64/no.txt\n", + "Saved 21798 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-24-generic-riscv64/full.txt\n", + "Saved 5796 groups to /Users/szhong/Code/DepSurf/data/output/inline/5.4.0-24-generic-riscv64/selective.txt\n" + ] + } + ], + "source": [ + "from depsurf import VersionGroup, Version\n", + "\n", + "groups = [VersionGroup.REGULAR, VersionGroup.ARCH]\n", + "\n", + "data: Dict[VersionGroup, Dict[Version, Dict[InlineType, float]]] = {}\n", + "for group in groups:\n", + " group_data = {}\n", + " for version in group.versions:\n", + " group_data[version] = count_inline(version)\n", + " data[group] = group_data" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
NoFullSelective
Regular4.4.0-21-generic-amd640.5434730.3466720.109855
4.8.0-22-generic-amd640.5436480.3468810.109472
4.10.0-19-generic-amd640.5423140.3489750.108711
4.13.0-16-generic-amd640.5345230.3505820.114896
4.15.0-20-generic-amd640.5364020.3486160.114983
4.18.0-10-generic-amd640.5478210.3505360.101643
5.0.0-13-generic-amd640.5455830.3540270.100390
5.3.0-18-generic-amd640.5488390.3532560.097905
5.4.0-26-generic-amd640.5473600.3544560.098184
5.8.0-25-generic-amd640.5684900.3274510.104059
5.11.0-16-generic-amd640.5769460.3227320.100322
5.13.0-19-generic-amd640.5558270.3470980.097075
5.15.0-25-generic-amd640.5567350.3487440.094521
5.19.0-21-generic-amd640.5617190.3494750.088806
6.2.0-20-generic-amd640.5587190.3532500.088030
6.5.0-9-generic-amd640.5608680.3505750.088557
6.8.0-31-generic-amd640.5602320.3503050.089463
Arch5.4.0-26-generic-arm640.5521550.3502480.097597
5.4.0-26-generic-armhf0.5676100.3446330.087757
5.4.0-26-generic-ppc64el0.5548540.3553160.089830
5.4.0-24-generic-riscv640.5359470.3665810.097472
\n", + "
" + ], + "text/plain": [ + " No Full Selective\n", + "Regular 4.4.0-21-generic-amd64 0.543473 0.346672 0.109855\n", + " 4.8.0-22-generic-amd64 0.543648 0.346881 0.109472\n", + " 4.10.0-19-generic-amd64 0.542314 0.348975 0.108711\n", + " 4.13.0-16-generic-amd64 0.534523 0.350582 0.114896\n", + " 4.15.0-20-generic-amd64 0.536402 0.348616 0.114983\n", + " 4.18.0-10-generic-amd64 0.547821 0.350536 0.101643\n", + " 5.0.0-13-generic-amd64 0.545583 0.354027 0.100390\n", + " 5.3.0-18-generic-amd64 0.548839 0.353256 0.097905\n", + " 5.4.0-26-generic-amd64 0.547360 0.354456 0.098184\n", + " 5.8.0-25-generic-amd64 0.568490 0.327451 0.104059\n", + " 5.11.0-16-generic-amd64 0.576946 0.322732 0.100322\n", + " 5.13.0-19-generic-amd64 0.555827 0.347098 0.097075\n", + " 5.15.0-25-generic-amd64 0.556735 0.348744 0.094521\n", + " 5.19.0-21-generic-amd64 0.561719 0.349475 0.088806\n", + " 6.2.0-20-generic-amd64 0.558719 0.353250 0.088030\n", + " 6.5.0-9-generic-amd64 0.560868 0.350575 0.088557\n", + " 6.8.0-31-generic-amd64 0.560232 0.350305 0.089463\n", + "Arch 5.4.0-26-generic-arm64 0.552155 0.350248 0.097597\n", + " 5.4.0-26-generic-armhf 0.567610 0.344633 0.087757\n", + " 5.4.0-26-generic-ppc64el 0.554854 0.355316 0.089830\n", + " 5.4.0-24-generic-riscv64 0.535947 0.366581 0.097472" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "pd.DataFrame(\n", + " {\n", + " (group, version): data[group][version]\n", + " for group in data\n", + " for version in data[group]\n", + " }\n", + ").T" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[utils_matplotlib.py:86 ] INFO: Saved figure to /Users/szhong/Code/DepSurf/paper/figs/inline.pdf\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA7gAAAGICAYAAABr3EzfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAewgAAHsIBbtB1PgAAiuZJREFUeJzt3Qm81OP///+rPZUikRRJRAsqZW8RInzsWVNkibJ+UNlFiOx72Qr5UKIkawuFUpJki1Zp0Z7SXvO/Pa//95rf+7zPzDkzc94z5z1zHvfb7dzOObNeM/Oe9/v9uq7X9bpKRSKRiAEAAAAAIMuVLu4GAAAAAAAQBAJcAAAAAEBOIMAFAAAAAOQEAlwAAAAAQE4gwAUAAAAA5AQCXAAAAABATiDABQAAAADkBAJcAAAAAEBOIMAFAAAAAOQEAlwAAAAAQE4gwAUAAAAA5AQCXAAAAABATiDABQAAAADkBAJcAAAAAEBOIMAFAAAAAOQEAlwAAAAAQE4gwAUAAAAA5AQCXAAAAABATiDABQAAAADkBAJcAAAAAEBOIMAFAAAAAOQEAlwAAAAAQE4gwAUAAAAA5AQCXAAAAABATiDABQAAAADkBAJcAAAAAEBOIMAFAAAAAOQEAlwAAAAAQE4oW9wNAOLZt/dok03m9zs10Mfbd999zYIFC+zfw4YNM+eee27M251wwglm7Nix5rXXXjOXXnqpKW6u3fPmzbN/F9W9995r+vTpY+655x77t/PFF1+Y4447zrRp08b+HVbZ0s6CHDz4YJNtZnaZmZbvYjxPPPGEufHGG9OynZQqVcr+jkQiJp3ifddSNX/+fFOvXj1Tt25d+3c69xPpki3tLMivBzU02aThb78G/ph//PGHeeqpp8y4cePs57l9+3ZTo0YNU6tWLXPEEUfY794555yT1m0+LMJwTMpkG9q2bWu+/PJLM378ePt3UQ0aNMhcdtllpkuXLvbvbPrss6mdRUWAC2SBO+64w5x55pmmbNn0f2WDPhgAueKYY44x+++/f8zrGjVqlPH2ACjce++9Zy666CKzefNms9tuu9nv8e67725Wr15tfvjhB/Pcc8+Zt99+O5AANwwy1SEGhBkBLhBylSpVMr///rt5+eWXzdVXX23CTqPJW7duNbVr107r8xx++OHm119/te8PkAlXXHFFKLIk0uXaa681F1xwgR3ZypX9BEq2v//+2460Kbi9+eabTd++fU3FihXz3GbatGnm3XffNSVFSTt2vv7662bDhg1mn332SevzaF+m97VcuXJpfR4khgAXCLkbbrjBPPTQQ+a+++4znTt3Dv1BqX79+hl5Hr0PBx10UEaeCygJFNhmIrjN5H4CJduHH35o1q9fb/baay/z6KOPxrzNYYcdZn9KipJ27Ex3YOsosC1J72vYUWQKCLlTTjnFzlNZsmSJneeXLKVeHX/88aZ69eqmQoUKdt5F165d7aiwl+bBKLVJ6cmi+TH63/1455oURPPUdHv/3A6lO+tyPY/Sws4++2x7Mq02Kb3zscceSyqlyrXXn0at59Xlaoceb+DAgfbkpXLlyqZatWqmffv2ZtKkSXEfd+PGjbYtRx55pNlll11sb/+BBx5oevbsaVauXFlgL3HLli3tyYPe65NPPtlMnDgx4deD3KAR3oK+L7pc1xdlJPiff/4xVatWtVMWFi5cWOC+Q8/1/PPPJ/S4mner2/vn33rb/O+//5rbbrvNpmrru7vnnnvaEbJFixYl9RrStZ/QyLDuo7mV5cuXN3vssYc566yzCvzO//LLL6Zjx472eXbaaSfTpEkTGwxpniayfwRXlJKcim3bttnsKW2X7hiq+YvXXHNNgd+9oI8vOl53797d3lbHGH3/9X3QZT/99FOe76/jPX57v2uxjp2ffvqpvaxhw4YFvhf6vut2M2bMCOR1eWlalB5bQWK87/imTZtsmrlup+9tIrz7lHj7as2xv+SSS+zr02esDrg777zTjvwnynvu4ec+Axk+fLg59thj7Weo8xKlzH/00UeBb4MffvihPXfceeed7blPq1atzMiRI01JQYALZIGHH37Y/n7kkUcSPljoAKETzwsvvNBMmDDBNGvWzJ746cCjglT6/5NPPone3p2o1qxZ0/5/0kkn2f/dT7y5h8nSgVRFPX777Tdz4oknmqOOOsoevG+55RZz0003mSCpEITSLnXAPe200+xr/Pzzz23w/u233+a7/eLFi23b1BYVJVHAqiBBB7n+/fubFi1axCw2pFF2vUfff/+9vY/eOx14dEAaMWJEoK8J0ImRTs4UgL344osxbzNnzhz7/dZtlfkRhLVr15qjjz7aPqdOrjt06GD3M+rc0Umarg9KKvsJXaeiezqJ06iN6hbst99+9n+d3Gm/5/fV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bJeRALdx48b29/vvvx+9TKO5bv6tf/RWFi1aZH/XrFkzE00EAAAAAGS5spl4krPOOst8+eWX5o033rABa6tWrezfWh9XAe55552X7z7fffddnlRlAAAAAACKfR3czZs3m+bNm9tlfxTQOnrq008/3YwYMSLffZo0aWJvf9ttt5m+ffumu4kAAAAAgCyXkRTlChUqmLFjx9qlgMqWLWsD23LlyplLLrnEjuT6TZgwwfzyyy/275NOOikTTQQAAAAAZLmMjOD6R3NVGXm33XYz5cuXj3mbefPmmT///NP+3bp16zyjvgAAAAAAhCLABQAAAAAga4tMAc62bdvM0qVL7d977rmnTVkHAABA9uM8DyVmDm4YLVu2zHz44Yfm7rvvNh06dDA1atSwqdD6ufTSS5N+vI8//thWi65Tp46dc6zf+l+XJ7NTePHFF22V6d13393stNNOpn79+qZbt27m559/LvT+c+fONRdffLHZY4897PrBjRo1Mo888oh93IJoEP+oo46yr/2VV14x6aSdnipj68ftAAEAAJD9OM9DiUtRXrlypXnzzTfNxIkTbTC2bt06ux5ugQ0sVcrMmTMn8LYUNK+3S5cuZtCgQQk9zo4dO8xVV11VYGB4xRVXmAEDBpjSpeP3J6xYscKccsopZurUqTGvV9D87LPP2seKZdasWeaYY46x77GfAu3hw4fHfc0vv/yyufLKK82RRx5pvvnmm7TOef7rr7+iSz8tXLjQdgQAAAAg+3GehzDIWN7AsGHDbCD4zz//2P8TjaszUWBqn332MQcddJD57LPPkr7vHXfcEQ1umzVrZnr27GlHXRWUa/R0+vTpNoDUiOyDDz4Y8zEU5CsIdcGtqk0r4Kxevbr59ttv7TJJGnHWSG7t2rXtiLNf9+7dbXCrdJD+/fubevXqmZEjR5pHH33UvP/+++att96yo7t+KvilpZgUfD/33HMU9AIAAACQtTIS4CpIu+iii+xopwLbvfbaywaDCuAKGtVMJ6Umt2zZ0v7UrFnTzJ8/3waFyfj9999tACktWrSwyxsprVj0uFrjt02bNua7776zQWfXrl3N/vvvn+9xBg8ebL766qtooKpA0zn88MNtQHvYYYfZzoHrr7/erg/sndOgHrJx48bZv9977z2bbiwa0V27dq0ZOHCgee2112IGuLfffrsdPb7mmmvsWsUA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NaqutXg10qzgVo8BAAAAANkiIwGuS71VGrJSjxUIHn300TFvO2nSJBtczZw5045YKnU23m2LQinI/jTkotDoq36KQqnH11xzjf0pCo0Iu9ToRCigfeedd4r0nAAAAABQIopMDRgwILq0joLdggLWo446yi6rs99++9n/X3zxxUw0EQAAAACQ5TIS4E6cONGO3vbu3Tvmmqt+uo2KNSnFVvcFAAAAACAUAa7m10qzZs0Svk/z5s3tbxU/AgAAAAAgFAFuxYoV7W8VTUqUu62qBwMAAAAAEIoiU5p7O2PGDDNq1CjTunXrhO6j24qbiwsAAFBSnXdbek/ZZiZx25LUlmTaE6a2oHg/pzBuxyVp+8nIu6nqwj/88IN55plnzMknn2yXvSnI+PHj7W01b7eolYkBAABSEaZADgAQogD3xhtvtEv+rFu3zq4Je9VVV5muXbuapk2b2nVkZceOHTYIfvXVV+1asFu3brXFpnRfAAi7MPXc05bwtyVswhTIhaktAIqGkcnsdV6GPrt0fH4ZaXmNGjXM0KFDzemnn262bNliXnjhBftTvnx5U716dTtSu3LlSnudqHqyrhs2bJjZbbfdMtFEAAAyhmAbAID0yFho3r59ezN58mQ7evvdd9/ZyzZv3myWLFmS77YtWrSwo7iHHnpoppqHkAhTzz1tAQAAALJL5saejbEpyVOmTDFTp041Y8aMMT/99JNZtWqVvU4juU2aNDEnnHCCadmyZSabBSBLR57C1BYAAACUsADXUQBLEAsAAAAAyLp1cAEAAAAASDcCXAAAAABATgg0RfnPP/+M/r3PPvvEvDwV3scCAAAAACDtAW69evXsby37s23btnyXp8L/WAAAAAAApD3A1fq1yVwOAAAAAEAoA9zXXnstqcsBAAAAAAhlgNulS5ekLgcAAAAAIChUUQYAAAAA5IRAR3Djef311+3vM88801StWjWh+6xfv96899579u/OnTuntX0AAAAAgOyXkQD30ksvtdWQW7RoYRo1apTQff7++297v9KlSxPgAgAAAACyP0WZCswAAAAAgKwOcLdv325/ly2bkUFmAAAAAECWC22AO2vWLPu7evXqxd0UAAAAAEAWSMvw6IQJE2JePnXqVLNixYoC77t582YzZ84c8+ijj9p5u02bNk1HEwEAAAAAOSYtAW7btm1tcOqfS9u1a9eEH0O312N069YtDS0EAAAAAOSatKUoK0B1P7EuK+ynTp065rnnnrNLCwEAAAAAUCwjuOPHj4/+rWC1Xbt2djT2lVdeMfXq1Yt7P92mYsWKplatWmbvvfdOR9MAAAAAADkqLQFumzZtYl5++OGHJ7wOLgAAAAAAycjIGjzz5s2zv2vXrp2JpwMAAAAAlEAZCXDr1q2biacBAAAAAJRgGQlwN27caIYNG2b/7tChg9l9990LvP3y5cvNxx9/bP++8MILTbly5TLRTAAAAABAFstIgDt06FBz2WWX2RTliy66qNDb77rrruaOO+4wixcvNuXLlzcXXHBBJpoJAAAAAMhiaVsmyGvUqFH29/nnn2/Kli08ptZtFNSqAvOIESMy0EIAAAAAQLbLSID7/fff2yWAWrdunfB93G2nTZuWxpYBAAAAAHJFRgLcJUuW2N/JrG1bp04d+1tpygAAAAAAhCLALVOmjP29efPmhO+zZcsW+1tpygAAAAAAhCLArVmzpv39008/JXyfmTNn2t+FVVwGAAAAACBjAe7RRx9tR2JfeumlhO8zYMAAO2/3yCOPTGvbAAAAAAC5ISMBrlsa6LvvvjM33HBDgWnHuk63ccWlEllWCAAAAACAjAS4HTp0MO3atbPB67PPPmuOOOII8+abb5oFCxbYubb60d9vvPGGvU63cVWXzzjjjEw0EQAAAACQ5QpflDYgQ4cONW3btrXzcDU626VLl7i3VSB88MEHm+HDh2eqeQAAAACALJeREVypXr26+fbbb82NN95odtppJxvExvqpVKmS+e9//2smT55s7wMAAAAAQKhGcEWB7eOPP27uueceM27cODN9+nSzYsUKe12NGjVM8+bNzXHHHWeqVauWyWYBAAAAAHJARgNcRwHsWWedZX8AAAAAAMiqFGUAAAAAANKJABcAAAAAkBMynqK8cuVKM2nSJDN37lyzbt06s3379kLvc/fdd2ekbQAAAACA7JWxAHfZsmXmpptuMu+++67Ztm1bUvclwAUAAAAAhCLAXb16tTn22GPNnDlz7FJAAAAAAABk5Rzcfv36mdmzZ9vgtn379uaTTz4xy5cvt+nJO3bsKPQHAAAAAIBQjOCOHDnSlCpVypx66qnmgw8+yMRTAgAAAABKmIyM4P7555/2d48ePTLxdAAAAACAEigjAW6VKlXs75o1a2bi6QAAAAAAJVBGAtyDDz7Y/l6wYEEmng4AAAAAUAJlJMDt1q2bLTD1xhtvZOLpAAAAAAAlUEYC3PPOO89cfPHF5v3337cVlQEAAAAAyMoqyhMmTDCXX365mTdvnrnjjjvMe++9Zy666CJz0EEHmUqVKhV6/9atW2eimQAAAACALJaRALdt27Z2mSBn2rRp9icRut+2bdvS2DoAAAAAQC7ISIArmoMLAAAAAEBWB7jjx4/PxNMAAAAAAEqwjAS4bdq0ycTTAAAAAABKsIxUUQYAAAAAIN0IcAEAAAAAOYEAFwAAAACQEzIyB7ddu3Yp31fLBI0dOzbQ9gAAgP9n3a/9irsJAABkT4D7xRdf2EC1oKWCvOvkirut/3IAAAAAAIotwG3dunWhgeq///5rZs+ebdasWWNv26BBA1OrVq1MNA8AgIxixBQAigf739yXsRHcRH300Ufm+uuvN6tWrTKvvPKKOeaYY9LaNgAAgLDjpDz870uY2gKUZBkJcJNxyimnmObNm9ufs846y0yfPt3Url27uJsFAABKWJAQpraECe8LECy+Uzke4Mqee+5pbrrpJtOrVy/zyCOPmKeeesqEVaJzhNu0aVPoSPbHH39sBg4caKZOnWqWL19udt99d9OyZUtz1VVXmQ4dOhR433Xr1pm+ffuaoUOHmsWLF9v7nnHGGaZPnz6mRo0aBd7Xvc+dOnUyb7zxRkKvBwAAACgIgRuKQygDXDn22GPt79GjR4c6wA3Cjh07bBCrlGyvRYsW2Z8RI0aYK664wgwYMMCULp1/ZadNmzbZStXfffddnvs+//zz5rPPPjOTJ082u+22W8zn/vXXX80TTzxhqlWrZvr372+KW5h2hGFqC8IvTNsLbQl/WwAAQAkLcMuXL29/azQyG1xzzTWme/fuca+vXLly3OvuuOOOaHDbrFkz07NnT1O/fn0zZ84cO7KqNO2XX37Zjso++OCD+e6vwFTBbbly5cx9991nR4t/+OEHOzKrwl29e/c2L730Usznvvbaa83WrVvtSK9GzhFOnJgDAAAAWRzgfvXVV/Z3pUqVTDbYY489TJMmTZK+3++//24effRR+3eLFi3MhAkTzE477WT/V3ry6aefbgNWBbAKZLt27Wr233//PI8xaNAg+1tBqoJZOeqoo8wuu+xiLrroIjNkyBA7mqsA2Ovtt98248aNMwcffLDp0aNHyq8dJUuYgu0wtQUAACBXrMvic6z8+a4hMGnSJDsSqfmthx9+uMllTz75pNm2bZv9+5lnnokGt44CfF0uup3Sif1zb+fOnWv/vvDCC/Nc17FjR1O2bFmzceNGM2vWrDzXrV+/3txyyy327+eee87eDgAAAACyWUaiGgWricxDXb16tR2p/Pbbb+3/CnBVbCpXRSIRM3LkSPv3QQcdZI488siYt9PlBx54oA1Sdftnn302Wtxq7dq10dv51w1W0Kq5t3///Xee28m9995r5+mqsFSrVq3S8OoAAAAAIAcDXAVTiVYbdoGfgjPNPz3xxBNNrpo3b150jrHSkAui6xXgKiidP3++qVevnr28atWq0dssXbrU1K1bN/q/RnxXrlxp/1YRKeeXX36xhbt03zAUlgIAAACAIGQsL1VBa0EUAO+88842cFMwp6rCjRo1Mtli2LBhdokeBZ9lypSxBZuOPvpoc+mll5rjjjsu5n0UaDoawS2I93pVPvYGuPpbwbLa4NKO5d1337VBrtKeGzRoEL1c8211eToKS/31118FXr9kyZJAnw8AAACZwXkeskFGAlylG+c6b7Aqql6sn9dff92ceeaZthCUdxTVv5OoU6dOgY+/9957R/9euHBhnusuueQSmwZ+55132o4EpRzPmDHDVlF2c3NdVeq33nrLrserwlKqoBw0bzsBAACQOzjPQzagslARqQiUKh0ff/zxdpS1SpUqZvny5ebLL780L774ok0R1jq2Z5xxhvn888/zVDJWgShH9yuId5khFYjyUiCrubkKarXEkNd+++1nHn744ejzUVgKAAAAQK4qm66CUloTtkaNGibXaU6sluPx09zh6667znTo0MGuY6uA94UXXjDXX3999DabNm2K/u1GWOOpUKFC9G9VRfYH2Xr8+++/36YpKz1Ea+Yq8FYasvsc7rnnHnudt7DUP//8Yz8zpTPrOqUsn3feeebuu++2KePJ8o8u++k5cr0yNgAAQC7iPA8lMsB1BaXOPffcmAGuiioplVa3eeWVV0y2ixXcOjVr1rSBo0Z2t27dapf78Qa4FStWjP69ZcuWAp9n8+bN0b/9SwmJ0p+1nq5bU9dv5syZ9vm9haUUKLdt29YG4Aqw69evb+bMmWMfQ2nMEydOzNPGRBSWag0AAIDsxHkeskHG18HVUkCaj6qfkkApwq4S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yVTzAAAAAABZLmMBrpx66qlm/vz55v333zdjxoyxc21XrVplr6tevbpp0qSJOeGEE8yZZ55pypUrl8mmAQAAAACyXNmMP2HZsqZjx472BwAAAACAoLDILAAAAAAgJxDgAgAAAAByAgEuAAAAACAnEOACAAAAAHICAS4AAAAAICcQ4AIAAAAAcgIBLgAAAAAgJxDgAgAAAAByAgEuAAAAACAnEOACAAAAAHICAS4AAAAAICcQ4AIAAAAAckJZE0Lt2rWL/l2qVCkzduzYYm0PAAAAACD8QhngfvHFFzawjUQi9jcAAAAAAFmboqzgFgAAAACArB7BnTdvXnE3AQAAAACQZUIZ4NatW7e4mwAAAAAAyDKhTVEGAAAAACB0I7gTJkywv1u2bGl22mmnhO6zadMmM2XKFPt369at09o+AAAAAED2y0iA27ZtW1O6dGnz448/mkaNGiV0n0WLFkXvt23btrS3EQAAAACQ3UqHvSoy1ZQBAAAAAFk9B3fHjh32d5kyZYq7KQAAAACALBDaAHfBggX2d7Vq1Yq7KQAAAACAkjoH988//4x5+ZIlS0yVKlUKvO/mzZvNnDlzzF133WVKlSplGjdunI4mAgAAAAByTFoC3Hr16sWcS9u+ffukH6tz584BtQoAAAAAkMvSEuDGKwyVTMGoihUrmuuvv9507do1wJYBAAAAAHJVWgLc1157Lc//l112mU03vv/++03t2rXj3k+3UWBbq1Yt06xZs0LTmQEAAAAASGuA26VLl3wBrpx55pkJr4MLAAAAAECxB7h+48ePjzs3FwAAAACArAlw27Rpk4mnAQAAAACUYBkJcLdv326+/vpr+/ehhx5a6Nq2a9asMT/++KP9u1WrVnZuLgAAAAAABSltMmDEiBGmbdu25pxzzjHlypUr9Pbly5c3Z599tjnuuOPM6NGjTUmyYMECc/PNN5uDDjrIVK5c2VSvXt20bNnS9O/f32zYsKHA+7777rvmqKOOsverWrWqOfHEE82ECRMKfc6ZM2faz0XPtWLFigBfDQAAAADkWID7/vvv298dO3Y0lSpVKvT2us35559vlxUaPny4KSlGjRplDjnkEPP444+bWbNm2YB29erV5rvvvjM9e/a0laVnz54d876PPfaYfX8nT55s77du3TozZswY065dO/Pee+8V+Lw9evQw27ZtMw888ICpUaNGml4dAAAAAORAgDt16lSbZqxgK1HutgrYSoLp06fboP6ff/6xyyMp2Pzmm2/M2LFjzZVXXmlv8/vvv5tTTz3VBq9ec+fONb1797Z/n3baaebzzz+3I99HHnmkTQ+/4oorzPr162M+7+uvv24mTpxoDjvsMNOtW7cMvFIAAAAAyOI5uAsXLky6ivK+++6b57657oYbbjAbN240ZcuWNZ999plNNfYG+wcccIAdxVWQq9Hae++9N3r9kCFD7Ahsw4YNzciRI03p0v9/v0Xr1q3t+7hy5UqbJt6pU6c8z7l27Vr7mOp8eO6556L3AwAAAIBslNGIRinHyd5WgVuumzJlih1FlcsvvzxPcOtoXq4CWHnqqafM1q1bo9f98MMP9vd5552XJ0jVSLBGdL238brrrrvM33//bbp27WqOOOKINLwyAAAAAMixAHf33Xe3v3/77beE7+NuWxLmhGp01bnsssti3kaBa+fOnaNVpt3awm4kVmrVqpXvfnvuuWee2zgzZswwzz//vNl1111Nv379AnolAAAAAJDjAa6qAGtEVvM9EzVo0CCbOtu8eXOT67766iv7W9WPNRc2kfWE3bJL4pZdWrp0ab77uMu8SzPps1BhKc3PpbAUAAAAgFyRkQD33HPPtb9VMEnzRwuj24wbN87+rcrAue7XX3+1v/fff387BzceLR3kv49bW9gtE+RNA//333/Nhx9+aP9u2rRp9PLBgwfbAFmdBxSWAgAAAJArMlJkStWBH374YZsWq6JGkyZNMjfeeKOt8usCOs211eVPPvmkTdnV6G2TJk3yFUbKNZs2bYquPVunTp0Cb6t0Yo3yKnD1Ft+66KKLzH333Wd++uknu9bwtddeazZv3mxHZ1VgapdddjFnnHFGNL25V69eaSss9ddffxV4vbfdS5YsyXf9tn/Suw5vYe2jLcXflmTaQ1toC20peltK2j6GttCWXPxea0paQYMk6X7+eOd5mXhPwrjNCG1Kvl2BbceRDJk3b15kr732ipQqVSpSunRp+1OhQoVIrVq17I/+dpfrNrVr17b3yXXLli3TkKv9Of/88wu9/R577GFv26RJkzyXP/DAA9HH8f6UKVMmMnTo0OjtevToYS/v2rVrWl5PrDbwww8//PDDDz/88JO+n4ULF6blvI7zPH5MFm7HGauirOVqtNbrmWee6QJrs2XLFjtHVD/626XXnn322eb777+PLhWU6yO4Tvny5Qu9fYUKFexvLSnkdfvtt5u33nrLHH744WannXayFZS1vNCYMWOiad56/1988UU7EqwRdeftt9+2VZQrVapkR3u11q7efwAAAADIJhlJUXb22GMP895779m1XEePHm0DLpeeq0JHmhOq4EprvpYUFStWjP6tIL8wSj0WBbF+F154of2JRZ0H3bt3t4Wl+vbtGy0spUC3d+/e9m91KKxfv9589NFHtkrzp59+alq1apXU6yls3WIF9KqQXbNmTVtdO9U0BKW9KJh3yyzFqiCdKbSFtmRrW8LWHtpCW2gLbaEtqXGrZqRbOs/zwvQZ0abiaVdQ23FGA1ynQYMG9gfG7LzzztG/FVwWRvNvRSO0yXj11VfN5MmTbSfC1VdfbS+bM2eOufPOO+183KFDh9piYAqE//vf/9q50FqTVzupZObpFjaP2BXTCpK+QIk8bybQlthoS/jbErb20JbYaEtstCU22hIbbUldps7zwvi+0KbsaVfGUpQRfwR3t912S2ji9+rVq6MB7t57753wc+h+GqX1F5ZSSrOKe5122mnRSte6zUMPPWR73f744w/zzTffFOHVAQAAAECOBLhKQ77uuuvM6aefblOPr7zySjNkyBCzdevWdD5t1mnUqJH9PXv2bBtwxqPRVKdhw4YJP77m5yoV/LLLLrOVq50ffvjB/j7mmGPyBd1u/WF3GwAAAAAIu7SkKP/999+2mJTyr2Olyt599912KaCDDz44HU+fdY499lgzceJEOzo7bdo0W/Apli+//DL6tz8ojUePN3DgQFtYql+/fnmuW7t2rf1drVq1fPdTsSnvbQAAAACgxI3gqoiRRmy//fZbO58z1s+8efPMSSedFC0wVdK5ytLy2muvxbzNjh07zOuvvx4NPo877rhCH1fvdY8ePex9VVhKacdeLrCNlRrtighUrVo1yVcDAAAAADkS4KpY0dSpU+1cTk0yf+WVV8zMmTNteu2wYcOiKbIa5X3ssceCfvqspIpjrlqx3q9Jkyblu43eq19//dX+fcMNN5hy5coV+rgvv/yy7Who1qxZtLCU16GHHmp/v/POO7ZjwlHxKd1PmjZtWoRXBgAAAABZHuC6JWeUoqx5n40bN7ZVk8855xybitumTRs7uqiAF/+/p556yi79ozm47du3t4WeVPVYy/V069bN9OzZ095O7+PNN99c6OOtWrXK3Hbbbbaj4fnnn49ZCfniiy+25ds19/eMM84wY8eONSNHjjSnnHKKDXjr16+fcCo0AAAAAOTcHFytbaugSkGYm8fpVaZMGdOnTx/Ttm1bm6q8bt26PEvllFQaZdVIaqdOncw///xjC0P5KbhV4a5E3i8FtytXrsxXWMpLAez9999vb6vH1Y9ToUIFO5qczBJBAAAAAFCcSkU0lBqgypUr20WelWbrFvv127Bhg13HVYGwRg/r1asXZBOy2oIFC+xoroJNzY0tX768TfXu2LGjufbaa02lSpUKfQyliCuo1fzZ33//Pd/cW7///e9/5vHHHzc///yzTX3WqO19991nWrRoEeArAwAAAIAsC3A14qfAVfNu3fI3Bd3up59+SmrJGwAAAAAAYin2/NOA42sAAAAAQAlV7AEuAAAAAAChLDLlqHLvHnvsEcjt7r777gBbBgAAAADIRWmbgxsk7xqtAAAAAABkbAQ3yJg56GAZAAAAAJCbAg9wx48fH/RDAgAAAACQ+RRlAAAAAACKA1WUAQAAAAA5gQAXAAAAAJATCHABAAAAADmBABcAUkD5guwQps8pTG0BACBXEeCiWLi1jXfs2FHcTQntyW/YToaLuz1z5swx27ZtM2ERhiXMivszCbutW7fazyks+xn/NsPnZ0L1fkydOtWsW7fOhOF9cO9Fcb8n3ucPw/fozz//LO4moACLFy82YRLr+1Pc36lssiME3/lQrYMLFKR///7mn3/+MXfeeaepUKGC/QKVLl08fS0zZ840v//+u5k9e7Y58MADzYknnmgqV65cLG3ZsGGDWb58ualUqZIpW7asqV69ep4dcqYDqrVr15qFCxfaIGH33Xc3derUMcWlW7duZtKkSeadd94xDRs2NMVJ28wff/xhfx955JGmadOmpmbNmsXSFm0vy5Yts98fbTMNGjQotm1GJzYLFiywAYK23RYtWpji1KdPH/u9HjBggP1OFed+ZsqUKebnn3823333nWnWrJlp27at2X///Yutk0QdRdpeitvSpUvtNrN69Wqz7777moMOOqjY2nLNNdeYTz75xAwePNi0atWq2DuwVq5caapVq2Y2b95sqlSpUmzt0PugtlSsWNF2TFetWrXY2nLllVea0aNHmwkTJtjvT3EK07lDWOicbtSoUWbQoEF2PxcG7hi5Zs0a+/moXcX93c4W27dvN2XKlDGbNm0yS5YsMfXq1TNZRcsEAZlyyy23REqVKhXZb7/9Io888khk06ZN9vLt27dnvC16/n322ce2x/1069Yt8ueff9rrd+zYkbG2PPvss5E2bdrYNlSvXj1Sp06dSL9+/SJfffVV9DaZbM/AgQMjrVu3jr4vVatWjbz55pu2DZlsh9x00022DaecckpkwYIFkeLUv3//SN26dfNsM1dccUXkt99+y3hbnnjiiUizZs1sG8qVKxcpX7585Nprr42899570dtk6nv1/PPPRw477LA878sDDzwQ2bhxY6Q43HzzzbYN1apVi1x33XWRDRs2FNt+5qGHHorsscceed6b0047LTJp0qSMt+X111+P/Pvvv/bvbdu2RYrTc889F2nRokX0PSldunTkwQcfjPz9998Zb4vbx/znP/+JzJs3L1KcXnvttcg555wT2W233SIHHXRQ5Igjjoi88847kT/++CN6m0ztg4cOHWr3b/vuu2+kUaNGdh/84YcfRorDjTfeaD+jDh06RObOnRspTmE6dwgL7e/dsej444+P/PDDD8XdJHse07Zt20jlypXt/kXHA23P7rgUxs8pbG3auHFjpEmTJpGrr7662I6hqSLARcasWLEi0rx58+iJp076Hn744WIJct0JsA5SvXr1sgfPnXbayV721FNPRTKpZ8+e0cC2ZcuW0aBFO+QDDzww8sILL2R056f3Q8+vg0K7du0ixx57rP1f78/YsWMjxXFSc/7550dmzZoVKU5um1GAe8cdd0SuvPLKSM2aNSMVKlSIvPTSS8Wyzej5dcJ30kknRU+0dNmtt94avW26v1d6LtcJ0rFjR/vj2pLp90W2bNli3xM9v4IE/S6uINd16DVo0CDy6KOPRvr27Rtp2LChvez222+PZFLv3r3t855xxhnR96K4gly3/e66666RCy+8MHL66adH9zFvvfVWse1jiqOjKtb7UrFiRbvNHHDAAfb/MmXK2O+4As5MHQu0feoY5NqjNrjv9bvvvhsp6ceBMJw7hIk7b3D7N3XYF2eQ645LCrjVSaTOIv2tyy666KJIGH322WeR+++/v9g7cLy++OIL+57pPdy8eXMog/B4CHCRUWeffbYNbnVQ0O9atWplPMjViaa+sGeeeWZk5syZ0ct1YqXLNXKp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E0Nt03fffbc9CcrE6CBtCX9bAFGHrevAdWn0Os4pfVajezomqlCaP5B0v5VSryVwglz7N4xtSuecXC3jEwTVDnGPqWWHXHE6//7Eu+/RMoeq5l6rVq1iKcAVJgS4QIK0k3U9avp5/PHHYxYqytRchzC1h7YA6eEdAVR2gtJeVQ3Tv5YzbaEtKJm8AU7fvn3tyOi9996b5xg3a9asyDXXXBMpX768HQmNFVDGSn3NpTZlMshVpljQyxI9+uij0csLCnK1fNEff/wRKekIcIEUUlG81TP9qTUltT20BUifBx980PbKq/OmuDMPaEv424KSwaUAq3iTltrRmtxapsYVbfJ2vih1vrCAMlfblCljx4615x4FzdEPIgW6sCAXBLhA0rzzGsKwQwlTe2gLEBydEGptVVcYrVGjRsUWONGW8LcFJZNSgLXW+3nnnWfXee/Xr1/c1QH8AaXSadMRSIaxTZmSjkJY3tHhoUOHRi/P5vcp3UobAEmpVauW/b1jxw5TunTxf4XC1B7aAgRHndBz5swx8+fPN506dTIfffSRadiwIW2hLUDU119/bbfBTz/91CxfvtysX7/eXl6qVKl8tz3ggAPMTTfdZC6//HLz+++/m1tuucV88MEHJaJNmVKpUqXAH7NVq1bmyy+/tH+ff/75ZtiwYdH3U/sg5FdKUW6MywEAQDHbtGmT+eOPP8w+++xjqlWrRltoC5DHhg0bzMcff2z69u1rZsyYYbfDcePGmf32288GP7GCSm2v999/v/nss8/MpEmTTL169XK+Tblg4sSJpk2bNvZvBbnnnHNOcTcptAhwAQAAgCylgHL06NGmX79+Zvr06TabQH/vtddecQNKjbBWrlzZ7LnnniWmTbkW5L7//vvmjDPOKO4mhRJ5ewAAAECIbd++Pc////77b5602A4dOpjevXvbFPm3337bPPjgg2bp0qVx01jr169f5EAyjG3KdUpXHjNmTPT9Qmxl41wOAAAAoJht27bNlC1b1qbDv/LKKzaF96+//jIHHXSQufTSS03jxo3NzjvvbANKBY933XWXeemll+x977zzThs0xhs1zaU2lRTt2rWz85rTMd83V5CiDAAAAISQRknLlCljA5r//Oc/ttiQ/lfxxK1bt5p9993XBpTdu3c3NWrUsLf75JNPbEA5d+5cc+WVVwYeUIaxTYAXKcoAAABAyGgVAAWOms964oknmgkTJpguXbrYgkyq3H377bebRYsWmYEDB9r5rStXrjRVqlQxJ598si3YpKJOgwYNsmnCf//9dyCBZBjbBPgR4AIAAAAh40ZENRKqasQ9e/Y0zz33nB0hVaCpoky6ftWqVeaFF16wAeWKFSuiAaWqGOtvVTQOKmEzjG0C/EhRBgAAAELo888/Nx07djQnnHCCGTx4sK0yrNHS++67zwwZMsSmAmskVWvJKsDs3LmzHR1VavC6devs8jxNmjQJtCBRGNsEeFFkCgAAAAgZjUFNmzbNjng+8cQTNpBcuHCh/VuB5BVXXGFTgdesWWNef/118+mnn9pqxUohvuWWW8zuu+9uTj/99EDTgMPYJsCPFGUAAAAgZBQEav3Yp556ytSuXdte9tlnn9mqxRdccIENJGWXXXaxo6SiEdP+/fubZ555xv4ddCAZxjYBfozgAgAAACFUp04dU6tWLTv3dcuWLebJJ580devWtXNbZfPmzaZChQp2yZiaNWuaG264wfzvf/8zF110kb1PSWkT4MVWBgAAAISU0nvlxx9/ND///LMNMPfaay97mQJJGTlypKlevbq56qqrzMSJE+16tCWtTYBDgAsAAACEXLVq1WxguXjxYjN9+vTo5S+99JKtStyiRQtTtWpVs/POO5foNgFUUQYAAABCTsvvXH755eatt94yrVq1MkceeaT566+/zLBhw+xIqdak3X///Ut8mwACXAAAACALzJ8/31x99dXmyy+/tHNdy5Ytaw499FDzxhtvFFsKcBjbhJKNFGUASLN9993XVo0cNGhQQre/99577e31O9e0bdu2wNe2YcMG06FDB3sbVej86aefTC7R60q0guirr74afR+2b99e6O2VHqjb6+RS6YJhoTUxk9n+ARR8PFHgqCV5evXqZZfg+eCDD4o1kAxjm1CyUUUZABAKWjfx1FNPNd98841Nafv888/tiVNJdd5559nqowpWtZbkKaecUmhALOogcMVeAOQerSV79tln25+wCGObUHIxggsAIXPttdeaX3/91f4uKZYuXWratGljg1ultn311VclOriVKlWqmPPPPz9P8BqP0gI1B040Hy5MHnroIbs9n3XWWcXdFABACUCACwAhU6NGDZvapd8lgeZvqTiJlpvQb83j0tqJ+H/B6qhRo8zKlSvj3k7Lcaxatcrsscce5rTTTjNhovUytT2r2ioAAOlGgAsAIRNvDq7mMOpyzWn8999/zW233WZTebXm4J577mm6dOliFi1alO/xvPeLF2Dqeu+IqeoPnn766fbyCy+8MOb9OnXqZK9XWnGq9Qq1fuIxxxxjZs+ebR9HqbjxAqHff//ddOvWzdSvX99UrFjR3q5169bmzTffLHC+7xdffGHXYPzPf/5j0+hKly4dnQ/q5kfrPRg/frxp37692XXXXc1OO+1kmjdvbl5//fUC2//uu++ak08+2T5u+fLl7XxZvS+//PKLCcJRRx1lGjVqZLZs2RL3dXpHeDt37mzn4DpKb/7vf/9rGjZsaCpVqmSX6mjZsqV59tlnzbZt2wqcL6v5zxpBVoCqZUC826MqpJ5wwglmt912M+XKlbO/1c4rr7zSdlTEe8xYNF/v+OOPtxVXtS3XrVvXdO3a1X7esRT1MwMA5DYCXADIMmvXrjVHH320efHFF21QoTmXCjB1Yq9gUdcXlQKIwYMH22BDAYiey2vgwIG2oMjee+9tnzfRwkleU6ZMsQGqgrCLL77YjBgxwgYpsSigUuqynleBpOajan3F77//3lxyySU2IIpH91WwO3fuXBuUnXjiiTaQ8geICrI0CqqAtWnTprZokzoNnnzyyXyPqeBQwV/Hjh1tAN2gQQNz5pln2kBX74va9sknn5ggR3Ffe+21mNdrSQ7NV/beVrQ8R5MmTcwTTzxhNm3aZF+3to85c+aY6667znYoaImPWJQqrtfgPiPd1q1jed9999n5wRpp1+PrPdDSIAqCX3nlFTNu3LiEXpe2Wb2/6kBRW5s1a2bn76nzQq9V/xf0Hib7mQEASggtEwQASJ+6detqeDPy2muvJXT7e+65x95ev710f12un5NOOimydu3a6HWrVq2KNG3a1F734IMPxrxfly5dYj7fvHnz7PVqp9+3334bKV++fKRixYqR6dOn28v0W/+XLVs28s0330SS0aZNG/tcJ5xwQqRKlSr27+uuuy6yY8eOuPf58ccfIxUqVLDPOXz48DzXzZ8/P3LwwQfbxxk8eHDM59LPc889V+BnU65cucioUaNivm/VqlWLbNiwIc91t99+u73uiCOOiMydOzfPdcOGDYuUKVMmsuuuu0ZWr16d5zrXnmQsW7bMtk/3mzZtWr7r+/bta687+uijo5ctWbIksttuu0VKlSoVef755yPbt2+PXrdixYpIu3bt7H369OmT57G0jbg29u7dO8/9ZNOmTZGddtrJfna//fZbvrbo8/j1119jPqZ/+3/hhRfs5TVq1IhuW6JtwX0HdtllF/v6g/jMAAAlAwEuAGRZgFu5cuXI4sWL893v7bffttcreAkqwJWnnnrKXr///vtH/vrrL/tb/z/66KORZHmDTv00b968wOBWzj///AKfb8qUKfb6ww47LOZz+d+PWJ/Nf//735jXH3TQQfb6CRMmRC9buXKlDfIUcOv9iKV79+72fs8880yRA1w555xz7P169OiR7zr3ebz88svRy3r16mUvu/baa2M+ntqtAHH33XfP8/67YLRBgwaRbdu25bufgk1df8ghhyTc9ngBbv369e3lTz/9dL77qE16Dl3/wAMPFPkzAwCUHKQoA0CWUeqo5kX6aZ6lxJqHWxTXX3+9Oeecc+w82caNG9vfmp978803p/yYSrHW3E2lGF9zzTVx5/Du2LHDfPzxx/ZvV1E41vuhisNKT1Uqrt+5555baHs0PzeWWO+p5n1u3LjRpvtqzm0sSol2qb5BuOKKK+xvVUpWxWRHacL6PLwVl2X06NEFvmdq9wEHHGCWL19u/vjjj3zXK91aKcd+SsHWHFjNs9Xnn+pcY6VVK1ValFLsp5T3yy67LPp+F/UzAwCUHAS4AJBl9tlnn5iXV61a1f6OFeQVleY7qqqz5vdqjdV4BYMSpfmgKtCk+bQDBgwwV111VcwgV5WD//nnH/u35vsq8PH/qGjU+vXrbTAcq9JwIssNJfOeai6vjB07NmZ79KM5qqIAMggqpKTXv3r1avP+++/nKy6l51OQ62+jqlLHa6MLTmO1saD3THOuVa358ccftx0eKjClOdGa67tixYqEXo8LPnVf9x77qZiY97Zh+B4AAMLv/5VaBABkBQV0QVJgWBiNorrgRb81+qaR06LQKPDw4cPt6PDLL79s2/HSSy/leX3etsUa6fPzF4+SeIWrUn1PXZtUwVqjuAXR8jhBUPtUjfj++++3BZguuOACs27dOttJEGvtW9dGjV5Xrly5wMdWkJnMe6agWRWMNUqsEWSNUqv6tbaRe+65xwbgKv6Ubd8DAEBuIMAFgBynUVJRQBTLggULCry/Uli1/IsCCi1Do9FbjRgqJbioa5tqzVYFRKqeq9FIBWaqxOuCF40aK9hSSvCjjz4airWBNZIqBx54YJFHspOhStF9+/Y1Y8aMMQsXLrRB5YYNG2wQrZRvfxv1ufXq1avIHRGx6DNR8OzSvzUKfOedd9oq12pnYduUS+12I/SxRnHdKHS8NHAAAGKh+xMAcpwLEH777beY17v5mrEozVPLwCg4VgCj0UP9P2/evAKX5kmG0ltHjhxpl4dRwKiRSjcCqXmgSmeWoUOHmjDQ6KQ6DbQ80LJlyzL2vEob1nPrvdH75NKTY30OWjoqk++Z5uY+8sgj9u8///zTplIXpE6dOtEU5FidBEpXd5cfd9xxaWkzACA3EeACQI47/PDD7QiZ5ly+8cYb+daIffrppwssMDVjxgzTrl07m34qSidWcPLee++Zp556KpA2nnTSSeaDDz6wI4Nqo0aKt2/fbq/T8yqgvPXWW+3avLFSqn/66SfbnkyoWbOmXUf233//tYWOZs6cme82KgSl1xOvUyFVLhVZn9mkSZNM2bJl7Xvlp/dql112sfNkH3vsMbNly5Z8t1EnxZtvvpnU82tkVp+/mxftNWrUKPt71113jTuv1uuWW26xv5V2rW3MG9xqpPqHH36wr0HZAwAAJIoUZQDIEJ3Iv/jii3Gvf/75503z5s0Df14FjX369DE33XSTDYZeeOEFO6r766+/2qBXI7Nqm9+QIUPsnFgFdPrbpQ0reHnnnXfs/NOePXva9NiWLVsWuZ0aqVWQpKBRz6cAVwGY3hP91siuftTeRo0a2VHDVatW2QBTVXlVMVipzpnQr18/s2TJElvVuGnTpubQQw81++23nw041RYFZwqANS81qHm4ctZZZ5nq1atH50MrxVufT6wRUo2Ka36zAkmNrjZp0sRW31ahMH32mkd9xBFHmE6dOiX8/BqZVcDZvXt3+7rr1atnL1c6tFLWVbyqf//+MSsw+3Xr1s3O31WHhtKo27RpY4tXqbL2rFmz7Har91efMwAAiSLABYAM0ZxCN68wllijYkG58cYbbWCkEVcFIj///LMNKp588klbLMkf4CrAuPrqq21QqyBjzz33zHP9YYcdZufEaiRTgaWCEo22FZVScJUyrcDt7bfftqO1CnaVFq0gWiOXn3/+ufn6669tAKzgTu2/9tprE1oOKCgKZNUuBYca0fz222/tKLIKOimIVJCuIlqtW7cO9HlVROviiy82zzzzjP2/oDRxPbc+52effda+p1OnTrUjywoiVYFYbVcAnAyN3GubUXEpvd6PPvrIjriqw0SdJxrx17aRCAXDqsisdGrN3Z02bZrtFNC2po6M3r1723nOAAAko5QWw03qHgAAAACQBGW6aA1tTTlZvHhxzAru6aT1ydU5p7W13VrlQVizZo254447zIcffmgze7Zu3WozUlSnIZvMnz8/mpUTjwoXKoOpKNQ5feyxx5rJkyfb/ydOnGj/DxIjuAAAAADSRhkkCm5FNQE07eSGG24wuUDruKuehQoBapqMCiYGOTUl0ypXrhw3IyrRDJ2CKPtLwa2yeNI1zkqACwAAACBttPybaDrDokWL7P+5EOBqtFZL3SmoVbG8RArshV2NGjXStgSeps2ocKSmIal+RmFLyqWKKsoAAAAA0kLrdf/vf/+zf6uoXJUqVWxwo1HdbKeU5G3bttl6ELkQ3KaT3qcuXbrYAoIDBgxI63MR4AIAAABIC6XvqoiiKrlrXWsVJvSO6saiObJKYdU8Vs3RVOE+VVRX4UPv6KKCZxW+0xxOLVGmQnx169a1t1eBxHhU6V7pxBqt1H1UmV9LqiWTMqv26blEI5H63/14598qsNMKClpxoFq1ana094ADDrBF+TSaHe+x9SNaf/6oo46y99VlmitbkKOOOsreToUa41HxQd1Glfkz5cEHH7TFBLV83V577ZXW5yJFGQAAAEBauEDWVX3Xb12mAOyJJ56wI3oFBccKDjWn9YQTTrBLwykglYULF5qTTz7ZLndXqVIlu3SdClcpaFRQrFHiiy66KN9jfvrppzbIUlV4LU+nUdivvvrKLqmmx1TAnAiNRq5fv94MHz4837xVt/KAKtcrHXfMmDE2sFWAr5FeLZGmavga2VZ74i0RqJUKtISgguNTTz3VrsTgAt94LrvsMjvHVR0BF1xwQczbKGiOV4lf1exVSEqBdLly5ez7pGr3Ralqrw4FrW+uNe/VvrRTFWUAAAAACNKsWbM0JBopV65cZNmyZdHLDzroIHv566+/HvN+bdq0sdfr57nnnst3/fbt2yMtWrSw17dv3z7PY8vGjRsjo0ePjvuYL774Yp7rxo4dGylVqlSkTJkykYULFyb8+ubNm2cfr27dujGv79Wrl72+fv369rbOli1bIpdffrm9rl69epHNmzfnuZ9rZ9WqVSOTJk2KJGPt2rWRSpUqRUqXLh3566+/8l0/Y8YM+9g1a9aMbN26Nd9rifWj96ZTp06RdevWRZKl13bIIYdEdt5558iCBQuil+s902NPnDgxEjRSlAEAAAAE7tVXX7W/tS64UowdN3JYUJqytGvXznTv3j3f5aNGjTLfffedXXdcI6jexxaNlp5yyikxH1Opyd26dcv3PBpd1BI2WkYoCJs2bTLPPfec/Vsj1aqy7GhkVOu6a+7uvHnzzLvvvhvzMTSqfOSRRyb1vFWrVrVrnGsdea01Hm/09pJLLrFrujsaGb/yyivtiLJGspX+raJQ999/vx0hV+VrPW6ylY/79OljK2j379/frsGeCQS4AAAAAAKluaeDBw+OmQrbuXNnG1xNmDDBzJkzJ+5jxFuu5pNPPrG/lYKsolXJ0PzcWBo2bGh/x5sXmywF4Ephrl69esznVNDoUojjBdXxXn9hLvu/NGD3/nurPg8ZMiTmZ6LOgoEDB5r27dubOnXq2NRxzU2+8847zbhx40yZMmXMZ599ZkaOHJlwO6ZMmWIefvhh24Gg5ZQyhQAXAAAAQKBGjx5tli5dapcG0uiol0YuNcKq0UA3yhuLd9TTyy0vk8p6s/FGEV0VZI28BsEFyvXq1Yt7G81v9d420ddfmLZt25r99tvPzJo1y873dT788EOzfPlyc8QRR0QD+kQcfvjh0SBdo+eJ0Pt46aWX2tH0l19+udC5w0GiyBQAAACAQLn0YwU6bdq0yXe9C+pUDOm+++6zI4R+BRWgSpUqMWeLVF9/qVKlbHB599132/dXRaq86cmpFHpSQDxixAjz119/JXT73377zfz666+2UnWs51PnhyukpQrRKhjWu3dvEwQCXAAAAACBUWXijz76yP69cuVK8/XXX8e97eLFi23KsaoEJzsKqyAqrDRyLZpjG4+qIntvG6QuXbqYe++917zzzjvmqaeesks1ffzxxzZojldduSD6HGXnnXdO6n4rVqwwX375ZYEVlosyWh1L9nRhAAAAAAg9jRqqYJNSYZWGHO+nZ8+eCRWb8tNon2iZHS1rE0YtWrSw84O1tNEHH3yQ7/qNGzdG16rV8kFB22effczxxx9vA9v33nvPFonSvGgV2dKIaTL0HrvUZKUrJ6Jp06YFfvZuDWEt6aT/vesbFxUBLgAAAIDAuHm1GkUsiIpNeeeGJkpVmZs1a2ZHfzt27BgdXXSUFq3RyuKkuac9evSwf998883RecOu2NMNN9xg03Q1RzfVYlKF6fp/haSUmlxYerIKTKl6sp9GoM844ww7Kr/LLrvEXDtXgbTmQ7///vsmDEhRBgAAABAIpaPOnj3bLjtTWCps48aNTfPmzc33339vl7RRIJjoPFoFUypepUBWo5XHHnus2W233ezc3hkzZthgbP78+aY4aYkcVVMeO3asncOqkVql+E6aNMn8+eeftr3Dhg0z5cuXT8vzn3nmmWbXXXe1z+/SgFXROJbnn3/eXH311fYzadCggW2TglulEG/evNm2VSPBmlPrp0rYCuDXrl1rwoARXAAAAACBcOnGqrqr4KowbhQ32TRlpbgqeNQyNArKFDQqAFOgpaJWury4KcjX/GIFj4ceeqhNx1VgrnVwVVxJgfhhhx2W1lHkCy+8MPq/RtTjVTO+/vrr7Wi40pi/+OILuzavqjAfcsgh5p577jG//PKLad26tckGpSLJrtYLAAAAAEAIMYILAAAAAMgJBLgAAAAAgJxAgAsAAAAAyAkEuAAAAACAnECACwAAAADICQS4AAAAAICcQIALAAAAAMgJBLgAAAAAgJxAgAsAAAAAyAkEuAAAAACAnECACwAAAADICQS4AAAAAICcQIALAAAAAMgJBLgAAAAAgJxAgAsAAAAAyAkEuAAAAACAnECACwAAAADICQS4AAAAAICcQIALAAAAAMgJBLgAAAAAgJxAgAsAAAAAyAkEuAAAAACAnECACwAAAAAwueD/A9Gh401dfpc0AAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from typing import List\n", + "\n", + "from matplotlib import pyplot as plt\n", + "from matplotlib.axes import Axes\n", + "from matplotlib.ticker import FuncFormatter\n", + "\n", + "from depsurf import InlineType, VersionGroup\n", + "from utils import get_legend_handles_labels, save_fig, ARCH_NAMES\n", + "\n", + "COLORS = {\n", + " InlineType.NO: \"tab:blue\",\n", + " InlineType.FULL: \"tab:green\",\n", + " InlineType.SELECTIVE: \"tab:red\",\n", + "}\n", + "\n", + "NAMES = {\n", + " InlineType.NO: \"Not inlined\",\n", + " InlineType.FULL: \"Fully inlined\",\n", + " InlineType.SELECTIVE: \"Selectively inlined\",\n", + "}\n", + "\n", + "GROUPS = {\n", + " VersionGroup.REGULAR: \"Linux Kernel Version\",\n", + " VersionGroup.ARCH: \"Arch for v5.4\",\n", + "}\n", + "\n", + "fig, axs = plt.subplots(\n", + " 1,\n", + " len(data),\n", + " figsize=(5, 1.25),\n", + " sharey=True,\n", + " width_ratios=[len(v) for v in data.values()],\n", + " gridspec_kw={\"wspace\": 0.1},\n", + ")\n", + "\n", + "axs: List[Axes]\n", + "\n", + "for group_idx, (ax, (group, group_data)) in enumerate(zip(axs, data.items())):\n", + " for i, (version, version_data) in enumerate(group_data.items()):\n", + " bottom = 0\n", + " for k, v in version_data.items():\n", + " ax.bar(i, v, 0.7, label=NAMES[k], bottom=bottom, color=COLORS[k])\n", + " bottom += v\n", + "\n", + " if group == VersionGroup.REGULAR:\n", + " labels = [v.short_version for v in group_data]\n", + " elif group == VersionGroup.ARCH:\n", + " labels = [ARCH_NAMES[v.arch] for v in group_data]\n", + "\n", + " ax.set_xticks(range(len(labels)), labels)\n", + " ax.set_xlabel(GROUPS[group], fontsize=8)\n", + " ax.set_xticklabels(labels, fontsize=8, rotation=45, ha=\"right\", va=\"top\")\n", + "\n", + " ax.yaxis.set_major_formatter(FuncFormatter(lambda x, _: f\"{x:.0%}\"))\n", + "\n", + "axs[0].set_ylabel(\"Pct. of Functions\")\n", + "\n", + "handles, labels = get_legend_handles_labels(fig)\n", + "fig.legend(\n", + " handles,\n", + " labels,\n", + " loc=\"upper center\",\n", + " ncol=5,\n", + " bbox_to_anchor=(0.5, 1.1),\n", + " fontsize=8,\n", + ")\n", + "\n", + "save_fig(fig, \"inline\")" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmEAAAFcCAYAAACA+WmlAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAewgAAHsIBbtB1PgAATxVJREFUeJzt3QeUU9XWB/CdZHqDKQww9N47goJIVQQREAsqFrBg791n12d5n+8927OCYq9YUEB6BwWRjiBILzOUoUxlWr71P3BjJpNkMkNu7k3y/62VNZnkJrkpM3dnn332sdjtdrsQERERUUBZA/twRERERAQMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwoiIiIgMwCCMiIiIyAAMwkzAYrGo01NPPaXbY4wdO1Y9RuPGjd1ej8txPbYLBXgttdeViIjIjEwdhM2fP99xIMVp9OjRPgcbPPgSERGRmZk6CHP19ddfy7p164zeDenXr58K8vCTiIiIqDoiJIjY7XZ58skn5dtvv5VQgudltB07dhi9C0RERGElaDJhaWlp6ud3330nq1atMnp3iIiIiMIjCLvzzjslOjpanX/iiSeM3h0iIiKi8AjCGjRoIOPHj1fnf/rpJ1m+fPlp3d/Bgwflscceky5dukjNmjUlJiZGzRC8+uqrZfHixV6L/hcsWKB+x0/niQPeZh9Wd3bkpEmTHNdjyLCsrEzeffdd6dWrlyQnJ0t8fLx07NhR/vnPf0p+fr5Ul7fZkc4TJHAevvrqKxk4cKDUqlVLYmNjpVWrVvLggw9Kdna2T4/3/fffy6WXXioNGzZUrz3eg+7du8vTTz8tR44cqfT2e/bskdtuu02aNm2qbp+RkSHDhw+X2bNnV+PZExERGcBuYvPmzUOxlDp98MEH9n379tljY2PV7+edd57b21x77bWO23gyY8YMe1JSkmM7d6fbbrvNXlpa6vG+PZ0aNWpU5eep3fbJJ5+scB2et3b9hg0b7AMHDvT42D169LDn5uZ6fV087R8ux/XYztv7MGfOHPtVV13lcR+aN29u379/v8fnmp2dbR8wYIDX1zA9Pd2+bNkyj/excOFCr+/fU089pV7Lyj4HRERERgqaTBjUrVtXbrnlFnV+5syZHjNW3qxevVouvPBCOX78uERGRso999wj8+bNU5m1d955R5o0aaK2+9///iePPPJIudsi24TZmcjYAH7id+cT9ksvN954o9rXa6+9VqZOnSorV65UNXJnnXWWuh7P4bnnnhM9Pf744/LJJ5/IyJEj1QQJ7MO0adPkggsuUNdv3bpVvabunDhxQgYNGiRz584Vm82mso6ff/65/PLLL7Jo0SL1+qampsqBAwdk6NChsnPnzgr3sWvXLhk2bJh6/6xWq9x8880q+7VixQqZOHGitGjRQmUU8foQERGZmj2IMmGQlZVlj4+PV5f179+/ypmwM844Q11ns9lURsxdpqZt27ZqG6vVal+/fn2Fbfr27auux09/8DUThtPHH39cYZvCwkJ7+/bt1fWpqan24uJi3TJhOD333HMVtikrK1PZSVwfERFhP3DgQIVtHn30UXV9zZo17b/99pvb/dixY4e9bt26arsrr7yywvWXXHKJYz8+++yzCtcfP37c3qlTp3L7S0REZEZBlQmD9PR0uf3229V5ZIVw8hUyRciYaFml8847r8I2qLNCzRWg/urNN98Usxg1apRcddVVFS7HhAXtNTl8+LBs3LhRt33o1q2bPProoxUuR73Yvffeq86XlJTIsmXLyl2fm5ursovw7LPPqvtxp1GjRirbpvWFy8vLc1yXmZmpMn+AbNgVV1xR4faJiYmO94+IiMjMgi4IgwceeEAdbEE7YPvCuWj7+uuv97hd7969pU2bNhVuY7QxY8Z4vM45qNm2bZtu+3DllVd6XI3A2z5gEsOxY8fU+UsuucTrY5xzzjnqZ3FxsRru1CDgLi0tVefHjRvn8fY9evSQdu3a+fR8iIiIjBKUQRjqhu6++251fsmSJTJjxgyfbrd+/Xr1MyoqSjp37ux12549e6qfW7ZskaKiIjGD1q1be7wuJSXFcT4nJ8d0+/Dbb7+Vq+1znVXqfGrfvn257JfGebWEM844w+t+IhAjIiIys6AMwgBDX2hrAOii7wutfQKChYgI74sF1KlTR/1EyZYvLRMCIS4uzuN1KFLXaNkiM+0Diu2rw7nt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sV27dpW7j06dOsltt93myJDiPpCZxLJHCIxxf2jWisuJiIiCgekK82Hw4MFy5513ymuvvabWbtSCIE3Dhg3VATxQ3dGxHE7btm1l48aNjiVysA/kO0xiQGYTwSvq+dABHyd3EORiCNgV1pvct2+fqsvD0Cayas4wRIyFzBHIERERmZ0pM2GA9QM/++wzNTSJ5XrQDgJrCT788MMqe9KmTZuA7o/WMwxYkF89WF9z+/bt8vLLL8uAAQNUhgzLPeG9RQCFDBgCLSzE7a7eDtsiY/bxxx9Lnz591MxU9C/DZwHreyIrhsXBiYiIgoHFHojq9hAwZswYFRRi4gCG1Lwtv0NEREQUtJkwM0FLiu+++84RjDEAIyIiotPFIMwHqE3DJAG4+eabjd4dIiIiCgGmLMw3GtY6RF0SFo6eN2+ePP/8845+V1rjUSIiIqLTwZowNxCAoVDcGYrAUfjNmXdERETkDxyOrER6erqMGDFCLbnDAIyIiIj8hZkwIiIiIgMwE0ZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZERERkAAZhRERERAZgEEZEREQkgff/emxVBRNbF9YAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from depsurf import VERSION_DEFAULT\n", + "\n", + "pie_data = data[VersionGroup.REGULAR][VERSION_DEFAULT]\n", + "\n", + "PIE_COLORS = {\n", + " InlineType.NO: \"lightgray\",\n", + " InlineType.FULL: \"lightskyblue\",\n", + " InlineType.SELECTIVE: \"lightcoral\",\n", + "}\n", + "\n", + "plt.figure(figsize=(2, 2))\n", + "plt.pie(\n", + " list(pie_data.values()),\n", + " labels=[NAMES[k] for k in pie_data.keys()],\n", + " colors=[PIE_COLORS[k] for k in pie_data.keys()],\n", + " autopct=\"%1.0f%%\",\n", + ");\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/41_transform.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/41_transform.ipynb new file mode 100644 index 00000000..6aae0c0d --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/41_transform.ipynb @@ -0,0 +1,533 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Function Transformation\n", + "\n", + "This notebook generates the table for function transformation." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "metadata": {} + }, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "from depsurf import TransformType, Version\n", + "\n", + "\n", + "def count_transform(v: Version):\n", + " result = {t: 0 for t in TransformType}\n", + " total = 0\n", + "\n", + " for sym in v.img.func_groups.iter_symbols():\n", + " total += 1\n", + " if not sym.has_suffix:\n", + " continue\n", + " result[sym.transform_type] += 1\n", + "\n", + " gcc_version = v.img.comment.split(\" \")[3]\n", + "\n", + " return {\n", + " **result,\n", + " \"Total\": total,\n", + " \"GCC\": gcc_version,\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "from depsurf import VersionGroup\n", + "from typing import Dict\n", + "\n", + "groups = [VersionGroup.REGULAR, VersionGroup.ARCH]\n", + "\n", + "DataType = Dict[VersionGroup, Dict[Version, Dict[str, int]]]\n", + "data: DataType = {}\n", + "for group in groups:\n", + " group_data = {}\n", + " for version in group.versions:\n", + " group_data[version] = count_transform(version)\n", + " data[group] = group_data" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
israconstproppartcoldlocalalias≥2TotalGCC
Regular4.4.0-21-generic-amd645771985220164383325.3.1
4.8.0-22-generic-amd645782345610063403246.2.0
4.10.0-19-generic-amd645892515750059413026.3.0
4.13.0-16-generic-amd646082537250070430917.2.0
4.15.0-20-generic-amd646282587600065447367.3.0
4.18.0-10-generic-amd6470926373618750161489018.2.0
5.0.0-13-generic-amd6472126274919100157497398.3.0
5.3.0-18-generic-amd6478542877443570334544009.2.1
5.4.0-26-generic-amd6478340977432280247541729.3.0
5.8.0-25-generic-amd64612764974362803725979910.2.0
5.11.0-16-generic-amd64631796998383403956275210.3.0
5.13.0-19-generic-amd64524743725383503146130011.2.0
5.15.0-25-generic-amd64522767714809805616658011.2.0
5.19.0-21-generic-amd64564845520854105316869512.2.0
6.2.0-20-generic-amd64575884494573504466688712.2.0
6.5.0-9-generic-amd64827724503602604516975113.2.0
6.8.0-31-generic-amd64865768533659104697311613.2.0
Arch5.4.0-26-generic-arm6499232481500114533829.3.0
5.4.0-26-generic-armhf0504814004508489.3.0
5.4.0-26-generic-ppc64el5912936740074450879.3.0
5.4.0-24-generic-riscv645142046350050388169.3.0
\n", + "
" + ], + "text/plain": [ + " isra constprop part cold localalias ≥2 Total GCC\n", + "Regular 4.4.0-21-generic-amd64 577 198 522 0 1 64 38332 5.3.1\n", + " 4.8.0-22-generic-amd64 578 234 561 0 0 63 40324 6.2.0\n", + " 4.10.0-19-generic-amd64 589 251 575 0 0 59 41302 6.3.0\n", + " 4.13.0-16-generic-amd64 608 253 725 0 0 70 43091 7.2.0\n", + " 4.15.0-20-generic-amd64 628 258 760 0 0 65 44736 7.3.0\n", + " 4.18.0-10-generic-amd64 709 263 736 1875 0 161 48901 8.2.0\n", + " 5.0.0-13-generic-amd64 721 262 749 1910 0 157 49739 8.3.0\n", + " 5.3.0-18-generic-amd64 785 428 774 4357 0 334 54400 9.2.1\n", + " 5.4.0-26-generic-amd64 783 409 774 3228 0 247 54172 9.3.0\n", + " 5.8.0-25-generic-amd64 612 764 974 3628 0 372 59799 10.2.0\n", + " 5.11.0-16-generic-amd64 631 796 998 3834 0 395 62752 10.3.0\n", + " 5.13.0-19-generic-amd64 524 743 725 3835 0 314 61300 11.2.0\n", + " 5.15.0-25-generic-amd64 522 767 714 8098 0 561 66580 11.2.0\n", + " 5.19.0-21-generic-amd64 564 845 520 8541 0 531 68695 12.2.0\n", + " 6.2.0-20-generic-amd64 575 884 494 5735 0 446 66887 12.2.0\n", + " 6.5.0-9-generic-amd64 827 724 503 6026 0 451 69751 13.2.0\n", + " 6.8.0-31-generic-amd64 865 768 533 6591 0 469 73116 13.2.0\n", + "Arch 5.4.0-26-generic-arm64 992 324 815 0 0 114 53382 9.3.0\n", + " 5.4.0-26-generic-armhf 0 504 814 0 0 4 50848 9.3.0\n", + " 5.4.0-26-generic-ppc64el 591 293 674 0 0 74 45087 9.3.0\n", + " 5.4.0-24-generic-riscv64 514 204 635 0 0 50 38816 9.3.0" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "pd.DataFrame(\n", + " {\n", + " (group, version): data[group][version]\n", + " for group in data\n", + " for version in data[group]\n", + " }\n", + ").T" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[utils_matplotlib.py:86 ] INFO: Saved figure to /Users/szhong/Code/DepSurf/paper/figs/rename.pdf\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA4sAAAGqCAYAAACifNHZAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAewgAAHsIBbtB1PgAA06dJREFUeJztnQXYFNX7v4+EpKhIGNiFioGCii0WGNiFgdiKiYWIip2oKAgmtgg2JioGFoiigmIjIqKiiIFB7f+6z+/77H+Yd3ff7Z3d/dzXtezL7uzMM2fOnDnPeWqJWCwWc0IIIYQQQgghRIA6wf8IIYQQQgghhBAgZVEIIYQQQgghRA2kLAohhBBCCCGEqIGURSGEEEIIIYQQNZCyKIQQQgghhBCiBlIWhRBCCCGEEELUQMqiEEIIIYQQQogaSFkUQgghhBBCCFEDKYtCCCGEEEIIIWogZVEIIYQQQgghRA2kLAohhBBCCCGEqIGURSGEEEIIIYQQNZCyKIQQQgghhBCiBlIWhRBCCCGEEELUQMqiEEIIIYQQQogaSFkUQgghhBBCCFEDKYtCCCGEEEIIIWogZVEIIYQQQgghRA2kLAohhBBCCCGEqIGURSGEEEIIIYQQNZCyKIQQQgghhBCiBlIWhRBCCCGEEELUQMqiEEIIIYQQQogaSFkUQgghhBBCCFEDKYtCCCGEEEIIIWogZVEIIYQQQgghRA2kLAohhBBCCCGEqIGURSGEEEIIIYQQNahX8yMRJVbr86wrN769eo+87m+11VZz06ZNc1OnTvV/i+yZ0nY9V06s99mUUosgROb0X9qVFf1/L7UEIgM2vHdDV05M6jHJlRtLLLGEf4/FYhn9bocddnCvv/66e/XVV/3f5crgE8e4cqLX0M4uavz888/uhRde8K/33nvPTZ8+3dWpU8etssoqbtddd3W9e/cumzmtLItCCFFmvPbaa34yU86TESGKCZMy7plvv/221KIIIaqA3r17ux49erhHHnnENW7c2HXr1s3tuOOObvbs2e6WW25x7dq1cy+99JIrB2RZFJHnlVdecfPnz3crrbRSqUURQgghhBAiJc2bN3eXXHKJO+aYYxabv/7111/uuOOOc8OHD3eHHHKI++qrr9yyyy7rooyURRF51lxzzVKLIIQQQgghqoCrr77a/fvvv65r166uY8eO3n00U26++eaEnzdt2tTddddd7tlnn/VWRt4PP/xwF2XkhirK0n3o999/d/369XMbbriha9KkiWvQoIFbccUV3dZbb+0uuugib4k0+B2/Zz8LFy50N9xwg2vfvr2/YS0uAT799FN38cUX+32wCrTkkku65ZZbzu28885uxIgRRT9vURj+/vtvd9NNN7ltttnGr+bRd1ZddVW31157uYceeqjGtjw0Nt10U7fUUkt5V5INNtjA973ffvutxr6DfY1Yl9tvv91tttlmvo8uvfTSPk7hnXfeSSjXl19+6Y4++mi3+uqre5non8i1xx57uGHDhsW3w/UUVxYgNobj2SsY/3DUUUf5z+655x730Ucfuf3228+1bNnSNWrUyG200UZu4MCB/n4I079/f/873r/77ju/Krryyiu7+vXr+33mo20WLFjgrr32Wr898rRo0cIddNBB7rPPPkv7OoroYv0R7rjjjvg9sMwyy7jdd9/dvfvuuwl/l80YHHTJpk8y/q+33nq+P9LX6P98T9w7cH8F7xl+L8qPQo7jtUHsGWP1Cius4Bo2bOjWXnttd8EFF7h//vknj2coSsnkyZO9VXDLLbd0rVq1ct27d3f333+/j0PMB/TBddddN96foo4si6LsYODnAcHNzOR3p5128hORH3/80U823377be8rzsQkCJN3JswEG2+77bZ+QvHJJ5/Ev0eJZLWnbdu2Xgnl90yWCVTHFZYJDtuI8oVBuUuXLn5SymDNpJTJ6IwZM9zYsWPdpEmT/EMBWPGjb3344YeuWbNmrnPnzl5hQkG74oor/IRkzJgxSQPUe/bs6behr+25555+P8QnvPHGG34fW2yxRXxb+jKy/PHHH/4BwvZ169Z133//vd8e+dgfID8TlBdffNG1bt3a/99A6Qozfvx4d9JJJ7nll1/enw+TIybIZ5xxhnvzzTf9JDy4aBJUXllUYcKObNw/tv9c2+bggw92o0aNcttvv71XXJFx5MiR7vnnn3ejR492nTp1yvjaiujBOMyEnv6z9957+/uLa8x9QL/bd999F9s+lzEYKwAKI/f2dttt5zbeeGP366+/urXWWsvHDT366KNu7ty5bv/99/cLMQb3hSgvijmOh2GOwbiF0oCySBwa/erGG2/0/VRUBtddd50fTxivXn75Zffwww/7F89KFh2wONIHUSZ5VmcKBg0zgNCPoo6URVF2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d3e9e/f2mfiFEBFVFsmAevvtt7tBgwa5Tz/9NOE266+/vi+tcdxxxykTqhBCCCFEFTJkyBA3cODAjH7z4IMP+tdaa63lDRAtW7Z0v/76qxs/fry76qqr3F133eXGjBnjNthgg4LJLUSlUTQ31N9++81tt9127uSTT/aKopXPCL/47qSTTvLbUpNRCCGEEEJUFyh7Z599tlf+sCoeccQRtf6G7WfOnOm+/PJL99JLL7mHHnrIvfjii2769OnuwAMP9CXbjj322KLIL0SlUBTLIkrg3nvv7d566y3//+WWW84ddNBBbosttnDLL7+8/+zHH3/0Kz8jRoxwv/zyi3v77bf9b15//fViiCiEEEIIISJCWKmrU6d2+8Ymm2yS8POmTZu6AQMGuJEjR7p3333X/fHHH65Zs2Z5k1WISqYoyiIrO2+++aZ3K+3evbu79dZb3VJLLVVjuyOPPNJdffXVrlevXu7+++/3v3n44YfdoYceWgwxhRBCCCFEBVKvXr240lm/fv1SiyNE2VA0ZRG23357rwSmgtWfe++913333XfeqvjAAw9IWRRCCCHKGJWrEKXkv//+c3379vV/77LLLq5Ro0alFkmIsqEoyuIHH3zgrYqnnHJK2r8hyQ3K4sSJEwsqmxBCCCGEqByYd958880+DGrWrFnuvffe8yFOHTt29EluhBARUxatPMbqq6+e9m9sW/utEEIIIYQQtYF3Gl5qQXbeeWd32223uZVWWqlkcglRjhQlG+rSSy/t33/44Ye0f0M2K1AAshBCCCGESJd99tnHWxUXLFjgvv32W3fnnXf6jKpkWH300UdLLZ4QZUVRlEVuThg2bFjav7Ft7bdCCCGEEEKkS926dd2qq67qjjnmmHiixZ49e/oM/EKICCmLBxxwgF/heeKJJ1z//v3936m47LLL3GOPPeZvauriCCGEEEIIkS2rrbaa23HHHd1ff/3lazAKISKkLB533HFu3XXX9UoiiuDGG2/sbrjhBl93kcKpX331lf+bz/gOhRLatm3rfyuEEEIIIQrL559/7m655RZ31FFHuQ033NCXm2Dh/vLLL0+4/aJFi3xd7Isuushts802vo42ZSlatGjhs44++OCDtRoIikmTJk38+88//1xqUYQoG4qS4IaB4/nnn3c77bSTmzp1qvvkk0/cOeeck3R7BpY11ljD/8bq4gghhBBCiMIxZMgQN3DgwLS3/+abb9zWW2/t/27evLnr0KGDW3bZZf3nL7/8sn8NHz7ce4stueSSrtTlM3BFhXXWWaeksghRThTFsmjm/48//tidddZZPuENCmGiF9+dffbZ7sMPP3SrrLJKscQTQgghhKhqyBPBHAyLIAlhjjjiiJTbY3Xs3LmzX9zHWvfiiy965XD8+PHutdde85a8Z555xl199dUFl53jo+z+8ccfNb6bMWOGPxcSLTIfxeophEiPoprtGDSuu+46d8UVV7j333/fTZ48OV4agxUpBqnNNtus5KtPQgghhBDVxrHHHrvY/+vUSW1TWHPNNd0rr7yS8Lvtt9/e9enTx1144YXuvvvu866qmdZKPPnkk+P///rrr/075S9QQA3yYaywwgru77//9tufccYZbpNNNvFKIUaI6dOn+33NmzfPrbjiiu7JJ590DRs2zEgWIaqZkvh4ogx26tTJv4QQQgghROXRvn17/47ClilYCMeNG1fj8++//96/gu6l0KpVKzdgwAD3xhtveGMEltF//vnHLbPMMm7LLbd0e+21lzv++ONVkk2IDFFAoBBCCCGEyDskMQQsf5myww47ZJQcp3Hjxq53797+JYQow5hFIYQQQghRHeAWevPNN/u/999//1KLI4SIgmURn3TjyCOPTPh5NgT3JYQQQghRSeUqRo8e7XM58MJ9cuHChb7UWL9+/RKWq3j33XfdCy+84MaMGeO3x2WTBIG4fVL2onv37j75TCkhfpAM+MQJ9u3bt6SyCCEioiwyQDE48QoqePZ5NoT3JYQQQghRKVRiuQoU3XvvvdcnkhkxYoSvv5gJg08c4wpNr6GdC34MISqBvLuhWgmMZJ9n8xJCCCGEqETKuVxFIm644Qaf+bRBgwY+U6kptkKI8iSvlkXcDTL5XAghhBCimolSuYpcueWWW3w9bSyaWDa7dOlS1OMLISKuLK666qoZfS6EEEIIIaJRriIXBg8e7E477bS4orjHHnsU9fhCiMKgbKhCCCGEEBVCLuUqsmXo0KHulFNOiSuKe+65Z9GOLYSoAGXx6KOPdsccc4ybOXNm2r+ZNWtW/HdCCCGEECJ65SruuOMOn/lUiqIQlUle3VCTcc899/iAbPzY013pIg20/e6uu+4quIxCCCGEEOVMruUqPvjgA78P4+uvv/bvt912m0+aY5C4hvnchx9+6E444QSfjHCNNdZwjz76qH8lgjmdEKL8KIqyKIQQQggholuuwhbqx40bV+Pz77//3r+M//77z7/PmTMnnrX+s88+869kSFkUojyJrLL477//+ndSLwshhBBCiMKWq9hhhx0yKlmW6fbpMrTT6a7Q9HKTCn4MISqByCa4eeutt/x769atSy2KEEIIIUQkUbkKIUTZWRYvvfTShJ/feuutrlWrVil/i2sDPvJPP/20j1eMcjHX1VZbzU2bNs316NFD7hVCCCGEKCoqVyGEKEtlsX///l7RC4KbwpAhQ9LeB9vjd3/OOee4QjJv3jxfuHbkyJHu448/drNnz3b169d3K620kttqq63ccccd59+FEEIIIaKCylUIIco6ZjHow26KYzp+7SiIZNhCQTv77LPdxhtvXCgRvVWQVbhPPvmkhgL5xRdf+BcWw1NPPdUNHDiwhgIshBBCCFFsClGuYvCJY1yh6TW0c8GPIYQoA2Vx0aJFi/2/Tp06XtGaPHmyW3/99V0UmD9//mKK4kYbbeR69+7t1l13Xffnn3+6N9980w0YMMDNnTvXxwOQhrpPnz6lFlsIIYQQFYTKVQghXLVnQ11llVW8ssgKWFR46qmn4opip06d3NixY13dunXj3++yyy6uW7du/jsUy2uuucZbOuvVi2wCWSGEEEKUGSpXIYRw1Z4N9dtvv/VFYtdaay0XFd5+++343+eff/5iiqKx2WabxV07GJynTJlSVBmFEEIIUdlY+YnaXiTVy2T7QpS0EEJUH5EtnVFoiEs0cONIxpprrpnwN+ly5ZVXeqsqr/322y++MiiEEEIIIYQQrtqVxR9//NEdffTR/jVjxoxat2cbtj3mmGN8dtJCQGyi8c033yTdzmIHUPbWXnvttPfPih5uqxdccIH/f8+ePX3GVQrmCiGEEEIIIUTUKUoA3v333+/95jfZZBNfkqI22IYA7o8++shnQ6WGUL459NBDXb9+/XysAPGIu+++ew1X1IkTJ7pnn33W/929e3fXrFmztPa9cOFCX3Jj2LBh/v9nnnmmT5ajbKpCCCGEMJSBVAgRdYqiLI4ePdorSgcccEDavzn44IO9wvj8888XRFls0aKFV2JRGt966y3XsWNHd8YZZ7h11lnH/fXXX/4zFDxcTzfddFP/dzrgZso+yVoGl156qbvwwgszli8Y1J6ImTNnZrxPIYQQQohEDO10esGP0ctNKvgxygnN9UQ5UBRlkZIZsPnmm6f9mw4dOvj3jz/+uGByke30/fff94rgXXfd5Xr06LHY961bt3aXXXaZtxI2bty41v2hZO6zzz7ulVde8coxJTd69eqVlWwrr7xyVr8TQgghhBDRR3M9UQ4UJWbx119/9e8tW7bMyPIX/G0hwGp43333+TIaibKG/fTTT+6BBx5wL7/8cq37Qs6ddtrJK4qU1+B32SqKQgghhBBCCFEVlsWmTZu633//3b/ShVhCKFRtxrlz57quXbvG6yuee+65PgkNmVH//fdfX/MIF9I333zTWwuvv/5617t376RuAtttt5379NNPXaNGjXwimz322CMn+aZPn57ye46ZiaVWCCGEEEJEB831RDlQFGWxTZs2XlF85513vFKVDsQMQjoJcbKhf//+XlGEsAsqCuouu+zidtxxR7frrru6V1991Z1zzjneckjCnUQxmcYll1ySs6JobSaEEEE+//xzP97gPs+L2q8k1MJdnoRdYRYtWuTeffdd98ILL7gxY8b47VmIW3rppV379u3dUUcd5ZN3KflW6a6RTRife+65+G8I3cDzhYzgd955Z9HPQQhRHDTXE+VAUZRFCsjy8COG76STTqo1qyiTmUGDBvkJDL/NN7ic3n333f5vEtqEYxUN3El5wG+zzTZ+0kVG1xtvvLHGdltvvbX76quvvNsqSugWW2yRtlIshBDpMmTIEDdw4MC0t6csEOMTNG/e3MeCL7vssv5z3Ot5DR8+3D322GMF8+KoNjK9RkD7kzVbCCGEqMqYxRNOOMErfpjTsbqhVKWqycg2P/zwg/8Nv803HN/qN7K6norNNtss/vdnn32WcJu11lrLxyoSk/n33397+c0yKoQQ+aJdu3a+fuuDDz7oLVZHHHFEyu0ZQzt37uyzSv/888/uxRdf9Mrh+PHj3WuvveaaNGninnnmGXf11VcX7RwqnUyvEay++uru1FNP9eWWKBll9XmFEEKIqrAsbrDBBu700093N910k3v77be9ckVpjG233datsMIKfhsUyTfeeMONGDHCK1xMckgQQ23GfIPF0FiwYEHKbefPn5/wd4nOEYWRidkvv/zi4yGZmHXq1ClPUgshqp1jjz12sf/XqZN6vW/NNdf041Iitt9+e9enTx9f2odEXxdddFFeZa1WMr1GsPfee/uX8fjjjxdENhE9VK5CCBF1iqIsAgliiFtk5ZTkMrxb0foglpWUBy7KZSHAHQtXWNxdiaNEYUymCL7++uuLrf6mYsMNN/RuXSiMWC67dOniXnrpJQUnCyEiiXlW1JZkQQghhBDVSZ2iHahOHZ9I5sknn4xb21AMgy8gvubpp592t99+e8GSLiCLJaHB3fWKK65IuN1vv/3mzjvvvPj/99xzz1r3TQIcFEbiglBGSZAzYcKEPEovhBD54csvv/Tv5uEhhBBCCFESy6LRrVs3/8Ly9uGHH3qXTauryCo3SlYxwOWK+oq4vJKUhgx0JLqx0hlkEMSy+d133/ntyYSK4pcOnAcWxZ133tnNmTPH/w5XsNriI4UQolgw9t18883+7/3339+VM8pAKoQQQlSIshh0BcVds1S0bdvWK4uHHnqoV1hHjRrlX4lATmonZgKJcYhZpAQHFkoUR1LXJyq9IYQQxebkk092U6dOdSuuuKLr27evK2eUgVQIIYQoczfUKIICR4bTa665xpfoIJtp/fr1XaNGjXx84kEHHeTdZs2tNFOIVURhXGqppbwlleNNmqRAcyFEacHidu+997qGDRv6pGLLLbecK2eUgVQIIYSoMMtiVGCSdO655/pXpnz77be1brPlllv62EUhhIgCN9xwg3fDb9CggXviiSfidRjLGWUgzZ97rsEiKX2FMiskpVt11VW9u/L555/vmjZtWrRzEEIIUUXKIllHn332WTd27FhfFPrPP//0D65UkOQmWep3IYQQ6XPLLbe4s846yy255JLeDZOMzaJyycY9F2688UbXu3dv//ylxFXr1q39c/vKK6/0/ebNN9/0eQaEEEJUPkVTFnm44BpkCWPAMqAmgocU3xcqI6oQQlQTgwcPdqeddlpcUbSM0KJyMfdckqttuummXtm7//77U/5m4sSJfkGhbt26Po6fmsGWEInkdCzennjiie7RRx8t0lkIIYSoeGWRuEBWsP/55x+vADJZWXvttX2Sm3TchYQQQmTP0KFD3SmnnBJXFNMpAyRcVbrnXnXVVf453bNnz7iiCI0bN/blr8gYTh/iuU6iOCGEEJVNUZRFVjNZlWSl8pJLLvGr24p5EEKIwnPHHXf4zKdSFEVtUDqEUBHo3r17je+JWyTGFZdU4l2JXxRCCFHZFEVZpGQE7qSnn3562adoF0KIUvHBBx94xc/4+uuv/fttt93mnnnmmfjnTORXWGEFX8v2hBNO8JYiLEK4DiZzH7znnnuKcAaVT6bXCGbOnOn23Xff+Hfff/+9f3/66ad9kjTj1ltv9e6kheKLL77wC7vQoUOHhNvwOcoi7qpCCCEqn6Ioi9QxhODDUAghRGaQWXncuHE1Pke5MAUD/vvvP/8+Z86ceGw4boO8kiFlsTTXyP5O9JtZs2b5V3DfhYS6m7DMMsv4kk+JWHnllRfbVgghRGVTFGWR+oU//PCDr18ohBAiO6gHmyoxWK7bi9zJps1XW221SFwnMpRDkyZNkm5jISQqCSWEENVBUbLLbLPNNv598uTJxTicEEIIIYQQQohyUBap10RyG+o9UWtRCCGEENHCXE/nzp2bdJu//vrLvzdr1qxocgkhhKhwZbFjx47upptuch999JHbb7/94jGMQgghhIgGuMNarKu5pIaZPn36YtsKIYSobIoSs3jppZf6980339xngyP99i677OJrNFG7qTYuuuiiIkgphBDRZvCJYwq6/15DO7tyJEoZSMv5Gq277rr+mUxG1AkTJrgdd9yxxjZ8DoXMyiqEEKLKlMX+/fv70hnA+z///ONGjRrlX+kgZVEIIaLF559/7kaPHu3ef/99/5oyZYpbuHChu+yyy1y/fv1S/vbll192N9xwgxs/frx3eWQBcf/99/d1+7KpwVvOGUijBLU499hjDzdy5Ej30EMP1VAWp02b5t5++23/t7KbCyFEdVAUZRHCmd6ikPlNCCFEdgwZMsTHoWfKjTfe6OPYWTjcdtttXevWrX3dviuvvNI99thj7s0333QtWrSomgykUaNPnz6+FuewYcO8At+lSxf/OdbGY445xi8I8DmeQUIIISqfoiiLixYtKsZhhBBCFIl27dq5s88+27Vv3967JKLs3X///Sl/QyH3s846yyc8w7Oka9eucUWkW7du7pVXXnEnnniiV1ZEadxzuZYDBgzwCv3uu+/utt9+e9eqVSuv0OO6i6vq0KFDS3A2QgghKtqyKIQQonI49thjF/t/nTq150u76qqrvDWvZ8+ecUURiJO766673BprrOGti5999pksV3kgG/dcOPPMM92GG27olUZzFV5llVW8mzAvy5oqhBCi8pGyKIQQZcLQTqcXdP+93KSC7XvevHnu2Wef9X937969xvfELW699dbegoWlC6WkGpLKFJJs3HONnXfe2b+EEEJUN0UpnSGEEKK6+eKLL7y7KXTo0CHhNvY57qpCCCGEKD2yLAohhCg4U6dO9e/LLLNMUjfGlVdeebFty5Fytv4KIYQQJVEWSWaQLWTMW7BgQV7lEUIIUVysyHuTJk2SbmNlM6qpXIUQQgjhql1ZVHpyIYQQorgollMIIURZKIsXX3xxrduQbY2Ylpdeesn9+++/bsstt3S77rprMcQTQghRYMz1lLE+GX/99Zd/b9asWdHkEkIIIUQZKIvGr7/+6gv/UgOKjHm9evUqqGxCCCEKz2qrrebf58yZ411SE8UtTp8+fbFt00VxgkIIIUSVZENdbrnlfEHmjTfe2Nd6SlQjSgghRHlBMXfqKcKECRMSbmOfUxheCCGEEKUncsoi1KtXz5122mk+sc0NN9xQanGEEELkyJJLLun22GMP//dDDz1U4/tp06a5t99+2/+97777Fl0+IYQQQpRR6Yx27dr597feeqvUogghhMgDffr08Z4jw4YNc/vvv7/r0qWL/5z6i4QfLFy40H/etm3bUotaEcg9VwghRMUqiyS5gV9++aXUogghhAjxwQcfuJNPPjn+/6+//tq/33bbbT7m3HjiiSfcCiusEHcvHTBggOvdu7fbfffd3fbbb+9atWrlxo4d62bOnOldVYcOHVqCsxFCCCFEWSmLjz/+uH9v2bJlqUURQggRglqIiWLKv//+e/8y/vvvv8W+JxZ9ww039Erj+PHjfXbUVVZZxZ1//vn+lSjxjRBCCCFKQ+SURSYOt9xyixs4cKBbYokl3E477VRqkYQQQoTYYYcdsq6hu/POO/uXEEIIIaJNUZTFzp1rL9y7aNEi99tvv/lai/PmzfOTkKZNm7oLLrigGCIKIYQQQgghhCi2svjaa695K2Emq9Crrrqqe+CBB9zaa69dUNmEEEIIIYQQQpRIWdxuu+28spiKOnXq+FiV1Vdf3Sc9IMV6/fr1iyGeEEKIDBl84piC7r/X0No9UoQQQghRIZZFIYQQQgghhBDlQ51SCyCEEEIIIYQQogqURZLZkMF02rRp+d61EEIIIYQQQohydUO1ZDaUwEjEl19+6XbbbTe/jRVxFkIIUV4M7XR6Qfffy00q6P6FEEIIEcE6i5TF+Pbbb2tNeCOEEEIIIYQQonQoZlEIIYQQQgghRA2kLAohhBBCCCGEqIGURSGEyIHvvvvOnXLKKW7dddd1jRo1cg0bNvT1Ynv06OE++uijUosnhBBCCJE1UhaFEGVHVBS0cePGuXbt2rnBgwf7pF677rqr23333X1M9n333ec6dOjgRo4cWTR5hBBCCCHyiZRFIURZESUF7fjjj3d//vmnf586dap76qmn3OOPP+6++uor169fP7dgwQL/3b///lsUeYQQQgghykJZVLZTIUQlK2i//vqr+/jjj/3fl19+uatfv378uzp16rj+/ft7q+ecOXPclClTCiqLEEIIIURZlc5gtT84eTLmz58f/3uNNdaodT+qxyiEyERBGzBgQFxBa9++fcFkadCgQdrbtmjRomByCCGEEEKUnbI4Y8aMWq2O1FusDVkohRBRVNCaNm3qtt12Wzd27Fhv0Rw0aFBceV20aJFXXP/55x/XtWtXt/LKKxdUFiGEEEKIslAWV1lllapQ8FZbbTU3bdo0n1DjnnvuKbU4QlQFUVPQ7rjjDh8vefvtt7tnn33Wx0vWrVvXTZw40S+YHXHEEV5GIYQQQohyJO/KYjrWwihz3nnnuWuvvTb+/1dffdXtsMMOJZVJCBFNBY1srO+8844/5ujRoxfzqFh//fX92NGsWbOiyCKEEEIIkW+UDTXAhx9+6G644YZSiyGESENBIy4a5cwS3JDsZq211iqqgvbWW2+5DTfc0E2ePNk99NBD7scff3SzZ892o0aN8vHZxxxzjH8JIYQQQpQjUhb/By5sZFAkk2KrVq1KLY4QIuIKGkl09t13Xzdr1iyvrB566KGudevWbtlll3V77rmne+GFF1zjxo3d3Xff7T0UhBBCCCHKDSmL/+Pmm2927733nmvbtq0sAUJElCgpaLjAIgdZnbfYYosa3wc/f/nllwsqixBCCCFEIZCy6Jz77rvv3IUXXuj/Hjp0qFtyySVLLZIQIuIKGuMGpHJ5XXrppf07lk8hhBBCiHJDyqJzrlevXu6vv/7ymU233377vO33yiuv9Jlhee23337uv//+y9u+hahGoqSgrbTSSv79s88+c7///nuN73GJ/eCDD/zfq6++ekFlEUIIIYQoBFWvLI4YMcI988wzrnnz5u7666/Pyz5jsZg7++yz3QUXXOD/37NnTzdy5MiMasQJIaKtoFGeo0mTJr5Ux3HHHecXnIx58+a5M8880yu3lPY44IADCiqLEEIIIURZlM4ot/in008/3f99zTXX5KWI98KFC/3EcdiwYf7/TBgHDBiQce3J77//PuX3M2fOzElOIcoRU9Dmzp3r7zNiE6m9aApa7969i6agtWzZ0rut22LQa6+95jp27OiPPWHCBJ+ptU6dOj4eGvdYIYQQIojmeqIcqGpl8dxzz/WZFLfeeuu8JLXBzZSEG0888YT//6WXXhqPhcyUYhQUF6LciJqCdvjhh/vMrDfddJN744033CuvvOI9C1ZYYQV32GGHudNOO81tvvnmBZdDCCFE+aG5nigHqlZZHDt2rLvzzjtdvXr1/OQzU8tfGFzQ9tlnHz9ZZF+33HKLj4UUQlS2grbxxhvHPQmEEEIIISqJvCqLf/zxh38vVkHsbMFdjZqKTDBxE23Xrl1O+/v111/d7rvv7saPH++Vz3vvvdd17949p31Onz69VtcEWSxEtSIFTQghRLmjuZ6oOmVxmWWW8S5gH3/8sVt//fXjn993333+HctbFBRJspSSIGOVVVZxF198cU774kbebrvt3KeffuoaNWrkXeP22GOPnGVs06ZNzvsQQgghhBDRRHM9UZVuqFjrwhx11FHeNbNDhw6LKZGlACXxqquu8n/jKkqyjFwYPXp0/O9LLrkkL4qiEEIIIYQQQlSUsli3bl23aNEi7+YZVW688UYvH8kv/v77bzd8+PAa20yePDn+95gxY3wSHNhrr71qKJckx/nqq6/cTz/95Pr37+8LgmNpFEJUBoNPHFPQ/fca2rmg+xdCCCGEiISySOmJn3/+2btkbrLJJi6KkLEUvvnmG5+5tDYuu+yy+N9Tp06toSyutdZa7rbbbnM77rijmzVrlrcsvvDCC16JFEJETzkDKWhCCCGEEEVWFjt16uSefPJJd9555/mC2euss45PaW+899577pdffsl4v1G31G2wwQY+I2Pnzp39+VEL7sUXX/TtIYQob4Z2+r9arIWil5tU0P0LIYQQQkRCWTzrrLPcqFGj3A8//OBOOeWUGrGMRx99dMb7JNZxwYIFeZPxnnvu8a9U4E5K/CG8+uqrbocddqh1v6Tyf/nll73COHv2bNelSxf30ksvKYuVEBFTzkAKmhBCCCFE7dRxeQTXy8cff9ytueaaXjm0lxH8LJNXOaXzR2FcdtllfRmRXXfd1RcKF0IIIYQQQghX7dlQSQLDi9oxM2bMcP/++6+3tmEhvOuuu9zqq6/uKpn27dt7i+LOO+/s5syZ4xVGXFT5XAghhBBCCCGqVlk0Vl55Zf8KgktmqUtnFIPNNtvMxyzusssu7rfffvOKI1lVsTwKIYQQQghRaM4991x33XXXxRM29uvXr9QiiWp3Q03GkUce6V+4Z1YLKMYojEsttZSPYURhnDRJcVJCCCGEEKKwvP32227AgAHes0+ISFoWg9SWUCZqkOCGVyq+/fbbWvez5ZZb+thFIYQQQgghigF1xI866ii3wgoruI4dO/pKBUJEWllMBIlrqHWI1Q2aN2/u1lhjDa2ACCGEEEIIkSXnn3+++/LLL92zzz7rRowYUWpxRJlTFDfUILhmkgCnWbNmvg4j1jde/M1n3bp1c6NHjy62WEIIIYQQQpQ1r732mrvlllt8+Nfuu+9eanFEBVA0ZXHevHmue/fuvuM+99xzbu7cuTVKZPAZqyAUtWdbfiOEEEIIIYRIzV9//eVrmrdu3drddNNNpRZHVAhFc0NF+XviiSe8UlivXj2fKXSLLbZwyy+/vP/+xx9/dOPHj/dlJ+bPn+8eeeQRt2DBApnPhRBCCCGEqIWzzz7bTZ061c+3qymppKgAZRFr4eOPP+7jEXfccUd39913u1VXXTXhtt99951fFaHUxGOPPeatkDKjCyGEEEIIkRhCuG677TZ3yCGHuH322afU4ogKok4xs6FSZ/CFF15IqijCKqus4p5//nm3ySab+P8PGzasGCIKIYQQQghRdvz+++/umGOOcS1btvTxikKUnbL47rvveqviWWed5erXr1/r9myDKR2XVX4rhIhmsV/ua16XX355qcURQgghqpIzzjjDff/9927QoEGuRYsWpRZHVBhFURZnzZrl39dff/20f9O2bVv//ssvvxRMLiHKjagoaCr2K4QQQkQDYhTJB3Lrrbe6HXbYYbEXHn1w1113+f/jpiqiO7+q2pjFJk2auDlz5rhff/017d/89ttv/r1x48YFlEyI8iGooGF1LxUq9iuEEEJEC5JCvv7660m///bbb/0rVShYtRKV+VVVWxbXXXdd/06G03Sxbe23QlQzQQVt7733jkSx39tvv90tvfTSJZVFCCGEqHYwyITL0dmrR48efpvLLrvM/x+FUURzflXVymK3bt18ByVZjSW7ScX999/v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Z9KkSWmftxBCCCGEKC4oabUZA/KB5nqiHPpw3pdN8qx7RtayaFAPsjYaNGjg3ymzIYQQQgghhBDlQN6VxR49euSsbD733HPu119/jazi2bBhw/jf8+bNq3V7akhCo0aN0j5GbS6rKKyfffaZt1q2bNkya1MzLqybb755vBzICius4EqFZCkPeSSLZJEskkWySJYoyFIoeXDhKwaFmutF7RpFVaaoyjUzDzLlsw/nXVmkrmAu5SguvvhirygaK6+8sosaSy21VPzvv/76q9btiVeEpk2bpn2MdEzHJNfJJ3TGYrhdpINkKQ95JEtiJEtiJEtiJEtiJEtiJEv5yBOFuV4U2ySKMkVVrhUiIFMksqFiSaTu4v777+8mT57sLYpoxLfccov74osvXBQti8stt1xawa2//fZbXFmMouIrhBBCCCGEEJFTFl966SW31VZbub322st98MEHXknEzD5gwAD39ddfu169eqUVE1gK1l9/ff/+1VdfpUzAg/uAsd566xVFNiGEEEIIIYQoS2Xx9ddfd9ttt53r0qWLGzdunFcSmzdv7q6++mr3zTffuDPPPHOxuMAoss022/h3rIbvv/9+ynM1tt5666LIJoQQQgghhBBlpSy+/fbbbuedd3adO3d2b731llcSl156aXfppZe6qVOnunPPPdc1btzYlQP77LNPrXGaixYtcvfdd5//e5lllnE77rhj0eQTQgghhBBCiMgrixMmTHBdu3Z12267rXv11Ve9kkiylwsvvNArif369cso+UsUIEsR5wN33XWXe+edd2psgzvtlClT/N+nn366q1+/ftHlFEIIIYQQQohIZEMN8tFHH7mLLrrIPfPMM/7/KIlNmjRxp5xyijvnnHO862k5M3DgQO9aSv3EXXfd1fXt29dbD/n/8OHD3e233+63W2edddxZZ51VanGFEEIIIYQQorTK4ieffOJLYDzxxBNxJZEagyeddJI777zzfBKbSqB9+/bukUcecYcffrj7448/vLIYBkXx2WefXazchhBCCCGEEEJEnSViaHJ55NBDD3UjR470CiKvBg0auBNOOMH16dOnaEVOi820adO8lRGlkFIaZHClLs6BBx7orajlEocphBBCCCGEEAVTFuvU+f9hkFgQTzvttJzrCx555JF5kEwIIYQQQgghREmVxSWWWCJv+2NfqeoYCiGEEEIIIYQok5jFPOufQgghhBBCCCHKXVmkNIYQQgghhBBCiPIm726oQgghhBBCCCHKn/+fjUYIIYQQQgghhPgfUhaFEEIIIYQQQtRAyqIQQgghhBBCiBpIWRRCCCGEEEIIUQMpi0IIIYQQQgghaiBlUQghhBBCCCFEDaQsVhhRq4SyaNGiUosQWaJ2raJCVNolKnJEDbXL4miME9mieyk5ahshooPqLIq88O+//7ovvvjCjR8/3jVo0MC1atXK7bbbbvHJVJ06pVmXmD9/vqtfv74rddt89dVX7t1333VLL720W2qppVyXLl1cqSl120S1Xf7++2/XuHFjFzVKeR+J5Pzxxx+uWbNmpRZDRJiojnVRQG2TmB9++MGtuOKKpRZjMVAXllhiiVo/E5X3/JayWMb8+eef7vHHH3evvvqqmzNnjlfQLrroItemTZuiyvHrr7+6U045xb322mvup59+8p8x2e7WrZt76KGHin6j0C6jRo3y8iDb2muv7Y477ji32mqrubp167piwvFPP/109/rrr7sZM2b4NqAtTjvtNHf99de7evXqFXWwjUrbRK1dmPA/+OCD/l76/vvv3QorrODOPfdct9FGG7lGjRq5YiurEydOdG+//ba/Jssuu6zr2bNnSR7MURljYO7cuW7cuHG+79IOyy23nOvRo4efYBb7IUx/GTFihHvrrbfcJ5984rbeemu36667uq5du7piQ3/57LPP3BtvvOEX6lZaaSUvRykWgrhGH3zwgb+vFyxY4MeVXXbZxctUre0StbGOdpk0aZIbO3asH9u4fw4//HBXCqLWNlGhX79+/jl9zz33uPbt27uo8PPPP/sXz4ImTZpESrYos3DhQv8sZ2Fk5syZbvXVV3dlB8qiKD9+/vnn2E477RSrU6dObIkllogtueSS/n3rrbeOTZ061W+zaNGigsvx008/xdZdd11/7I4dO8aOPvro2A477BBbZpll/GeHH354rJjMmjXLt0vdunX98e212267xSZPnlxUWYJts+mmm8YOOuig2K677hqX6YwzzqjKtolau3Avbbvttv7Y9erVizVq1Mj/vdFGG8Vee+21ot1L8Msvv8T222+/2LLLLlvjGtFusHDhwqoaY6zvduvWLT6u2GuvvfaKvfrqq0WTw9plu+22W0wOXu3atYs9+eSTsWJCfznwwANjK6ywwmKynHTSSbEPP/ywqLLYNWrevPlisuyzzz6x5557rirbJWpjHe2y//77x1q2bLlYuxx55JGxr7/+uqiyRK1tosIVV1zhz79+/fp+/C32fZyM22+/3c/tmjRp4p8JSy+9dOzYY4+N/fPPP/77Yo7B6RA1ef755x//jDjxxBOL+hzPF1IWyxAmK2uvvbaf9B9yyCGxl156Kfbss8/6zxhk+KwYzJkzxyuIDB6XXnpp7L///vOf//DDD7EhQ4b4wYTJHfIVq13WWWcd3wYHH3ywP+4jjzwSb5eTTz45Vix+++23WIcOHeJtM2/evPjngwcPjj8Qq61totYuTHBpF5TEHj16xN5///3Y22+/7R/SyLHLLrvEikXwGqG8nn322bHDDjss1qJFC/9Zly5dqm6MCbcL16Vfv36xPn36+GvGZ3vvvXfszz//LEl/YZHliSee8PcUsrBYVorJdqdOnWI9e/b0i3N2D/Xq1atoE6bwNeL6nH766X7Cy2csgNhiR7W0S9TGuuA1YsGHSStKoslx1FFHxYpF1NomSpx33nn+3Ndbbz3/vv3225dcYTznnHPiCuwWW2wRa9u2bfze7t69eyxqjB49OnbZZZfFvvnmm1hUeO2113x70X42V46aQpsKKYtlBoMpE8mmTZvGrr766tiCBQvi333yySdeQdtqq60W+00hOiSDe9++fX3nZyCxwd5WS7777rv46vstt9wSK0a7bLPNNr5drrrqqsXOmZuUgY2JA/IV+galLc4//3x/7ueee25s/vz5/nM7Lqu7WIr4/p577olVS9tErV1Y7GClNNG9hOUMq8Raa60V+/fff4siC9eAydOVV14Zv59YjURJW2655Xy73HfffVUzxsDvv//uZWncuLFvl+BxxowZE7eS33zzzbFiXCNk4RpxHwVXhseOHRtr2LChn0Qhc6HHGGRh0oEsTIqC3HbbbfHJ9qhRo2KFJnyNgowYMSI+qSzWPR2FdoniWLflllv6dsFyFbynH3/88Xi7PPTQQwWXJWptEzXuvPNOf+6MMTvvvLP/m+dUUGEsppJxySWXeBl233332FtvveU/mz59euzee++Ne5sMGjQoFhXo37bAShsW4/mdDn/88Ufcgyk8TpYDUhbLCDr9aaed5le1cdGwQdZWKRhkV155Zd8hGUxmzJgR/y7ffPbZZ7E111zTrw6aHGGzOg9rbgxW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hG27yy67uOWWW8799ddf/rtMjytZylMWIUTpuOeee9zChQvdFlts4e/zZK9zzz3Xb3/XXXdltP8uXbr494cfftjNnTvXRZEOHTq4pk2butmzZ7unn366xvf//POPGz58uP97xx13zPvxV1llFbfTTju5P/74wz3++OPugQcecAsWLHD77befW3rppTPaF208atQo//fmm2+e1m822WSTlNee5wGMHTvW/58+k0/q5XVvQgghygJTRng/9NBDveLx4Ycfuk033dR/b0qIbQtLLbWUmz9/vt/2v//+kyxVJIsQojTcfffd/r1Hjx4ptzvyyCPdtdde65555hk3a9Ys17Jly7T2361bN9e+fXs3ceJEd+CBB7r777/fLzgZ//77r3v11Vdd165dXalo2LCh69Wrl7vmmmvcWWed5TbeeOO4gsR4d/rpp7sff/zRrb766u6AAw4oiAxHH320e+mll9ywYcP8saBnz54Jt7399tt9e6288sqLfT516lR33HHHuZkzZ7plllnG7zMMSumMGTPcVVdd5fbdd18XBaQsCiFElRJURg477DD/kFp++eWTbv/tt9/6VVEsXfaglizVI4sQori8/vrr7quvvnINGjTw93QqNthgA7+Q9MEHH7j77rvPK1XpwKLTE0884XbbbTf3/PPPeyvaNtts4xVGlJaPPvrIKzaMLaXkkksucRMmTHCvvPKKW2+99bwFkcWxd955x3333Xde3pEjR3rvi0Kwzz77uGWXXdYfH1ZbbTXXuXPnhNveeuut7sQTT/TXZJ111vEyoSiy2MciHrJioWzRokWN33799ddu2rRp7vfff3dRQW6oQghRxQTdHRMpIaao8KDDFRJ3KBSWoFVLslSPLEKI4mEupXvttZdXVGoD62Lwd+nCwhKKGJY7FBwUMJQZlJbtt9/ef15qUJhfeOEFr4hhWcTlEiW3fv367tRTT/VK7WabbVZQ6+ahhx4a/z+W3mRu/qeddpq30uKq+tprr7lHH33Uff75526jjTZyF198sfv000/ddttt58qFJQhcLLUQQgghoofFxKGEXH755d795qSTTnKDBw9eTEmRLJJFCCFEZSJlUQghREJwl2G1lsQJb7zxhjv88MO9exMEk6tIFskihBCiMtFTRAghRA1++eUXd/PNN7stt9zSvf/+++6cc84pmRIiWaIvixBCiMpElkUhhBA1mDdvnnvzzTd9TEinTp1c9+7dS6aESJboyyKEEKIykbIohBAiITwe/v77b9ekSZOSx79JlujLIoQQovKQsiiEEKJWoqSESJboyyKEEKIykLIohBBCCCGEEKIGCmoQQgghhBCiSpg4caKrW7eur0+YjH/++ccNGTLE13hceeWVXePGjV2jRo1cmzZt3G677eauvvpq980336Q8DvYoagxSn3D11Vf37vLUK2R/e+65p7v99tvdn3/+mfT306dPd/369fNJvFq2bOlrKi6zzDJu0003daeffrp77733Mj539nnKKae4Nddc09dubNGihT+fZ5991mXD888/74499ljXoUMHt8IKK/h9LrXUUm6TTTZxffv29YnIErHzzju7Zs2auR9//NFFHVkWhRBCCCGEqBK22WYb9+GHH3plr1WrVjW+f+mll9wRRxzhfvrpJ58sC8VntdVWc0suuaRXblDS5s6d6xXOa6+91vXu3bvGPtj3AQcc4BVTWG+99dy6667rlakZM2a48ePH+yRdKGsTJkxwq6666mK/Z78XXnih36Zp06Zuiy228LKiXE6aNMlNmzbNb0cWaLZNB+Tu0qWLmz17tlfsNt98c/frr7+6cePGufnz57uLLrrIXXLJJRm15eGHH+4efPBBt9Zaa/k2Qqlln5zfnDlzvMxjxoxxG2ywwWK/45w7duzojjrqKF8fN9KgLAohhBBCCCEqm5EjR2Ikip1zzjkJvx81alSsbt26fpuePXvGZsyYUWObefPmxR599NHYpptuGjvhhBNqfD9t2rRYq1at/D46deoU++ijj2ps88cff8SuueaaWLNmzWITJ05c7LvzzjvP/7Z+/fqx66+/Pvbvv//W+P0777wT69y5c2zvvfdO67z/+eef2Morr+z3e/DBB8f+/vvv+Hfjx4+PLbfccv670aNHxzJh4sSJsZkzZ9b4/M8//4wdeOCBfp9bbrllwt/uueeesSWWWCL24YcfxqKMLItCCCGEEEJUAVtvvbV7++233WeffeYtfUGwiOGe+fvvv7szzzzT3XDDDSn3tXDhQm+h3GyzzRb7fLvttnNjx471lrvXX3/du54m46uvvvLuqVj64JVXXvEumvD444+7fffdN+lvUWEoH7TtttvWet4PP/ywLy+EG+vUqVP9exBq1uLaitUV2fPB9OnT3SqrrOL/pk1xOw3y5JNP+vPr2bOnu/vuu11UUcyiEEIIIYQQFQ4uoSiKxACGFUW45ZZbvFKz/PLL+5jE2sANNawoohyasjV06NCUiiLgvmmKIlx++eX+vVu3bikVRSD7czqKIlh8I/KGFUUwBfWtt97KWxxhvXr1/DuuvMRbhtljjz28Gy6KLK6xUUXKohBCCCGEEBUOlqygYhTmqaee8u8HHXSQj0/MBtvHhhtu6Nq3b5/Rb4nxe+ONN/zfPXr0cPnkr7/+8u/LLbdcwu9R2sxa+cEHH+R8vP/++88nuIFddtnFJwcKgwK5ww47uH///de9+OKLLqr8n8orhBBCCCGEqFhItAKdOnWq8d2CBQvcxx9/7P8m8Uq2kLgl232gpC1atChnGRJhiXySZXANfo6bajay33zzzV7ZnDVrlrdkkgmV87jrrruS/m6rrbbyGWNxvyVrbBSRsiiEEEIIIUSFE8xMGgY3SFPUyOiZiMGDBycsV3HPPffE/0ZRgkRZVmvDfpvt71PRuXNnd8UVV7j333/ft0PY6onLrPHHH39kvP/vvvvO3XvvvYt9hgX3tttucyuttFLS31mW1HxYMwuFlEUhhBBCCCEqGEpd8Erlilkbr776qnvsscdSKotRBWWRxDu4uRIPeeutt/r/k9SHv++77z7vFkoJDWIMM2WfffbxVkWS/nz//ffu5ZdfdhdffLFr166d3zdlRBJh14IyJVFFMYtCCCGEEEJUMCSuMSgaH6Z58+Y+YUzYwhcEd0kUIl5k+kyEWSV//vnnjGUMWjSz+X1tjBw50meDRZlDYSTRDdlfBwwY4DOhbrzxxvG2yJa6dev6mpHHHHOMz9RKm5LtNFnSHMuQ+ttvv7moImVRCCGEEEKICiaYAZTC9okyd2600UaLxR1mg2VHTeSuWhu4hppVL5vf1waurWRqHT16tOvTp4877rjjXL9+/fyxbrzxRjdjxox4cp58sNpqq7kdd9zRJ9d56aWXUirxyy67rIsqUhaFEEIIIYSoYBo3buzrGQKul4nA2gYjRozw7pjZsPfee/v3SZMmxWMk0wWFyUphhOP/8gWWPrKTXnXVVe722293l112mevQoYP7+uuv3cyZM71b6Kabbpq34zX5X5sns5TatWjdurWLKlIWhSgirDIxUKXr39+/f3+/Pe+VBumiU53b33//7bp27eq3ITh88uTJrpLgvMzlpzYo1mvtQDxEbfCAZntWin/44QcXFY466qiM+n+pISMe8u6+++4Z//a1117zq9brr7++nwARC8MkhCLVp5xyio9nwZUrFVOmTHG9e/f2q+381vZBJsPzzz/ff58MJnrDhg3zcTQUhSZtO5PFNdZYw8fOPPjgg27evHlpZU+kDfg9ae1rgwkRKff5zfjx411UqOSxVIh0MSXo008/Tfj9aaed5t0iUZouuOCCrJ/tuHrCSSed5EtIpMKUNMOO+/TTT7snnngi5W8ZQ3H1zAfXX3+9fz/++OOzLhsShnM3+dZZZx2XCJvbhOtVRgkpi0KIyMGklJW/F154wRfspUguQeLVCjWvmjZt6hW/dGoxoVwCyvaKK65YBAkrE0vksP/++6f9G1Kl77bbbt716M477/RZ9Zg4cQ1R8lCmyChI/042OSCF/Zlnnun7PK5RZNkj/Tr7oJg2SiwFs/l+0KBBNX5PVj0Kbh999NF+woWCSfHnPffc09cSo9ba4Ycf7icvLMqkgvNYffXVfR2whx56qNbzv//++72iimwoxkKI6MD9DO+8807C7xkfSMaCK+h1113nF7yCilxQSeO5nIwHHnjA72vcuHE+sQxWxjAk27nhhhv8OBhM7sLYeNZZZ/m/DznkEL9NIoWTrKaMtabkpQNKcjjTKePtlVde6bOWMt9IpCQPGjTItW3b1h155JGLfc54PmTIkITZU3FpPeKII/xzG0MB55WIt99+27/TTpElJoQoGquuuiqmhNiwYcPS2n7WrFmxKVOm+PdKY/vtt/dtcfHFFy/2+cyZM2MbbbSR/27jjTeO/fjjj7FKhPPLZAg+5phj/Pb7779/yu3+/fffWPPmzf22TzzxRCxK/PDDD74/z5kzJ1YObLnllrG6deumff/99ttvsXXXXde3fdu2bWNjxoxJuN2kSZNiRx99dKxx48YJvz/44IP9Ppo1a+bHigULFiz2/aJFi2IvvvhibNNNN42dfvrpi333/vvv+/3y+z333DP2zTff1Nj/zz//HDv//PNjSy65pJe5Ni677DK/v80226zWbTfYYAO/7Y033hiLEpU8lgqRLh988IG/PzfffPOU2z3//POxli1b+m0ZA7n3efYcfvjhsa5du8aWX355/12dOnViRx55ZMJ9fPnll/FnOa/1118/tt9++8UOOeSQ2Lbbbhtr0KCB/7x169axadOm1fj9FVdcEatfv77fZqmllortvPPOse7du8e6desWW2211eL7Pe+889I+f8bLhg0bxrbeeuvYQQcdFNt777398dnPWmutFZs6dWrC31188cV+G+YtQdiezxlLaVP2eeCBB/pnB5/x3Yorrhj78MMPE+533rx5sRYtWniZfv3111hUkbIoRISVxUomkbLIwMuAzec8TMpFqSiGsvj222/HH0q//PJL0u0eeeQRv12rVq1i8+fPz5O01cf3338fW2KJJWI77rhj2r9hIkXbr7HGGrHZs2fXuv24ceNqfHbXXXf5fTBJevfdd1P+nokG/SL4f47N7/fZZ5/YwoULU/5+/Pjxsb///rtWOadPn+4njOz3448/Tnk+1kellAkRTbbaait/n3766acpt/vrr79igwYNiu2+++6xlVZaySs0KHgoPyhuLCJ9/fXXKffBGMQzCSWK+U+jRo38Ptq0aeMXs+64447Y3Llzk/7+22+/9QtbHTt2jC233HKxevXqxZZeeulY+/btveKH8psJLLKhIK688speDhbk2Pe1116bciy8OImyiOwDBgzw+1xzzTW9UouMKIDbbbdd7Lrrrov9/vvvSff7+OOP+/327NkzFmWkLAoRYWXRBqiw9Y3f83mPHj38gN6nTx8/UDFJY5WMlT4mu2GCv0uErZIhZ9CKsddee/nPWRFMxGGHHea/56HC9tkoi5MnT/YPIT7bY489Ug7cn3/+eez444/3E2Mb8FEu77///pTHevXVV2NvvPGGf0gxmKMM2LWwa0MbYBHaZZddYssss4x/QPJguvfee1Oez8iRI2O77bab3y8Tfc6Fdvnkk0/yoiwCK7P85qabbkq6DTKwzdlnn73Y5zNmzIideeaZ3uLFA7tp06axDh06xG655ZaESiV9xPoqljAe9qwms5Ic7I8jRoyI7bTTTt6ayUOS9/XWWy927LHHxj766KOk+0zEww8/HOvcuXNs2WWX9X15lVVW8Q9Rrncicr1mqaBd2DeTpXT46quvfNvwm6eeeiqrY3LvmLJ32mmnZfz7e+65J66sYaHPJ9zb7PuMM85Ius0JJ5zgtznggAMW+xzF+aKLLvKeAvQ7+l+7du38ZDPRRDE47mFxwArL5JL+FRy7XnrpJX8vszDCd1x7Fpu4715//fWk+0zECy+84McdrCncvyussILv8++9916tY8rEiRNj++67r5/M0vb0/+uvvz7tsVCIYsKzir7bu3fvUotS9ey5555+HsIYEmWkLApRxsoi1gPcPJgkodCxusXEyRS+sGUuG2XRJnsm+5AhQxb77rbbbvOfs1KXyuKVSlnEImGuk0z0UlnEUE5QBszVj0kaCkaTJk2SrtDZsU4++WQ/oUfpQvHdddddYw899JDfxs7vwgsv9IM3bjdsgzuJKXaJXOuQlUkl36O4smqLGwoTYz5jYoxLTz6URVYwzT03mQXIFBZc7gwmzihgfI77Dm48KJX2Ge2AVSqRYnfcccf58+J3nCf9jIkwXHLJJX4bJuqsoh566KFeqUARoA3D7ZVMWWRSzQKH7YvrSduvs846/jPcKhO1YbbXLB122GEHv0+U7HRAged4tGltFr1koFyb3LiTZgr3Ar/lGuWbxx57zO+bxZBwXwEWd1jxZ5vgtWKxhLGBz1HAunTp4uUz169NNtmkxjhl4x4uZ4wLLFLgAocL21lnnRVXjLk+vLbYYgvvuku/xjUXK2jYPTeVstivXz//HfvCPY1+jFzmgoe1N9mYwkKdKYj0PT43K2xYBiGiAv2cZ2alhnmUA+PHj/fjxFFHHRWLOlIWhShjZZEXk/6gmwOKnU10rrzyyrwoi4BCx6QIRc1WwXjn/0zwg+5w6WCTLdxZsDbw96mnnppyNR4XOBQXjsnkNeyusuGGG/r9hC1KdixegwcPTnltsCqMGjUqYbsxGQ5bPPv27eu/Y8Iajg9jBZeJIwpEODYsG2WRWDOL4UikTFx++eX+OxRWAwsTFg8mwrfeeutiigzKPYoZv0HxS6TY2YQ4rAARG2kWys8++6yGLFyPoMIa3Ge4/7MAYYpIcIWVvmD3AAsinH8+rlltcByuW7Ada+OII47wx8PKmi3mgsp9lo0LsSlll156aSzfoCBaDFP43oMHHnggvmhkfYV2x+OBz1HI/vvvv/j2WBRRyhIt8Ng154VrL30tzOqrr+6/Hzt2bI3vfvrppxruacnGUhRbPmdMGT169GLf3XnnnfH+hedDsjFl6NChi333yiuv+PuNPsQCjhBRg/uDhcVevXqVWpSqZaeddvJuq/n2AikEUhaFKGNlkZVBkoaEGT58uP8eRSBfyiIMHDjQf4+rF26uFl9olqZMCE62eGERqM1tyxJ/JDuerdSFE3HYscLtkejaJHPNwYrJ97ixGgSkozAx0Uzk9gtYM/kdbo25KouAhYXfJXrI2/VgkmsQ/M9np5xySsL9ITeTYRSBYPubYod1L5xgxRQqvseynS7JlEVTKG6++eYav0EmS5JAwoNcr1k63H777Rn3a5I+pHLVJsEB5x9+BZWdq6++2u8DS1o2mMU9rLzkC6x67B93zTC26IBSGF4EwNUqEX/++WfchTQY42njHlbFZHHLWJtZCEiXZGMpE7ZUfQjZzcKeaEzB2pkILKh8f99996UtoxBCRBGVzhCijKGQ7AorrFDj8/XWWy+eujmfUIOJMgJfffWV22CDDfw7RXwtzXU2bLXVVr5+HOn+qcmUrPbcokWL3PPPP+//Pvjgg5O2ByUmqDNIqv8w1Jerjb322ivh54na9NVXX3X//POPL41ADcRkNaeC6bFz5dhjj/XvlDEIphN//fXX/fXg/IPt8+yzz6ZsM+Ree+213axZs9yXX35Z43vq9NWtW7fG5y1btvTpwD/++GN//ZPV7aqN77//3tfZgh49etT4ntp4PXv2jLd3rtcsHR5//HH/vt9++7l8MX36dF9kOvzimpUL1vcoaRNMp//tt9/6axO8Vun0Pfoq9yyp6997770a3++8885u6aWXTvhbynL8/vvvPpU9KfQZHzKF41r6f2qAJuKYY44pat8TQoioIWVRiDKGYtuJoKguJFKYcoUaftRPYqJGDb9cC6xTe+jRRx/1RXCpc0RB3EQK46+//hqvZbTyyivHi9oHX9SG+uuvv/zEke3DoNzks02/+eYb//7KK68klIcXtfEAZSwf7Lrrrv78f/vtt8UKFlttRavJGJZx2223TSqjKXqJZEzVZtTjatWqla+DxeIB9fwoYE9tQOoNpoNNpvmttXGYNddcc7FtC3kfUOOT60nxauoLpgv3RKrrTI3D/3nz+NdOO+2UUAGH2bNnu4ULF6Z97PDvqf1VCKgzxuIOsqHoGsOGDfPnRA23NdZYo0bfo9ZYsr733HPPZdX3br31Vn8s6jqicC6zzDK+Ta+44gpflzIdGCOsbyS71sXse0IIEUXqlVoAIUT2oBzlk3RW57HumSLAO1YhJmu5gHWSAuhYLSlkjhx33HHHYucXlC2RBSpMgwYNanzWqFGjvLapyUQhX6yLtU208wHyYQW57LLL/CSdosV//vmnV7iDlpCwjFhVmzRpknLfKGyZtBkKKFYlLEhYNrGevvjii76PXHzxxV6ZTaQURfk+GDVqlC8qT1/MBJRLFBcs5LR5NjJRnBrmzZvnPvroI7/PTH+PBTORlS5f0L+4ziwS9enTxyuJpjgm63tdunRxrVu3TrnfVVddNaO+h+Xu888/d6NHj3ZjxozxMo0dO9b/femll7q77rrLHX744a7cxmAhhIgaUhaFqCKw3gHKRSKmTZuW8ve4KR533HF+goT7FxNGLFm4fSZzF0sXLC8oF7j+YSVjosmEzyZjWG6YPOL2ef3118ctOaUECx+su+66OVtYM+Hoo492l19+uXv55Ze9coCC9vfff8ctP2EZuW7nnXdezkp9IrgmKKLm4ouFqF+/fu7222/3ctbWp8x91yzHiayLZqFK5uqbT1i0yMYFlf6LOy4WX6xl/D9TNtpoI2/hmjp1qlfAMlUW9957b/fkk0/6/vDTTz/VqqBlA/f76aef7hU1XDi5H7nGWPbCbUbf++yzz7wSmY4LeKbUq1fPW7J5Af0HK/cll1ziTjjhBLfvvvumXCBhcYRFJdy56WO0fyn7nhBCRBEtiQlRRdiEhwlcIizGKBG4Ux144IFe0UQZwKrF/5nYohTkAyZ9Tz31lGvYsKFXvrCgmXWCuDlcVmHEiBEuCmA1QwF/7bXXCub6lwjc8zg2bUM7mQtqouvQtWvXorYZrpDXXnut/xt3QJSnVLRp0ybu6pdI4cZyZZ/j5lhI5s6d6y1V66+/fsaWYKzLFpvXu3dv76adKbhl9u3b1/89ZMgQN378+Fpj7t599934/w877DDfN7BMEv9bm6cAsX4oe5mAizPWbKDfWd/r3r27v29L2fdYaOjfv79XXFk8+eKLL2pVNrfZZhv/d7LFHju/Qvc9IYSIKlIWhagiSArBhIoYNVzmgowcOdLdfPPNKZPb4BrXuXNn72IIuIwy0SchyMCBA/Mi42677eaefvppb7FCRiyYFr/FcVHOzjnnHG95STQZnjx5cjxBSaHBcnPqqad6JYNEF5MmTaqxDVYLzieZgp4t5vLHNXvnnXf8xJe2CkNbMXnG4jJgwACvSIRB4X/ggQcyOj7WJK6/xZGGXTlh2WWXTRqHGOTss8/277jW0seCiiIW1A8//NCfA1btQoJFEOUpUxdUY/DgwV5pxJKLhRfX3ETguktin2RJZLDC4QrL4gj9PBy/SLvgbskxhg8fHv+cRFEoZihtWOlJTsS1DUNM5IUXXuhdp4NJkjLtexzL4mbDLqhA/DHupYwtWLYTeTT8+OOP3uU8E1AE6c+J4hxxRSXulMUlFiJqw5JzoZwTqxoEBZJ7l3bFmiqEENWI3FCFKAFMiocOHZoyeUOmLmjpgAKGi9aZZ57pFQsmSFgbp0yZ4hVILIbIFubBBx/0EzqUI/4211AUgUceecRPOs8991w/ee3YsWPOcjJJRuFAAeN4TJZRZmgT3rE48kJerEBYs5gAo6wxCcfCk89Mlqm4+uqrfWZIspNusskmbuONN/aJN1DekAVFB2WSOL58xS0CLnbNmzePx4/i9pjI7ZAJM9ZaFCCUMqx+7dq181l0sX5x7Yk73WKLLTKK8cJiiPJ28skn+/O2BCEoSrglYyW77rrrEmZSDYPLIDFnlqxk++2394lziP/D3ZF+S/taApdCu6BmqyyiHOOaiZUNxYNMuLQ/7YOyiyJK+9BPUfg23HDDhK7BnOvyyy/vlU/6OQoN9xXXm2tGu9DnaNtwFk+2e+ONN7zVn3vomWeece3bt/d9kvsWJX/ChAn+nuKzRLG9tbHlllv6+84SI3F+icYrXEDxVqBv0u9wTcbVkzYxyx/9j2udyUIACx60CQshtCHZfFHoUMLN0nrBBRek1V+wfjKOsCjBuMNYRtIaFndoZ9qYsZoETkIIUY1IWRSiBBAHY7EwiUhkrckXZ5xxhp90YglkUv/JJ5/4CetNN93krSJhZZHJ+oknnugnmjaJDSfVIIYQCxtKGhMsJsa5gpulTTSxnmBFRHFkEsyEGIvaSy+95CfnTHxRlJD/lFNOKUh8VDJQCpELRQtL27hx47x1k4kyChkKLwl8tttuu7wel0k+boe33HKL/38qV2COzXUeNGiQb1MSoGBRYpLOxBjZM1WQsCjTZ7Cecb5Y5VCAWHxgIQJLtCVsqQ0USzKrMnFHocA9EgWbvoYyRCIV4kILCe1B23BeKPzZQpsSS4qyyP1C/0R5QzlaaqmlvFKNxY0+ipU+UYIUFB+uK66ktAduzihBZPplH+uss44vUUHboCiF4f5AEUP5ZqGAe5LrTzvTJ1lo4Hrz4ljZgCXRrHKp+h5KFuVVULiwQvI3lnBijlEaWcBAnkxdYdkffY8xjHEABZLszCwSsYBB26YLYx5KIm3O/UtbIx9jDfLhkSGEENXKEhRbLLUQQgghRCnBCodSj7XKYi6FEEKIakeWRSGEEFUPcX7ExOJCKoQQQoj/Q5ZFIYQQQgghhBA1UDZUIYQQQgghhBA1kLIohBBCCCGEEKIGUhaFEEIIIYQQQtRAyqIQQgghhBBCiBpIWRRCCCGEEEIIUQMpi0IIIYQQQgghaiBlUQghhBBCCCFEDaQsCiGEEEIIIYSogZRFIYQQQgghhBA1kLIohBBCCCGEEKIGUhaFEEIIIYQQQtRAyqIQQgghhBBCiBpIWRRCCCGEEEIIUQMpi0IIIYQQQgghaiBlUQghhBBCCCFEDaQsCiGEEEIIIYSogZRFIYQQQgghhBA1kLIohBBCCCGEEKIGUhaFEEIIIYQQQtRAyqIQQgghhBBCCBfm/wEsVUMc8tkJjgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from utils import get_legend_handles_labels, save_fig, format_yticks, ARCH_NAMES\n", + "import matplotlib.pyplot as plt\n", + "\n", + "COLORS = {\n", + " TransformType.ISRA: \"C0\",\n", + " TransformType.PART: \"C1\",\n", + " TransformType.COLD: \"C2\",\n", + " TransformType.CONSTPROP: \"C3\",\n", + " TransformType.MULTIPLE: \"C4\",\n", + "}\n", + "\n", + "GROUPS = {\n", + " VersionGroup.REGULAR: \"Linux Kernel Version / GCC Version\",\n", + " VersionGroup.ARCH: \"Arch for v5.4\\n(GCC 9.3)\",\n", + "}\n", + "\n", + "\n", + "fig, axs = plt.subplots(\n", + " 1,\n", + " len(data),\n", + " figsize=(5, 1.25),\n", + " sharey=True,\n", + " width_ratios=[len(v) for v in data.values()],\n", + " gridspec_kw={\"wspace\": 0.1},\n", + ")\n", + "\n", + "\n", + "for group_idx, (ax, (group, group_data)) in enumerate(zip(axs, data.items())):\n", + " for i, (version, version_data) in enumerate(group_data.items()):\n", + " bottom = 0\n", + " for k, v in version_data.items():\n", + " if k not in COLORS:\n", + " continue\n", + " ax.bar(i, v, 0.7, label=k, bottom=bottom, color=COLORS[k])\n", + " bottom += v\n", + "\n", + " # label total on top\n", + " percentage = f\"{bottom / version_data['Total'] * 100:.0f}\"\n", + " ax.text(i, bottom, percentage, ha=\"center\", va=\"bottom\", fontsize=8)\n", + "\n", + " labels = []\n", + " for version, version_data in group_data.items():\n", + " if group == VersionGroup.REGULAR:\n", + " gcc_version = version_data[\"GCC\"].rsplit(\".\", 1)[0]\n", + " label = f\"{version.short_version} / {gcc_version}\"\n", + " elif group == VersionGroup.ARCH:\n", + " label = f\"{ARCH_NAMES[version.arch]}\"\n", + " labels.append(label)\n", + " ax.set_xticks(range(len(labels)), labels)\n", + " ax.set_xlabel(GROUPS[group], fontsize=8)\n", + " ax.set_xticklabels(labels, fontsize=8, rotation=45, ha=\"right\", va=\"top\")\n", + " format_yticks(ax)\n", + "\n", + " if group == VersionGroup.REGULAR:\n", + " ax.set_ylabel(\"No. of Functions\")\n", + "\n", + "handles, labels = get_legend_handles_labels(fig)\n", + "fig.legend(\n", + " handles,\n", + " labels,\n", + " loc=\"upper center\",\n", + " ncol=5,\n", + " bbox_to_anchor=(0.5, 1.1),\n", + " fontsize=8,\n", + " # handlelength=1.5,\n", + " # handletextpad=0.5,\n", + " # columnspacing=1,\n", + ")\n", + "save_fig(fig, \"rename\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "4.15 -> 4.18:\n", + "- `-freorder-blocks-and-partition` enabed by default in GCC 8\n", + "\n", + "- https://gcc.gnu.org/gcc-8/changes.html\n", + "\n", + "5.0 -> 5.3:\n", + "- \"Hot/cold partitioning is now more precise and aggressive.\" since GCC 9\n", + "\n", + "- https://gcc.gnu.org/gcc-9/changes.html\n", + "\n", + "5.13 -> 5.15:\n", + "\n", + "- Non-static functions renamed e.g., `ipv6_local_rxpmtu`\n", + "\n", + "5.19 -> 6.2: \n", + "\n", + "- `-falign-functions=16` added since Linux 6.2\n", + "\n", + "- https://github.com/torvalds/linux/commit/c27cd083cfb9d392f304657ed00fcde1136704e7\n", + "\n", + "- https://github.com/torvalds/linux/commit/d49a0626216b95cd4bf696f6acf55f39a16ab0bb" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/42_dup.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/42_dup.ipynb new file mode 100644 index 00000000..de96bb07 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/42_dup.ipynb @@ -0,0 +1,322 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Function Duplication\n", + "\n", + "This notebook generates the table for function duplication." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from depsurf import (\n", + " Version,\n", + " VersionGroup,\n", + " FuncGroup,\n", + " FuncGroups,\n", + " CollisionType,\n", + " VERSION_DEFAULT,\n", + ")\n", + "from utils import OUTPUT_PATH\n", + "from typing import Dict, TextIO\n", + "\n", + "\n", + "def print_group(group: FuncGroup, file: TextIO):\n", + " header = f\"{group.name}\"\n", + " if group.num_funcs > 1:\n", + " header += f\" ({group.num_funcs})\"\n", + " print(header, file=file)\n", + " for func in group.funcs:\n", + " line = f\" {func.file}\"\n", + " line += f\" at {func.loc}\"\n", + " line += \" (global)\" if func.external else \" (static)\"\n", + " line += \" (inline)\" if func.inline_actual else \" (not inline)\"\n", + " print(line, file=file)\n", + "\n", + "\n", + "def count_dup(v: Version):\n", + " results: Dict[CollisionType, Dict[str, FuncGroup]] = {c: {} for c in CollisionType}\n", + "\n", + " func_groups = FuncGroups.from_dump(v.func_groups_path)\n", + " for group in func_groups.iter_groups():\n", + " results[group.collision_type][group.name] = group\n", + "\n", + " output_path = OUTPUT_PATH / \"dup\" / v.name\n", + " output_path.mkdir(parents=True, exist_ok=True)\n", + " for c in [\n", + " CollisionType.INCLUDE_DUP,\n", + " CollisionType.STATIC_STATIC,\n", + " CollisionType.STATIC_GLOBAL,\n", + " ]:\n", + " path = output_path / f\"{c.name.lower()}.txt\"\n", + " with open(path, \"w\") as f:\n", + " for group in sorted(\n", + " results[c].values(), key=lambda x: x.num_funcs, reverse=True\n", + " ):\n", + " print_group(group, file=f)\n", + " print(f\"Saved {len(results[c]):5} groups to {path}\", flush=True)\n", + "\n", + " return {k: len(v) for k, v in results.items()}\n", + "\n", + "\n", + "# count_dup(VERSION_DEFAULT)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.4.0-21-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 4042 groups to /Users/szhong/Code/DepSurf/data/output/dup/4.4.0-21-generic-amd64/include_dup.txt\n", + "Saved 404 groups to /Users/szhong/Code/DepSurf/data/output/dup/4.4.0-21-generic-amd64/static_static.txt\n", + "Saved 10 groups to /Users/szhong/Code/DepSurf/data/output/dup/4.4.0-21-generic-amd64/static_global.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/4.15.0-20-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 4809 groups to /Users/szhong/Code/DepSurf/data/output/dup/4.15.0-20-generic-amd64/include_dup.txt\n", + "Saved 398 groups to /Users/szhong/Code/DepSurf/data/output/dup/4.15.0-20-generic-amd64/static_static.txt\n", + "Saved 26 groups to /Users/szhong/Code/DepSurf/data/output/dup/4.15.0-20-generic-amd64/static_global.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.4.0-26-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 5461 groups to /Users/szhong/Code/DepSurf/data/output/dup/5.4.0-26-generic-amd64/include_dup.txt\n", + "Saved 411 groups to /Users/szhong/Code/DepSurf/data/output/dup/5.4.0-26-generic-amd64/static_static.txt\n", + "Saved 27 groups to /Users/szhong/Code/DepSurf/data/output/dup/5.4.0-26-generic-amd64/static_global.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/5.15.0-25-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 6162 groups to /Users/szhong/Code/DepSurf/data/output/dup/5.15.0-25-generic-amd64/include_dup.txt\n", + "Saved 444 groups to /Users/szhong/Code/DepSurf/data/output/dup/5.15.0-25-generic-amd64/static_static.txt\n", + "Saved 26 groups to /Users/szhong/Code/DepSurf/data/output/dup/5.15.0-25-generic-amd64/static_global.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ groups.py:47 ] INFO: Loading funcs from /Users/szhong/Code/DepSurf/data/dataset/func_groups/6.8.0-31-generic-amd64.jsonl\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 7418 groups to /Users/szhong/Code/DepSurf/data/output/dup/6.8.0-31-generic-amd64/include_dup.txt\n", + "Saved 498 groups to /Users/szhong/Code/DepSurf/data/output/dup/6.8.0-31-generic-amd64/static_static.txt\n", + "Saved 29 groups to /Users/szhong/Code/DepSurf/data/output/dup/6.8.0-31-generic-amd64/static_global.txt\n" + ] + } + ], + "source": [ + "data = {}\n", + "\n", + "for v in VersionGroup.LTS:\n", + " data[v] = count_dup(v)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ utils_latex.py:118] INFO: Saved dup to /Users/szhong/Code/DepSurf/paper/tabs/dup.tex\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Linux Kernel Version
\\multicolumn{1}{c}{4.4}\\multicolumn{1}{c}{4.15}\\multicolumn{1}{c}{5.4}\\multicolumn{1}{c}{5.15}\\multicolumn{1}{c}{6.8}
Unique Global17.2k20.1k22.7k26.6k31.5k
Unique Static35.7k41.7k48.2k53.3k60.2k
Static Duplication4.0k4.8k5.5k6.2k7.4k
Static-Static Collision404398411444498
Static-Global Collision1026272629
\n", + "
" + ], + "text/plain": [ + " Linux Kernel Version \n", + " \\multicolumn{1}{c}{4.4} \\multicolumn{1}{c}{4.15} \\multicolumn{1}{c}{5.4} \\multicolumn{1}{c}{5.15} \\multicolumn{1}{c}{6.8}\n", + "Unique Global 17.2k 20.1k 22.7k 26.6k 31.5k\n", + "Unique Static 35.7k 41.7k 48.2k 53.3k 60.2k\n", + "Static Duplication 4.0k 4.8k 5.5k 6.2k 7.4k\n", + "Static-Static Collision 404 398 411 444 498\n", + "Static-Global Collision 10 26 27 26 29" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from utils import save_latex, center_cell\n", + "import pandas as pd\n", + "\n", + "\n", + "table = {}\n", + "for version, dup_counts in data.items():\n", + " col = {}\n", + " col_max = max(dup_counts.values())\n", + " for dup_type, count in dup_counts.items():\n", + " text = f\"{count / 1000:.1f}k\" if count > 1000 else count\n", + " col[dup_type] = text\n", + "\n", + " col_name = center_cell(version.short_version)\n", + " table[(\"Linux Kernel Version\", col_name)] = col\n", + "\n", + "df = pd.DataFrame(table)\n", + "latex = df.to_latex(multicolumn_format=\"c\", column_format=\"l|rrrrr\")\n", + "save_latex(latex, \"dup\")\n", + "df" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/50_programs.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/50_programs.ipynb new file mode 100644 index 00000000..04b90901 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/50_programs.ipynb @@ -0,0 +1,177 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Analyze eBPF Programs\n", + "\n", + "This notebook compiles, analyzes, and generates the report for eBPF programs. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from depsurf import system\n", + "from utils import SOFTWARE_PATH\n", + "\n", + "BCC_PATH = SOFTWARE_PATH / \"bcc\"\n", + "BCC_TOOLS_PATH = BCC_PATH / \"libbpf-tools\"\n", + "BCC_OBJ_PATH = BCC_TOOLS_PATH / \".output\"\n", + "\n", + "TRACEE_PATH = SOFTWARE_PATH / \"tracee\"\n", + "TRACEE_OBJ_FILE = TRACEE_PATH / \"dist\" / \"tracee.bpf.o\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following cell compiles the BCC tools. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "system(f\"make -C {BCC_TOOLS_PATH} -j $(nproc)\", linux=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following cell compiles the eBPF program for Tracee." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "system(f\"make -C {TRACEE_PATH} bpf -j $(nproc)\", linux=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following cell analyzes and generates the report for eBPF programs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from depsurf import BPFProgram, VersionGroup, DepReport, DepKind\n", + "from utils import OUTPUT_PATH, save_pkl\n", + "\n", + "GROUPS = [VersionGroup.REGULAR, VersionGroup.ARCH]\n", + "PROG_PATHS = sorted(BCC_OBJ_PATH.glob(\"*.bpf.o\")) + [TRACEE_OBJ_FILE]\n", + "\n", + "\n", + "REPORT_KINDS = [\n", + " DepKind.FUNC,\n", + " DepKind.TRACEPOINT,\n", + " DepKind.LSM,\n", + " DepKind.FIELD,\n", + " DepKind.STRUCT,\n", + " DepKind.SYSCALL,\n", + "]\n", + "\n", + "results = {}\n", + "for path in PROG_PATHS:\n", + " bpf = BPFProgram(path)\n", + " result_path = OUTPUT_PATH / \"programs\" / bpf.name\n", + " result_path.mkdir(parents=True, exist_ok=True)\n", + " prog_report = {}\n", + " for dep in bpf.deps:\n", + " if dep.kind not in REPORT_KINDS:\n", + " continue\n", + " with open(result_path / f\"{dep.kind} {dep.name}.md\", \"w\") as f:\n", + " report = DepReport.from_groups(dep, GROUPS)\n", + " report.print(file=f)\n", + " prog_report[dep] = report\n", + " print(f\"Report saved to {result_path}\", flush=True)\n", + " results[bpf.name] = prog_report\n", + "\n", + "\n", + "save_pkl(results, \"bcc\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "import csv\n", + "import json\n", + "from collections import Counter\n", + "\n", + "results_dir = Path(\"./results\")\n", + "results_dir.mkdir(parents=True, exist_ok=True)\n", + "\n", + "rows = list(results.keys())\n", + "kinds = list(REPORT_KINDS)\n", + "cols = [k.name for k in kinds] + [\"TOTAL\"]\n", + "\n", + "matrix = []\n", + "for prog in rows:\n", + " prog_report = results.get(prog, {})\n", + " counts = Counter(dep.kind for dep in prog_report.keys() if dep.kind in kinds)\n", + " row = [int(counts.get(k, 0)) for k in kinds]\n", + " matrix.append([*row, int(sum(row))])\n", + "\n", + "csv_path = results_dir / \"50_programs.csv\"\n", + "with csv_path.open(\"w\", newline=\"\") as f:\n", + " w = csv.writer(f)\n", + " w.writerow([\"PROGRAM\", *cols])\n", + " for prog, row in zip(rows, matrix):\n", + " w.writerow([prog, *row])\n", + "\n", + "print(f\"Saved CSV to: {csv_path}\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/51_plot.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/51_plot.ipynb new file mode 100644 index 00000000..6627cf96 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/51_plot.ipynb @@ -0,0 +1,375 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot Dependency Report\n", + "\n", + "This notebook plots the dependency report.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ utils_pickle.py:18 ] INFO: Loding bcc from /Users/szhong/Code/DepSurf/data/output/bcc.pkl\n", + "[utils_matplotlib.py:86 ] INFO: Saved figure to /Users/szhong/Code/DepSurf/paper/figs/report.pdf\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAo8AAALdCAYAAABN1omHAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAewgAAHsIBbtB1PgABAABJREFUeJzsnQeYE9XXhy8LS9mlg/QioEhVVJCqYgELSBFUUEFBQJT+t6OABVCwIU3Ajr3QLGChig0QEBFUqnRUBJQOy873vFdvvtlsspssmcwkOe/zhF2SbOZmyp1zT/mdXJZlWUoQBEEQBEEQQiAplDcJgiAIgiAIAojxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIAiCIISMGI+CIAiCIAhCyIjxKAiCIDhO8+bNVa5cufRPQRBimzxuD0AQBCHSLFy4UF1yySWZns+dO7cqXLiwKlKkiKpYsaI6//zzVbNmzdQ111yj8ubN68pYBeFUzvOpU6eq7777Tm3fvl0dPnxYpaSkqHLlyqnq1aurCy64QF1++eX6Z1KS+IqEyJHLsiwrgp8nCILgWeMxGKeddprq37+/uv/++1WePLKmdgI8josWLVIXX3yxPj5Czjl48KDq0qWLmjlzZkjvnzNnjrryyisjPo5XX31VdevWTf++efNmdfrpp0d8G4I3kVlSEIS45o477lB33nlnhhvvvn371I8//qjmzZun5s6dq/788081ZMgQ9dFHH6mPP/5YG5OC4FU6duyoPvvsM/37GWecoXr27KkaNGigihUrpg4dOqTWr1+vvv76a/Xhhx+qP/74w+3hCnGIGI+CIMQ1pUqVUnXq1Mn0/FVXXaXuu+8+tXbtWnXzzTerlStXqqVLl6r27dur+fPnSxhb8CSffPKJz3C84oor1KxZs1S+fPkyvKdp06bq1ltvVZMmTdLeSVI0BMHTxmNaeprac2SP8hIlC5RUeZLEThYEITO1atXSXhpuuBiQ/D5hwgQ1aNAgt4cmCJnAWDQ8/fTTmQxH/xzfDh06RGlkQiIRcYsKw7HFBy2Ul/ii4xeqTGoZt4chCIJHKVCggHr99ddV3bp1FWngTz31lOrbt69KTk4O+P7du3ercePGaQ/Qpk2bdKgQD2fjxo1Vr169dJFCIH777TdVpUoV/fsrr7yivUPvv/++mjx5sg6jHzhwQFWuXFl7P/GKFi1aNNuxL1iwQOeeLV68WI+LnE0+gxw3DGCKJwLx8MMPq0ceeUT/znc+evSo/k5vv/22DntCzZo1VdeuXVXv3r2zzQWlaANjhnHs379flS1bVrVo0ULddddd6qyzzlKhsmHDBm28k06wdetWdfz4cf1ZF110kT4m9evXzzbPlX1CjuV7773n27ekK1SqVEm1bdtW57YWL14827HMnj1bvfXWW+qbb75Rv//+uzp58qQey3nnnaeLrK6//npdoAI8x+KjRo0a6ueff87yc//66y99XPhupFVMnDgx5P3DPjEQso4E4Z5DgXKKzXnt/7lSXR+fSPmVIAiCUqp27dra2IGdO3eqZcuWBXzfm2++qW/aI0eOVMuXL9f5kxgBVLtiCPIZPXr0UGlpadlu87bbbtMGCLmX5F1iwP3666/qiSee0OP55Zdfgv4t7+3cubO69NJLdcUtBQtHjhzRBuhPP/2kDWAqbsnjzA4MIwzfe++9VxtAGFo82Af9+vVT1157rUpPTw/6988++6z23H7wwQf6s44dO6YN5RdeeEFXtGOEhQJjxhM8ZswY/R3++ecf/T35bq+99pquGh46dGi2n8NYKSi54YYbdArCnj179OesW7dOPfnkk6phw4baSMrKuGMB0KpVK3282T6VzOZ7TZ8+XReKYJwaOObAMcOQzgo+k3MGunfvrsLBnk6RnZGaHZE8h4TEQoxHQRCE/7B7DPHC+IOxgFGCp7Fq1arqmWeeUZ9++qk2IqdNm6auvvpq/b6XXnpJG2JZgbfp5Zdf1gYR3r7vv/9eG1kYk8aAJaeNG7k/eAopmnjnnXf0//GC4Tkl5P7tt9+q5557TnvZGCfv47OzAuOQ3E8qzr/44gv9ffC44XkEjAcMwUDMmDFD/e9//9MGGxJIGNV46ngMHz5ch05vuukm/X2yAqPunnvuUSdOnFBnn322ev7557X3kbFjbGHc8r0fe+wxNXbs2Cw/i+KnN954Q7Vr104benwf9i3GoPFuBktLwEjEq4ZBDxi/eC/Zt4yF7xvIG8d3xINtvMpZYV7newbzpAYDD6cBTyyLjpxwKucQxTmrV6/Wx9eAF57n7A/eJ8QpVoTZdXCXVefVOp56MCZBEBKHBQsWIEGmH8OGDQv57+bOnev7u+7du2d47c8//7SKFCnie+3EiRMBP2Pw4MH6PUlJSdYvv/yS4bXNmzf7Pp/H1VdfHfBzHn30Ud977rnnnkyvT5kyRb+WnJxszZkzJ+A49u7da9WuXVu/r2nTppleZ7+YbfA57DN//vrrL6t06dL6PWeffXam148dO2aVK1dOv86+Wbt2bab3rF692ipcuLBvWxdffHGm96xZs0aPwRyv9PT0TO85efKkdfPNN+v3FCxYUH+/YMecx/DhwzN9Bp/bsmVL/XqePHmsP/74I9N7Bg0a5PuMPn36BByL+e67d+/O8FyXLl18++Lw4cMB/27FihW+z3/22WetcNm6dauVkpLi+4wCBQpYHTt2tMaNG2ctXbpUjysUInEOvfLKK75xcG4LiYN4HmMUQid0ayBPJR5BL6x169ZuD0NIMEqUKOH7nXC0HTxhf//9typfvrz2GgbLASSPkPfgiSMUGAwKHfDmBfqcBx980FchjhfThDiNx2jUqFH6dzyFwfT7kG3Bmwd4k0weYyAITQfKTSMv0Oj44Uni+/sXbxiPIt4+46m0w/fg+2QFuZJ4HPHCDRs2TM9t/iByTU4m+42QOiHyYOAtHDx4cKbn+Vy8pEBaAR42O+Rq4mU0n4H3LdBYTPi4dOnSGZ4zoWv2Ex7PrLyO/D1V/uFC5fS7776rChYsqP9PmJl9wTHEi40IPvmhpBLs3bs34Gc4cQ4JiYUYj35gjDFZ5M+fX+3YsSPT60ywgWQ/cgpJ62yPiXHbtm2ZXifnh1AI7yFEESsQsuK7MRkLQqxgbsjgHy5GMw9Y1GRV4YoxSIgV/I0TOy1btgxazMJ8cMstt+jfMQBWrFjhe43w8saNG/XvhBOzAiPCkNVYCLkGAyPKGBzkxNkhrAzMT2a8gcAADWaEgcmpozI4q/dRQERRU3bf58Ybbwz6Oeb7AMVOdsiPJGxtjCpC7uHA/iZHMFjomkUA6QAmTFyyZEmVEzgHyXdkjP6fQV4mKRcYydWqVQu4gHHiHBISCzEeg8AFSNJ6tOBmRN6TP8FWr1TCseIk/8qrxiMeGDEehVjCbjDiwTFQZfvDDz/o3/FMYZhk9TBesayKMrLLB8OLZMDrZ7DnnmGkZjUOuzGc1VioEA6GvSrZ36A246LSNitDCNH1YN1HtmzZ4svbe+CBB7Ldt+b7O/F9KBYyXHjhhSonUARlDFG+m/8ChGKcnBTK+FOhQgXtGaVAiZxOKtT5zDPPPNP3HuZfjHp/Q9aJc0hILMR4DEK9evV0SCm7JO9IQaJ9IOORVapJ8rZjvKPhrowFQQgOVbmBjAy8f6FUT/tjvFiBQNonK+whUXv4MacdQ7Iai5GbCYS9JzJGtB0zruy+C/iHeL34fezHH0menICxhsQTnloqxO1QIAWkNVAMFQn4PhTR0EWJFAcqyjEO6dluQC7Jbig7sc+FxEKMxyCQL8PEEor3kZsKFYCECPAgssLm7/FehgphFjwbdmkOVnmsXnktlJxH3k94iBUp42DyQ9OM9/rnEqLTRX4RIXHCQKbXLJ5O/o9hSnjHvhIH9NLQpqPSlPeUKVNGr3bNahoIV1M1aTwSZgVrHweVkHhWmOTJqyE08vnnn2f6nl999ZV+H9tim1nlkAnCqWI/3+3ahHYjg7w2/6rSYI9A57Qhq/BsVtjHQrg31LHYWzRGmpx+F//vgwxPqN8nu4pmt8BINvnazM8YkYAjwpwPaGc6ufBn7kYFwOhAkr9rUgy8eg4JsYW0XQkCRg8XON5HBGWD5SaZmwkrTHJHWOEtWbJEPf744zonBVmHUMB4wujD0/joo4/q50xSdCDPYyDIF1qzZo1OnMZIZHWJ7AaisvaQETIVGKS33367TthGy4v8G1pZYfSaCYLvgGwIunNmtc7nkSeEkYrhyPamTJmif6Jtxk0E2Q9Wv3hSSdo24SzTL5hwNgZmkyZN9HclcZx9hqFMHph9nOxTwkCs5lm1Y7gyMaKBJwiRhvPbYPfc2L2QGAORyHsm3Bjq6/bt24t6yAGMZA52uLDwC+W7ZPUe+/fBY+fm97GH3nft2hVQ+DoUuCcw95MjumjRIp0rz8LXGG2mCMlJUlNTtYYjjg0zn3rxHBJiEzEes4AKQS54qtLILQnEqlWrtOHIZGF00DC+CONglKGw76/EHwiMrk6dOmmDyxiPaJthiGWVnG/PbSHPkMq4u+++2/c8OUT+YAzyXpPUjygvIZSePXtqzyfaXubGgIH55Zdf+iox+W4YyHYaNWqkJym8hOQJoV1GGIXvgs6av+HK96ODBnlh9hCSWaHbx8m2Te4RhiyVhngc2LeCEEkQRTbafpxndv09FjgsWFgkUXUaCYKJkAd63X5zP/fcc32/Mxa7kRttiFKwaMRIIvpgN0rskNNojzzYIaKAPiQVypHatznFrqHI3JNT45HqZZwBCMczXzF/Gk8p85k9L9FJ7E4Pu3c4UufQqXichdhGwtZZwKRGQQqeNVahgTCdE4z8g8EYWDSxDxW8gRhX3DTMz0Ah60AQfuYGR/jZX2LEH4xFYzgC3RaALgPGcLQ/b69INCK4pjsBOUIYj2CvCA3GzJkztYQJ4Sm74RhoImKc9qR1PJeEEv0rJAXhVKH4jEiDWcCwAPOX0GnTpo3+yQILQeRThRBmsHmFa8Tky7GIsxs1/I5hAsxNXIdui6qz37JKKbGHb/0hfGvE1dknp9o15VRgoY/HDpAF8s+JDBXmNuNdZJFMCJloTCQKZYLtx0DYC2O4n0X6HCKdyBBOmpYQ+4jxmA0PPfSQzmkMlvtINR0ThX+PUUK6hAP8q+2ygtUgVYKErvE68hkYdKGAdxIP6Zw5c3TODWHw0aNHB6yOsxuIwKrfeFsCPW83RkmQHzBggN4GhiQGnVmd+2vABQJ5CPYXhmF2+I/T3EizM44FIRyQLcHzYvIdL774Yt1v2B/Oe1N5imGAFzIrWDiSIxwMbrZ49gMZKMw3ppIZY8MefeD6MRqGLKQwerO6cSP3NX78eOUERBZMYQnhUaIFgfbviBEjsvwcIiQYkRjNpKrgsQsG+4v5Mav35BTmbI4JUME8cODAoMYaupRZFZ5w3FgQU2RiDMlChQqp66677pTGyLlJF59gGo72FAyzAMEgtndPitQ5ZC8qMtI/QmIgYetsYLVGXiCrM3IfnXbf42lEjJhJhr6s/t65rGCiI3cR7x6eEUR7yVskl9AepgiWqB3sefvkSeiYkDcFMVSkczNlwidMk1Xv25wQyngEITu4wROSNtBujQUIhh1ham6y5pzCi46niNw7f1gwmdxmPIaEtcnBveqqq7QXB2MCg2bp0qX6M7gpU4xAGkcg+Htepyc07e4IZTJWtmFaxvG5XMf+9O7dW4+bvDr6aeP1x+ihuIxFHzd7PKREIpCHwUPkhE4s0Q48dOwT9in777777tNhWvYp2zdi1Cyw7Xl3/uFvUlHYDxibhOl79eqlF8/sdzxjhL3RGWTfsv8xro33LJJgBLNv+XwMJrbJvmWMfF+OMTqKpOXQno9zIBCk62Cw8VlmEc/8aTybOYVoD3JR5I7jsWWxw/4iZQBHB/uYY04rTTMnM0679FSkziHuKzzP8eE85bpBRs7ct6gqt0erhPhBjMcQvY9UB5tJ0A4XChcoyvv27gokh5OHyOvhGo+EdJkc6TMaLlR8EzLnwZgw8OjewPhPFW4O3GyZtBijIVDXgWDGNONjf3GDYGyC4DQsxnhkBR50Fl/0ow7WOQbIQaarCgYDnh+KzHgEghtoVoZCnz59dDEFIV3ynQN5dVgEmgiA//VFQR3eULaP1yerXtqhSOnkFAr1yLVm+8x5/nnWKCpgyPCeYMYjsP/ZX/wkisH7TXcTfzDi7CHTSMJ4WXDzvch7xAOJIZsTyIW3F2GdasjaGGRGcBxHAY9gsI/IMWefOnEO4eRAqJwoF8anveARyPkP1LlIiH0kbB0CGDx4H1nt+YeBTa7OmDFjMjz/zDPP6J+hVkrbt8Vn4TG0iwRnB6ER/7wVPouLO1K5KMYT6O/58//uYG6a/iLhhLm4qTKh+XsqxaMoOA3nHsYYKRHk03JTnTZtmvYmEcbLynA04N2nQARPmfGM4XHBw0IKBzItXP94yrIrlqOIgjQVbrB4jghP06GEmzhh8azSO9gmbRIp2kNhAc8Y343rlJ8szlAqwFPndB4hOaIUzGFcY2TwPVg4YyyRdxfqPEjRHh5bFqh4ZKl+5pgwn7BfMOgwdOj+5Z8qFEnYLoY90mV4VY38mZEMI/RM6JxCwaxgvjOpDqQkoTBxqlC8SToU9yPuSxxn0nnYT5yDFMng8SRVgDxLI5vm1DlEigXFolxPqAKI9nBiIJ7HMCqv8QSS02OXiTnnnHO0jAxhbQwlQgiErQg9MXGEUmntDyvBcGGSuOyyy3RYhBsOEwnhCDyggbwaOcH0TGWVSYiOFTAJ7v4ty+wtwNhvbJ9JipsuEz7PERpisjHV5BQHMelhNAvCqWLCpk7BtWA8/KcKBkh2RkhWcMMfO3Zs2H+HXBaPSO1LDKOsjCOjJZsdGONENuzRjUgf81DfhyoEj5yCkUcf7kjL87D4wRuaU49opM4h48HEw2r6eguJgRiPIYLRwyrPv2MAvPjii3o1SvgJg41CF0I3w4YNi9r4KHbhBkRYGSMX45GVLuEiVuuRAi8JK1RaYTEBE6agSMdfB5PWaxiIeAmoNMTLiJGJBwGvIx4acqUwJAkTkRfm1VaLgiAIOcF0lGE+pihFEOKFXFaEl+e7D+1WLT5oobzEFx2/UGVSy7g9DEEQEhxC2UadgJB1sGILIfYhEkXqELmxhL4pShGEeEE8j4IgCIIQAaiWp0qZVoSkBGA4EtYN1KxBEGIZMR4FQRAEIQJQ6OSf2kRXLrvIuyDEA2I8CoIgCEIEQUqIkDXV4+SIC0K8EfGcx7T0NLXnyB7lJUoWKKnyJImdLAiCIAiC4DnjURAEQRAEQYhfRCRcEARBEARBCBmJ5QqCIAhCnEGXIyq/EbT/3//+5/ZwhDhDwtaCIAiCEGfQUpE2jnQCo/2mIEQSCVsLgiAIgiAIISPGoyAIgiAIghAyYjwKgiCQw5Mrl36ES/PmzfXfLVy40JFxCYLwL6effrq+1mjzeapwvfJZXL+xTHOX5h8xHgVBEOL0BikIguAEUm0tCIJwCkydOlUdPnxYVapUye2hCIIgRAUxHgVBEE4BMRoFQUg0JGwtCILgxwsvvKDOP/98lZqaqooWLaquvvpq9d1334Wdc5SWlqYmTZqkmjRpoooUKaLy58+vzjzzTNW/f38to2Ln1Vdf1Z+zZcsW/f8qVar48jADff7SpUvV9ddfr8qVK6d7KZcqVUpdc8016osvvgg4zltvvVV/DttZtWqVuvbaa9Vpp52mChQooM4++2z13HPPqZMnT57CXhNiOc/3lVdeUY0bN9bnqX/axM6dO7VWZM2aNVVKSooqVKiQatCggRo/frw+x/35888/1dixY/V1w3nMOYbeZP369dWoUaPU0aNHg45p7dq16rrrrlMlS5bUf1enTh311FNPZXlu8jfDhg1TTZs21dJEXA8lSpRQl19+uXrvvfey3Q8nTpzQ46pdu7beJn/L9fHzzz8H/Zt9+/bpbdarV0/vD/ZL3bp11fDhw3Ukwp8DBw7oeYXPZQ5gbuHB3zz44INq//79Qbe1bds21b17d1W2bFnfHMLfHDlyRLmGFWHS09Ot48ePe+rBmARBELKC6ZDHoEGDrFy5clnNmjWzOnfubNWpU0c/nydPHmv69OmZ/u7iiy/Wry9YsCDD80ePHrUuv/xy/Vr+/Pmtq666yrrhhhusihUr6udKlixpLV++3Pf+xYsXW7fccouVmpqqX+/QoYP+v3n8/PPPvvdOmTLFSkpK0u8799xz9TibNGni+w4PP/xwpnHyGbx2xx136PGcfvrpejwtW7a08ubNq1/r2LGjzJdxQvny5fUx5WcwzPnSt29ffT6Zc75hw4bWb7/9pt+zaNEiq1ixYvp9nDNt2rSxrrjiCt9znD/cZ+28/vrrvm1zfXTq1Mm67LLLrIIFC+rnGzdurK8Pf7gGzPlftWpV/XdcQ8nJyfp6qFy5sn5t8+bNGf7utttu08/XqFFDj43zmm2Ya4Rr2h+uV17jumEbKSkp1pVXXqm3Y67RokWLZtoWrFmzxveesmXL6r+75pprrNKlS+vn6tWrZ+3fvz/Td+O10047Te9nc+2VKFFCP3/GGWdYe/bsybQtrvtSpUr5tnXddddZV199tVWgQAH9HXkEmn+cJuLGIyfR6tWrPfXwP7EFQRCC3UiZlOfNm5fhtdGjR+vXihQpYv3+++8hGY/33Xeffr5atWoZbkDMR+ZmV6VKFevYsWMZ/i7YDdLw448/akMWA3fq1KkZXps9e7bPEPz8888DGo887rzzTuvEiRO+13766Sd9U+O1SZMmhbzPhPgwHgsXLmx9++23mV7ftWuXNm441yZOnGidPHnS9xqGzqWXXqr//pFHHsnwd2vXrg34eXv37tUGE3/DNWXnyJEjPoNs4MCBVlpamu+1VatW6cWWGa//tbFw4UJr48aNmbb3yy+/WBUqVNB/s2TJkoDGo1mA8V3tY8EI5bVevXpl+LvDhw/ra5rXHnrooQzX76FDh7TxzWvdunXL8Hfbtm2z5s6dm2Efmr/p2rWr77r0p0GDBvq166+/Xo/LsGXLFt843DAeJWwtCIJg4/bbb1eXXnpphufuueceHXL7+++/1YsvvpjtZxCWmzBhgv792Wef1RXUhuTkZB3SK126tNq8ebP64IMPwhof4WVChe3bt1ddunTJ8NpVV12levXqpX9/8sknA/49oa+nn35a5cnz/ynvhOuGDh2qf+c1IbG4++67VaNGjTI9P2bMGPXXX3+pPn36qDvuuEMlJf2/yUBol2IxzmfC1/ZmdYS3A31esWLF1Lhx4/Tv77//fobXpk2bpsOzFStWVKNHj1a5c+f2vUZaBWHaYFx88cWqatWqmZ4/66yz1JAhQ/Tvwa4zQvSE7MuUKeN7jtDwI488on+fO3duhve/9tprauPGjap169bqscce0yFyA6HrKVOm6BSS119/XYe27R1/Lrvssgz70PzN888/r69H/33y9ddfq2XLlunw9sSJE/W47LnWhPPdQgpmBEEQbNxyyy0Bn+/atav6/vvvde7h4MGDs/wM3nfw4EFVvHhxnYfoDzeMTp06aUNwwYIF6sYbbwx5fCb3kRzGQNx22236Zr548WKdJ2a/CQN5kvabkP179+vXT61fv17nuJFLKSQGHTt2DPj8J598on/ecMMNAV8nv5D8O3IOOW+qV6/ue41zj3P1m2++Ubt27dL5ef9FO/Xrv/76a8DzmvMTgzTQ+Tlo0KCg34Hrbc6cOWrlypVqz5496vjx4/p5th1oe3Yj7Jxzzsn0PAYw+OcmZ7dPChYsqBeas2fP1oZfy5YtM7zO/uDa3Lp1q86NNPsDI5RcUQxOjGz7Prnyyiu1se5P27ZtdY4qi9poI8ZjDiGZmERgVves2gRBiA+4rrN6PpQ+weaGE+yzoFq1ahneGyrZfbb5XLyfeI3wgtgJ9nck/XOD4m/4jmI8Jg52z7idTZs26Z8XXnhhtp+B4WOMRwxJPONr1qwJ+v5//vknw//NdRXs/MSgCmYoffTRR6pbt2763A11e9mpJVDgA8eOHQu4T7p06ZLJ8x9onxj++OMP1aFDB/XVV19l+TeM0xiP2e0TvKYcOwrgoo0Yj1mAmxh3/QUXXKCWLFni9nAEQfAA9vBcvJII31H4f6gwDkR6errPM0noNCvsnjHej+FIaPfee+9VtWrV0sYYHkU8gvny5YvY2FlM4QXEs8m2brrpJm1Q4QEkRPz555+rK664Iug57R9Gzg6zT6688kqdepIVlStX9v3eo0cPbThS0U5IHG8nRqLxsrJYw0saK9eeGI9Z8Oabb+qTEEmMDRs2qDPOOMPtIQmC4DDkISK/4Y+RLiF3KTsI55nPCobxYJj3hgrvJ+eKv0fGJNjnEpombO5PsDEhJWI8N6F8RyH+If8QL+J9992nQ7Gh8Msvv6gff/xRe7xnzJiRIbcW+LxAmOsgWGclpGyCeR0xHPF0IrfjT7Dtnco++eWXX3R6SLBwvz+HDh3SYWwMVX4i/+X/+u7du8PeJ2CkvaKNFMwEgQmW3IRnnnlGa6FhSAqCEP+Q6J7V86H0wuVGi+dj79696sMPP8z0Oje7d955R/9+ySWXZHjNJOAH0s+zbx+9xkC8/PLLvlCj/40bSMr3D8XZvx+L5HANWiE+oQALQtFKNHDOG09aoPPvjTfeCFr0YraF7qI/FOdktT27l8+AF++tt95Sbu+Tv//+W+eA4n31NxzNPgnkcTT75NNPP/V9TzvMLVnpQzqJGI9BwFjEpdyqVSu9usjKeKSakhMX1z8H+6effsrwOisK8jFYzeOup9qRRFf/1QTJvkz4hAfIP2Lb/jkjJMlzU8JV365dO/07xi15l/4iqrjXSchHhBQvBO/D1U4yv/+JiyAy48dTQSI/VW+CkIhQ+egvyM01TgSC6xKPQ3ZwvZHyAnfddVcG7wA3xgEDBuh5gVwmf++F8foFyxfjb7kpz5w5M9ONmBDd5MmT9e/BcrEphvGfLxBDfvTRR/XvWRUlCIkFKgMYOzhRqMI3RSj+jhb7eUjeI0Vaq1evznQd4SXkWgoE1wGLFgpJHnjgAV94GLinIr4dCFPYQjW1KY4Bzm8UBHACRRLUDCpXrqwXYXhk8dj7w7WNILiB8Db2BIae/+KU5gN830BgD5x33nm6GIj5xL7o4x7tar1FpLV/4kXnEbFRtNjgyy+/1DpKS5cu9b2OzhTP1a1bVwunjho1SmtdFS9eXOul7d692/deREjRh0MT6sUXX7RGjhxpXXLJJVp81YBeG1paiI2OGzdOfx6f6y9SilYbAr+1a9e2unfvbj3//PNa1JSxoMNl59Zbb9XPI048ZswY66mnnrLatm2rP98wfPhwvV0ES/l7vgN6Wmx73759Ye83QYhVjF4aGnNcExdddJHWbOMa5/ncuXNb77//flgi4QgjG+1IhH25zipVqqSfQz/v+++/z/R548eP168jqHzttdfqeYgHmnWGyZMn+wSQzzvvPOvGG2+0mjZtqsednUh479699RyCxiQizOjZGW3I9u3bi0h4Auo8ZgX3KaOxiFg12o433XST1bp1a5/OIKLidgYMGKCf5xzl+uA64jw12ojBtoteI2LdRh+V87NFixZaJJxrIZAGKnql559/vu+aadWqldZE5L38ndFbZRyBdB79nw9l//z000/6HmmExJkruAbbtWtn1apVS1+HCIbbefbZZ32fx/5in5hrtkuXLkH1XREkNxqs5cqV09+Nfc9+atSokYiEe8l4ZELnYHzxxRf6/0ymCI1yQfgbj9wUtm/f7nseIVK7oj0GGP9/8skng27vwIED+gTs2bNnhucxQDE67c+bG8Cjjz6a4b2InHIBGebPn6/f179//0zbMzcHOghwQxwxYkSG19lniBD7Py8I8Yz9RsGijC4RXN8IKLOo+/rrrwP+XTDj0dzYWJQxyRcqVEgbadwU+/Xrl2HesIOI8OOPP64XiBh5wUSAv/vuO90RpkyZMvp6xRjlxukvDu4/d7zyyivWihUrdEcM/iZfvnx6W88880wG4XAhtomU8QgI4w8ZMkQbgOY85p6IY2TYsGFauN7/HvPSSy/pexIGHfcxuqq888472W6X+w+GIo4Yzs2aNWvq64FzM5iBxT108ODB1llnnaWvGYxcDDnu5cGMxFMxHuGff/7RQucYb9y/MVTpAIOo9z333GN98803lj8zZ87U+4z3s1/q16+v5wf2V1bNARAExxmEQcq+p/sORjEC41nNP06Si38i6ckkJBNMT8ktEAoNpBsVDHp4kidBaNhopOEexjVvnjNSPZ07d86UU4E4Ku5pkmpxM5Pn0KJFC+2uNiX4dkgqpt/l/PnzdYjZDpVjJMCbpF/C1oiUUvZPGNoeyuLzTV5E3759dbU4eleBkuaB8AEhtXXr1mXKw7jooot0CCFYn1xBEGILM3cgiBxMI1KIH0h/4H7FPB6KvJQghINUW/tBngSJ7CSx26sSGzZsqHM+5s2bl0H0E4FUf8j5MMm05DhSAYaRRt4DhiXyBQgOG0V7Yxj6d7Xw15symPxFOxildjV7qjFJWA5mOJrtsnYI9B0gHINbEARBEITEQIxHP/D+kXSLAWmqIe1QOOOvGJ8dAwcO1F0mSHD/7LPPdLukxx9/XG/r3HPP9SUG4zm0t0gy+Fes+XeMyClsF5FRCnUCfSbFOIIgCIIgCHbEeAxgHKJPZfrS2pk+fboOMU+aNClLDSnCwP6K/XR9wPvIg79BRw5PJqFw0xGC7V5++eUR+R58JoYqYexg3kfeg+eR8Lu9rZQgCIIgCEIwRKrHT3sNA5GwMrIB/g/yCCnLt+u24U20txdDzoNuNEYLit6VtAnzN9qQ/DBl96jfE5oeOXJkQH0re4ujUKENEoahae5ux6S5kmeJx5H3+Ke+8v+sWj0JghBboAvJdS35joIgnCriebSBUYhx2KZNm4Cvk69oBMPJgTSCus2aNVN33HGHNgbHjBmj2zTRJsl4IS+77DLd7J0WTYSg8V7+/vvvWk8RMBzRlqNPJppOPM920LuiCXvTpk3V+PHjw/ou5GzyeWPHjtWeTvQdCVPTkJ3XMIQxYtHOQmOKAiB0IzFqyfVkjOhZSd9uQRAEQRDsiPFoA6OQYhQqowNBayGEu3mf8cpR+MLzGI1UQNMHG0MPIXDTyoiKbAptyGnEeKxRo4YuqME7aLjxxht1gcsTTzyhnnzySW2IUiWHSCgC4zmBqsqzzz5bvfTSS1rslabydL5o0qSJ7z3333+/DllTeW28lIyZvM5gRrQgCIIgCImLSPUIgiAIQpwhUj2Ck0jOoyAIQpyAUsTDDz+coU1bIiL74V81DftPQYgkYjwKgiDECRhLpJ8kstEEsh/+1Sy2/xSESCLGoyAIgiAIghAyYjwKgiAIgiAI7lVbU01MgYqX8O/QIgiCIAiCIHjE80i7OyqbvfRgTIIgxA/oknJdI3wtCLFy7i1cuFD/LT+zo3nz5vohRA+ZV0JHwtaCIOjJkkkz0AMtULd46623tIaqED7Bjqf/IxRDxotMnDjRsZu8V6+HSPLPP/+E/TeHDh2Ki/0o88qpI/FcQRB8PProo7rXuZ06deq4Osn/9NNPauDAgRmer1y5sm4nKvqtwaEpgZ2pU6eqL774ItPzNWvWVLFqPJYsWdLRdouBrofatWtroyjWz72iRYvmKCqXk+ptmVfiDzEeBUHwQU92uhB5HW56dIMSgnPzzTdn+P93332njUf/5/05fPiwSklJcXh0sUGsXA85YfDgwRmMx7///lsbxRiVjRs31i1y0Yikm9pXX32lzws6lcXzfpR5JXQkbC0IQkiTKqLL/px++ukZPD8mTPX111+r//3vf/oGlJqaqtq3b6/+/PPPTH8/Z84cdfHFF+ue6vR4b9CggfYKAPle9HbfsmWLL9TF9rLKTZo/f75u6ck2uQm2bdtW/fzzzxnew/fgbzds2KDHzvto3UkbUG6QiQT7GA/Q8uXL1UUXXaSNRowKmDVrlm7HStvUfPnyqWrVqqnHHnssoOdpyZIl6uqrr1bFihXT+562qM8991yG9/zyyy+qY8eOqnjx4voGjTHx4YcfZniPOX++/PJLdfvtt6sSJUro84I2sPv27fO9j/NgzZo1atGiRb5zI1r5gcHOvVC+XzCmTJmi92+BAgV0i9vFixcrpxk+fLg+nuaxfv16fb3w/d59913dZhfvLr9zDdKylu8YSWReiV3E8ygIQgbvw549ezI8R2gwXPr166cNiWHDhukJmfyivn376huRgQm6e/fuOgz4wAMP6Ml25cqV6tNPP9W93h988EE9Hlqr0XsdChYsGHSbc+fO1R6OqlWr6omc8NO4ceNU06ZN1YoVK3w3CMP111+vQ2mPP/64fv3FF19UpUqVUqNGjVKJBJ4l9lunTp20V7J06dK+48P+5mbNT26gQ4cO1blyTz75pO/v8Wa2bt1alS1bVg0YMECVKVNG31g//vhj/X/A0OM40CqPXDduwu+9955q166dmjZtmjYC7HCucD5wHGl3+/zzz+ubvSk44XziHGNcnCdgxu309RCIcL+fnZdeekkbyk2aNNFh1E2bNqk2bdpoI7RixYoqWnzzzTd6fyclJQVULMEAw+DMCTKvlIq/eYXe1oIgJDavvPIKPe4DPoCfw4YNy/R3lStXtm655ZZMn3P55Zdb6enpvucHDRpk5c6d29q/f7/+Pz8LFSpkNWzY0Dpy5EiGz7T/XatWrfQ2/Nm8ebPeDtsz1KtXzypVqpT1119/+Z5btWqVlZSUZHXt2tX3HN+Dv+3evXuGz2zfvr1VokQJK5ZZvny5/m789KdPnz6+42m4+OKL9XOTJk3K9P7Dhw9neu7222+3UlJSrKNHj+r/p6WlWVWqVNHHaN++fUGP42WXXWbVrVvX93fm9SZNmlhnnnlmpvPn/PPPt44fP+57fvTo0fr5WbNm+Z6rXbu2Hn+4++FUr4dA516o32/BggX6b/kJfEfOWc7dY8eO+d43ZcoU/b5g3y8U+Fw+g5+hwHcoVqyYNWHCBGvZsmXW+vXrrbVr11rz5s2zHnroIatgwYL6PeEg84oVF/NKICRsLQiCjwkTJmhPkv2RE3r16pUhn4qQD+FOvEfA5x44cEB7afxzjHKSxE8buh9++EGHi/DYGAiftmjRQs2ePTvT3/Tu3TvD/xkjXricVKHGMoSkCa35QwjVwLHCc8Q+IgRnwpd4dDZv3qw9Znh4Ah3HvXv3aq8lHhnzOTzY11dccYUOl+7YsSPT+WMvWrjjjju09yvQcXT7esjJ9zN8//336o8//tDnYt68eX3Pcx4T8owmL7/8sjrnnHO0J69hw4Zar5mUhssvv1yNHDlSe9pyWt0u88pfcTevSNhaEAQf5FtFIrG9UqVKGf5PqAlM3trGjRsjWnFpbh6BGhRQTfzZZ59pmRHCiaGMkTypRIFQq91wsYdiH3roIW0Y+d/4CPuFehzJAcPJNGTIEP0IBAYU4zCceeaZGV4nrEhYnFCl29eD/xhy8v38z1v/74vhTJg0mnA9LFiwQIdzV69era8DDC7yTjEqTyUtQOYVFXfzihiPgiDkmGCyHblz5w74/L+RKm8QC2OMBnYPo2H//v264ICbHTIrFHPgySGH67777tNVuKFi3nv33XdrT1wgzjjjDBWrxNv3q1ChgvYis2BIS0vTzx07dkxt3bo1oHHkBDKveB8xHgVByBZWzxgUdo4fP67DOjkBYwTQWsvqxhpqqAl9NqC4wh9CrCTn270DQtZQmEKobfr06boK20CIOthxJLwZCONBw5sW7D3+EOq95JJLfP8/ePCgPteo6DZ4pXNYTr6f/3nL97300kt9z584cULvazx+0QJjkUr7GTNmqN27d0dU5zEYMq/ELhHPebTS0tSJ3bs99WBMgiDkHCZl5FP85UVyeiNB9gMZDSoSjx49GnSFzsRsQqRZQUizXr166rXXXstwM+Im8vnnn2cwOoTQvSf2Y8FNHekWO+edd56uLKXq1d8IMH9LpSnyKJMnTw5oFASSWuHcwoAyUG2NF4yqV/u54b9NN8jJ9zMQykV2ZtKkSXr/GsgtjPZ369mzpxaQ5yfVyxw/cgyR7MGQ53tyHCKJzCuxS8Q9j2l79qgNzf9/xegFzli4QCWXKeP2MAQhZunRo4dOBO/QoYNOFF+1apXO98mJ3AYQDkUmg89FAgQJDbwQfC4FGUzWcP755+sbGXIxvI/ct2uuuSbgZyIfg3GBwPFtt93mk9Sg8CCQlpwQHGRjOB633HKL6t+/v/bUYFj4h96QdcGg4Jhwk6XwhhsuXhlyJjlHTMFEs2bNVN26dbVxgrfu999/V99++63OseO428GQuuyyy3QRCl4fjFb+HgkbA+cG20Y+Bi8Txo3dexdNwv1+BryVjB+pHsZ+ww03aI/jK6+8EvWcR7zN5LgiBG7aEKJneOWVV+qCJa5RPNEYlJFC5pXYRcLWgiBkCzdEbmpo0qGXRgUhlY3c4HMKEzE3/CeeeEKLFHMjrVGjhho0aJDvPXfeeaeuduRmyk2BMFKwSZ6QIWNDAw49Qj6PvD301fxbowlZQ5EEOo133XWXNii4AaMByfH2z+vj/xRaPPLII+rpp5/WOYB4lDhnDLVq1dKVxbwHrxohcY79ueeeq4+VP3i73nzzTf0aHsjOnTursWPHZgg38hoFDaNHj9YVthxrt4zHcL+fHYwxPG0YKRhuGKCIiwcrvnEKDHYq2o1njmPOtYfxCFzz5HVGEplXYpdc6PVE8gMJE4vnURAEIfpQ0IJXhY4xhJRjDQwvvJfLli07percWN8PkYDqaKq8MaTwgmYHXXwwgNl3FEch2YOnDqMLQ5KOQXgEeY8giOfxFGAV3KdPH71KFgRBEIRY5amnntJ5fEYfkbxB8jVHjBih0xWQq6FbiiB42ngsP36cyl24sEo/cEBt79M36ttHL4pwCC70nTt3ah00wgnk4BBmCCRvIQiCIAixCB5KUhMMFJ6QF0ilO8UnOc1DFOITTxqPBc4/X6U2bKhyFyqkTh44oP9/ZPnyqG2fpunXXXed7ryAKx/BUfJBvvrqK52TQiI4FWGCIAiCEC9gJJK/Sm9y8kjprEI+IAUldMkJJHQuJCaeNB5LdOv2r+F48KD+WaJ7N7U9SsYjybudOnXSFwydFagcNBCippsAxqUgCIIQWTBWeAjRB+dIx44ddZ6kScuigIV7Id1RiLxR1ENBiiB4rrd1rgIFVL4zz1BWerpK27VL/8x35pn6+WhAqBo3PdVfdsPRgCTEgAEDMjw3c+ZM7Z3EU1m7dm1dmWWHikCqu8gZIdxNJSOeTf82VySLc8F+/fXXWkIA/S+q3tq3b59JK4yKRmQCypUrp1JSUrQO19q1a9Xpp5+eafJFn4resxUrVtRj5DtQKRZOlwhBEAQhfkGOh3sERUbcs+y1tBTM8DqyQoLgSc9jkQ7XquTy5dWJXbvUtt53qEpTX1PJ5crp5/e/8abj2//oo4+0vhY6Z6Gu1tC+wjgkRwQ5CTSraOWEkQhUDn7zzTfao0nrJ4xG9MkQlsXgw/iz069fP32xIg3AexHgpfKN/BPDAw88oA1d5AWQykDHip/+wqhoWyErQMgBLTFaSzEW/h5BWz5bEARBSGzocsP9AHkhpIb8CbVqW0gMvGc8tmqlcuXJo45v2aJO7NihTmzdqvKWL6+fd9p4pD0TRhbCqKFCbggGoGmLhAeQllJvv/22NvigVatWOhxgB6MP0dFp06apLl26ZHgNo5OqN6NphocQoxRFfIRJuYCfeeYZ1a5dO91KyoDGmL9oKe+j+GflypXqzDPP1M9hROKxJASBjhurTUEQBCFxIXpG9Kt169a+glBzD0KoHT1E5I8EwXNh6+SKFVXeihVV+rFjav/77+vn9r33nv4/z/O608Yj4EEMFQREjeEIZ599tla537Rpk+85e2U2gres6ggd03weTS1/qOa2i+GSd4KILKEEmDdvnm7VhbfT32Ppz/vvv6//Hk/mnj17fA/GzWf6t4YSBEEQEg8k59atW6dTn4zGJvcUnA6IoFNAg9ajIHjO81iiZ0+Vp2RJdWzTJnVg7jz9HD9P7Nyp8lWpol/fnY1a/6mA0ae3eeBAyH9DGNgfDDUSjA20M0IzCzV7PJv2XJJA/TX9P5PPA/OZxoj0b/xevHhx33vtoYgff/xR508GwiRHC4IgCIlLo0aNdEHoW2+9pVOtdu/erZ/n3oERedNNN/lSsQTBO8ZjUpIqcN65+tdj69bhovv3+RMn1LFff9XGo349KYk4rmPGI+Fcmp6HSu7cuQM+bzcQufAwHClaIVRN6BnPIjmQgYpWQvnMUOHz6Rl67733Bny9evXqYX+mIAiCEH/ggDDpVoIQE8Zj6sUX6UKZk//8o/569dUMr/H/1CZN9eu879CChY6Ng3wPNBxpaI+hFwk++OADdcstt+i+rwYKW6iCzglIJwCrRHtvTcLhdo8nEFKnepwwtSAI/w+LRK6lQGkqFJrRTxlvC40BBCERmDNnjr73oe6BtrG/wwKnB0okguCZnMfiN92schcooEPUR39YleE1/n9i5w79Ou9zEjx0yOP06NEjYGUZxSfh5n3gSfS/CMeNG6dzDnMCTeNpYE/Ftp1AbRK58TEZfPbZZ5lew3gld1IQEhEK21BXCAQKCOjajRw5MurjEgQ3oCEGzhPOeQoxKdqkw5r/QxA843lMKlJE5a1yuv79cJCm64eXLlP5a9TQ7+P96QFyBSMBnjpyPm644QZVs2bNDB1mkLihACVcEVsuyNdff12Hq0k8xpibO3dujvNHaHiP1iSezDZt2qgrr7xSS/WwaqSFlL3Yho44H374oR4D46Za7tChQ2r16tXaI4oUkLSdEhIFvPB0ywAWdPZrxQ4LO7z45AwLQiKAXnH37t21c8RfPk4QPGk8Fr/pJi3Hk7Zvn57Qi/fokek9lrL067yv+E03qj0TM3rdIgkGGUUmSNnMmjVLe/gQ16aSGoOtZ8+eYX0eFyPexzfffFOHq5s2baqNR3QZcwoi31zgL7zwgv4sQuysFJs1a+ZrbA+8Z9GiRXo1ieE7depUndtJriPSPhi0gpAoIJu1bds23//p5Wv34OOJR3WBRRWhayS1BCERuPrqq/X9QgxHIRRyWTmpwsiCE7t3qw3NLwnrb07/4H1VoE6dkN9/5Kef1G8drwv5/WcsXKCSy5RR8Q5haKqt6QLw4IMPuj0cQfAcCO8beSoWVYCIPuCFJB2Emyfdpag+Je8xb968KlZA+ovoAl1CzjvvPJWoyH74N0KFmkYwcW80hu3qHCyahgwZoqNjaAjzd4E885deeqnjYxe8j+uex6TUFGUdP64OLV0a8t8gIs7fpR86rBIV5H/s+pFgusXQuUYQhMzgbTckJSWpN954Q914442ujkkQ3IAWuRiHxn9kfl+zZo2OUtkxr/Ezp7n6QnzhuvGIAbjlxpvcHkbMQatCugEQaiCHizaJdLVp2bKlDosLgpA1CxYs0HnNgpCo578gxKzxKOQM8i8JsdHfmnCDKaKRxvWCEBrkB1M8JgiJiEnXEISYluoRwoM8HgplaDVIJThFAIStTSWpIAhZw2ILdQX6vrsFIv70n2/YsKEuZGNBaDxCFNf1799f7dy507XxCYkFChxom9KekKLKqlWrZnoIgiOeR9oLUqDiJRiTIAiCHdI+hg4dqs4999/OVm7Qp08frZhAFfgFF1ygJkyYkEETloIPetgjoyIITvLQQw9pVY6LLrpIpz6hRUxf63r16mklD1Q8Onbs6PYwhXg1HilmSYTKZkEQYhu8KP4dmaINmrKDBw9Wjz76qI4iYDwauFmjM3v33Xe7OkYhMUBKDm/8s88+qw4cOKCNR85HupPxf/LpBcEgYWtBEBKSl19+WReeofOIpqMbJCcn66pvCCSL8t133wVsnygIkQY5n7POOkv/zjmHZBV6p+b/LGRee+01l0cpeAUpmBEEISFp3769FgXv27evzi087bTTdM6hHQy6LVu2ODaGLl26qMcff1zt2LFD5zGzPULVu3btUh9//LE2bu+//37Hti8IBnRNSY/o3bu3/v8ll1yinnjiCe2hRw/yvffey3FXNCH+EONREISEhB7xwdoTRounnnpKe3WmTJmiXnrpJf3cfffdp39yo0a0GWFzQYjGuThx4kR17Ngx3VGNbmpXXXWVatGihX6dhdUrr7zi9jCFeO0wIwiCIIQH0zAhwt27d+v/4wXF42NC2qEinVX+RfZD9h1mQoF0joULF+qfKAJUrFgx4uMUYhPxPAqCR0C2ZdmyZeqMM85wNTzklXFEk4MHD2q9VMLY/lSqVMnx7ePtoWNU+fLlfc9t3749qmMQEosPP/xQFS1aNNv3If/GY/PmzerHH3/UygCCIMajIEQRpC4GDRoUsAsQhku/fv100vrrr7+eEONwE4xFKp1nzJjh8/gFwsl2bPPnz1d33XWXWr16dQaJnmiOQUhM6F+dk7QNORcFEONREKLI9OnT1bXXXhvQaMubN6/q3r271h5MlHG4Sc+ePdWnn36qjeg6deqo66+/Xt1+++26e9O0adN0j197L2wnoIIVo5GiGEKC/gU7guAUX3zxRYb/41VEMoo8xwsvvFCnThCF+Ouvv7RwPU0pXnzxRdfGK3gLmakEwWHGjh2bITzEJFzGpoWKpw8v2Pr169XkyZMdMyC8Mg6vQC4Xwsj33HOPr01h27Zt1ZVXXqnuuOMOdeONN2oju1evXo6NgZxGCmQQCxeEaBeM2Rk4cKBeSAVaNHI9ULxFNyQWnYIQ33cHQfAAc+bMUZ999pn+nTARWml0NwlE5cqVteEWz+PwCrT1NAZyamqqliP54YcftPEIeF+cFujGoH/ssce0ADPdPATBLZCHyqrXOwvLX375JapjEhLIeLTS0lTanj3Ka+0J6XwjCG5AxwaqHQlPXnrppapHjx66f6wx4jBgEOQtW7asrpCM93F4hWuuuUa3BsSrQjeXzp07qxEjRujKUgzJ5557TtWsWdPRMSCHsnfvXr0djEdChf5wbBYtWuToOAShTZs2+nzctGmTrqwmSnHixAltVBK2/uabb3Q6iyBAxC0qDMcNzS/x1N6l17a0TBTcokaNGvoBF198sbrhhhv0z0Qdh5d07UzPXkCs+88//9QGJAY2BUNO53jlzp1bnX766fohCG5CpIGIwxtvvKFzfu2LF64FrgtplSk4pvN4YvduMR4FQYhp2Z6jR4+qkiVLqlhD9A3/RfbDqek84n3fv3+/NhyLFy+uRcMFwY7EcgUhytDujhW+PfeOql+0/po3bx4wdBlpli5dqj766CNdqGEvmokmGGiEw37++Wd14MABdeutt/r2C+367JqH0QRNOwpZRo0apXMRzz33XMe3OW/ePLV48WItGcR6nht/s2bNdHcPt7vgCIkFBXO//vprUN1TFAIEQYxHQYgitKBDDub999/XvZXRTKOH7HfffaeNBnIOqfDFaHESbgAYZ+g5usFXX32ltSbxjAAGEgUqGI/79u3TcjmjR49Wt912m2NjwLNIW8BA1aMch1WrVumwNoadUyAETq4ZhTpIJDEmI48yfPhwLSH0ySefSGePBICFFHNBMJDSGTBggH6fE/D5KAywmGMu4po0gUn7AkaMRwHC633lMOVGj1KV33k76IPXY00KhIuOnwa8K07nN1FBy3Zpd2bAo8VDcJcnn3xSJ51jOMLzzz+vvv/+e/XWW2/phHRa0iEd4zR4uK677jod0nIDilQwiAgr4om1Z89QrNK7d29tPDkJhSp4e4NB2JNOO06CDBDjQHOPSleMyZ07d+rfZ8+erf7++29HpYIEb4AX/vLLL9fXPkUqdvbs2aMXnJyP27Ztc2wMLCRZzLJY4hzkmvzggw+03unDDz+sF5uck4LgOc9jcqVKKqVevaCvH47CGDC8unXrFvA19NieeOKJKIziX2OPSeOnn36KyvaE6IBBb5LOMVw4n/r27auLV4xR9b///c/xceA9ePnll/W57kY+E6GxMWPG6JAwXjZ/TqUfb1bwfe1elAcffFB7WgJpXbLoo1DASb788ktduOOvuUflO5JBzDk8hPiGoq13331XG4nor7755puqevXquuKfRRSpLegv3nvvvY6NYeXKlXpxy72HuckoMKAEgMYjBi7dkK644grHxiDEDp4yHg3Hd+5Uaf+Fs+yc2Lo1amNAab9KlSoZniOEFKsQfhPcB2/be++9pxo0aKAFdzFUHnjgAd/rGEwkqDtN3bp11ddff61z6+68807tDQ8kCu6UNAfXEgu11q1b657OYIw68q2QFcLTEmkIidPT12wPY97u4bTLFRHC46bp9PmAN4duN1Re28Fg+Pjjj13L/RSiC2kcjRo1Ul26dFH169fX5yDnZ4cOHbSEjtOpC0WKFNEeR2BBST91tGFJq4DChQurrVG8BwvexpPGI4bjlk6dXR0DLZq4gOMF8qkE9xk2bJhOXaACFOMFnUFT1Uve48SJE7VB5TR4OAzBvOmMzynjcfz48erqq6/WRqu5KRI2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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from typing import Dict, List\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from matplotlib import colors\n", + "from matplotlib.axes import Axes\n", + "from matplotlib.lines import Line2D\n", + "\n", + "from depsurf import DepKind, VersionGroup, IssueEnum, Dep, DepReport, IssuesDict\n", + "from utils import load_pkl, save_fig, FONT_MONO, ARCH_NAMES\n", + "\n", + "FULL = True\n", + "\n", + "\n", + "if FULL:\n", + " KEYS = {\n", + " \"biotop\": [\n", + " DepKind.FUNC(\"blk_mq_start_request\"),\n", + " DepKind.FUNC(\"blk_account_io_start\"),\n", + " DepKind.FUNC(\"blk_account_io_done\"),\n", + " DepKind.FUNC(\"__blk_account_io_start\"),\n", + " DepKind.FUNC(\"__blk_account_io_done\"),\n", + " DepKind.TRACEPOINT(\"block_io_start\"),\n", + " DepKind.TRACEPOINT(\"block_io_done\"),\n", + " DepKind.FIELD(\"request::rq_disk\"),\n", + " DepKind.FIELD(\"request_queue::disk\"),\n", + " ],\n", + " \"readahead\": [\n", + " DepKind.FUNC(\"__do_page_cache_readahead\"),\n", + " DepKind.FUNC(\"do_page_cache_ra\"),\n", + " DepKind.FUNC(\"__page_cache_alloc\"),\n", + " DepKind.FUNC(\"mark_page_accessed\"),\n", + " ],\n", + " }\n", + "\n", + " GROUPS = {\n", + " VersionGroup.REGULAR: \"Kernel\\nVersion\\n(x86)\",\n", + " VersionGroup.ARCH: \"Arch\\n(v5.4)\",\n", + " }\n", + " SEPS = [\n", + " (\"Function\", 5),\n", + " (\"Tracept\", 2),\n", + " (\"Field\", 2),\n", + " (\"Function\", 4),\n", + " ]\n", + "else:\n", + " KEYS = {\n", + " \"biotop\": [\n", + " DepKind.FUNC(\"blk_mq_start_request\"),\n", + " DepKind.FUNC(\"blk_account_io_start\"),\n", + " DepKind.FUNC(\"blk_account_io_done\"),\n", + " DepKind.STRUCT(\"gendisk\"),\n", + " DepKind.STRUCT(\"request\"),\n", + " DepKind.FIELD(\"request::rq_disk\"),\n", + " ],\n", + " }\n", + " GROUPS = {\n", + " VersionGroup.REGULAR: \"Kernel\\nVersion\\n(x86)\",\n", + " }\n", + " SEPS = [\n", + " (\"Function\", 3),\n", + " (\"Struct\", 2),\n", + " (\"Field\", 1),\n", + " ]\n", + "\n", + "ISSUE_SYMBOLS = {\n", + " IssueEnum.ABSENT: \"\",\n", + " IssueEnum.CHANGE: r\"$\\Delta$\",\n", + " IssueEnum.SELECTIVE_INLINE: \"S\",\n", + " IssueEnum.FULL_INLINE: \"F\",\n", + " IssueEnum.DUPLICATE: \"D\",\n", + " IssueEnum.COLLISION: \"C\",\n", + " IssueEnum.TRANSFORMATION: \"T\",\n", + "}\n", + "\n", + "LEGNED = [\n", + " (\"No Mismatch\", \"\", \"tab:green\"),\n", + " (\"Absence\", \"\", \"lightgray\"),\n", + " (\"Change\", r\"$\\Delta$\", \"tab:red\"),\n", + " (\"Full Inline\", r\"$\\text{F}$\", \"tab:red\"),\n", + " (\"Selective Inline\", r\"$\\text{S}$\", \"tab:red\"),\n", + " (\"Transformation\", r\"$\\text{T}$\", \"tab:red\"),\n", + " (\"Duplication\", r\"$\\text{D}$\", \"tab:red\"),\n", + " (\"Name Collision\", r\"$\\text{C}$\", \"tab:red\"),\n", + "]\n", + "\n", + "if not FULL:\n", + " LEGNED = LEGNED[0:-3]\n", + "\n", + "data: Dict[str, Dict[Dep, DepReport]] = load_pkl(\"bcc\")\n", + "\n", + "\n", + "def proc_issues_dict(dep: Dep, issues_dict: IssuesDict) -> IssuesDict:\n", + " result: IssuesDict = {}\n", + " for (group, version), issues in issues_dict.items():\n", + " # For structs, we only care about their existence\n", + " if dep.kind == DepKind.STRUCT:\n", + " if IssueEnum.ABSENT not in issues:\n", + " issues = []\n", + " # Simplify the issue set for blk_account_io_done in non-full mode\n", + " if not FULL:\n", + " if dep == DepKind.FUNC(\"blk_account_io_done\"):\n", + " issues = [i for i in issues if i != IssueEnum.CHANGE]\n", + " result[(group, version)] = issues\n", + " return result\n", + "\n", + "\n", + "reports = {\n", + " dep: proc_issues_dict(dep, data[prog_name][dep].issues_dict)\n", + " for prog_name, deps in KEYS.items()\n", + " for dep in deps\n", + "}\n", + "\n", + "\n", + "fig, ax = plt.subplots(figsize=(2.75, 10) if FULL else (3, 10))\n", + "ax: Axes\n", + "\n", + "\n", + "def get_color(issues: List[IssueEnum]):\n", + " if len(issues) == 0:\n", + " return \"tab:green\"\n", + " if IssueEnum.ABSENT in issues:\n", + " return \"lightgray\"\n", + " return \"tab:red\"\n", + "\n", + "\n", + "color = np.array(\n", + " [\n", + " [\n", + " colors.to_rgb(get_color(issues))\n", + " for (g, v), issues in report.items()\n", + " if g in GROUPS\n", + " ]\n", + " for report in reports.values()\n", + " ]\n", + ")\n", + "\n", + "if FULL:\n", + " color = color.swapaxes(0, 1)\n", + "ax.imshow(color, aspect=0.618 if FULL else 1)\n", + "\n", + "xlabels = []\n", + "for g in GROUPS:\n", + " for v in g.versions:\n", + " if g == VersionGroup.REGULAR:\n", + " xlabels.append(v.short_version)\n", + " elif g == VersionGroup.ARCH:\n", + " xlabels.append(ARCH_NAMES[v.arch])\n", + "\n", + "ylabels = [d.name for d in reports.keys()]\n", + "\n", + "if FULL:\n", + " xlabels, ylabels = ylabels, xlabels\n", + "\n", + "ax.set_xticks(\n", + " np.arange(len(xlabels)),\n", + " labels=xlabels,\n", + " rotation=90,\n", + " font=FONT_MONO if FULL else None,\n", + " fontsize=8 if FULL else 6,\n", + ")\n", + "ax.set_yticks(\n", + " np.arange(len(ylabels)),\n", + " labels=ylabels,\n", + " fontsize=6,\n", + ")\n", + "ax.set_xticks(np.arange(len(xlabels) + 1) - 0.5, minor=True)\n", + "ax.set_yticks(np.arange(len(ylabels) + 1) - 0.5, minor=True)\n", + "\n", + "\n", + "ax.grid(which=\"minor\", color=\"white\", linestyle=\"-\", linewidth=0.1)\n", + "ax.xaxis.set_ticks_position(\"top\")\n", + "ax.xaxis.set_label_position(\"top\")\n", + "ax.spines[\"top\"].set_visible(True)\n", + "ax.spines[\"bottom\"].set_visible(False)\n", + "ax.tick_params(which=\"minor\", length=0)\n", + "ax.tick_params(which=\"major\", length=0)\n", + "\n", + "\n", + "def plot_secondary_ticks(\n", + " ax: Axes,\n", + " axis_name,\n", + " lengths,\n", + " labels,\n", + " pad,\n", + " rotation=0,\n", + " linewidth=0.5,\n", + " linestyle=\"--\",\n", + " fontsize=8,\n", + "):\n", + " val = np.array(list(lengths))\n", + " cum = np.cumsum(val)\n", + " mid = cum - val / 2 - 0.5\n", + " div = np.array([*cum][:-1]) - 0.5\n", + "\n", + " if FULL:\n", + " axis_name = \"y\" if axis_name == \"x\" else \"x\"\n", + "\n", + " if axis_name == \"x\":\n", + " axis = ax.secondary_xaxis(\"top\").xaxis\n", + " else:\n", + " axis = ax.secondary_yaxis(\"left\").yaxis\n", + "\n", + " # plot labels\n", + " axis.set_ticks(\n", + " mid, labels, rotation=rotation, va=\"center\", ha=\"center\", fontsize=fontsize\n", + " )\n", + " axis.set_tick_params(length=0, pad=pad)\n", + "\n", + " # plot ticks\n", + " tick_length = pad + (5 if axis_name == \"x\" else 10)\n", + " axis.set_ticks(div, labels=[], minor=True)\n", + " axis.set_tick_params(length=tick_length, width=linewidth, which=\"minor\")\n", + "\n", + " axline = ax.axvline if axis_name == \"x\" else ax.axhline\n", + " for d in div:\n", + " axline(d, color=\"black\", lw=linewidth, linestyle=linestyle)\n", + "\n", + "\n", + "if FULL:\n", + " plot_secondary_ticks(\n", + " ax,\n", + " \"x\",\n", + " [len(g) for g in GROUPS],\n", + " GROUPS.values(),\n", + " linewidth=1,\n", + " linestyle=\"-\",\n", + " pad=35,\n", + " rotation=0,\n", + " )\n", + "\n", + "plot_secondary_ticks(\n", + " ax,\n", + " \"y\",\n", + " [s[1] for s in SEPS],\n", + " [s[0] for s in SEPS],\n", + " fontsize=6,\n", + " linestyle=\"--\" if FULL else \"-\",\n", + " pad=70 if FULL else 95,\n", + " rotation=0,\n", + ")\n", + "\n", + "if FULL:\n", + " plot_secondary_ticks(\n", + " ax,\n", + " \"y\",\n", + " [9, 4],\n", + " [\"biotop\", \"readahead\"],\n", + " linewidth=1,\n", + " linestyle=\"-\",\n", + " pad=80 if FULL else 115,\n", + " rotation=0 if FULL else 90,\n", + " )\n", + "\n", + "\n", + "for i, report in enumerate(reports.values()):\n", + " for j, issues in enumerate(report.values()):\n", + " text = \"\".join([ISSUE_SYMBOLS[e] for e in issues])\n", + " ax.text(\n", + " i if FULL else j,\n", + " j if FULL else i,\n", + " text,\n", + " ha=\"center\",\n", + " va=\"center\",\n", + " color=\"white\",\n", + " fontsize=6.5,\n", + " )\n", + "\n", + "\n", + "ax.legend(\n", + " handles=[\n", + " Line2D(\n", + " [],\n", + " [],\n", + " linewidth=8,\n", + " color=color,\n", + " marker=marker,\n", + " markerfacecolor=\"white\",\n", + " markeredgecolor=\"white\",\n", + " markeredgewidth=0.2,\n", + " markersize=5,\n", + " )\n", + " for label, marker, color in LEGNED\n", + " ],\n", + " labels=[label for label, _, _ in LEGNED],\n", + " loc=\"upper left\",\n", + " # (x: positive to the right, y: positive to the top)\n", + " bbox_to_anchor=(-0.45, 1.64) if FULL else (-1.3, 1.25),\n", + " ncol=1,\n", + " fontsize=6,\n", + " handlelength=0.8,\n", + " labelspacing=1,\n", + " handletextpad=1.25,\n", + ")\n", + "\n", + "\n", + "if FULL:\n", + " ax.set_xlabel(\"Dependency Set\", fontsize=10, labelpad=15)\n", + " ax.set_ylabel(\"Dependency Surface\", fontsize=10, labelpad=35)\n", + "else:\n", + " ax.set_xlabel(\"Kernel Dependency Surface\", fontsize=10, labelpad=10)\n", + " ax.set_ylabel(\"Program\\nDependency\\nSet\", fontsize=10, labelpad=45)\n", + "\n", + "save_fig(fig, \"report\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/52_summary.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/52_summary.ipynb new file mode 100644 index 00000000..0a839f8d --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/52_summary.ipynb @@ -0,0 +1,1795 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Program Summary\n", + "\n", + "This notebook generates the tables for the summary of eBPF programs.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ utils_pickle.py:18 ] INFO: Loding bcc from /Users/szhong/Code/DepSurf/output/bcc.pkl\n", + "[ utils_latex.py:118] INFO: Saved bcc to /Users/szhong/Code/DepSurf/paper/tabs/bcc.tex\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Program bashreadline has no dependencies\n", + "Program gethostlatency has no dependencies\n", + "Program funclatency has no dependencies\n", + "Program ksnoop has no dependencies\n", + "Program javagc has no dependencies\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\\multirow{2}{*}{Program}FunctionStructFieldTraceptSyscall
$\\Sigma$$\\varnothing$$\\Delta$FSTD$\\Sigma$$\\varnothing$$\\Sigma$$\\varnothing$$\\Delta$$\\Sigma$$\\varnothing$$\\Delta$$\\Sigma$$\\varnothing$
0Tracee67141651414298142505391334446202
1klockstat143\\color{lightgray}{-}\\color{lightgray}{-}4\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
2vfsstat8\\color{lightgray}{-}5\\color{lightgray}{-}61\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
3\\textbf{biotop}52232\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}72122\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
4cachestat522\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}221\\color{lightgray}{-}\\color{lightgray}{-}
5fsdist521\\color{lightgray}{-}22\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
6tcptracer5\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}6\\color{lightgray}{-}14\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
7\\textbf{readahead}43123112111\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
8fsslower41\\color{lightgray}{-}\\color{lightgray}{-}21\\color{lightgray}{-}5\\color{lightgray}{-}6\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
9filelife4\\color{lightgray}{-}3\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}5162\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
10biostacks31223\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}52\\color{lightgray}{-}22\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
11tcpconnlat3\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}41111\\color{lightgray}{-}111\\color{lightgray}{-}\\color{lightgray}{-}
12numamove22\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
13biosnoop21112\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}921413\\color{lightgray}{-}\\color{lightgray}{-}
14filetop2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}6\\color{lightgray}{-}10\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
15tcpsynbl2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}1\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
16tcpconnect2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}3\\color{lightgray}{-}8\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
17bindsnoop2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}5\\color{lightgray}{-}1441\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
18\\textcolor{blue}{tcptop}2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}9\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
19oomkill1\\color{lightgray}{-}1\\color{lightgray}{-}11\\color{lightgray}{-}3142\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
20capable1\\color{lightgray}{-}1\\color{lightgray}{-}11\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
21tcprtt1\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}6\\color{lightgray}{-}12\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
22mdflush1\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}3\\color{lightgray}{-}42\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
23solisten1\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}5\\color{lightgray}{-}8\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
24slabratetop1\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}2\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
25memleak\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1191714\\color{lightgray}{-}1047\\color{lightgray}{-}\\color{lightgray}{-}
26tcppktlat\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}7112\\color{lightgray}{-}\\color{lightgray}{-}333\\color{lightgray}{-}\\color{lightgray}{-}
27mountsnoop\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}716\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}
28runqlat\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}5\\color{lightgray}{-}11313\\color{lightgray}{-}3\\color{lightgray}{-}\\color{lightgray}{-}
29tcpstates\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}411371111\\color{lightgray}{-}\\color{lightgray}{-}
30\\textcolor{blue}{runqlen}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}4\\color{lightgray}{-}5\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
31biolatency\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}7213\\color{lightgray}{-}3\\color{lightgray}{-}\\color{lightgray}{-}
32bitesize\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}62\\color{lightgray}{-}1\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}
33sigsnoop\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}5\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}13\\color{lightgray}{-}
34\\textcolor{blue}{execsnoop}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}3\\color{lightgray}{-}4\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}
35biopattern\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2266\\color{lightgray}{-}1\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}
36tcplife\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2112101111\\color{lightgray}{-}\\color{lightgray}{-}
37\\textcolor{blue}{syscount}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}4\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
38statsnoop\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}54
39opensnoop\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}21
40\\textcolor{blue}{futexctn}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}
41profile\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}11111\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
42llcstat\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1111\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
43offcputime\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}62\\color{lightgray}{-}1\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}
44runqslower\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}52\\color{lightgray}{-}3\\color{lightgray}{-}3\\color{lightgray}{-}\\color{lightgray}{-}
45cpudist\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}52\\color{lightgray}{-}1\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}
46wakeuptime\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}4\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}
47\\textcolor{blue}{exitsnoop}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}4\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
48\\textcolor{blue}{hardirqs}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
49drsnoop\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}
50\\textcolor{blue}{softirqs}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}2\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
51\\textcolor{blue}{cpufreq}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}1\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}
52syncsnoop\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}\\color{lightgray}{-}61
\n", + "
" + ], + "text/plain": [ + " \\multirow{2}{*}{Program} Function Struct Field Tracept Syscall \n", + " $\\Sigma$ $\\varnothing$ $\\Delta$ F S T D $\\Sigma$ $\\varnothing$ $\\Sigma$ $\\varnothing$ $\\Delta$ $\\Sigma$ $\\varnothing$ $\\Delta$ $\\Sigma$ $\\varnothing$\n", + "0 Tracee 67 14 16 5 14 14 2 98 14 250 53 9 13 3 4 446 202\n", + "1 klockstat 14 3 \\color{lightgray}{-} \\color{lightgray}{-} 4 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "2 vfsstat 8 \\color{lightgray}{-} 5 \\color{lightgray}{-} 6 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "3 \\textbf{biotop} 5 2 2 3 2 \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 7 2 1 2 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "4 cachestat 5 2 2 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 2 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "5 fsdist 5 2 1 \\color{lightgray}{-} 2 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "6 tcptracer 5 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 6 \\color{lightgray}{-} 14 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "7 \\textbf{readahead} 4 3 1 2 3 1 1 2 1 1 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "8 fsslower 4 1 \\color{lightgray}{-} \\color{lightgray}{-} 2 1 \\color{lightgray}{-} 5 \\color{lightgray}{-} 6 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "9 filelife 4 \\color{lightgray}{-} 3 \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} 5 1 6 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "10 biostacks 3 1 2 2 3 \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 5 2 \\color{lightgray}{-} 2 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "11 tcpconnlat 3 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} 4 1 11 1 \\color{lightgray}{-} 1 1 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "12 numamove 2 2 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "13 biosnoop 2 1 1 1 2 \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 9 2 1 4 1 3 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "14 filetop 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} 6 \\color{lightgray}{-} 10 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "15 tcpsynbl 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} 1 \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "16 tcpconnect 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 3 \\color{lightgray}{-} 8 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "17 bindsnoop 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 5 \\color{lightgray}{-} 14 4 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "18 \\textcolor{blue}{tcptop} 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 9 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "19 oomkill 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} 1 1 \\color{lightgray}{-} 3 1 4 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "20 capable 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} 1 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "21 tcprtt 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 6 \\color{lightgray}{-} 12 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "22 mdflush 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 3 \\color{lightgray}{-} 4 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "23 solisten 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 5 \\color{lightgray}{-} 8 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "24 slabratetop 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 2 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "25 memleak \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 11 9 17 14 \\color{lightgray}{-} 10 4 7 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "26 tcppktlat \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 7 1 12 \\color{lightgray}{-} \\color{lightgray}{-} 3 3 3 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "27 mountsnoop \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 7 1 6 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-}\n", + "28 runqlat \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 5 \\color{lightgray}{-} 11 3 1 3 \\color{lightgray}{-} 3 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "29 tcpstates \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 4 1 13 7 1 1 1 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "30 \\textcolor{blue}{runqlen} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 4 \\color{lightgray}{-} 5 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "31 biolatency \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 7 2 1 3 \\color{lightgray}{-} 3 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "32 bitesize \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 6 2 \\color{lightgray}{-} 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "33 sigsnoop \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 5 \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 1 3 \\color{lightgray}{-}\n", + "34 \\textcolor{blue}{execsnoop} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 3 \\color{lightgray}{-} 4 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-}\n", + "35 biopattern \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 2 6 6 \\color{lightgray}{-} 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "36 tcplife \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 1 12 10 1 1 1 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "37 \\textcolor{blue}{syscount} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} 4 \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "38 statsnoop \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 5 4\n", + "39 opensnoop \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 1\n", + "40 \\textcolor{blue}{futexctn} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-}\n", + "41 profile \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 1 1 1 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "42 llcstat \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 1 1 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "43 offcputime \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 6 2 \\color{lightgray}{-} 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "44 runqslower \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 5 2 \\color{lightgray}{-} 3 \\color{lightgray}{-} 3 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "45 cpudist \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 5 2 \\color{lightgray}{-} 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "46 wakeuptime \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 4 \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "47 \\textcolor{blue}{exitsnoop} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 4 \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "48 \\textcolor{blue}{hardirqs} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "49 drsnoop \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-}\n", + "50 \\textcolor{blue}{softirqs} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 2 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "51 \\textcolor{blue}{cpufreq} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 1 \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-}\n", + "52 syncsnoop \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} \\color{lightgray}{-} 6 1" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from typing import Dict, Tuple, List\n", + "\n", + "import pandas as pd\n", + "\n", + "from depsurf import DepKind, IssueEnum, Dep, DepReport\n", + "from utils import GRAY_DASH, load_pkl, save_latex, text_color, bold\n", + "\n", + "COUNT = \"Count\"\n", + "\n", + "KEYS = {\n", + " COUNT: r\"$\\Sigma$\",\n", + " IssueEnum.ABSENT: r\"$\\varnothing$\",\n", + " IssueEnum.CHANGE: r\"$\\Delta$\",\n", + " IssueEnum.SELECTIVE_INLINE: \"S\",\n", + " IssueEnum.FULL_INLINE: \"F\",\n", + " IssueEnum.TRANSFORMATION: \"T\",\n", + " IssueEnum.DUPLICATE: \"D\",\n", + "}\n", + "\n", + "KINDS = {\n", + " DepKind.FUNC: \"Function\",\n", + " DepKind.STRUCT: \"Struct\",\n", + " DepKind.FIELD: \"Field\",\n", + " DepKind.TRACEPOINT: \"Tracept\",\n", + " DepKind.SYSCALL: \"Syscall\",\n", + "}\n", + "\n", + "COLUMNS = [\n", + " (DepKind.FUNC, COUNT),\n", + " (DepKind.FUNC, IssueEnum.ABSENT),\n", + " (DepKind.FUNC, IssueEnum.CHANGE),\n", + " (DepKind.FUNC, IssueEnum.FULL_INLINE),\n", + " (DepKind.FUNC, IssueEnum.SELECTIVE_INLINE),\n", + " (DepKind.FUNC, IssueEnum.TRANSFORMATION),\n", + " (DepKind.FUNC, IssueEnum.DUPLICATE),\n", + " (DepKind.STRUCT, COUNT),\n", + " (DepKind.STRUCT, IssueEnum.ABSENT),\n", + " (DepKind.FIELD, COUNT),\n", + " (DepKind.FIELD, IssueEnum.ABSENT),\n", + " (DepKind.FIELD, IssueEnum.CHANGE),\n", + " (DepKind.TRACEPOINT, COUNT),\n", + " (DepKind.TRACEPOINT, IssueEnum.ABSENT),\n", + " (DepKind.TRACEPOINT, IssueEnum.CHANGE),\n", + " (DepKind.SYSCALL, COUNT),\n", + " (DepKind.SYSCALL, IssueEnum.ABSENT),\n", + "]\n", + "\n", + "PROG_NAMES = {\n", + " \"tracee\": \"Tracee\",\n", + "}\n", + "\n", + "NUM_DEPS = r\"\\textbf{# uniq dep}\"\n", + "\n", + "data: Dict[str, Dict[Dep, DepReport]] = load_pkl(\"bcc\")\n", + "data[NUM_DEPS] = {\n", + " dep: report for prog_name, deps in data.items() for dep, report in deps.items()\n", + "}\n", + "\n", + "table: Dict[str, Dict[Tuple[DepKind, str], int]] = {}\n", + "\n", + "for prog_name, deps in data.items():\n", + " if len(deps) == 0:\n", + " print(f\"Program {prog_name} has no dependencies\")\n", + " continue\n", + "\n", + " if prog_name in PROG_NAMES:\n", + " prog_name = PROG_NAMES[prog_name]\n", + "\n", + " row = {col: 0 for col in COLUMNS}\n", + " for dep, report in deps.items():\n", + " kind = dep.kind\n", + " if kind not in KINDS:\n", + " continue\n", + " row[(kind, COUNT)] += 1\n", + "\n", + " num_absent = sum(\n", + " 1 for issues in report.issues_dict.values() if IssueEnum.ABSENT in issues\n", + " )\n", + " row[(kind, IssueEnum.ABSENT)] += min(num_absent, 1)\n", + "\n", + " if kind not in [DepKind.STRUCT, DepKind.SYSCALL]:\n", + " num_delta = sum(\n", + " 1\n", + " for issues in report.issues_dict.values()\n", + " if IssueEnum.CHANGE in issues\n", + " )\n", + " row[(kind, IssueEnum.CHANGE)] += min(num_delta, 1)\n", + "\n", + " if kind == DepKind.FUNC:\n", + " for issue in [\n", + " IssueEnum.SELECTIVE_INLINE,\n", + " IssueEnum.FULL_INLINE,\n", + " IssueEnum.TRANSFORMATION,\n", + " IssueEnum.DUPLICATE,\n", + " ]:\n", + " num_issue = sum(\n", + " 1 for issues in report.issues_dict.values() if issue in issues\n", + " )\n", + " row[(kind, issue)] += min(num_issue, 1)\n", + "\n", + " has_issue = False\n", + " for (kind, key), count in row.items():\n", + " if key == COUNT:\n", + " continue\n", + " if count != 0:\n", + " has_issue = True\n", + " continue\n", + "\n", + " if not has_issue:\n", + " prog_name = text_color(prog_name, \"blue\")\n", + " elif prog_name in (\"biotop\", \"readahead\"):\n", + " prog_name = bold(prog_name)\n", + "\n", + " table[prog_name] = row\n", + "\n", + "num_deps = table.pop(NUM_DEPS)\n", + "num_progs = {col: 0 for col in COLUMNS}\n", + "for prog_name, row in table.items():\n", + " for (kind, key), count in row.items():\n", + " if count != 0:\n", + " num_progs[(kind, key)] += 1\n", + "\n", + "\n", + "df = pd.DataFrame(\n", + " {\n", + " tool: {(KINDS[kind], KEYS[key]): count for (kind, key), count in row.items()}\n", + " for tool, row in table.items()\n", + " }\n", + ").T\n", + "\n", + "df = df.sort_values(by=df.columns.tolist(), ascending=False)\n", + "df = df.map(lambda x: GRAY_DASH if pd.isna(x) or x == 0 else int(x))\n", + "df.index.name = r\"\\multirow{2}{*}{Program}\"\n", + "df = df.reset_index()\n", + "\n", + "from pathlib import Path\n", + "\n", + "kind_abbr = {\n", + " \"Function\": \"func\",\n", + " \"Struct\": \"struct\",\n", + " \"Field\": \"field\",\n", + " \"Tracept\": \"tp\",\n", + " \"Syscall\": \"sys\",\n", + "}\n", + "key_abbr = {\n", + " r\"$\\\\Sigma$\": \"sigma\",\n", + " r\"$\\\\varnothing$\": \"empty\",\n", + " r\"$\\\\Delta$\": \"delta\",\n", + " \"F\": \"f\",\n", + " \"S\": \"s\",\n", + " \"T\": \"t\",\n", + " \"D\": \"d\",\n", + "}\n", + "\n", + "df_table7 = df.copy()\n", + "prog_col = df_table7.columns[0]\n", + "flat_cols = []\n", + "for col in df_table7.columns:\n", + " if col == prog_col:\n", + " flat_cols.append(\"program\")\n", + " continue\n", + " if isinstance(col, tuple) and len(col) == 2:\n", + " kind, key = col\n", + " else:\n", + " kind, key = \"\", str(col)\n", + " flat_kind = kind_abbr.get(str(kind), str(kind).strip().lower())\n", + " flat_key = key_abbr.get(str(key), str(key).strip().lower())\n", + " flat_cols.append(f\"{flat_kind}_{flat_key}\" if flat_kind else flat_key)\n", + "\n", + "df_table7.columns = flat_cols\n", + "df_table7 = df_table7.replace({GRAY_DASH: pd.NA})\n", + "out_dir = Path(\"results\")\n", + "out_dir.mkdir(parents=True, exist_ok=True)\n", + "df_table7.to_csv(out_dir / \"52_table7.csv\", index=False, na_rep=\"\")\n", + "\n", + "\n", + "latex = df.to_latex(\n", + " multicolumn_format=\"c|\",\n", + " column_format=r\"l|rrrrrrr|rr|rrr|rrr|rr\",\n", + " index=False,\n", + ")\n", + "\n", + "save_latex(latex, \"bcc\", midrule=False)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[ utils_latex.py:118] INFO: Saved summary to /Users/szhong/Code/DepSurf/paper/tabs/summary.tex\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
# Programs# Uniq DepsReported Issue No.
Func$\\Sigma$\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{25}}\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{126}}\\color{lightgray}{-}
$\\varnothing$\\colorbox{bg}{\\makebox[{0.90cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.60cm}][r]{10}}\\colorbox{bg}{\\makebox[{1.15cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.35cm}][r]{29}}\\bccissue{3687}, \\bccissue{3695}, \\bccissue{3692}, \\bccissue{3747}, \\bccissue{4337}, \\bccissue{4885}
$\\Delta$\\colorbox{bg}{\\makebox[{0.66cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.84cm}][r]{14}}\\colorbox{bg}{\\makebox[{1.13cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.37cm}][r]{31}}\\bccissue{1911}, \\bccissue{3360}, \\bccissue{4339}, \\bccissue{4340}, \\bccissue{4346}
F\\colorbox{bg}{\\makebox[{1.14cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.36cm}][r]{6}}\\colorbox{bg}{\\makebox[{1.37cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.13cm}][r]{11}}\\bccissue{4261}, \\bccissue{4478}, \\bccissue{4638}, \\bccissue{4700}, \\bccissue{5115}
S\\colorbox{bg}{\\makebox[{0.66cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.84cm}][r]{14}}\\colorbox{bg}{\\makebox[{1.12cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.38cm}][r]{32}}\\bccissue{703}, \\bccissue{1667}, \\bccissue{2252}, \\bccissue{2373}, \\bccissue{3913}
T\\colorbox{bg}{\\makebox[{0.66cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.84cm}][r]{14}}\\colorbox{bg}{\\makebox[{1.17cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.33cm}][r]{28}}\\bccissue{1754}, \\bccissue{3293}, \\bccissue{3339}, \\bccissue{3315}, \\bccissue{4937}
D\\colorbox{bg}{\\makebox[{1.38cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.12cm}][r]{2}}\\colorbox{bg}{\\makebox[{1.46cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.04cm}][r]{3}}\\color{lightgray}{-}
Struct$\\Sigma$\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{43}}\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{135}}\\color{lightgray}{-}
$\\varnothing$\\colorbox{bg}{\\makebox[{1.05cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.45cm}][r]{13}}\\colorbox{bg}{\\makebox[{1.16cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.34cm}][r]{31}}\\bccissue{4340}, \\bccissue{4339}
Field$\\Sigma$\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{43}}\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{342}}\\color{lightgray}{-}
\\multirow[c]{2}{*}{$\\varnothing$}\\multirow[c]{2}{*}{\\colorbox{bg}{\\makebox[{0.73cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.77cm}][r]{22}}}\\multirow[c]{2}{*}{\\colorbox{bg}{\\makebox[{1.05cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.45cm}][r]{102}}}\\bccissue{1384}, \\bccissue{3612}, \\bccissue{3647}, \\bccissue{3650}, \\bccissue{3658}, \\bccissue{3672}
\\bccissue{3680}, \\bccissue{3859}, \\bccissue{3903}, \\bccissue{3926}, \\bccissue{3936}
$\\Delta$\\colorbox{bg}{\\makebox[{1.15cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.35cm}][r]{10}}\\colorbox{bg}{\\makebox[{1.44cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.06cm}][r]{13}}\\bccissue{3845}, \\bccissue{3865}
Tracept$\\Sigma$\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{25}}\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{44}}\\color{lightgray}{-}
$\\varnothing$\\colorbox{bg}{\\makebox[{0.90cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.60cm}][r]{10}}\\colorbox{bg}{\\makebox[{0.99cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.51cm}][r]{15}}\\bccissue{1636}, \\bccissue{2816}, \\bccissue{4384}
$\\Delta$\\colorbox{bg}{\\makebox[{0.42cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.08cm}][r]{18}}\\colorbox{bg}{\\makebox[{0.72cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.78cm}][r]{23}}\\bccissue{3317}, \\bccissue{3338}, \\bccissue{4076}, \\bccissue{4476}
Syscall$\\Sigma$\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{8}}\\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{448}}\\color{lightgray}{-}
$\\varnothing$\\colorbox{bg}{\\makebox[{0.75cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.75cm}][r]{4}}\\colorbox{bg}{\\makebox[{0.82cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.68cm}][r]{204}}\\bccissue{3012}, \\bccissue{3668}, \\bccissue{3843}, \\bccissue{4287}
\n", + "
" + ], + "text/plain": [ + " # Programs # Uniq Deps Reported Issue No.\n", + "Func $\\Sigma$ \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{25}} \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{126}} \\color{lightgray}{-}\n", + " $\\varnothing$ \\colorbox{bg}{\\makebox[{0.90cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.60cm}][r]{10}} \\colorbox{bg}{\\makebox[{1.15cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.35cm}][r]{29}} \\bccissue{3687}, \\bccissue{3695}, \\bccissue{3692}, \\bccissue{3747}, \\bccissue{4337}, \\bccissue{4885}\n", + " $\\Delta$ \\colorbox{bg}{\\makebox[{0.66cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.84cm}][r]{14}} \\colorbox{bg}{\\makebox[{1.13cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.37cm}][r]{31}} \\bccissue{1911}, \\bccissue{3360}, \\bccissue{4339}, \\bccissue{4340}, \\bccissue{4346}\n", + " F \\colorbox{bg}{\\makebox[{1.14cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.36cm}][r]{6}} \\colorbox{bg}{\\makebox[{1.37cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.13cm}][r]{11}} \\bccissue{4261}, \\bccissue{4478}, \\bccissue{4638}, \\bccissue{4700}, \\bccissue{5115}\n", + " S \\colorbox{bg}{\\makebox[{0.66cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.84cm}][r]{14}} \\colorbox{bg}{\\makebox[{1.12cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.38cm}][r]{32}} \\bccissue{703}, \\bccissue{1667}, \\bccissue{2252}, \\bccissue{2373}, \\bccissue{3913}\n", + " T \\colorbox{bg}{\\makebox[{0.66cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.84cm}][r]{14}} \\colorbox{bg}{\\makebox[{1.17cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.33cm}][r]{28}} \\bccissue{1754}, \\bccissue{3293}, \\bccissue{3339}, \\bccissue{3315}, \\bccissue{4937}\n", + " D \\colorbox{bg}{\\makebox[{1.38cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.12cm}][r]{2}} \\colorbox{bg}{\\makebox[{1.46cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.04cm}][r]{3}} \\color{lightgray}{-}\n", + "Struct $\\Sigma$ \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{43}} \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{135}} \\color{lightgray}{-}\n", + " $\\varnothing$ \\colorbox{bg}{\\makebox[{1.05cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.45cm}][r]{13}} \\colorbox{bg}{\\makebox[{1.16cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.34cm}][r]{31}} \\bccissue{4340}, \\bccissue{4339}\n", + "Field $\\Sigma$ \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{43}} \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{342}} \\color{lightgray}{-}\n", + " \\multirow[c]{2}{*}{$\\varnothing$} \\multirow[c]{2}{*}{\\colorbox{bg}{\\makebox[{0.73cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.77cm}][r]{22}}} \\multirow[c]{2}{*}{\\colorbox{bg}{\\makebox[{1.05cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.45cm}][r]{102}}} \\bccissue{1384}, \\bccissue{3612}, \\bccissue{3647}, \\bccissue{3650}, \\bccissue{3658}, \\bccissue{3672}\n", + " \\bccissue{3680}, \\bccissue{3859}, \\bccissue{3903}, \\bccissue{3926}, \\bccissue{3936}\n", + " $\\Delta$ \\colorbox{bg}{\\makebox[{1.15cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.35cm}][r]{10}} \\colorbox{bg}{\\makebox[{1.44cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.06cm}][r]{13}} \\bccissue{3845}, \\bccissue{3865}\n", + "Tracept $\\Sigma$ \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{25}} \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{44}} \\color{lightgray}{-}\n", + " $\\varnothing$ \\colorbox{bg}{\\makebox[{0.90cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.60cm}][r]{10}} \\colorbox{bg}{\\makebox[{0.99cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.51cm}][r]{15}} \\bccissue{1636}, \\bccissue{2816}, \\bccissue{4384}\n", + " $\\Delta$ \\colorbox{bg}{\\makebox[{0.42cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.08cm}][r]{18}} \\colorbox{bg}{\\makebox[{0.72cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.78cm}][r]{23}} \\bccissue{3317}, \\bccissue{3338}, \\bccissue{4076}, \\bccissue{4476}\n", + "Syscall $\\Sigma$ \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{1.50cm}][r]{8}} \\colorbox{bg}{\\makebox[{0.00cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{1.50cm}][r]{448}} \\color{lightgray}{-}\n", + " $\\varnothing$ \\colorbox{bg}{\\makebox[{0.75cm}][r]{\\phantom{0}}}\\colorbox{prog}{\\makebox[{0.75cm}][r]{4}} \\colorbox{bg}{\\makebox[{0.82cm}][r]{\\phantom{0}}}\\colorbox{dep}{\\makebox[{0.68cm}][r]{204}} \\bccissue{3012}, \\bccissue{3668}, \\bccissue{3843}, \\bccissue{4287}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from utils import mini_bar, multirow\n", + "\n", + "KINDS = {\n", + " **KINDS,\n", + " DepKind.FUNC: \"Func\",\n", + "}\n", + "\n", + "MULTIROW = (DepKind.FIELD, IssueEnum.ABSENT)\n", + "\n", + "ISSUES = {\n", + " (DepKind.FUNC, IssueEnum.ABSENT): [3687, 3695, 3692, 3747, 4337, 4885],\n", + " (DepKind.FUNC, IssueEnum.CHANGE): [1911, 3360, 4339, 4340, 4346],\n", + " (DepKind.FUNC, IssueEnum.SELECTIVE_INLINE): [703, 1667, 2252, 2373, 3913],\n", + " (DepKind.FUNC, IssueEnum.FULL_INLINE): [4261, 4478, 4638, 4700, 5115],\n", + " (DepKind.FUNC, IssueEnum.TRANSFORMATION): [1754, 3293, 3339, 3315, 4937],\n", + " (DepKind.STRUCT, IssueEnum.ABSENT): [4340, 4339],\n", + " (DepKind.FIELD, IssueEnum.ABSENT): [\n", + " 1384,\n", + " 3612,\n", + " 3647,\n", + " 3650,\n", + " 3658,\n", + " 3672,\n", + " 3680,\n", + " 3859,\n", + " 3903,\n", + " 3926,\n", + " 3936,\n", + " ],\n", + " (DepKind.FIELD, IssueEnum.CHANGE): [3845, 3865],\n", + " (DepKind.TRACEPOINT, IssueEnum.ABSENT): [1636, 2816, 4384],\n", + " (DepKind.TRACEPOINT, IssueEnum.CHANGE): [3317, 3338, 4076, 4476],\n", + " (DepKind.SYSCALL, IssueEnum.ABSENT): [3012, 3668, 3843, 4287],\n", + "}\n", + "\n", + "\n", + "PROG = \"# Programs\"\n", + "UNIQ_DEP = \"# Uniq Deps\"\n", + "BUG = \"Reported Issue No.\"\n", + "\n", + "COLORS = {\n", + " PROG: \"prog\",\n", + " UNIQ_DEP: \"dep\",\n", + "}\n", + "\n", + "\n", + "from pathlib import Path\n", + "\n", + "kind_abbr = {\n", + " DepKind.FUNC: \"func\",\n", + " DepKind.STRUCT: \"struct\",\n", + " DepKind.FIELD: \"field\",\n", + " DepKind.TRACEPOINT: \"tp\",\n", + " DepKind.SYSCALL: \"sys\",\n", + "}\n", + "key_abbr = {\n", + " COUNT: \"sigma\",\n", + " IssueEnum.ABSENT: \"empty\",\n", + " IssueEnum.CHANGE: \"delta\",\n", + " IssueEnum.FULL_INLINE: \"f\",\n", + " IssueEnum.SELECTIVE_INLINE: \"s\",\n", + " IssueEnum.TRANSFORMATION: \"t\",\n", + " IssueEnum.DUPLICATE: \"d\",\n", + "}\n", + "\n", + "rows = []\n", + "for kind, key in COLUMNS:\n", + " metric = f\"{kind_abbr.get(kind, str(kind))}_{key_abbr.get(key, str(key))}\"\n", + " programs = num_progs.get((kind, key), 0)\n", + " uniq_deps = num_deps.get((kind, key), 0)\n", + " rows.append(\n", + " {\n", + " \"metric\": metric,\n", + " \"programs\": programs if programs != 0 else pd.NA,\n", + " \"uniq_deps\": uniq_deps if uniq_deps != 0 else pd.NA,\n", + " }\n", + " )\n", + "\n", + "df_table8 = pd.DataFrame(rows).set_index(\"metric\")\n", + "out_dir = Path(\"results\")\n", + "out_dir.mkdir(parents=True, exist_ok=True)\n", + "df_table8.to_csv(out_dir / \"52_table8.csv\", na_rep=\"\")\n", + "\n", + "table = {}\n", + "for name, data in [(PROG, num_progs), (UNIQ_DEP, num_deps)]:\n", + " row = {}\n", + " for (kind, key), count in data.items():\n", + " text = mini_bar(\n", + " text=count,\n", + " percent=count / data[(kind, COUNT)],\n", + " total_width=1.5,\n", + " color=COLORS[name],\n", + " bg_color=\"bg\",\n", + " )\n", + " if (kind, key) == MULTIROW:\n", + " row[(KINDS[kind], multirow(KEYS[key]))] = multirow(text)\n", + " row[(KINDS[kind], \"\")] = \"\"\n", + " else:\n", + " row[(KINDS[kind], KEYS[key])] = text\n", + " table[name] = row\n", + "\n", + "\n", + "def bccissues(issues: List[int]) -> str:\n", + " return \", \".join(f\"\\\\bccissue{{{issue}}}\" for issue in issues)\n", + "\n", + "\n", + "row = {}\n", + "for (kind, key), issues in ISSUES.items():\n", + " if (kind, key) == MULTIROW:\n", + " n = (len(issues) + 1) // 2\n", + " row[(KINDS[kind], multirow(KEYS[key]))] = bccissues(issues[:n])\n", + " row[(KINDS[kind], \"\")] = bccissues(issues[n:])\n", + " else:\n", + " row[(KINDS[kind], KEYS[key])] = bccissues(issues)\n", + "table[BUG] = row\n", + "\n", + "\n", + "df = pd.DataFrame(table)\n", + "df = df.fillna(GRAY_DASH)\n", + "latex = df.to_latex(column_format=\"llrrr\")\n", + "save_latex(latex, \"summary\", rotate=False)\n", + "df" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/60_website.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/60_website.ipynb new file mode 100644 index 00000000..f0d68151 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/60_website.ipynb @@ -0,0 +1,300 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generate Website\n", + "\n", + "This notebook generates the website for the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from depsurf import DepKind, VersionGroup, DepReport, LinuxImage, DATA_PATH, Dep\n", + "from typing import Iterator, List\n", + "from pathlib import Path\n", + "\n", + "\n", + "WEBSITE_URL = \"https://depsurf.github.io\"\n", + "GROUPS = [VersionGroup.REGULAR, VersionGroup.ARCH, VersionGroup.FLAVOR]\n", + "\n", + "\n", + "def get_report_kind_path(kind: DepKind):\n", + " return DATA_PATH / f\"website-{kind.value.lower()}\"\n", + "\n", + "\n", + "def get_report_json_path(dep: Dep):\n", + " return (\n", + " get_report_kind_path(dep.kind)\n", + " / dep.name.replace(\"_\", \"\").lower()[0]\n", + " / f\"{dep.name}.json\"\n", + " )\n", + "\n", + "\n", + "def get_report_url(dep: Dep):\n", + " return f\"{WEBSITE_URL}/{get_report_json_path(dep).relative_to(DATA_PATH).with_suffix('.html')}\"\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate JSON Reports" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def test_report(dep: Dep):\n", + " json_path = get_report_json_path(dep)\n", + " if json_path.exists():\n", + " return DepReport.from_dump(json_path)\n", + " else:\n", + " return DepReport.from_groups(dep, GROUPS)\n", + "\n", + "\n", + "dep = DepKind.FUNC(\"__blk_account_io_done\")\n", + "dep = DepKind.FUNC(\"__page_cache_release\")\n", + "dep = DepKind.STRUCT(\"task_struct\")\n", + "dep = DepKind.STRUCT(\"fs_context\")\n", + "dep = DepKind.STRUCT(\"inode\")\n", + "dep = DepKind.FUNC(\"vfs_rename\")\n", + "dep = DepKind.FUNC(\"init_once\")\n", + "dep = DepKind.FUNC(\"vfs_read\")\n", + "dep = DepKind.STRUCT(\"xfrm_policy_afinfo\")\n", + "dep = DepKind.STRUCT(\"xfrm_sec_ctx\")\n", + "dep = DepKind.STRUCT(\"address_space_operations\")\n", + "dep = DepKind.FUNC(\"blk_account_io_start\")\n", + "\n", + "# test_report(dep)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def get_deps_names(img: LinuxImage, kind: DepKind) -> Iterator[str]:\n", + " if kind == DepKind.FUNC:\n", + " return (func.name for func in img.func_groups.iter_funcs())\n", + " elif kind == DepKind.STRUCT:\n", + " return iter(img.struct_types.data)\n", + " elif kind == DepKind.LSM:\n", + " return iter(img.lsm_hooks)\n", + " elif kind == DepKind.TRACEPOINT:\n", + " return iter(img.tracepoints.data)\n", + " elif kind == DepKind.KFUNC:\n", + " return iter(img.kfuncs)\n", + " else:\n", + " raise ValueError(f\"Unknown kind: {kind}\")\n", + "\n", + "\n", + "def dump_reports(kinds: List[DepKind]):\n", + " for dep in sorted(\n", + " set(\n", + " kind(name)\n", + " for group in GROUPS\n", + " for v in group\n", + " for kind in kinds\n", + " for name in get_deps_names(v.img, kind)\n", + " )\n", + " ):\n", + " report = DepReport.from_groups(dep, GROUPS)\n", + " report.dump_json(get_report_json_path(dep))\n", + "\n", + "\n", + "dump_reports(\n", + " [\n", + " # DepKind.FUNC,\n", + " # DepKind.STRUCT,\n", + " # DepKind.LSM,\n", + " # DepKind.TRACEPOINT,\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate Markdown Reports" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def dump_markdowns(kinds: List[DepKind]):\n", + " for kind in kinds:\n", + " paths = get_report_kind_path(kind).rglob(\"*.json\")\n", + " for json_path in paths:\n", + " report = DepReport.from_dump(json_path)\n", + " report.dump_md(json_path.with_suffix(\".md\"))\n", + "\n", + "\n", + "dump_markdowns(\n", + " [\n", + " # DepKind.FUNC,\n", + " # DepKind.STRUCT,\n", + " # DepKind.LSM,\n", + " # DepKind.TRACEPOINT,\n", + " ]\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generate Index Pages" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Iterable\n", + "\n", + "from depsurf import DepKind, IssueEnum\n", + "from typing import TextIO\n", + "\n", + "\n", + "ISSUE_SYMBOLS = {\n", + " IssueEnum.ABSENT: \"∅\",\n", + " IssueEnum.CHANGE: \"Δ\",\n", + " IssueEnum.SELECTIVE_INLINE: \"S\",\n", + " IssueEnum.FULL_INLINE: \"F\",\n", + " IssueEnum.DUPLICATE: \"D\",\n", + " IssueEnum.COLLISION: \"C\",\n", + " IssueEnum.TRANSFORMATION: \"T\",\n", + "}\n", + "\n", + "ISSUE_NAMES = {\n", + " IssueEnum.ABSENT: \"Absence\",\n", + " IssueEnum.CHANGE: \"Change\",\n", + " IssueEnum.SELECTIVE_INLINE: \"Selective Inline\",\n", + " IssueEnum.FULL_INLINE: \"Full Inline\",\n", + " IssueEnum.DUPLICATE: \"Duplication\",\n", + " IssueEnum.COLLISION: \"Collision\",\n", + " IssueEnum.TRANSFORMATION: \"Transformation\",\n", + "}\n", + "\n", + "\n", + "def print_row(report_path: Path, group_only: bool, file: TextIO):\n", + " report = DepReport.from_dump(report_path)\n", + " dep = report.dep\n", + " name = f\"[`{dep.name}`]({get_report_url(dep)})\"\n", + " if group_only:\n", + " grouped_issues = {group: set() for group in GROUPS}\n", + " for (group, _), issues in report.issues_dict.items():\n", + " grouped_issues[group].update(issues)\n", + " rows = [\n", + " \", \".join([ISSUE_NAMES[e] for e in grouped_issues[group]])\n", + " for group in GROUPS\n", + " ]\n", + " else:\n", + " rows = [\n", + " \",\".join([ISSUE_SYMBOLS[e] for e in issues])\n", + " for issues in report.issues_dict.values()\n", + " ]\n", + " print(\"|\".join([\"\", name, *rows, \"\"]), file=file)\n", + "\n", + "\n", + "def print_header(group_only: bool, file: TextIO):\n", + " if group_only:\n", + " col_names = [g for g in GROUPS]\n", + " else:\n", + " col_names = [g.to_str(v) for g in GROUPS for v in g]\n", + " print(\"| Name | \" + \" | \".join(col_names) + \" |\", file=file)\n", + " print(\"| \" + \" | \".join([\"-\"] * (len(col_names) + 1)) + \" |\", file=file)\n", + "\n", + "\n", + "def print_index(\n", + " report_paths: Iterable[Path], file_path: Path, group_only: bool = False\n", + "):\n", + " with open(file_path, \"w\") as f:\n", + " kind = file_path.parent.name\n", + " print(f\"# {kind}\", file=f)\n", + " print_header(group_only, file=f)\n", + " for report_path in sorted(\n", + " report_paths, key=lambda d: d.stem.replace(\"_\", \"\").lower()\n", + " ):\n", + " print_row(report_path, group_only=group_only, file=f)\n", + " print(f\"Saved {file_path}\", flush=True)\n", + "\n", + "\n", + "def dump_index(kinds: List[DepKind]):\n", + " for kind in kinds:\n", + " website_path = DATA_PATH / \"website\"\n", + " kind_path = get_report_kind_path(kind)\n", + " subdirs = sorted(d for d in kind_path.iterdir() if d.is_dir())\n", + " if kind in [DepKind.FUNC, DepKind.STRUCT]:\n", + " for subdir in subdirs:\n", + " print_index(\n", + " report_paths=subdir.glob(\"*.json\"),\n", + " file_path=website_path / f\"{kind.value.lower()}-{subdir.stem}.md\",\n", + " group_only=(kind == DepKind.FUNC),\n", + " )\n", + " else:\n", + " print_index(\n", + " report_paths=[p for d in subdirs for p in d.glob(\"*.json\")],\n", + " file_path=website_path / f\"{kind.value.lower()}.md\",\n", + " )\n", + "\n", + "\n", + "dump_index(\n", + " [\n", + " # DepKind.FUNC,\n", + " # DepKind.STRUCT,\n", + " # DepKind.LSM,\n", + " # DepKind.TRACEPOINT,\n", + " ]\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/LICENSE b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/LICENSE new file mode 100644 index 00000000..7997343a --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Shawn Zhong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/README.md b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/README.md new file mode 100644 index 00000000..265e10f3 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/README.md @@ -0,0 +1,129 @@ +DepSurf +=== + + +DepSurf Logo + + +Website for [EuroSys'25](https://dl.acm.org/doi/proceedings/10.1145/3689031) paper "**Revealing the Unstable Foundations of eBPF-Based Kernel Extensions**" + +*Shawn (Wanxiang) Zhong, Jing Liu, Andrea Arpaci-Dusseau, and Remzi Arpaci-Dusseau* + +[Paper](https://depsurf.github.io/assets/paper.pdf) | +[Code](https://github.com/ShawnZhong/DepSurf) | +[Dataset](https://github.com/ShawnZhong/DepSurf-dataset) | +[Website](https://depsurf.github.io/) | +[Slides](https://depsurf.github.io/assets/slides.pdf) | +[Poster](https://depsurf.github.io/assets/poster.pdf) + +
+ +Abstract + +eBPF programs significantly enhance kernel capabilities, but encounter substantial compatibility challenges due to their deep integration with unstable kernel internals. We introduce DepSurf, a tool that identifies dependency mismatches between eBPF programs and kernel images. Our analysis of 25 kernel images spanning 8 years reveals that dependency mismatches are pervasive, stemming from kernel source code evolution, diverse configuration options, and intricate compilation processes. We apply DepSurf to 53 real-world eBPF programs, and find that 83% are impacted by dependency mismatches, underscoring the urgent need for systematic dependency analysis. By identifying these mismatches, DepSurf enables a more robust development and maintenance process for eBPF programs, enhancing their reliability across a wide range of kernels. +
+
+ +Citation + + +``` +@inproceedings{10.1145/3689031.3717497, + author = {Zhong, Shawn Wanxiang and Liu, Jing and Arpaci-Dusseau, Andrea and Arpaci-Dusseau, Remzi}, + title = {Revealing the Unstable Foundations of eBPF-Based Kernel Extensions}, + year = {2025}, + isbn = {9798400711961}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/3689031.3717497}, + doi = {10.1145/3689031.3717497}, + abstract = {eBPF programs significantly enhance kernel capabilities, but encounter substantial compatibility challenges due to their deep integration with unstable kernel internals. We introduce DepSurf, a tool that identifies dependency mismatches between eBPF programs and kernel images. Our analysis of 25 kernel images spanning 8 years reveals that dependency mismatches are pervasive, stemming from kernel source code evolution, diverse configuration options, and intricate compilation processes. We apply DepSurf to 53 real-world eBPF programs, and find that 83\% are impacted by dependency mismatches, underscoring the urgent need for systematic dependency analysis. By identifying these mismatches, DepSurf enables a more robust development and maintenance process for eBPF programs, enhancing their reliability across a wide range of kernels.}, + booktitle = {Proceedings of the Twentieth European Conference on Computer Systems}, + pages = {21–41}, + numpages = {21}, + location = {Rotterdam, Netherlands}, + series = {EuroSys '25} +} +``` + +
+ +## Prerequisites + +DepSurf requires Python 3.11 or higher. Tested on Ubuntu 22.04 and Ubuntu 24.04. + +We recommend using [uv](https://astral.sh/uv/) for environment setup: + +```sh +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +Download the source code from GitHub: + +```sh +git clone https://github.com/ShawnZhong/DepSurf.git +cd DepSurf +git submodule update --init --recursive +``` + +Then, you can run the following commands to start Jupyter Lab: + +```sh +uv run jupyter lab +``` + +## Result Reproduction + +Please follow the instructions in the following Jupyter notebooks to reproduce the results in the paper. + +> [!NOTE] +> We have pre-generated the dataset and made it available at [data/dataset](https://github.com/ShawnZhong/DepSurf-dataset). If you only wish to analyze the results, you may skip `11_download.ipynb` and `20_dataset.ipynb` to save time and disk space. + +- [`00_deps.ipynb`](./00_deps.ipynb) installs the dependencies (3 min) + +- [`11_download.ipynb`](./11_download.ipynb) downloads the Linux kernel packages (15 min, 23 GB) + +- [`20_dataset.ipynb`](./20_dataset.ipynb) generates the dataset (10 min, 20 GB) + +- [`30_diff.ipynb`](./30_diff.ipynb) analyzes the dependency surface differences (2 min) + +- [`35_src.ipynb`](./35_src.ipynb) generates Table 3 for source code changes + +- [`36_breakdown.ipynb`](./36_breakdown.ipynb) generates Table 4 for a breakdown of changes + +- [`39_config.ipynb`](./39_config.ipynb) generates Table 5 for configuration differences + +- [`40_inline.ipynb`](./40_inline.ipynb) plots Figure 5 for function inlining (3 min) + +- [`41_transform.ipynb`](./41_transform.ipynb) plots Figure 6 for function transformations (3 min) + +- [`42_dup.ipynb`](./42_dup.ipynb) generates Table 6 for functions with the same name (30 sec) + +- [`50_programs.ipynb`](./50_programs.ipynb) analyzes the eBPF programs (5 min) + +- [`51_plot.ipynb`](./51_plot.ipynb) plots Figure 4 for dependency report + +- [`52_summary.ipynb`](./52_summary.ipynb) generates Table 7 & 8 for summary of dependency set analysis + + +## Project Structure + +- [depsurf](./depsurf): source code of the DepSurf library + + - [btf](./depsurf/btf): processing type information + + - [diff](./depsurf/diff): diffing the dependency surface + + - [funcs](./depsurf/funcs): extracing kernel functions information + + - [linux](./depsurf/linux): analyzing Linux kernel images + +- [data](./data): data files used in the project + + - [dataset](https://github.com/ShawnZhong/DepSurf-dataset): dataset for kernel dependency surfaces + + - [software](./data/software): eBPF programs analyzed + + - [website](https://github.com/DepSurf/depsurf.github.io): website for DepSurf + +- [utils](./utils): helper functions used by the notebooks diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/.clang-format b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/.clang-format new file mode 100644 index 00000000..59d0684d --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/.clang-format @@ -0,0 +1,2 @@ +BasedOnStyle: Google +SortIncludes: Never diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/55_category.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/55_category.ipynb new file mode 100644 index 00000000..174005d6 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/55_category.ipynb @@ -0,0 +1,206 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Categorize BCC Programs\n", + "\n", + "This notebook categorizes the BCC programs. Feel free to skip this notebook." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from enum import StrEnum\n", + "\n", + "\n", + "class Category(StrEnum):\n", + " CPU = \"CPU\"\n", + " PROC = \"Process\"\n", + " MEMORY = \"Memory\"\n", + " BLOCK = \"Block Device\"\n", + " FILESYSTEM = \"Filesystem\"\n", + " NETWORK = \"Network\"\n", + " USERSPACE = \"Userspace\"\n", + " OTHER = \"Other\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "BCC_CATEGORY = {\n", + " \"argdist\": Category.OTHER,\n", + " \"bashreadline\": Category.USERSPACE,\n", + " \"bindsnoop\": Category.NETWORK,\n", + " \"biolatency\": Category.BLOCK,\n", + " \"biolatpcts\": Category.BLOCK,\n", + " \"biopattern\": Category.BLOCK,\n", + " \"biosnoop\": Category.BLOCK,\n", + " \"biotop\": Category.BLOCK,\n", + " \"bitesize\": Category.BLOCK,\n", + " \"btrfsdist\": Category.FILESYSTEM,\n", + " \"btrfsslower\": Category.FILESYSTEM,\n", + " \"cachestat\": Category.FILESYSTEM,\n", + " \"cachetop\": Category.FILESYSTEM,\n", + " \"capable\": Category.OTHER,\n", + " \"compactsnoop\": Category.MEMORY,\n", + " \"cpudist\": Category.CPU,\n", + " \"cpuunclaimed\": Category.CPU,\n", + " \"criticalstat\": Category.CPU,\n", + " \"dbslower\": Category.USERSPACE,\n", + " \"dbstat\": Category.USERSPACE,\n", + " \"dcsnoop\": Category.FILESYSTEM,\n", + " \"dcstat\": Category.FILESYSTEM,\n", + " \"deadlock\": Category.OTHER,\n", + " \"dirtop\": Category.FILESYSTEM,\n", + " \"drsnoop\": Category.MEMORY,\n", + " \"execsnoop\": Category.PROC,\n", + " \"exitsnoop\": Category.PROC,\n", + " \"ext4dist\": Category.FILESYSTEM,\n", + " \"ext4slower\": Category.FILESYSTEM,\n", + " \"filegone\": Category.FILESYSTEM,\n", + " \"filelife\": Category.FILESYSTEM,\n", + " \"fileslower\": Category.FILESYSTEM,\n", + " \"filetop\": Category.FILESYSTEM,\n", + " \"funccount\": Category.OTHER,\n", + " \"funcinterval\": Category.OTHER,\n", + " \"funclatency\": Category.OTHER,\n", + " \"funcslower\": Category.OTHER,\n", + " \"gethostlatency\": Category.USERSPACE,\n", + " \"hardirqs\": Category.CPU,\n", + " \"inject\": Category.OTHER,\n", + " \"killsnoop\": Category.PROC,\n", + " \"klockstat\": Category.OTHER,\n", + " \"kvmexit\": Category.PROC,\n", + " \"llcstat\": Category.CPU,\n", + " \"mdflush\": Category.BLOCK,\n", + " \"memleak\": Category.MEMORY,\n", + " \"mountsnoop\": Category.FILESYSTEM,\n", + " \"mysqld_qslower\": Category.USERSPACE,\n", + " \"netqtop\": Category.NETWORK,\n", + " \"nfsdist\": Category.FILESYSTEM,\n", + " \"nfsslower\": Category.FILESYSTEM,\n", + " \"offcputime\": Category.CPU,\n", + " \"offwaketime\": Category.CPU,\n", + " \"oomkill\": Category.MEMORY,\n", + " \"opensnoop\": Category.FILESYSTEM,\n", + " \"pidpersec\": Category.PROC,\n", + " \"ppchcalls\": Category.OTHER,\n", + " \"profile\": Category.CPU,\n", + " \"readahead\": Category.FILESYSTEM,\n", + " \"runqlat\": Category.CPU,\n", + " \"runqlen\": Category.CPU,\n", + " \"runqslower\": Category.CPU,\n", + " \"shmsnoop\": Category.PROC,\n", + " \"slabratetop\": Category.MEMORY,\n", + " \"sofdsnoop\": Category.NETWORK,\n", + " \"softirqs\": Category.CPU,\n", + " \"solisten\": Category.NETWORK,\n", + " \"sslsniff\": Category.NETWORK,\n", + " \"stackcount\": Category.OTHER,\n", + " \"statsnoop\": Category.FILESYSTEM,\n", + " \"swapin\": Category.MEMORY,\n", + " \"syncsnoop\": Category.FILESYSTEM,\n", + " \"syscount\": Category.OTHER,\n", + " \"tcpaccept\": Category.NETWORK,\n", + " \"tcpcong\": Category.NETWORK,\n", + " \"tcpconnect\": Category.NETWORK,\n", + " \"tcpconnlat\": Category.NETWORK,\n", + " \"tcpdrop\": Category.NETWORK,\n", + " \"tcplife\": Category.NETWORK,\n", + " \"tcpretrans\": Category.NETWORK,\n", + " \"tcprtt\": Category.NETWORK,\n", + " \"tcpstates\": Category.NETWORK,\n", + " \"tcpsubnet\": Category.NETWORK,\n", + " \"tcpsynbl\": Category.NETWORK,\n", + " \"tcptop\": Category.NETWORK,\n", + " \"tcptracer\": Category.NETWORK,\n", + " \"threadsnoop\": Category.PROC,\n", + " \"trace\": Category.OTHER,\n", + " \"ttysnoop\": Category.OTHER,\n", + " \"vfscount\": Category.FILESYSTEM,\n", + " \"vfsstat\": Category.FILESYSTEM,\n", + " \"virtiostat\": Category.FILESYSTEM,\n", + " \"wakeuptime\": Category.CPU,\n", + " \"xfsdist\": Category.FILESYSTEM,\n", + " \"xfsslower\": Category.FILESYSTEM,\n", + " \"zfsdist\": Category.FILESYSTEM,\n", + " \"zfsslower\": Category.FILESYSTEM,\n", + " # libbpf-tools\n", + " \"biostacks\": Category.BLOCK,\n", + " \"cpufreq\": Category.CPU,\n", + " \"fsdist\": Category.FILESYSTEM,\n", + " \"fsslower\": Category.FILESYSTEM,\n", + " \"futexctn\": Category.PROC,\n", + " \"javagc\": Category.USERSPACE,\n", + " \"ksnoop\": Category.OTHER,\n", + " \"numamove\": Category.MEMORY,\n", + " \"sigsnoop\": Category.PROC,\n", + " \"tcppktlat\": Category.NETWORK,\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU (11): cpufreq, runqslower, profile, hardirqs, runqlen, runqlat, llcstat, wakeuptime, softirqs, offcputime, cpudist\n", + "Process ( 4): execsnoop, futexctn, sigsnoop, exitsnoop\n", + "Memory ( 5): slabratetop, memleak, oomkill, drsnoop, numamove\n", + "Block Device ( 7): biopattern, biotop, mdflush, biostacks, biosnoop, biolatency, bitesize\n", + "Filesystem (11): fsslower, cachestat, syncsnoop, readahead, filelife, vfsstat, fsdist, filetop, statsnoop, mountsnoop, opensnoop\n", + "Network (11): tcpstates, tcptracer, tcpsynbl, solisten, tcppktlat, tcpconnect, tcprtt, tcpconnlat, bindsnoop, tcplife, tcptop\n", + "Userspace ( 3): bashreadline, gethostlatency, javagc\n", + "Other ( 5): syscount, funclatency, capable, ksnoop, klockstat\n" + ] + } + ], + "source": [ + "from utils import BCC_OBJ_PATH\n", + "\n", + "categories = {c: [] for c in Category}\n", + "\n", + "for path in BCC_OBJ_PATH.glob(\"*.bpf.o\"):\n", + " name = path.name.removesuffix(\".bpf.o\")\n", + " c = BCC_CATEGORY[name]\n", + " categories[c].append(name)\n", + "\n", + "for c in categories:\n", + " print(f\"{c:12} ({len(categories[c]):2}): {', '.join(categories[c])}\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/91_test_diff.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/91_test_diff.ipynb new file mode 100644 index 00000000..4a6baa1a --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/91_test_diff.ipynb @@ -0,0 +1,966 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "metadata": {} + }, + "outputs": [], + "source": [ + "from depsurf import Version, DepKind, VersionPair\n", + "\n", + "v1 = Version.from_str(\"5.4.0-26-generic-amd64\")\n", + "v2 = Version.from_str(\"5.4.0-26-generic-armhf\")\n", + "\n", + "img1 = v1.img\n", + "img2 = v2.img\n", + "\n", + "p = VersionPair(v1, v2)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'kind': 'UNION',\n", + " 'name': 'intel_x86_pebs_dse',\n", + " 'size': 8,\n", + " 'members': [{'name': 'val',\n", + " 'bits_offset': 0,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'ld_dse',\n", + " 'bits_offset': 0,\n", + " 'bitfield_size': 4,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'ld_stlb_miss',\n", + " 'bits_offset': 4,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'ld_locked',\n", + " 'bits_offset': 5,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'ld_reserved',\n", + " 'bits_offset': 6,\n", + " 'bitfield_size': 26,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'st_l1d_hit',\n", + " 'bits_offset': 0,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'st_reserved1',\n", + " 'bits_offset': 1,\n", + " 'bitfield_size': 3,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'st_stlb_miss',\n", + " 'bits_offset': 4,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'st_locked',\n", + " 'bits_offset': 5,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'st_reserved2',\n", + " 'bits_offset': 6,\n", + " 'bitfield_size': 26,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}}]}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "img1.get_dep(DepKind.UNION(\"intel_x86_pebs_dse\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "metadata": {} + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'kind': 'STRUCT',\n", + " 'name': 'task_struct',\n", + " 'size': 9280,\n", + " 'members': [{'name': 'thread_info',\n", + " 'bits_offset': 0,\n", + " 'type': {'kind': 'STRUCT', 'name': 'thread_info'}},\n", + " {'name': 'state',\n", + " 'bits_offset': 128,\n", + " 'type': {'kind': 'VOLATILE',\n", + " 'name': '(anon)',\n", + " 'type': {'kind': 'INT', 'name': 'long int'}}},\n", + " {'name': 'stack',\n", + " 'bits_offset': 192,\n", + " 'type': {'kind': 'PTR', 'type': {'name': 'void', 'kind': 'VOID'}}},\n", + " {'name': 'usage',\n", + " 'bits_offset': 256,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'refcount_t'}},\n", + " {'name': 'flags',\n", + " 'bits_offset': 288,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'ptrace',\n", + " 'bits_offset': 320,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'wake_entry',\n", + " 'bits_offset': 384,\n", + " 'type': {'kind': 'STRUCT', 'name': 'llist_node'}},\n", + " {'name': 'on_cpu',\n", + " 'bits_offset': 448,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'cpu',\n", + " 'bits_offset': 480,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'wakee_flips',\n", + " 'bits_offset': 512,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'wakee_flip_decay_ts',\n", + " 'bits_offset': 576,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'last_wakee',\n", + " 'bits_offset': 640,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'task_struct'}}},\n", + " {'name': 'recent_used_cpu',\n", + " 'bits_offset': 704,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'wake_cpu',\n", + " 'bits_offset': 736,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'on_rq',\n", + " 'bits_offset': 768,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'prio', 'bits_offset': 800, 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'static_prio',\n", + " 'bits_offset': 832,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'normal_prio',\n", + " 'bits_offset': 864,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'rt_priority',\n", + " 'bits_offset': 896,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'sched_class',\n", + " 'bits_offset': 960,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'CONST',\n", + " 'name': '(anon)',\n", + " 'type': {'kind': 'STRUCT', 'name': 'sched_class'}}}},\n", + " {'name': 'se',\n", + " 'bits_offset': 1024,\n", + " 'type': {'kind': 'STRUCT', 'name': 'sched_entity'}},\n", + " {'name': 'rt',\n", + " 'bits_offset': 4608,\n", + " 'type': {'kind': 'STRUCT', 'name': 'sched_rt_entity'}},\n", + " {'name': 'sched_task_group',\n", + " 'bits_offset': 5184,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'task_group'}}},\n", + " {'name': 'dl',\n", + " 'bits_offset': 5248,\n", + " 'type': {'kind': 'STRUCT', 'name': 'sched_dl_entity'}},\n", + " {'name': 'uclamp_req',\n", + " 'bits_offset': 6976,\n", + " 'type': {'kind': 'ARRAY',\n", + " 'name': '(anon)',\n", + " 'nr_elems': 2,\n", + " 'type': {'kind': 'STRUCT', 'name': 'uclamp_se'}}},\n", + " {'name': 'uclamp',\n", + " 'bits_offset': 7040,\n", + " 'type': {'kind': 'ARRAY',\n", + " 'name': '(anon)',\n", + " 'nr_elems': 2,\n", + " 'type': {'kind': 'STRUCT', 'name': 'uclamp_se'}}},\n", + " {'name': 'preempt_notifiers',\n", + " 'bits_offset': 7104,\n", + " 'type': {'kind': 'STRUCT', 'name': 'hlist_head'}},\n", + " {'name': 'btrace_seq',\n", + " 'bits_offset': 7168,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'policy',\n", + " 'bits_offset': 7200,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'nr_cpus_allowed',\n", + " 'bits_offset': 7232,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'cpus_ptr',\n", + " 'bits_offset': 7296,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'CONST',\n", + " 'name': '(anon)',\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'cpumask_t'}}}},\n", + " {'name': 'cpus_mask',\n", + " 'bits_offset': 7360,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'cpumask_t'}},\n", + " {'name': 'rcu_tasks_nvcsw',\n", + " 'bits_offset': 15552,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'rcu_tasks_holdout',\n", + " 'bits_offset': 15616,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u8'}},\n", + " {'name': 'rcu_tasks_idx',\n", + " 'bits_offset': 15624,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u8'}},\n", + " {'name': 'rcu_tasks_idle_cpu',\n", + " 'bits_offset': 15648,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'rcu_tasks_holdout_list',\n", + " 'bits_offset': 15680,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'sched_info',\n", + " 'bits_offset': 15808,\n", + " 'type': {'kind': 'STRUCT', 'name': 'sched_info'}},\n", + " {'name': 'tasks',\n", + " 'bits_offset': 16064,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'pushable_tasks',\n", + " 'bits_offset': 16192,\n", + " 'type': {'kind': 'STRUCT', 'name': 'plist_node'}},\n", + " {'name': 'pushable_dl_tasks',\n", + " 'bits_offset': 16512,\n", + " 'type': {'kind': 'STRUCT', 'name': 'rb_node'}},\n", + " {'name': 'mm',\n", + " 'bits_offset': 16704,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'mm_struct'}}},\n", + " {'name': 'active_mm',\n", + " 'bits_offset': 16768,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'mm_struct'}}},\n", + " {'name': 'vmacache',\n", + " 'bits_offset': 16832,\n", + " 'type': {'kind': 'STRUCT', 'name': 'vmacache'}},\n", + " {'name': 'rss_stat',\n", + " 'bits_offset': 17152,\n", + " 'type': {'kind': 'STRUCT', 'name': 'task_rss_stat'}},\n", + " {'name': 'exit_state',\n", + " 'bits_offset': 17312,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'exit_code',\n", + " 'bits_offset': 17344,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'exit_signal',\n", + " 'bits_offset': 17376,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'pdeath_signal',\n", + " 'bits_offset': 17408,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'jobctl',\n", + " 'bits_offset': 17472,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'personality',\n", + " 'bits_offset': 17536,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'sched_reset_on_fork',\n", + " 'bits_offset': 17568,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'sched_contributes_to_load',\n", + " 'bits_offset': 17569,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'sched_migrated',\n", + " 'bits_offset': 17570,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'sched_remote_wakeup',\n", + " 'bits_offset': 17571,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'sched_psi_wake_requeue',\n", + " 'bits_offset': 17572,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'in_execve',\n", + " 'bits_offset': 17600,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'in_iowait',\n", + " 'bits_offset': 17601,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'restore_sigmask',\n", + " 'bits_offset': 17602,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'in_user_fault',\n", + " 'bits_offset': 17603,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'no_cgroup_migration',\n", + " 'bits_offset': 17604,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'frozen',\n", + " 'bits_offset': 17605,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'use_memdelay',\n", + " 'bits_offset': 17606,\n", + " 'bitfield_size': 1,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'atomic_flags',\n", + " 'bits_offset': 17664,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'restart_block',\n", + " 'bits_offset': 17728,\n", + " 'type': {'kind': 'STRUCT', 'name': 'restart_block'}},\n", + " {'name': 'pid',\n", + " 'bits_offset': 18112,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'pid_t'}},\n", + " {'name': 'tgid',\n", + " 'bits_offset': 18144,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'pid_t'}},\n", + " {'name': 'stack_canary',\n", + " 'bits_offset': 18176,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'real_parent',\n", + " 'bits_offset': 18240,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'task_struct'}}},\n", + " {'name': 'parent',\n", + " 'bits_offset': 18304,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'task_struct'}}},\n", + " {'name': 'children',\n", + " 'bits_offset': 18368,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'sibling',\n", + " 'bits_offset': 18496,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'group_leader',\n", + " 'bits_offset': 18624,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'task_struct'}}},\n", + " {'name': 'ptraced',\n", + " 'bits_offset': 18688,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'ptrace_entry',\n", + " 'bits_offset': 18816,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'thread_pid',\n", + " 'bits_offset': 18944,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'pid'}}},\n", + " {'name': 'pid_links',\n", + " 'bits_offset': 19008,\n", + " 'type': {'kind': 'ARRAY',\n", + " 'name': '(anon)',\n", + " 'nr_elems': 4,\n", + " 'type': {'kind': 'STRUCT', 'name': 'hlist_node'}}},\n", + " {'name': 'thread_group',\n", + " 'bits_offset': 19520,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'thread_node',\n", + " 'bits_offset': 19648,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'vfork_done',\n", + " 'bits_offset': 19776,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'completion'}}},\n", + " {'name': 'set_child_tid',\n", + " 'bits_offset': 19840,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'INT', 'name': 'int'}}},\n", + " {'name': 'clear_child_tid',\n", + " 'bits_offset': 19904,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'INT', 'name': 'int'}}},\n", + " {'name': 'utime',\n", + " 'bits_offset': 19968,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'stime',\n", + " 'bits_offset': 20032,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'gtime',\n", + " 'bits_offset': 20096,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'prev_cputime',\n", + " 'bits_offset': 20160,\n", + " 'type': {'kind': 'STRUCT', 'name': 'prev_cputime'}},\n", + " {'name': 'nvcsw',\n", + " 'bits_offset': 20352,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'nivcsw',\n", + " 'bits_offset': 20416,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'start_time',\n", + " 'bits_offset': 20480,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'real_start_time',\n", + " 'bits_offset': 20544,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'min_flt',\n", + " 'bits_offset': 20608,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'maj_flt',\n", + " 'bits_offset': 20672,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'posix_cputimers',\n", + " 'bits_offset': 20736,\n", + " 'type': {'kind': 'STRUCT', 'name': 'posix_cputimers'}},\n", + " {'name': 'ptracer_cred',\n", + " 'bits_offset': 21376,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'CONST',\n", + " 'name': '(anon)',\n", + " 'type': {'kind': 'STRUCT', 'name': 'cred'}}}},\n", + " {'name': 'real_cred',\n", + " 'bits_offset': 21440,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'CONST',\n", + " 'name': '(anon)',\n", + " 'type': {'kind': 'STRUCT', 'name': 'cred'}}}},\n", + " {'name': 'cred',\n", + " 'bits_offset': 21504,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'CONST',\n", + " 'name': '(anon)',\n", + " 'type': {'kind': 'STRUCT', 'name': 'cred'}}}},\n", + " {'name': 'cached_requested_key',\n", + " 'bits_offset': 21568,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'key'}}},\n", + " {'name': 'comm',\n", + " 'bits_offset': 21632,\n", + " 'type': {'kind': 'ARRAY',\n", + " 'name': '(anon)',\n", + " 'nr_elems': 16,\n", + " 'type': {'kind': 'INT', 'name': 'char'}}},\n", + " {'name': 'nameidata',\n", + " 'bits_offset': 21760,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'nameidata'}}},\n", + " {'name': 'sysvsem',\n", + " 'bits_offset': 21824,\n", + " 'type': {'kind': 'STRUCT', 'name': 'sysv_sem'}},\n", + " {'name': 'sysvshm',\n", + " 'bits_offset': 21888,\n", + " 'type': {'kind': 'STRUCT', 'name': 'sysv_shm'}},\n", + " {'name': 'last_switch_count',\n", + " 'bits_offset': 22016,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'last_switch_time',\n", + " 'bits_offset': 22080,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'fs',\n", + " 'bits_offset': 22144,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'fs_struct'}}},\n", + " {'name': 'files',\n", + " 'bits_offset': 22208,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'files_struct'}}},\n", + " {'name': 'nsproxy',\n", + " 'bits_offset': 22272,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'nsproxy'}}},\n", + " {'name': 'signal',\n", + " 'bits_offset': 22336,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'signal_struct'}}},\n", + " {'name': 'sighand',\n", + " 'bits_offset': 22400,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'sighand_struct'}}},\n", + " {'name': 'blocked',\n", + " 'bits_offset': 22464,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'sigset_t'}},\n", + " {'name': 'real_blocked',\n", + " 'bits_offset': 22528,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'sigset_t'}},\n", + " {'name': 'saved_sigmask',\n", + " 'bits_offset': 22592,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'sigset_t'}},\n", + " {'name': 'pending',\n", + " 'bits_offset': 22656,\n", + " 'type': {'kind': 'STRUCT', 'name': 'sigpending'}},\n", + " {'name': 'sas_ss_sp',\n", + " 'bits_offset': 22848,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'sas_ss_size',\n", + " 'bits_offset': 22912,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'size_t'}},\n", + " {'name': 'sas_ss_flags',\n", + " 'bits_offset': 22976,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'task_works',\n", + " 'bits_offset': 23040,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'callback_head'}}},\n", + " {'name': 'audit_context',\n", + " 'bits_offset': 23104,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'audit_context'}}},\n", + " {'name': 'loginuid',\n", + " 'bits_offset': 23168,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'kuid_t'}},\n", + " {'name': 'sessionid',\n", + " 'bits_offset': 23200,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'seccomp',\n", + " 'bits_offset': 23232,\n", + " 'type': {'kind': 'STRUCT', 'name': 'seccomp'}},\n", + " {'name': 'parent_exec_id',\n", + " 'bits_offset': 23360,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u32'}},\n", + " {'name': 'self_exec_id',\n", + " 'bits_offset': 23392,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u32'}},\n", + " {'name': 'alloc_lock',\n", + " 'bits_offset': 23424,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'spinlock_t'}},\n", + " {'name': 'pi_lock',\n", + " 'bits_offset': 23456,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'raw_spinlock_t'}},\n", + " {'name': 'wake_q',\n", + " 'bits_offset': 23488,\n", + " 'type': {'kind': 'STRUCT', 'name': 'wake_q_node'}},\n", + " {'name': 'pi_waiters',\n", + " 'bits_offset': 23552,\n", + " 'type': {'kind': 'STRUCT', 'name': 'rb_root_cached'}},\n", + " {'name': 'pi_top_task',\n", + " 'bits_offset': 23680,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'task_struct'}}},\n", + " {'name': 'pi_blocked_on',\n", + " 'bits_offset': 23744,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'rt_mutex_waiter'}}},\n", + " {'name': 'journal_info',\n", + " 'bits_offset': 23808,\n", + " 'type': {'kind': 'PTR', 'type': {'name': 'void', 'kind': 'VOID'}}},\n", + " {'name': 'bio_list',\n", + " 'bits_offset': 23872,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'bio_list'}}},\n", + " {'name': 'plug',\n", + " 'bits_offset': 23936,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'blk_plug'}}},\n", + " {'name': 'reclaim_state',\n", + " 'bits_offset': 24000,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'reclaim_state'}}},\n", + " {'name': 'backing_dev_info',\n", + " 'bits_offset': 24064,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'backing_dev_info'}}},\n", + " {'name': 'io_context',\n", + " 'bits_offset': 24128,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'io_context'}}},\n", + " {'name': 'capture_control',\n", + " 'bits_offset': 24192,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'capture_control'}}},\n", + " {'name': 'ptrace_message',\n", + " 'bits_offset': 24256,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'last_siginfo',\n", + " 'bits_offset': 24320,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'kernel_siginfo_t'}}},\n", + " {'name': 'ioac',\n", + " 'bits_offset': 24384,\n", + " 'type': {'kind': 'STRUCT', 'name': 'task_io_accounting'}},\n", + " {'name': 'psi_flags',\n", + " 'bits_offset': 24832,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'acct_rss_mem1',\n", + " 'bits_offset': 24896,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'acct_vm_mem1',\n", + " 'bits_offset': 24960,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'acct_timexpd',\n", + " 'bits_offset': 25024,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'mems_allowed',\n", + " 'bits_offset': 25088,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'nodemask_t'}},\n", + " {'name': 'mems_allowed_seq',\n", + " 'bits_offset': 26112,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'seqcount_t'}},\n", + " {'name': 'cpuset_mem_spread_rotor',\n", + " 'bits_offset': 26144,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'cpuset_slab_spread_rotor',\n", + " 'bits_offset': 26176,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'cgroups',\n", + " 'bits_offset': 26240,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'css_set'}}},\n", + " {'name': 'cg_list',\n", + " 'bits_offset': 26304,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'closid',\n", + " 'bits_offset': 26432,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u32'}},\n", + " {'name': 'rmid',\n", + " 'bits_offset': 26464,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u32'}},\n", + " {'name': 'robust_list',\n", + " 'bits_offset': 26496,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'robust_list_head'}}},\n", + " {'name': 'compat_robust_list',\n", + " 'bits_offset': 26560,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'compat_robust_list_head'}}},\n", + " {'name': 'pi_state_list',\n", + " 'bits_offset': 26624,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'pi_state_cache',\n", + " 'bits_offset': 26752,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'futex_pi_state'}}},\n", + " {'name': 'futex_exit_mutex',\n", + " 'bits_offset': 26816,\n", + " 'type': {'kind': 'STRUCT', 'name': 'mutex'}},\n", + " {'name': 'futex_state',\n", + " 'bits_offset': 27072,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'perf_event_ctxp',\n", + " 'bits_offset': 27136,\n", + " 'type': {'kind': 'ARRAY',\n", + " 'name': '(anon)',\n", + " 'nr_elems': 2,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'perf_event_context'}}}},\n", + " {'name': 'perf_event_mutex',\n", + " 'bits_offset': 27264,\n", + " 'type': {'kind': 'STRUCT', 'name': 'mutex'}},\n", + " {'name': 'perf_event_list',\n", + " 'bits_offset': 27520,\n", + " 'type': {'kind': 'STRUCT', 'name': 'list_head'}},\n", + " {'name': 'mempolicy',\n", + " 'bits_offset': 27648,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'mempolicy'}}},\n", + " {'name': 'il_prev',\n", + " 'bits_offset': 27712,\n", + " 'type': {'kind': 'INT', 'name': 'short int'}},\n", + " {'name': 'pref_node_fork',\n", + " 'bits_offset': 27728,\n", + " 'type': {'kind': 'INT', 'name': 'short int'}},\n", + " {'name': 'numa_scan_seq',\n", + " 'bits_offset': 27744,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'numa_scan_period',\n", + " 'bits_offset': 27776,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'numa_scan_period_max',\n", + " 'bits_offset': 27808,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'numa_preferred_nid',\n", + " 'bits_offset': 27840,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'numa_migrate_retry',\n", + " 'bits_offset': 27904,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'node_stamp',\n", + " 'bits_offset': 27968,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'last_task_numa_placement',\n", + " 'bits_offset': 28032,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'last_sum_exec_runtime',\n", + " 'bits_offset': 28096,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'numa_work',\n", + " 'bits_offset': 28160,\n", + " 'type': {'kind': 'STRUCT', 'name': 'callback_head'}},\n", + " {'name': 'numa_group',\n", + " 'bits_offset': 28288,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'numa_group'}}},\n", + " {'name': 'numa_faults',\n", + " 'bits_offset': 28352,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}}},\n", + " {'name': 'total_numa_faults',\n", + " 'bits_offset': 28416,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'numa_faults_locality',\n", + " 'bits_offset': 28480,\n", + " 'type': {'kind': 'ARRAY',\n", + " 'name': '(anon)',\n", + " 'nr_elems': 3,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}}},\n", + " {'name': 'numa_pages_migrated',\n", + " 'bits_offset': 28672,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'rseq',\n", + " 'bits_offset': 28736,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'rseq'}}},\n", + " {'name': 'rseq_sig',\n", + " 'bits_offset': 28800,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u32'}},\n", + " {'name': 'rseq_event_mask',\n", + " 'bits_offset': 28864,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'tlb_ubc',\n", + " 'bits_offset': 28928,\n", + " 'type': {'kind': 'STRUCT', 'name': 'tlbflush_unmap_batch'}},\n", + " {'name': 'rcu_users',\n", + " 'bits_offset': 37184,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'refcount_t'}},\n", + " {'name': 'rcu',\n", + " 'bits_offset': 37184,\n", + " 'type': {'kind': 'STRUCT', 'name': 'callback_head'}},\n", + " {'name': 'splice_pipe',\n", + " 'bits_offset': 37312,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'pipe_inode_info'}}},\n", + " {'name': 'task_frag',\n", + " 'bits_offset': 37376,\n", + " 'type': {'kind': 'STRUCT', 'name': 'page_frag'}},\n", + " {'name': 'delays',\n", + " 'bits_offset': 37504,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'task_delay_info'}}},\n", + " {'name': 'nr_dirtied',\n", + " 'bits_offset': 37568,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'nr_dirtied_pause',\n", + " 'bits_offset': 37600,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'dirty_paused_when',\n", + " 'bits_offset': 37632,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'timer_slack_ns',\n", + " 'bits_offset': 37696,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'default_timer_slack_ns',\n", + " 'bits_offset': 37760,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'u64'}},\n", + " {'name': 'curr_ret_stack',\n", + " 'bits_offset': 37824,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'curr_ret_depth',\n", + " 'bits_offset': 37856,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'ret_stack',\n", + " 'bits_offset': 37888,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'ftrace_ret_stack'}}},\n", + " {'name': 'ftrace_timestamp',\n", + " 'bits_offset': 37952,\n", + " 'type': {'kind': 'INT', 'name': 'long long unsigned int'}},\n", + " {'name': 'trace_overrun',\n", + " 'bits_offset': 38016,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'atomic_t'}},\n", + " {'name': 'tracing_graph_pause',\n", + " 'bits_offset': 38048,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'atomic_t'}},\n", + " {'name': 'trace',\n", + " 'bits_offset': 38080,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'trace_recursion',\n", + " 'bits_offset': 38144,\n", + " 'type': {'kind': 'INT', 'name': 'long unsigned int'}},\n", + " {'name': 'memcg_in_oom',\n", + " 'bits_offset': 38208,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'mem_cgroup'}}},\n", + " {'name': 'memcg_oom_gfp_mask',\n", + " 'bits_offset': 38272,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'gfp_t'}},\n", + " {'name': 'memcg_oom_order',\n", + " 'bits_offset': 38304,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'memcg_nr_pages_over_high',\n", + " 'bits_offset': 38336,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'active_memcg',\n", + " 'bits_offset': 38400,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'mem_cgroup'}}},\n", + " {'name': 'throttle_queue',\n", + " 'bits_offset': 38464,\n", + " 'type': {'kind': 'PTR',\n", + " 'type': {'kind': 'STRUCT', 'name': 'request_queue'}}},\n", + " {'name': 'utask',\n", + " 'bits_offset': 38528,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'uprobe_task'}}},\n", + " {'name': 'sequential_io',\n", + " 'bits_offset': 38592,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'sequential_io_avg',\n", + " 'bits_offset': 38624,\n", + " 'type': {'kind': 'INT', 'name': 'unsigned int'}},\n", + " {'name': 'pagefault_disabled',\n", + " 'bits_offset': 38656,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'oom_reaper_list',\n", + " 'bits_offset': 38720,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'task_struct'}}},\n", + " {'name': 'stack_vm_area',\n", + " 'bits_offset': 38784,\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'vm_struct'}}},\n", + " {'name': 'stack_refcount',\n", + " 'bits_offset': 38848,\n", + " 'type': {'kind': 'TYPEDEF', 'name': 'refcount_t'}},\n", + " {'name': 'patch_state',\n", + " 'bits_offset': 38880,\n", + " 'type': {'kind': 'INT', 'name': 'int'}},\n", + " {'name': 'security',\n", + " 'bits_offset': 38912,\n", + " 'type': {'kind': 'PTR', 'type': {'name': 'void', 'kind': 'VOID'}}},\n", + " {'name': 'thread',\n", + " 'bits_offset': 39424,\n", + " 'type': {'kind': 'STRUCT', 'name': 'thread_struct'}}]}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "img1.get_dep(DepKind.STRUCT(\"task_struct\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'kind': 'FUNC',\n", + " 'name': 'vfs_read',\n", + " 'type': {'kind': 'FUNC_PROTO',\n", + " 'params': [{'name': 'file',\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'file'}}},\n", + " {'name': 'buf',\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'INT', 'name': 'char'}}},\n", + " {'name': 'count', 'type': {'kind': 'TYPEDEF', 'name': 'size_t'}},\n", + " {'name': 'pos',\n", + " 'type': {'kind': 'PTR', 'type': {'kind': 'TYPEDEF', 'name': 'loff_t'}}}],\n", + " 'ret_type': {'kind': 'TYPEDEF', 'name': 'ssize_t'}}}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "img1.get_dep(DepKind.FUNC(\"vfs_read\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[FieldRemove(name='thread_info', type={'kind': 'STRUCT', 'name': 'thread_info'}),\n", + " FieldRemove(name='cpu', type={'kind': 'INT', 'name': 'unsigned int'}),\n", + " FieldRemove(name='preempt_notifiers', type={'kind': 'STRUCT', 'name': 'hlist_head'}),\n", + " FieldRemove(name='restore_sigmask', type={'kind': 'INT', 'name': 'unsigned int'}),\n", + " FieldRemove(name='closid', type={'kind': 'TYPEDEF', 'name': 'u32'}),\n", + " FieldRemove(name='rmid', type={'kind': 'TYPEDEF', 'name': 'u32'}),\n", + " FieldRemove(name='compat_robust_list', type={'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'compat_robust_list_head'}}),\n", + " FieldRemove(name='mempolicy', type={'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'mempolicy'}}),\n", + " FieldRemove(name='il_prev', type={'kind': 'INT', 'name': 'short int'}),\n", + " FieldRemove(name='pref_node_fork', type={'kind': 'INT', 'name': 'short int'}),\n", + " FieldRemove(name='numa_scan_seq', type={'kind': 'INT', 'name': 'int'}),\n", + " FieldRemove(name='numa_scan_period', type={'kind': 'INT', 'name': 'unsigned int'}),\n", + " FieldRemove(name='numa_scan_period_max', type={'kind': 'INT', 'name': 'unsigned int'}),\n", + " FieldRemove(name='numa_preferred_nid', type={'kind': 'INT', 'name': 'int'}),\n", + " FieldRemove(name='numa_migrate_retry', type={'kind': 'INT', 'name': 'long unsigned int'}),\n", + " FieldRemove(name='node_stamp', type={'kind': 'TYPEDEF', 'name': 'u64'}),\n", + " FieldRemove(name='last_task_numa_placement', type={'kind': 'TYPEDEF', 'name': 'u64'}),\n", + " FieldRemove(name='last_sum_exec_runtime', type={'kind': 'TYPEDEF', 'name': 'u64'}),\n", + " FieldRemove(name='numa_work', type={'kind': 'STRUCT', 'name': 'callback_head'}),\n", + " FieldRemove(name='numa_group', type={'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'numa_group'}}),\n", + " FieldRemove(name='numa_faults', type={'kind': 'PTR', 'type': {'kind': 'INT', 'name': 'long unsigned int'}}),\n", + " FieldRemove(name='total_numa_faults', type={'kind': 'INT', 'name': 'long unsigned int'}),\n", + " FieldRemove(name='numa_faults_locality', type={'kind': 'ARRAY', 'name': '(anon)', 'nr_elems': 3, 'type': {'kind': 'INT', 'name': 'long unsigned int'}}),\n", + " FieldRemove(name='numa_pages_migrated', type={'kind': 'INT', 'name': 'long unsigned int'}),\n", + " FieldRemove(name='stack_vm_area', type={'kind': 'PTR', 'type': {'kind': 'STRUCT', 'name': 'vm_struct'}}),\n", + " FieldRemove(name='stack_refcount', type={'kind': 'TYPEDEF', 'name': 'refcount_t'}),\n", + " FieldRemove(name='patch_state', type={'kind': 'INT', 'name': 'int'}),\n", + " StructLayoutChange()]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p.diff_dep(DepKind.STRUCT(\"task_struct\")).changes" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "DepDelta(v1=5.4.0-26-generic-amd64, v2=5.4.0-26-generic-armhf, in_v1=True, in_v2=False, changes=[])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p.diff_dep(DepKind.FUNC(\"do_syscall_64\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tracepoint Old: 752\n", + "Tracepoint New: 690\n", + "Tracepoint Added: 70\n", + "Tracepoint Removed: 132\n", + "Syscall Old: 333\n", + "Syscall New: 378\n", + "Syscall Added: 74\n", + "Syscall Removed: 29\n" + ] + } + ], + "source": [ + "d = p.diff(kinds=[DepKind.TRACEPOINT, DepKind.SYSCALL])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/92_test_sections.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/92_test_sections.ipynb new file mode 100644 index 00000000..cbfa7b52 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/92_test_sections.ipynb @@ -0,0 +1,1029 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "from elftools.elf.elffile import ELFFile\n", + "\n", + "\n", + "class Sections:\n", + " def __init__(self, path: Path):\n", + " with open(path, \"rb\") as fin:\n", + " self.data = self.get_section_info(ELFFile(fin))\n", + "\n", + " @staticmethod\n", + " def get_section_info(elffile: ELFFile):\n", + " import pandas as pd\n", + "\n", + " df = pd.DataFrame(\n", + " [\n", + " {\n", + " \"name\": s.name,\n", + " **{\n", + " k.removeprefix(\"sh_\"): v\n", + " for k, v in s.header.items()\n", + " if k not in (\"sh_name\", \"sh_addr\")\n", + " },\n", + " \"addr\": s.header.sh_addr,\n", + " # \"data\": s.data()[:15],\n", + " }\n", + " for s in elffile.iter_sections()\n", + " ]\n", + " ).set_index(\"name\")\n", + " return df\n", + "\n", + " def _repr_html_(self):\n", + " return self.data.to_html(formatters={\"addr\": hex, \"offset\": hex, \"size\": hex})\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
typeflagsoffsetsizelinkinfoaddralignentsizeaddr
name
SHT_NULL00x00x000000x0
.textSHT_PROGBITS60x2000000xe00eb100409600xffffffff81000000
.rela.textSHT_RELA640x158478500x86c7187218240x0
.notesSHT_NOTE20x1000eb40x1ec00400xffffffff81e00eb4
.rela.notesSHT_RELA640x160b3f680x487238240x0
__ex_tableSHT_PROGBITS20x10010a00x82a400400xffffffff81e010a0
.rela__ex_tableSHT_RELA640x160b3fb00x30fd87258240x0
.rodataSHT_PROGBITS30x12000000x477bb200409600xffffffff82000000
.rela.rodataSHT_RELA640x160e4f880x10eee87278240x0
.pci_fixupSHT_PROGBITS20x1677bc00x2ff0001600xffffffff82477bc0
.rela.pci_fixupSHT_RELA640x161f3e700x47e87298240x0
.tracedataSHT_PROGBITS20x167abb00x7800100xffffffff8247abb0
.rela.tracedataSHT_RELA640x161f86580x12072118240x0
__ksymtabSHT_PROGBITS20x167ac280x1000800400xffffffff8247ac28
.rela__ksymtabSHT_RELA640x161f87780x4002072138240x0
__ksymtab_gplSHT_PROGBITS20x168ac300x10a7000400xffffffff8248ac30
.rela__ksymtab_gplSHT_RELA640x162387980x429c072158240x0
__ksymtab_stringsSHT_PROGBITS20x169b6a00x35ab300100xffffffff8249b6a0
__init_rodataSHT_PROGBITS20x16d11600x290003200xffffffff824d1160
.rela__init_rodataSHT_RELA640x1627b1580x54072188240x0
__paramSHT_PROGBITS20x16d13f00x35e800800xffffffff824d13f0
.rela__paramSHT_RELA640x1627b6980x601872208240x0
__modverSHT_PROGBITS20x16d49d80x62800800xffffffff824d49d8
.rela__modverSHT_RELA640x162816b00x1e072228240x0
.dataSHT_PROGBITS30x18000000x25770000819200xffffffff82600000
.rela.dataSHT_RELA640x162818900x129cd872248240x0
__bug_tableSHT_PROGBITS30x1a577000x15ec400100xffffffff82857700
.rela__bug_tableSHT_RELA640x163ab5680x57b1072268240x0
.vvarSHT_PROGBITS30x1a6e0000x1000001600xffffffff8286e000
.data..percpuSHT_PROGBITS30x1c000000x2d00000409600x0
.rela.data..percpuSHT_RELA640x164030780x13872298240x0
.init.textSHT_PROGBITS60x1c9c0000x8b30f001600xffffffff8289c000
.rela.init.textSHT_RELA640x164031b00xedee872318240x0
.altinstr_auxSHT_PROGBITS60x1d2730f0x8df00100xffffffff8292730f
.rela.altinstr_auxSHT_RELA640x164f10980x22e072338240x0
.init.dataSHT_PROGBITS30x1d280000x1c350000819200xffffffff82928000
.rela.init.dataSHT_RELA640x164f33780x12ebc872358240x0
.x86_cpu_dev.initSHT_PROGBITS20x1eeb5000x2800800xffffffff82aeb500
.rela.x86_cpu_dev.initSHT_RELA640x16621f400x7872378240x0
.parainstructionsSHT_PROGBITS20x1eeb5280x20bec00800xffffffff82aeb528
.rela.parainstructionsSHT_RELA640x16621fb80x311e872398240x0
.altinstructionsSHT_PROGBITS20x1f0c1180x4e0000100xffffffff82b0c118
.rela.altinstructionsSHT_RELA640x166531a00x1140072418240x0
.altinstr_replacementSHT_PROGBITS60x1f10f180x15a400100xffffffff82b10f18
.rela.altinstr_replacementSHT_RELA640x166645a00x273072438240x0
.iommu_tableSHT_PROGBITS20x1f124c00x11800800xffffffff82b124c0
.rela.iommu_tableSHT_RELA640x16666cd00x1b072458240x0
.apicdriversSHT_PROGBITS30x1f125d80x4000800xffffffff82b125d8
.rela.apicdriversSHT_RELA640x16666e800xc072478240x0
.exit.textSHT_PROGBITS60x1f126180x1f5f00100xffffffff82b12618
.rela.exit.textSHT_RELA640x16666f400x58b072498240x0
.smp_locksSHT_PROGBITS20x1f150000xa00000400xffffffff82b15000
.rela.smp_locksSHT_RELA640x1666c7f00x3625872518240x0
.data_nosaveSHT_PROGBITS30x1f1f0000x100000400xffffffff82b1f000
.bssSHT_NOBITS30x1f200000x4e000000409600xffffffff82b20000
.brkSHT_NOBITS30x1f200000x2c00000100xffffffff83000000
.init.scratchSHT_PROGBITS30x26000000x400000003200xffffffff83200000
.commentSHT_PROGBITS480x2a000000x2400110x0
.debug_arangesSHT_PROGBITS00x2a000300x31650001600x0
.rela.debug_arangesSHT_RELA640x166a2a480x3ab1872588240x0
.debug_infoSHT_PROGBITS00x2a316800xe58e52a00100x0
.rela.debug_infoSHT_RELA640x166dd5600x147f174072608240x0
.debug_abbrevSHT_PROGBITS00x10fbfbaa0x6a76ee00100x0
.debug_lineSHT_PROGBITS00x116672980x1814dbd00100x0
.rela.debug_lineSHT_RELA640x2aececa00x3d89072638240x0
.debug_frameSHT_PROGBITS00x12e7c0580x2d728000800x0
.rela.debug_frameSHT_RELA640x2af0c5300x28032072658240x0
.debug_strSHT_PROGBITS480x131532d80x38b94700110x0
.debug_locSHT_PROGBITS00x134dec1f0xf1558b00100x0
.rela.debug_locSHT_RELA640x2b18c8500x165ef7072688240x0
.debug_rangesSHT_PROGBITS00x143f41b00xf80960001600x0
.rela.debug_rangesSHT_RELA640x2c7eb7c00x1dd762072708240x0
.symtabSHT_SYMTAB00x15374b100x2b06f873908318240x0
.strtabSHT_STRTAB00x156252080x22264500100x0
.shstrtabSHT_STRTAB00x2e5c2de00x28e00100x0
" + ], + "text/plain": [ + "<__main__.Sections at 0x138883610>" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from depsurf import VERSION_DEFAULT\n", + "\n", + "Sections(VERSION_DEFAULT.vmlinux_path)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/93_test_funcs.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/93_test_funcs.ipynb new file mode 100644 index 00000000..6eaafea5 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/93_test_funcs.ipynb @@ -0,0 +1,2025 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/Users/szhong/Code/DepSurf/data/intermediate/vmlinux/5.4.0-26-generic-amd64:\tfile format elf64-x86-64\n", + "\u001b[0;33m\n", + "0x03de2f0a: \u001b[0m\u001b[0;34mDW_TAG_inlined_subroutine\u001b[0m\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x03de2f6b\u001b[0m \"vfs_fsync\")\n", + " \u001b[0;36mDW_AT_entry_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff81319206)\n", + " \u001b[0;36mDW_AT_GNU_entry_view\u001b[0m\t(\u001b[0;33m\u001b[0m0x01)\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff81319206)\n", + " \u001b[0;36mDW_AT_high_pc\u001b[0m\t(0xffffffff8131921d)\n", + " \u001b[0;36mDW_AT_call_file\u001b[0m\t(\u001b[0;32m\"/build/linux-Rhtntk/linux-5.4.0/fs/sync.c\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_call_line\u001b[0m\t(222)\n", + " \u001b[0;36mDW_AT_call_column\u001b[0m\t(9)\n", + " \u001b[0;36mDW_AT_sibling\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x03de2f47\u001b[0m)\n", + "\u001b[0;33m\n", + "0x03de2f6b: \u001b[0m\u001b[0;34mDW_TAG_subprogram\u001b[0m\n", + " \u001b[0;36mDW_AT_external\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_file\u001b[0m\t(\u001b[0;32m\"/build/linux-Rhtntk/linux-5.4.0/fs/sync.c\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_line\u001b[0m\t(210)\n", + " \u001b[0;36mDW_AT_decl_column\u001b[0m\t(5)\n", + " \u001b[0;36mDW_AT_prototyped\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_type\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x03dc892c\u001b[0m \"int\")\n", + " \u001b[0;36mDW_AT_inline\u001b[0m\t(\u001b[0;35mDW_INL_inlined\u001b[0m)\n", + " \u001b[0;36mDW_AT_sibling\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x03de2f96\u001b[0m)\n", + "\u001b[0;33m\n", + "0x03de3bf7: \u001b[0m\u001b[0;34mDW_TAG_subprogram\u001b[0m\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x03de2f6b\u001b[0m \"vfs_fsync\")\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff813191c0)\n", + " \u001b[0;36mDW_AT_high_pc\u001b[0m\t(0xffffffff813191de)\n", + " \u001b[0;36mDW_AT_frame_base\u001b[0m\t(DW_OP_call_frame_cfa)\n", + " \u001b[0;36mDW_AT_GNU_all_call_sites\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_sibling\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x03de3c3b\u001b[0m)\n", + "\u001b[0;33m\n", + "0x040f4312: \u001b[0m\u001b[0;34mDW_TAG_GNU_call_site\u001b[0m\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff8133c756)\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x040ffd4b\u001b[0m \"vfs_fsync\")\n", + "\u001b[0;33m\n", + "0x040ffd4b: \u001b[0m\u001b[0;34mDW_TAG_subprogram\u001b[0m\n", + " \u001b[0;36mDW_AT_external\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_declaration\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_linkage_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_file\u001b[0m\t(\u001b[0;32m\"/build/linux-Rhtntk/linux-5.4.0/include/linux/fs.h\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_line\u001b[0m\t(2863)\n", + " \u001b[0;36mDW_AT_decl_column\u001b[0m\t(12)\n", + "\u001b[0;33m\n", + "0x04402350: \u001b[0m\u001b[0;34mDW_TAG_GNU_call_site\u001b[0m\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff81366958)\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x044025f6\u001b[0m \"vfs_fsync\")\n", + "\u001b[0;33m\n", + "0x044025f6: \u001b[0m\u001b[0;34mDW_TAG_subprogram\u001b[0m\n", + " \u001b[0;36mDW_AT_external\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_declaration\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_linkage_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_file\u001b[0m\t(\u001b[0;32m\"/build/linux-Rhtntk/linux-5.4.0/include/linux/fs.h\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_line\u001b[0m\t(2863)\n", + " \u001b[0;36mDW_AT_decl_column\u001b[0m\t(12)\n", + "\u001b[0;33m\n", + "0x04eccb3f: \u001b[0m\u001b[0;34mDW_TAG_GNU_call_site\u001b[0m\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff81411529)\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x04ecce77\u001b[0m \"vfs_fsync\")\n", + "\u001b[0;33m\n", + "0x04ecce77: \u001b[0m\u001b[0;34mDW_TAG_subprogram\u001b[0m\n", + " \u001b[0;36mDW_AT_external\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_declaration\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_linkage_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_file\u001b[0m\t(\u001b[0;32m\"/build/linux-Rhtntk/linux-5.4.0/include/linux/fs.h\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_line\u001b[0m\t(2863)\n", + " \u001b[0;36mDW_AT_decl_column\u001b[0m\t(12)\n", + "\u001b[0;33m\n", + "0x09888606: \u001b[0m\u001b[0;34mDW_TAG_GNU_call_site\u001b[0m\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff8172d7bc)\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x0988faab\u001b[0m \"vfs_fsync\")\n", + "\u001b[0;33m\n", + "0x0988d915: \u001b[0m\u001b[0;34mDW_TAG_GNU_call_site\u001b[0m\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff8172a63c)\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x0988faab\u001b[0m \"vfs_fsync\")\n", + "\u001b[0;33m\n", + "0x0988d949: \u001b[0m\u001b[0;34mDW_TAG_GNU_call_site\u001b[0m\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff8172a688)\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x0988faab\u001b[0m \"vfs_fsync\")\n", + "\u001b[0;33m\n", + "0x0988faab: \u001b[0m\u001b[0;34mDW_TAG_subprogram\u001b[0m\n", + " \u001b[0;36mDW_AT_external\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_declaration\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_linkage_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_file\u001b[0m\t(\u001b[0;32m\"/build/linux-Rhtntk/linux-5.4.0/include/linux/fs.h\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_line\u001b[0m\t(2863)\n", + " \u001b[0;36mDW_AT_decl_column\u001b[0m\t(12)\n", + "\u001b[0;33m\n", + "0x0b1ef055: \u001b[0m\u001b[0;34mDW_TAG_GNU_call_site\u001b[0m\n", + " \u001b[0;36mDW_AT_low_pc\u001b[0m\t(\u001b[0;33m\u001b[0m0xffffffff818a5e3b)\n", + " \u001b[0;36mDW_AT_abstract_origin\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;33m0x0b1f8095\u001b[0m \"vfs_fsync\")\n", + "\u001b[0;33m\n", + "0x0b1f8095: \u001b[0m\u001b[0;34mDW_TAG_subprogram\u001b[0m\n", + " \u001b[0;36mDW_AT_external\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_declaration\u001b[0m\t(\u001b[0;33m\u001b[0mtrue)\n", + " \u001b[0;36mDW_AT_linkage_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_name\u001b[0m\t(\u001b[0;33m\u001b[0m\u001b[0;32m\"vfs_fsync\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_file\u001b[0m\t(\u001b[0;32m\"/build/linux-Rhtntk/linux-5.4.0/include/linux/fs.h\"\u001b[0m)\n", + " \u001b[0;36mDW_AT_decl_line\u001b[0m\t(2863)\n", + " \u001b[0;36mDW_AT_decl_column\u001b[0m\t(12)\n" + ] + } + ], + "source": [ + "from depsurf import VERSION_DEFAULT\n", + "\n", + "!llvm-dwarfdump {VERSION_DEFAULT.vmlinux_path} --name vfs_fsync" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ffffffff824a6e48 r __kstrtab_vfs_fsync\n", + "ffffffff824a6e52 r __kstrtab_vfs_fsync_range\n", + "ffffffff82489bd4 r __ksymtab_vfs_fsync\n", + "ffffffff82489be0 r __ksymtab_vfs_fsync_range\n", + "ffffffff813191c0 T vfs_fsync\n", + "ffffffff81319140 T vfs_fsync_range\n" + ] + } + ], + "source": [ + "from depsurf import VERSION_DEFAULT\n", + "\n", + "!nm {VERSION_DEFAULT.vmlinux_path} | grep vfs_fsync" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[dwarf_funcs.py:231] INFO: Traversing 1/1: init/main.c\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0x0000000c compile_unit /build/linux-zdc93w/linux-6.8.0/init/main.c\n", + "0x0001b7ec subprogram fput (external)\n", + "0x0001b800 subprogram filp_open (external)\n", + "0x0001b821 subprogram free_reserved_area (external)\n", + "0x0001b847 subprogram add_device_randomness (external)\n", + "0x0001b85e subprogram __real_strlcat (external)\n", + "0x0001b884 subprogram strreplace (external)\n", + "0x0001b8a5 subprogram sprint_symbol_no_offset (external)\n", + "0x0001b8c1 subprogram strsep (external)\n", + "0x0001b8dd subprogram static_key_disable (external)\n", + "0x0001b8f4 subprogram static_key_enable (external)\n", + "0x0001b906 subprogram kstrtobool (external)\n", + "0x0001b922 subprogram get_option (external)\n", + "0x0001b93d subprogram bpf_trace_run2 (external)\n", + "0x0001b959 subprogram bpf_trace_run1 (external)\n", + "0x0001b970 subprogram trace_handle_return (external)\n", + "0x0001b98b subprogram trace_event_printf (external)\n", + "0x0001b9a4 subprogram trace_raw_output_prep (external)\n", + "0x0001b9bf subprogram __trace_trigger_soft_disabled (external)\n", + "0x0001b9d6 subprogram trace_event_buffer_commit (external)\n", + "0x0001b9ed subprogram trace_event_buffer_reserve (external)\n", + "0x0001ba0e subprogram perf_trace_run_bpf_submit (external)\n", + "0x0001ba43 subprogram perf_trace_buf_alloc (external)\n", + "0x0001ba69 subprogram trace_event_raw_init (external)\n", + "0x0001ba80 subprogram trace_event_reg (external)\n", + "0x0001baa1 subprogram __SCT__tp_func_initcall_finish (external)\n", + "0x0001bac1 subprogram __SCT__tp_func_initcall_start (external)\n", + "0x0001badc subprogram __rcu_read_unlock (external)\n", + "0x0001bae4 subprogram __rcu_read_lock (external)\n", + "0x0001baec subprogram kernel_execve (external)\n", + "0x0001bb11 subprogram __dynamic_pr_debug (external)\n", + "0x0001bb2a subprogram mark_rodata_ro (external)\n", + "0x0001bb32 subprogram rcu_barrier (external)\n", + "0x0001bb3b subprogram __compiletime_assert_269 (external)\n", + "0x0001bb44 subprogram __kmalloc (external)\n", + "0x0001bb60 subprogram kmalloc_trace (external)\n", + "0x0001bb81 subprogram kmalloc_large (external)\n", + "0x0001bb9d subprogram kfree (external)\n", + "0x0001bbaf subprogram init_irq_proc (external)\n", + "0x0001bbb9 subprogram driver_init (external)\n", + "0x0001bbc1 subprogram cpuset_init_smp (external)\n", + "0x0001bbc9 subprogram __SCT__tp_func_initcall_level (external)\n", + "0x0001bbe4 subprogram refcount_warn_saturate (external)\n", + "0x0001bc00 subprogram prepare_namespace (external)\n", + "0x0001bc08 subprogram wait_for_initramfs (external)\n", + "0x0001bc10 subprogram page_alloc_init_late (external)\n", + "0x0001bc19 subprogram sched_init_smp (external)\n", + "0x0001bc22 subprogram lockup_detector_init (external)\n", + "0x0001bc2b subprogram rcu_init_tasks_generic (external)\n", + "0x0001bc33 subprogram init_mm_internals (external)\n", + "0x0001bc3b subprogram do_sysctl_args (external)\n", + "0x0001bc43 subprogram rcu_end_inkernel_boot (external)\n", + "0x0001bc4c subprogram pti_finalize (external)\n", + "0x0001bc55 subprogram kgdb_free_init_mem (external)\n", + "0x0001bc5f subprogram ftrace_free_init_mem (external)\n", + "0x0001bc68 subprogram kprobe_free_init_mem (external)\n", + "0x0001bc72 subprogram async_synchronize_full (external)\n", + "0x0001bc7b subprogram wait_for_completion (external)\n", + "0x0001bc8d subprogram cpu_startup_entry (external)\n", + "0x0001bca1 subprogram schedule_preempt_disabled (external)\n", + "0x0001bcaa subprogram complete (external)\n", + "0x0001bcbc subprogram kthreadd (external)\n", + "0x0001bcd2 subprogram kernel_thread (external)\n", + "0x0001bcf7 subprogram numa_default_policy (external)\n", + "0x0001bcff subprogram set_cpus_allowed_ptr (external)\n", + "0x0001bd1b subprogram find_task_by_pid_ns (external)\n", + "0x0001bd37 subprogram user_mode_thread (external)\n", + "0x0001bd57 subprogram rcu_scheduler_starting (external)\n", + "0x0001bd60 subprogram get_random_u64 (external)\n", + "0x0001bd6d subprogram tracepoint_probe_register (external)\n", + "0x0001bd8d subprogram ktime_get (external)\n", + "0x0001bd9b subprogram sprintf (external)\n", + "0x0001bdb9 subprogram snprintf (external)\n", + "0x0001bddc subprogram memblock_alloc_try_nid (external)\n", + "0x0001be07 subprogram memblock_free (external)\n", + "0x0001be1e subprogram __read_overflow (external)\n", + "0x0001be26 subprogram parameqn (external)\n", + "0x0001be47 subprogram strncmp (external)\n", + "0x0001be68 subprogram strnchr (external)\n", + "0x0001be89 subprogram sysctl_is_alias (external)\n", + "0x0001be9f subprogram __read_overflow2_field (external)\n", + "0x0001beb6 subprogram __write_overflow_field (external)\n", + "0x0001becd subprogram __read_overflow2 (external)\n", + "0x0001bed5 subprogram acpi_subsystem_init (external)\n", + "0x0001bedf subprogram delayacct_init (external)\n", + "0x0001bee7 subprogram taskstats_init_early (external)\n", + "0x0001bef0 subprogram cgroup_init (external)\n", + "0x0001befd subprogram cpuset_init (external)\n", + "0x0001bf0a subprogram nsfs_init (external)\n", + "0x0001bf12 subprogram proc_root_init (external)\n", + "0x0001bf1b subprogram seq_file_init (external)\n", + "0x0001bf24 subprogram signals_init (external)\n", + "0x0001bf2e subprogram net_ns_init (external)\n", + "0x0001bf37 subprogram security_init (external)\n", + "0x0001bf43 subprogram key_init (external)\n", + "0x0001bf4c subprogram uts_ns_init (external)\n", + "0x0001bf54 subprogram proc_caches_init (external)\n", + "0x0001bf5c subprogram fork_init (external)\n", + "0x0001bf64 subprogram efi_enter_virtual_mode (external)\n", + "0x0001bf6d subprogram anon_vma_init (external)\n", + "0x0001bf75 subprogram pid_idr_init (external)\n", + "0x0001bf7d subprogram arch_cpu_finalize_init (external)\n", + "0x0001bf86 subprogram calibrate_delay (external)\n", + "0x0001bf8e subprogram sched_clock_init (external)\n", + "0x0001bf97 subprogram acpi_early_init (external)\n", + "0x0001bfa1 subprogram numa_policy_init (external)\n", + "0x0001bfa9 subprogram setup_per_cpu_pageset (external)\n", + "0x0001bfb2 subprogram panic (external)\n", + "0x0001bfc8 subprogram console_init (external)\n", + "0x0001bfd2 subprogram profile_init (external)\n", + "0x0001bfe0 subprogram perf_event_init (external)\n", + "0x0001bfe9 subprogram time_init (external)\n", + "0x0001bff1 subprogram timekeeping_init (external)\n", + "0x0001bffa subprogram softirq_init (external)\n", + "0x0001c004 subprogram srcu_init (external)\n", + "0x0001c00d subprogram init_timers (external)\n", + "0x0001c016 subprogram rcu_init_nohz (external)\n", + "0x0001c01e subprogram init_IRQ (external)\n", + "0x0001c026 subprogram early_irq_init (external)\n", + "0x0001c035 subprogram trace_init (external)\n", + "0x0001c03d subprogram rcu_init (external)\n", + "0x0001c045 subprogram maple_tree_init (external)\n", + "0x0001c04e subprogram radix_tree_init (external)\n", + "0x0001c057 subprogram __warn_printk (external)\n", + "0x0001c06b subprogram sched_init (external)\n", + "0x0001c074 subprogram early_trace_init (external)\n", + "0x0001c07c subprogram ftrace_init (external)\n", + "0x0001c085 subprogram mm_core_init (external)\n", + "0x0001c08d subprogram sort_main_extable (external)\n", + "0x0001c096 subprogram jump_label_init (external)\n", + "0x0001c09e subprogram boot_cpu_hotplug_init (external)\n", + "0x0001c0a7 subprogram setup_per_cpu_areas (external)\n", + "0x0001c0b0 subprogram setup_arch (external)\n", + "0x0001c0c2 subprogram early_security_init (external)\n", + "0x0001c0ce subprogram boot_cpu_init (external)\n", + "0x0001c0d7 subprogram cgroup_init_early (external)\n", + "0x0001c0e4 subprogram init_vmlinux_build_id (external)\n", + "0x0001c0ed subprogram set_task_stack_end_magic (external)\n", + "0x0001c101 subprogram _printk (external)\n", + "0x0001c119 subprogram strcmp (external)\n", + "0x0001c135 subprogram parameq (external)\n", + "0x0001c151 subprogram parse_args (external)\n", + "0x0001c18b subprogram __real_strnlen (external)\n", + "0x0001c1aa subprogram fortify_panic (external)\n", + "0x0001c1bd subprogram __write_overflow (external)\n", + "0x0001c1c5 subprogram __real_strscpy (external)\n", + "0x0001c1e9 subprogram console_on_rootfs (external)\n", + "0x0001c21b inlined_subroutine -> 0x000257c7 (IS_ERR)\n", + "0x0001c250 call_site -> 0x0001b800 (filp_open)\n", + "0x0001c279 call_site -> 0x00023148 (init_dup)\n", + "0x0001c291 call_site -> 0x00023148 (init_dup)\n", + "0x0001c2a9 call_site -> 0x00023148 (init_dup)\n", + "0x0001c2c1 call_site -> 0x0001b7ec (fput)\n", + "0x0001c2d9 call_site -> 0x0001c101 (_printk)\n", + "0x0001c2f5 subprogram kernel_init\n", + "0x0001c33f inlined_subroutine -> 0x00020785 (exit_boot_config)\n", + "0x0001c366 call_site -> 0x000248fc (xbc_exit)\n", + "0x0001c374 inlined_subroutine -> 0x0001c7a9 (mark_readonly)\n", + "0x0001c38f inlined_subroutine -> 0x00023176 (rodata_test)\n", + "0x0001c3b2 call_site -> 0x0001bb32 (rcu_barrier)\n", + "0x0001c3bf call_site -> 0x0001bb2a (mark_rodata_ro)\n", + "0x0001c3cc call_site -> 0x0001c101 (_printk)\n", + "0x0001c3eb call_site -> 0x00025e4d (__builtin___ubsan_handle_load_invalid_value)\n", + "0x0001c410 inlined_subroutine -> 0x0001d0b5 (try_to_run_init_process)\n", + "0x0001c438 lexical_block \n", + "0x0001c44e call_site -> 0x0001d0e2 (run_init_process)\n", + "0x0001c46a call_site -> 0x0001c101 (_printk)\n", + "0x0001c493 inlined_subroutine -> 0x0001d0b5 (try_to_run_init_process)\n", + "0x0001c4bb lexical_block \n", + "0x0001c4d1 call_site -> 0x0001d0e2 (run_init_process)\n", + "0x0001c4ed call_site -> 0x0001c101 (_printk)\n", + "0x0001c516 inlined_subroutine -> 0x0001d0b5 (try_to_run_init_process)\n", + "0x0001c53e lexical_block \n", + "0x0001c554 call_site -> 0x0001d0e2 (run_init_process)\n", + "0x0001c570 call_site -> 0x0001c101 (_printk)\n", + "0x0001c599 inlined_subroutine -> 0x0001d0b5 (try_to_run_init_process)\n", + "0x0001c5c1 lexical_block \n", + "0x0001c5d7 call_site -> 0x0001d0e2 (run_init_process)\n", + "0x0001c5f3 call_site -> 0x0001c101 (_printk)\n", + "0x0001c61c call_site -> 0x0001bc7b (wait_for_completion)\n", + "0x0001c63b call_site -> 0x0001c851 (kernel_init_freeable)\n", + "0x0001c648 call_site -> 0x0001bc72 (async_synchronize_full)\n", + "0x0001c655 call_site -> 0x0001bc68 (kprobe_free_init_mem)\n", + "0x0001c662 call_site -> 0x0001bc5f (ftrace_free_init_mem)\n", + "0x0001c66f call_site -> 0x0001bc55 (kgdb_free_init_mem)\n", + "0x0001c67c call_site -> 0x0001c731 (free_initmem)\n", + "0x0001c689 call_site -> 0x0001bc4c (pti_finalize)\n", + "0x0001c696 call_site -> 0x0001bcf7 (numa_default_policy)\n", + "0x0001c6a3 call_site -> 0x0001bc43 (rcu_end_inkernel_boot)\n", + "0x0001c6b0 call_site -> 0x0001bc3b (do_sysctl_args)\n", + "0x0001c6bd call_site -> 0x0001d0e2 (run_init_process)\n", + "0x0001c6ca call_site -> 0x0001c101 (_printk)\n", + "0x0001c6e9 call_site -> 0x0001d0e2 (run_init_process)\n", + "0x0001c6f6 call_site -> 0x0001bfb2 (panic)\n", + "0x0001c715 call_site -> 0x0001bfb2 (panic)\n", + "0x0001c731 subprogram free_initmem (external)\n", + "0x0001c74f inlined_subroutine -> 0x00024b94 (free_initmem_default)\n", + "0x0001c774 lexical_block \n", + "0x0001c785 call_site -> 0x0001b821 (free_reserved_area)\n", + "0x0001c7a9 subprogram mark_readonly\n", + "0x0001c7b4 subprogram set_debug_rodata\n", + "0x0001c7ea call_site -> 0x0001c119 (strcmp)\n", + "0x0001c80f call_site -> 0x0001c101 (_printk)\n", + "0x0001c831 subprogram arch_parse_debug_rodata\n", + "0x0001c851 subprogram kernel_init_freeable\n", + "0x0001c871 inlined_subroutine -> 0x0002594f (get_current)\n", + "0x0001c898 lexical_block -> 0x00025960 ()\n", + "0x0001c8ba lexical_block -> 0x000259b5 ()\n", + "0x0001c8df inlined_subroutine -> 0x00024d51 (task_pid)\n", + "0x0001c914 inlined_subroutine -> 0x00024d6f (get_pid)\n", + "0x0001c93c inlined_subroutine -> 0x00024e8b (refcount_inc)\n", + "0x0001c95f inlined_subroutine -> 0x00024ea2 (__refcount_inc)\n", + "0x0001c991 inlined_subroutine -> 0x00024ec5 (__refcount_add)\n", + "0x0001c9ce lexical_block \n", + "0x0001c9e0 inlined_subroutine -> 0x00025403 (atomic_fetch_add_relaxed)\n", + "0x0001ca20 inlined_subroutine -> 0x0002542e (raw_atomic_fetch_add_relaxed)\n", + "0x0001ca5c inlined_subroutine -> 0x00025457 (arch_atomic_fetch_add)\n", + "0x0001ca99 lexical_block -> 0x0002547c ()\n", + "0x0001cabf call_site -> 0x0001bbe4 (refcount_warn_saturate)\n", + "0x0001cadc call_site -> 0x0001bbe4 (refcount_warn_saturate)\n", + "0x0001cafa inlined_subroutine -> 0x00025091 (smp_prepare_cpus)\n", + "0x0001cb23 inlined_subroutine -> 0x0001d533 (do_pre_smp_initcalls)\n", + "0x0001cb3e lexical_block \n", + "0x0001cb50 inlined_subroutine -> 0x0002300f (trace_initcall_level)\n", + "0x0001cb78 inlined_subroutine -> 0x000259e4 (static_key_false)\n", + "0x0001cb9f inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001cbcf lexical_block \n", + "0x0001cbe4 lexical_block -> 0x00023027 ()\n", + "0x0001cc0a lexical_block -> 0x00023038 ()\n", + "0x0001cc30 lexical_block -> 0x0002307f ()\n", + "0x0001cc54 inlined_subroutine -> 0x00025348 (cpu_online)\n", + "0x0001cc87 inlined_subroutine -> 0x00025393 (cpumask_test_cpu)\n", + "0x0001ccbc inlined_subroutine -> 0x000257e5 (_test_bit)\n", + "0x0001ccf1 inlined_subroutine -> 0x00025864 (arch_test_bit)\n", + "0x0001cd25 inlined_subroutine -> 0x0002588d (variable_test_bit)\n", + "0x0001cd4d lexical_block \n", + "0x0001cd5d inlined_subroutine -> 0x000250d0 (__preempt_count_add)\n", + "0x0001cd90 lexical_block -> 0x000250e8 ()\n", + "0x0001cdb4 lexical_block -> 0x000230c0 ()\n", + "0x0001cde3 lexical_block -> 0x000230dd ()\n", + "0x0001ce09 lexical_block -> 0x000230ee ()\n", + "0x0001ce1f call_site -> 0x0001bbc9 (__SCT__tp_func_initcall_level)\n", + "0x0001ce3c inlined_subroutine -> 0x0002300f (trace_initcall_level)\n", + "0x0001ce6b lexical_block -> 0x00023027 ()\n", + "0x0001ce85 inlined_subroutine -> 0x000250b2 (__preempt_count_dec_and_test)\n", + "0x0001ceab lexical_block -> 0x000250c3 ()\n", + "0x0001cec7 lexical_block -> 0x00023112 ()\n", + "0x0001cedf inlined_subroutine -> 0x00025c19 (initcall_from_entry)\n", + "0x0001cf13 inlined_subroutine -> 0x00025dca (offset_to_ptr)\n", + "0x0001cf44 call_site -> 0x0001dd51 (do_one_initcall)\n", + "0x0001cf53 inlined_subroutine -> 0x0001d54e (do_basic_setup)\n", + "0x0001cf7a inlined_subroutine -> 0x0001f266 (do_ctors)\n", + "0x0001cfaf call_site -> 0x0001bbc1 (cpuset_init_smp)\n", + "0x0001cfbc call_site -> 0x0001bbb9 (driver_init)\n", + "0x0001cfc9 call_site -> 0x0001bbaf (init_irq_proc)\n", + "0x0001cfd6 call_site -> 0x0001d559 (do_initcalls)\n", + "0x0001cfe4 call_site -> 0x000231d5 (set_mems_allowed)\n", + "0x0001cff1 call_site -> 0x00024dce (workqueue_init)\n", + "0x0001cffe call_site -> 0x0001bc33 (init_mm_internals)\n", + "0x0001d00b call_site -> 0x0001bc2b (rcu_init_tasks_generic)\n", + "0x0001d018 call_site -> 0x0001bc22 (lockup_detector_init)\n", + "0x0001d025 call_site -> 0x00025079 (smp_init)\n", + "0x0001d032 call_site -> 0x0001bc19 (sched_init_smp)\n", + "0x0001d03f call_site -> 0x00024dc5 (workqueue_init_topology)\n", + "0x0001d04c call_site -> 0x0002319a (padata_init)\n", + "0x0001d059 call_site -> 0x0001bc10 (page_alloc_init_late)\n", + "0x0001d066 call_site -> 0x0001bc08 (wait_for_initramfs)\n", + "0x0001d073 call_site -> 0x0001c1e9 (console_on_rootfs)\n", + "0x0001d080 call_site -> 0x0002315f (init_eaccess)\n", + "0x0001d08d call_site -> 0x0002317e (integrity_load_keys)\n", + "0x0001d09a call_site -> 0x0001bc00 (prepare_namespace)\n", + "0x0001d0a7 call_site -> 0x0002317e (integrity_load_keys)\n", + "0x0001d0b5 subprogram try_to_run_init_process\n", + "0x0001d0e2 subprogram run_init_process\n", + "0x0001d134 lexical_block \n", + "0x0001d160 lexical_block \n", + "0x0001d175 subprogram __compiletime_assert_514 (external)\n", + "0x0001d17f lexical_block \n", + "0x0001d1a8 inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001d1ed call_site -> 0x0001bb11 (__dynamic_pr_debug)\n", + "0x0001d216 lexical_block \n", + "0x0001d242 lexical_block \n", + "0x0001d257 subprogram __compiletime_assert_516 (external)\n", + "0x0001d261 lexical_block \n", + "0x0001d28a inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001d2d6 call_site -> 0x0001bb11 (__dynamic_pr_debug)\n", + "0x0001d2ff lexical_block \n", + "0x0001d32b lexical_block \n", + "0x0001d340 subprogram __compiletime_assert_518 (external)\n", + "0x0001d34a lexical_block \n", + "0x0001d373 inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001d3b8 call_site -> 0x0001bb11 (__dynamic_pr_debug)\n", + "0x0001d3e1 lexical_block \n", + "0x0001d40d lexical_block \n", + "0x0001d422 subprogram __compiletime_assert_520 (external)\n", + "0x0001d42c lexical_block \n", + "0x0001d455 inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001d4a1 call_site -> 0x0001bb11 (__dynamic_pr_debug)\n", + "0x0001d4ca call_site -> 0x0001c101 (_printk)\n", + "0x0001d4ef call_site -> 0x0001baec (kernel_execve)\n", + "0x0001d533 subprogram do_pre_smp_initcalls\n", + "0x0001d54e subprogram do_basic_setup\n", + "0x0001d559 subprogram do_initcalls\n", + "0x0001d5c8 lexical_block \n", + "0x0001d5d1 inlined_subroutine -> 0x0001dcbd (do_initcall_level)\n", + "0x0001d606 lexical_block \n", + "0x0001d618 inlined_subroutine -> 0x0002300f (trace_initcall_level)\n", + "0x0001d640 inlined_subroutine -> 0x000259e4 (static_key_false)\n", + "0x0001d667 inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001d697 lexical_block \n", + "0x0001d6ac lexical_block -> 0x00023027 ()\n", + "0x0001d6d2 lexical_block -> 0x00023038 ()\n", + "0x0001d6f8 lexical_block -> 0x0002307f ()\n", + "0x0001d71c inlined_subroutine -> 0x00025348 (cpu_online)\n", + "0x0001d74f inlined_subroutine -> 0x00025393 (cpumask_test_cpu)\n", + "0x0001d784 inlined_subroutine -> 0x000257e5 (_test_bit)\n", + "0x0001d7b9 inlined_subroutine -> 0x00025864 (arch_test_bit)\n", + "0x0001d7ed inlined_subroutine -> 0x0002588d (variable_test_bit)\n", + "0x0001d815 lexical_block \n", + "0x0001d825 inlined_subroutine -> 0x000250d0 (__preempt_count_add)\n", + "0x0001d858 lexical_block -> 0x000250e8 ()\n", + "0x0001d87c lexical_block -> 0x000230c0 ()\n", + "0x0001d8ab lexical_block -> 0x000230dd ()\n", + "0x0001d8d1 lexical_block -> 0x000230ee ()\n", + "0x0001d8e7 call_site -> 0x0001bbc9 (__SCT__tp_func_initcall_level)\n", + "0x0001d8f6 inlined_subroutine -> 0x0002300f (trace_initcall_level)\n", + "0x0001d91d lexical_block -> 0x00023027 ()\n", + "0x0001d937 inlined_subroutine -> 0x000250b2 (__preempt_count_dec_and_test)\n", + "0x0001d95d lexical_block -> 0x000250c3 ()\n", + "0x0001d979 lexical_block -> 0x00023112 ()\n", + "0x0001d991 inlined_subroutine -> 0x00025c19 (initcall_from_entry)\n", + "0x0001d9c5 inlined_subroutine -> 0x00025dca (offset_to_ptr)\n", + "0x0001d9f6 call_site -> 0x0001c151 (parse_args)\n", + "0x0001da23 call_site -> 0x0001dd51 (do_one_initcall)\n", + "0x0001da30 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x0001da55 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x0001da7a call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x0001da9f call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x0001dac4 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x0001dae1 inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001db0b lexical_block \n", + "0x0001db37 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001db7d call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001db92 call_site -> 0x00025e6b (__builtin_memcpy)\n", + "0x0001dbb0 call_site -> 0x0001c1aa (fortify_panic)\n", + "0x0001dbce inlined_subroutine -> 0x00024c0c (kzalloc)\n", + "0x0001dc10 inlined_subroutine -> 0x00024c39 (kmalloc)\n", + "0x0001dc42 call_site -> 0x0001bb44 (__kmalloc)\n", + "0x0001dc60 call_site -> 0x0001bb9d (kfree)\n", + "0x0001dc78 call_site -> 0x0001bfb2 (panic)\n", + "0x0001dcbd subprogram do_initcall_level\n", + "0x0001dcf2 subprogram ignore_unknown_bootoption\n", + "0x0001dd51 subprogram do_one_initcall (external)\n", + "0x0001ddc0 lexical_block \n", + "0x0001dddd lexical_block \n", + "0x0001ddfd lexical_block \n", + "0x0001de1d inlined_subroutine -> 0x000252d8 (arch_local_save_flags)\n", + "0x0001de44 lexical_block -> 0x000252ea ()\n", + "0x0001de7a lexical_block -> 0x0002532c ()\n", + "0x0001de9c lexical_block -> 0x0002533a ()\n", + "0x0001deb4 inlined_subroutine -> 0x000251d2 (arch_irqs_disabled_flags)\n", + "0x0001dee6 lexical_block \n", + "0x0001df03 lexical_block \n", + "0x0001df21 call_site -> 0x0001c057 (__warn_printk)\n", + "0x0001df49 inlined_subroutine -> 0x00025199 (preempt_count)\n", + "0x0001df70 lexical_block -> 0x000251aa ()\n", + "0x0001df94 inlined_subroutine -> 0x00022ed6 (trace_initcall_start)\n", + "0x0001dfbc inlined_subroutine -> 0x000259e4 (static_key_false)\n", + "0x0001dfe3 inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001e013 lexical_block \n", + "0x0001e028 lexical_block -> 0x00022eee ()\n", + "0x0001e04a lexical_block -> 0x00022eff ()\n", + "0x0001e070 lexical_block -> 0x00022f46 ()\n", + "0x0001e094 inlined_subroutine -> 0x00025348 (cpu_online)\n", + "0x0001e0c7 inlined_subroutine -> 0x00025393 (cpumask_test_cpu)\n", + "0x0001e0fc inlined_subroutine -> 0x000257e5 (_test_bit)\n", + "0x0001e131 inlined_subroutine -> 0x00025864 (arch_test_bit)\n", + "0x0001e165 inlined_subroutine -> 0x0002588d (variable_test_bit)\n", + "0x0001e18d lexical_block \n", + "0x0001e19d inlined_subroutine -> 0x000250d0 (__preempt_count_add)\n", + "0x0001e1d0 lexical_block -> 0x000250e8 ()\n", + "0x0001e1f4 lexical_block -> 0x00022f87 ()\n", + "0x0001e227 lexical_block -> 0x00022fa4 ()\n", + "0x0001e24d lexical_block -> 0x00022fb5 ()\n", + "0x0001e263 call_site -> 0x0001bac1 (__SCT__tp_func_initcall_start)\n", + "0x0001e278 inlined_subroutine -> 0x000250b2 (__preempt_count_dec_and_test)\n", + "0x0001e29e lexical_block -> 0x000250c3 ()\n", + "0x0001e2ba lexical_block -> 0x00022fd9 ()\n", + "0x0001e2d1 inlined_subroutine -> 0x00022d67 (trace_initcall_finish)\n", + "0x0001e306 inlined_subroutine -> 0x000259e4 (static_key_false)\n", + "0x0001e32d inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001e35d lexical_block \n", + "0x0001e372 lexical_block -> 0x00022d8b ()\n", + "0x0001e394 lexical_block -> 0x00022d9c ()\n", + "0x0001e3ba lexical_block -> 0x00022de3 ()\n", + "0x0001e3de inlined_subroutine -> 0x00025348 (cpu_online)\n", + "0x0001e411 inlined_subroutine -> 0x00025393 (cpumask_test_cpu)\n", + "0x0001e446 inlined_subroutine -> 0x000257e5 (_test_bit)\n", + "0x0001e47b inlined_subroutine -> 0x00025864 (arch_test_bit)\n", + "0x0001e4af inlined_subroutine -> 0x0002588d (variable_test_bit)\n", + "0x0001e4d7 lexical_block \n", + "0x0001e4e7 inlined_subroutine -> 0x000250d0 (__preempt_count_add)\n", + "0x0001e51a lexical_block -> 0x000250e8 ()\n", + "0x0001e53e lexical_block -> 0x00022e24 ()\n", + "0x0001e571 lexical_block -> 0x00022e41 ()\n", + "0x0001e597 lexical_block -> 0x00022e52 ()\n", + "0x0001e5ad call_site -> 0x0001baa1 (__SCT__tp_func_initcall_finish)\n", + "0x0001e5c8 inlined_subroutine -> 0x000250b2 (__preempt_count_dec_and_test)\n", + "0x0001e5ee lexical_block -> 0x000250c3 ()\n", + "0x0001e60a lexical_block -> 0x00022e76 ()\n", + "0x0001e621 inlined_subroutine -> 0x00025199 (preempt_count)\n", + "0x0001e63c lexical_block -> 0x000251aa ()\n", + "0x0001e655 inlined_subroutine -> 0x00024f24 (add_latent_entropy)\n", + "0x0001e67c call_site -> 0x0001b847 (add_device_randomness)\n", + "0x0001e695 inlined_subroutine -> 0x000255a7 (strlcat)\n", + "0x0001e6d7 lexical_block \n", + "0x0001e72a inlined_subroutine -> 0x00025716 (strnlen)\n", + "0x0001e75c lexical_block \n", + "0x0001e780 call_site -> 0x0001c18b (__real_strnlen)\n", + "0x0001e79e call_site -> 0x0001c1aa (fortify_panic)\n", + "0x0001e7bd inlined_subroutine -> 0x00025234 (arch_local_irq_enable)\n", + "0x0001e7e4 lexical_block -> 0x00025242 ()\n", + "0x0001e814 inlined_subroutine -> 0x00025125 (preempt_count_set)\n", + "0x0001e862 lexical_block -> 0x00025154 ()\n", + "0x0001e889 lexical_block -> 0x00025166 ()\n", + "0x0001e8cc call_site -> 0x0001eb48 (initcall_blacklisted)\n", + "0x0001e8e4 call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x0001e8f2 subprogram trace_initcall_finish_cb\n", + "0x0001e974 inlined_subroutine -> 0x00024de9 (ktime_us_delta)\n", + "0x0001e9a9 inlined_subroutine -> 0x00024e13 (ktime_to_us)\n", + "0x0001e9cc inlined_subroutine -> 0x00024e30 (ktime_divns)\n", + "0x0001e9ff call_site -> 0x0001bd8d (ktime_get)\n", + "0x0001ea0c call_site -> 0x0001c101 (_printk)\n", + "0x0001ea39 subprogram trace_initcall_start_cb\n", + "0x0001ea93 inlined_subroutine -> 0x0002594f (get_current)\n", + "0x0001eaae lexical_block -> 0x00025960 ()\n", + "0x0001eac5 lexical_block -> 0x000259b5 ()\n", + "0x0001eadf inlined_subroutine -> 0x00024d33 (task_pid_nr)\n", + "0x0001eb14 call_site -> 0x0001c101 (_printk)\n", + "0x0001eb3a call_site -> 0x0001bd8d (ktime_get)\n", + "0x0001eb48 subprogram initcall_blacklisted\n", + "0x0001ebbf lexical_block \n", + "0x0001ebe9 lexical_block \n", + "0x0001ec15 lexical_block \n", + "0x0001ec2a subprogram __compiletime_assert_512 (external)\n", + "0x0001ec34 lexical_block \n", + "0x0001ec5d inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001eca9 call_site -> 0x0001bb11 (__dynamic_pr_debug)\n", + "0x0001ecd8 lexical_block \n", + "0x0001ed02 inlined_subroutine -> 0x00025c65 (list_empty)\n", + "0x0001ed36 lexical_block -> 0x00025c84 ()\n", + "0x0001ed4c call_site -> 0x0001b8a5 (sprint_symbol_no_offset)\n", + "0x0001ed6b call_site -> 0x0001b884 (strreplace)\n", + "0x0001ed8e call_site -> 0x0001c119 (strcmp)\n", + "0x0001eda6 call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x0001ede0 subprogram initcall_blacklist\n", + "0x0001ee52 lexical_block \n", + "0x0001ee7e lexical_block \n", + "0x0001ee93 subprogram __compiletime_assert_510 (external)\n", + "0x0001ee9d lexical_block \n", + "0x0001eec6 inlined_subroutine -> 0x00025a02 (arch_static_branch)\n", + "0x0001ef12 call_site -> 0x0001bb11 (__dynamic_pr_debug)\n", + "0x0001ef41 inlined_subroutine -> 0x00024a32 (memblock_alloc)\n", + "0x0001ef82 call_site -> 0x0001bddc (memblock_alloc_try_nid)\n", + "0x0001efac inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001eff2 call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001f007 inlined_subroutine -> 0x00024a32 (memblock_alloc)\n", + "0x0001f03c call_site -> 0x0001bddc (memblock_alloc_try_nid)\n", + "0x0001f061 inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001f0c1 call_site -> 0x00025e7f (__builtin_strcpy)\n", + "0x0001f0d6 inlined_subroutine -> 0x00025c95 (list_add)\n", + "0x0001f117 inlined_subroutine -> 0x00025cba (__list_add)\n", + "0x0001f160 lexical_block -> 0x00025cea ()\n", + "0x0001f177 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001f1bd call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001f1d2 call_site -> 0x0001b8c1 (strsep)\n", + "0x0001f1f7 call_site -> 0x0001bfb2 (panic)\n", + "0x0001f223 call_site -> 0x0001bfb2 (panic)\n", + "0x0001f266 subprogram do_ctors\n", + "0x0001f281 subprogram print_unknown_bootoptions\n", + "0x0001f302 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001f348 call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001f356 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001f37e lexical_block \n", + "0x0001f395 call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001f3ab inlined_subroutine -> 0x00024a32 (memblock_alloc)\n", + "0x0001f3ec call_site -> 0x0001bddc (memblock_alloc_try_nid)\n", + "0x0001f417 call_site -> 0x0001bd9b (sprintf)\n", + "0x0001f43c call_site -> 0x0001bd9b (sprintf)\n", + "0x0001f461 call_site -> 0x0001c101 (_printk)\n", + "0x0001f486 call_site -> 0x0001be07 (memblock_free)\n", + "0x0001f4a4 call_site -> 0x0001c101 (_printk)\n", + "0x0001f4e8 subprogram early_randomize_kstack_offset\n", + "0x0001f541 call_site -> 0x0001b906 (kstrtobool)\n", + "0x0001f560 call_site -> 0x0001b8f4 (static_key_enable)\n", + "0x0001f57f call_site -> 0x0001b8dd (static_key_disable)\n", + "0x0001f58c call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x0001f599 call_site -> 0x00025e4d (__builtin___ubsan_handle_load_invalid_value)\n", + "0x0001f5be subprogram initcall_debug_enable\n", + "0x0001f5d9 lexical_block \n", + "0x0001f5e7 lexical_block \n", + "0x0001f5f8 subprogram trap_init (external)\n", + "0x0001f612 subprogram thread_stack_cache_init (external)\n", + "0x0001f62c subprogram smp_setup_processor_id (external)\n", + "0x0001f646 subprogram arch_post_acpi_subsys_init (external)\n", + "0x0001f660 subprogram do_early_param\n", + "0x0001f6e4 call_site -> 0x0001c119 (strcmp)\n", + "0x0001f709 call_site -> 0x0001c119 (strcmp)\n", + "0x0001f728 call_site \n", + "0x0001f73d call_site -> 0x0001c135 (parameq)\n", + "0x0001f755 call_site \n", + "0x0001f76a call_site -> 0x0001c101 (_printk)\n", + "0x0001f791 subprogram setup_command_line\n", + "0x0001f814 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001f85a call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001f868 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001f8ae call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001f8bc inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001f8e4 lexical_block \n", + "0x0001f903 inlined_subroutine -> 0x00025716 (strnlen)\n", + "0x0001f937 lexical_block \n", + "0x0001f95b call_site -> 0x0001c18b (__real_strnlen)\n", + "0x0001f981 call_site -> 0x0001c1aa (fortify_panic)\n", + "0x0001f99e call_site -> 0x0001c1aa (fortify_panic)\n", + "0x0001f9bb inlined_subroutine -> 0x00024a32 (memblock_alloc)\n", + "0x0001f9f0 call_site -> 0x0001bddc (memblock_alloc_try_nid)\n", + "0x0001fa1b inlined_subroutine -> 0x00024a32 (memblock_alloc)\n", + "0x0001fa50 call_site -> 0x0001bddc (memblock_alloc_try_nid)\n", + "0x0001fa7b inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001fab0 lexical_block \n", + "0x0001fadc inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001fb01 lexical_block \n", + "0x0001fb20 inlined_subroutine -> 0x00025716 (strnlen)\n", + "0x0001fb50 lexical_block \n", + "0x0001fb74 call_site -> 0x0001c18b (__real_strnlen)\n", + "0x0001fb9c inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001fbd1 lexical_block \n", + "0x0001fbf5 call_site -> 0x00025e7f (__builtin_strcpy)\n", + "0x0001fc0b inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001fc40 lexical_block \n", + "0x0001fc64 call_site -> 0x00025e7f (__builtin_strcpy)\n", + "0x0001fc7a inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001fcaf lexical_block \n", + "0x0001fcdb inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001fd03 lexical_block \n", + "0x0001fd22 inlined_subroutine -> 0x00025716 (strnlen)\n", + "0x0001fd62 lexical_block \n", + "0x0001fd8e call_site -> 0x0001c18b (__real_strnlen)\n", + "0x0001fdaa call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001fdc0 call_site -> 0x00025e6b (__builtin_memcpy)\n", + "0x0001fddc inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001fe22 call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001fe30 inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001fe90 call_site -> 0x00025e7f (__builtin_strcpy)\n", + "0x0001fea5 inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001ff05 call_site -> 0x00025e7f (__builtin_strcpy)\n", + "0x0001ff20 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0001ff66 call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0001ff7b inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x0001ffb0 lexical_block \n", + "0x0001ffde inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x00020013 lexical_block \n", + "0x00020037 call_site -> 0x00025e7f (__builtin_strcpy)\n", + "0x0002004d call_site -> 0x0001bfb2 (panic)\n", + "0x0002007f call_site -> 0x0001bfb2 (panic)\n", + "0x000200ae subprogram rdinit_setup\n", + "0x000200f6 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x00020112 subprogram init_setup\n", + "0x0002015a call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x00020176 subprogram unknown_bootoption\n", + "0x000201fc lexical_block \n", + "0x00020217 call_site -> 0x0001be47 (strncmp)\n", + "0x0002023b call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x00020260 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x00020285 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x000202a7 lexical_block \n", + "0x000202c2 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x000202e7 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x00020309 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x00020331 lexical_block \n", + "0x00020348 call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0002035e inlined_subroutine -> 0x000212c3 (obsolete_checksetup)\n", + "0x00020386 lexical_block \n", + "0x000203a5 lexical_block -> 0x000212f6 ()\n", + "0x000203c0 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x00020405 call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x0002041a call_site -> 0x0001be26 (parameqn)\n", + "0x0002043e call_site \n", + "0x00020453 call_site -> 0x0001c101 (_printk)\n", + "0x00020470 call_site -> 0x0001be89 (sysctl_is_alias)\n", + "0x00020488 call_site -> 0x000205a5 (repair_env_string)\n", + "0x000204a6 call_site -> 0x0001be68 (strnchr)\n", + "0x000204c8 subprogram set_init_arg\n", + "0x0002054c call_site -> 0x000205a5 (repair_env_string)\n", + "0x00020564 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x00020583 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x000205a5 subprogram repair_env_string\n", + "0x000205ec lexical_block \n", + "0x00020659 lexical_block \n", + "0x0002066b lexical_block \n", + "0x00020698 lexical_block \n", + "0x000206a6 lexical_block \n", + "0x000206b7 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x000206fd call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x00020712 call_site -> 0x00025e93 (__builtin_memmove)\n", + "0x0002072d inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x0002076f call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x00020785 subprogram exit_boot_config\n", + "0x00020790 subprogram setup_boot_config\n", + "0x00020833 inlined_subroutine -> 0x00021181 (get_boot_config_from_initrd)\n", + "0x0002085b lexical_block \n", + "0x000208b2 inlined_subroutine -> 0x000254ee (memcmp)\n", + "0x000208f4 lexical_block \n", + "0x00020915 inlined_subroutine -> 0x000249f2 (xbc_calc_checksum)\n", + "0x0002095d call_site -> 0x0001c101 (_printk)\n", + "0x0002097c call_site -> 0x0001c101 (_printk)\n", + "0x00020998 inlined_subroutine -> 0x00025638 (strscpy)\n", + "0x000209da lexical_block \n", + "0x00020a06 inlined_subroutine -> 0x00025716 (strnlen)\n", + "0x00020a1e lexical_block \n", + "0x00020a3a call_site -> 0x0001c18b (__real_strnlen)\n", + "0x00020a60 call_site -> 0x0001c1aa (fortify_panic)\n", + "0x00020a7d call_site -> 0x0001c1c5 (__real_strscpy)\n", + "0x00020aa7 inlined_subroutine -> 0x000257c7 (IS_ERR)\n", + "0x00020adc call_site -> 0x0001c151 (parse_args)\n", + "0x00020b1c call_site -> 0x00024921 (xbc_init)\n", + "0x00020b47 call_site -> 0x0001c101 (_printk)\n", + "0x00020b66 call_site -> 0x00024905 (xbc_get_info)\n", + "0x00020b84 call_site -> 0x0001c101 (_printk)\n", + "0x00020ba9 call_site -> 0x00020d70 (xbc_make_cmdline)\n", + "0x00020bc8 call_site -> 0x00020d70 (xbc_make_cmdline)\n", + "0x00020be7 call_site -> 0x00025e4d (__builtin___ubsan_handle_load_invalid_value)\n", + "0x00020c0c call_site -> 0x00025e4d (__builtin___ubsan_handle_load_invalid_value)\n", + "0x00020c31 call_site -> 0x0001c101 (_printk)\n", + "0x00020c50 call_site -> 0x0001c101 (_printk)\n", + "0x00020c7c call_site -> 0x0001c101 (_printk)\n", + "0x00020c9b call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x00020ca9 subprogram warn_bootconfig\n", + "0x00020cdb subprogram bootconfig_params\n", + "0x00020d4d call_site -> 0x0001c119 (strcmp)\n", + "0x00020d70 subprogram xbc_make_cmdline\n", + "0x00020df6 inlined_subroutine -> 0x0002496d (xbc_find_node)\n", + "0x00020e1e call_site -> 0x000249ab (xbc_node_find_subkey)\n", + "0x00020e39 inlined_subroutine -> 0x00024a32 (memblock_alloc)\n", + "0x00020e6e call_site -> 0x0001bddc (memblock_alloc_try_nid)\n", + "0x00020e99 call_site -> 0x00020f3d (xbc_snprint_cmdline)\n", + "0x00020ebb call_site -> 0x00020f3d (xbc_snprint_cmdline)\n", + "0x00020edf call_site -> 0x0001c101 (_printk)\n", + "0x00020efe call_site -> 0x0001be07 (memblock_free)\n", + "0x00020f1c call_site -> 0x0001c101 (_printk)\n", + "0x00020f3d subprogram xbc_snprint_cmdline\n", + "0x00020ffb call_site -> 0x0002498b (xbc_node_find_next_key_value)\n", + "0x0002101a call_site -> 0x00024947 (xbc_node_compose_key_after)\n", + "0x00021046 call_site -> 0x000249dc (xbc_node_get_child)\n", + "0x00021053 call_site -> 0x0001bdb9 (snprintf)\n", + "0x000210af call_site -> 0x0002498b (xbc_node_find_next_key_value)\n", + "0x000210ce call_site -> 0x000249c6 (xbc_node_get_data)\n", + "0x000210e6 call_site -> 0x0001bdb9 (snprintf)\n", + "0x00021143 call_site -> 0x000249dc (xbc_node_get_child)\n", + "0x0002115b call_site -> 0x000249c6 (xbc_node_get_data)\n", + "0x00021173 call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x00021181 subprogram get_boot_config_from_initrd\n", + "0x000211ea subprogram loglevel\n", + "0x00021231 call_site -> 0x0001b922 (get_option)\n", + "0x0002124f call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x0002125d subprogram quiet_kernel\n", + "0x00021290 subprogram debug_kernel\n", + "0x000212c3 subprogram obsolete_checksetup\n", + "0x000212f6 lexical_block \n", + "0x00021303 subprogram set_reset_devices\n", + "0x00021336 subprogram kunit_run_all_tests\n", + "0x00021346 subprogram __bpf_trace_initcall_finish\n", + "0x000213b1 lexical_block \n", + "0x000213e2 lexical_block \n", + "0x0002141e lexical_block \n", + "0x0002142b lexical_block \n", + "0x00021455 lexical_block \n", + "0x00021462 lexical_block \n", + "0x00021474 lexical_block \n", + "0x000214a5 lexical_block \n", + "0x000214e1 lexical_block \n", + "0x000214ee lexical_block \n", + "0x00021518 lexical_block \n", + "0x00021525 lexical_block \n", + "0x00021537 call_site -> 0x0001b93d (bpf_trace_run2)\n", + "0x00021561 subprogram __bpf_trace_initcall_start\n", + "0x000215b7 lexical_block \n", + "0x000215e8 lexical_block \n", + "0x00021624 lexical_block \n", + "0x00021631 lexical_block \n", + "0x0002165b lexical_block \n", + "0x00021668 lexical_block \n", + "0x0002167a call_site -> 0x0001b959 (bpf_trace_run1)\n", + "0x00021697 subprogram __bpf_trace_initcall_level\n", + "0x000216ed lexical_block \n", + "0x0002171e lexical_block \n", + "0x0002175a lexical_block \n", + "0x00021767 lexical_block \n", + "0x00021791 lexical_block \n", + "0x0002179e lexical_block \n", + "0x000217b0 call_site -> 0x0001b959 (bpf_trace_run1)\n", + "0x000217cd subprogram perf_trace_initcall_finish\n", + "0x000218c0 lexical_block \n", + "0x000218d2 lexical_block \n", + "0x000218f0 inlined_subroutine -> 0x000225e4 (trace_event_get_offsets_initcall_finish)\n", + "0x0002194d lexical_block -> 0x0002263d ()\n", + "0x00021962 lexical_block -> 0x0002263f ()\n", + "0x00021978 inlined_subroutine -> 0x00024b4d (bpf_prog_array_valid)\n", + "0x0002199f lexical_block -> 0x00024b6c ()\n", + "0x000219b5 inlined_subroutine -> 0x00024b78 (perf_fetch_caller_regs)\n", + "0x000219dd inlined_subroutine -> 0x00025c37 (hlist_empty)\n", + "0x00021a10 lexical_block -> 0x00025c54 ()\n", + "0x00021a26 call_site -> 0x0001ba43 (perf_trace_buf_alloc)\n", + "0x00021a4a call_site -> 0x0001ba0e (perf_trace_run_bpf_submit)\n", + "0x00021a6c call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x00021a7f subprogram perf_trace_initcall_start\n", + "0x00021b5c lexical_block \n", + "0x00021b6e lexical_block \n", + "0x00021b8c inlined_subroutine -> 0x00022647 (trace_event_get_offsets_initcall_start)\n", + "0x00021bdc lexical_block -> 0x00022694 ()\n", + "0x00021bf2 inlined_subroutine -> 0x00024b4d (bpf_prog_array_valid)\n", + "0x00021c19 lexical_block -> 0x00024b6c ()\n", + "0x00021c2f inlined_subroutine -> 0x00024b78 (perf_fetch_caller_regs)\n", + "0x00021c57 inlined_subroutine -> 0x00025c37 (hlist_empty)\n", + "0x00021c8a lexical_block -> 0x00025c54 ()\n", + "0x00021ca0 call_site -> 0x0001ba43 (perf_trace_buf_alloc)\n", + "0x00021cc3 call_site -> 0x0001ba0e (perf_trace_run_bpf_submit)\n", + "0x00021ce5 call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x00021cf8 subprogram perf_trace_initcall_level\n", + "0x00021dd8 lexical_block \n", + "0x00021dea lexical_block \n", + "0x00021e08 inlined_subroutine -> 0x0002269c (trace_event_get_offsets_initcall_level)\n", + "0x00021e3c lexical_block \n", + "0x00021e58 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x00021e7b lexical_block \n", + "0x00021e92 call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x00021eac inlined_subroutine -> 0x00024b4d (bpf_prog_array_valid)\n", + "0x00021ed3 lexical_block -> 0x00024b6c ()\n", + "0x00021ee9 inlined_subroutine -> 0x00024b78 (perf_fetch_caller_regs)\n", + "0x00021f11 inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x00021f45 lexical_block \n", + "0x00021f69 call_site -> 0x00025e7f (__builtin_strcpy)\n", + "0x00021f87 inlined_subroutine -> 0x00025c37 (hlist_empty)\n", + "0x00021fba lexical_block -> 0x00025c54 ()\n", + "0x00021fd0 call_site -> 0x0001ba43 (perf_trace_buf_alloc)\n", + "0x00021ff6 call_site -> 0x0001ba0e (perf_trace_run_bpf_submit)\n", + "0x00022027 call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x0002203a subprogram trace_event_raw_event_initcall_finish\n", + "0x000220e9 inlined_subroutine -> 0x00024b20 (trace_trigger_soft_disabled)\n", + "0x00022110 lexical_block \n", + "0x00022122 call_site -> 0x0001b9bf (__trace_trigger_soft_disabled)\n", + "0x00022138 inlined_subroutine -> 0x000225e4 (trace_event_get_offsets_initcall_finish)\n", + "0x0002219c lexical_block -> 0x0002263d ()\n", + "0x000221b1 lexical_block -> 0x0002263f ()\n", + "0x000221c7 call_site -> 0x0001b9ed (trace_event_buffer_reserve)\n", + "0x000221ea call_site -> 0x0001b9d6 (trace_event_buffer_commit)\n", + "0x00022202 call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x00022210 subprogram trace_event_raw_event_initcall_start\n", + "0x000222aa inlined_subroutine -> 0x00024b20 (trace_trigger_soft_disabled)\n", + "0x000222d1 lexical_block \n", + "0x000222e3 call_site -> 0x0001b9bf (__trace_trigger_soft_disabled)\n", + "0x000222f9 inlined_subroutine -> 0x00022647 (trace_event_get_offsets_initcall_start)\n", + "0x00022350 lexical_block -> 0x00022694 ()\n", + "0x00022366 call_site -> 0x0001b9ed (trace_event_buffer_reserve)\n", + "0x00022389 call_site -> 0x0001b9d6 (trace_event_buffer_commit)\n", + "0x000223a1 call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x000223af subprogram trace_event_raw_event_initcall_level\n", + "0x00022441 inlined_subroutine -> 0x00024b20 (trace_trigger_soft_disabled)\n", + "0x00022468 lexical_block \n", + "0x0002247a call_site -> 0x0001b9bf (__trace_trigger_soft_disabled)\n", + "0x00022490 inlined_subroutine -> 0x0002269c (trace_event_get_offsets_initcall_level)\n", + "0x000224c4 lexical_block \n", + "0x000224e0 inlined_subroutine -> 0x000256cf (__fortify_strlen)\n", + "0x00022503 lexical_block \n", + "0x0002251a call_site -> 0x00025e61 (__builtin_strlen)\n", + "0x00022532 inlined_subroutine -> 0x0002548b (strcpy)\n", + "0x00022566 lexical_block \n", + "0x0002258a call_site -> 0x00025e7f (__builtin_strcpy)\n", + "0x000225a0 call_site -> 0x0001b9ed (trace_event_buffer_reserve)\n", + "0x000225be call_site -> 0x0001b9d6 (trace_event_buffer_commit)\n", + "0x000225d6 call_site -> 0x00025e75 (__stack_chk_fail)\n", + "0x000225e4 subprogram trace_event_get_offsets_initcall_finish\n", + "0x0002263d lexical_block \n", + "0x0002263f lexical_block \n", + "0x00022647 subprogram trace_event_get_offsets_initcall_start\n", + "0x00022694 lexical_block \n", + "0x0002269c subprogram trace_event_get_offsets_initcall_level\n", + "0x000226ef subprogram trace_raw_output_initcall_finish\n", + "0x0002278e call_site -> 0x0001b9a4 (trace_raw_output_prep)\n", + "0x000227ad call_site -> 0x0001b98b (trace_event_printf)\n", + "0x000227d2 call_site -> 0x0001b970 (trace_handle_return)\n", + "0x000227e9 subprogram trace_raw_output_initcall_start\n", + "0x00022888 call_site -> 0x0001b9a4 (trace_raw_output_prep)\n", + "0x000228a7 call_site -> 0x0001b98b (trace_event_printf)\n", + "0x000228cc call_site -> 0x0001b970 (trace_handle_return)\n", + "0x000228e3 subprogram trace_raw_output_initcall_level\n", + "0x00022982 call_site -> 0x0001b9a4 (trace_raw_output_prep)\n", + "0x000229a1 call_site -> 0x0001b98b (trace_event_printf)\n", + "0x000229c6 call_site -> 0x0001b970 (trace_handle_return)\n", + "0x000229dd subprogram __probestub_initcall_finish (external)\n", + "0x00022a28 subprogram __traceiter_initcall_finish (external)\n", + "0x00022aaa lexical_block \n", + "0x00022ac7 lexical_block \n", + "0x00022ad9 subprogram __compiletime_assert_502 (external)\n", + "0x00022ae3 lexical_block \n", + "0x00022af8 subprogram __compiletime_assert_503 (external)\n", + "0x00022b01 call_site \n", + "0x00022b19 subprogram __probestub_initcall_start (external)\n", + "0x00022b55 subprogram __traceiter_initcall_start (external)\n", + "0x00022bc2 lexical_block \n", + "0x00022bdf lexical_block \n", + "0x00022bf1 subprogram __compiletime_assert_499 (external)\n", + "0x00022bfb lexical_block \n", + "0x00022c10 subprogram __compiletime_assert_500 (external)\n", + "0x00022c19 call_site \n", + "0x00022c2b subprogram __probestub_initcall_level (external)\n", + "0x00022c67 subprogram __traceiter_initcall_level (external)\n", + "0x00022cd4 lexical_block \n", + "0x00022cf1 lexical_block \n", + "0x00022d03 subprogram __compiletime_assert_496 (external)\n", + "0x00022d0d lexical_block \n", + "0x00022d22 subprogram __compiletime_assert_497 (external)\n", + "0x00022d2b call_site \n", + "0x00022d3d subprogram register_trace_initcall_finish\n", + "0x00022d67 subprogram trace_initcall_finish\n", + "0x00022d8b lexical_block \n", + "0x00022d9c lexical_block \n", + "0x00022dad lexical_block \n", + "0x00022dbf lexical_block \n", + "0x00022dd1 lexical_block \n", + "0x00022de3 lexical_block \n", + "0x00022df5 lexical_block \n", + "0x00022e04 lexical_block \n", + "0x00022e15 lexical_block \n", + "0x00022e24 lexical_block \n", + "0x00022e41 lexical_block \n", + "0x00022e52 lexical_block \n", + "0x00022e53 subprogram __compiletime_assert_488 (external)\n", + "0x00022e5d lexical_block \n", + "0x00022e76 lexical_block \n", + "0x00022e8f lexical_block \n", + "0x00022e9c lexical_block \n", + "0x00022eac subprogram register_trace_initcall_start\n", + "0x00022ed6 subprogram trace_initcall_start\n", + "0x00022eee lexical_block \n", + "0x00022eff lexical_block \n", + "0x00022f10 lexical_block \n", + "0x00022f22 lexical_block \n", + "0x00022f34 lexical_block \n", + "0x00022f46 lexical_block \n", + "0x00022f58 lexical_block \n", + "0x00022f67 lexical_block \n", + "0x00022f78 lexical_block \n", + "0x00022f87 lexical_block \n", + "0x00022fa4 lexical_block \n", + "0x00022fb5 lexical_block \n", + "0x00022fb6 subprogram __compiletime_assert_480 (external)\n", + "0x00022fc0 lexical_block \n", + "0x00022fd9 lexical_block \n", + "0x00022ff2 lexical_block \n", + "0x00022fff lexical_block \n", + "0x0002300f subprogram trace_initcall_level\n", + "0x00023027 lexical_block \n", + "0x00023038 lexical_block \n", + "0x00023049 lexical_block \n", + "0x0002305b lexical_block \n", + "0x0002306d lexical_block \n", + "0x0002307f lexical_block \n", + "0x00023091 lexical_block \n", + "0x000230a0 lexical_block \n", + "0x000230b1 lexical_block \n", + "0x000230c0 lexical_block \n", + "0x000230dd lexical_block \n", + "0x000230ee lexical_block \n", + "0x000230ef subprogram __compiletime_assert_472 (external)\n", + "0x000230f9 lexical_block \n", + "0x00023112 lexical_block \n", + "0x0002312b lexical_block \n", + "0x00023138 lexical_block \n", + "0x00023148 subprogram init_dup (external)\n", + "0x0002315f subprogram init_eaccess (external)\n", + "0x00023176 subprogram rodata_test\n", + "0x0002317e subprogram integrity_load_keys (external)\n", + "0x00023187 subprogram context_tracking_init\n", + "0x00023190 subprogram dbg_late_init (external)\n", + "0x0002319a subprogram padata_init (external)\n", + "0x000231a3 subprogram housekeeping_init (external)\n", + "0x000231ac subprogram tick_init (external)\n", + "0x000231b5 subprogram efi_enabled\n", + "0x000231d5 subprogram set_mems_allowed\n", + "0x00023217 lexical_block \n", + "0x00023235 lexical_block \n", + "0x00023251 lexical_block \n", + "0x0002326f inlined_subroutine -> 0x0002594f (get_current)\n", + "0x00023289 lexical_block -> 0x00025960 ()\n", + "0x000232a0 lexical_block -> 0x000259b5 ()\n", + "0x000232ba inlined_subroutine -> 0x00024d02 (task_lock)\n", + "0x000232ed inlined_subroutine -> 0x00025035 (spin_lock)\n", + "0x0002331c call_site -> 0x00025065 (_raw_spin_lock)\n", + "0x00023333 inlined_subroutine -> 0x00025216 (arch_local_irq_save)\n", + "0x00023366 inlined_subroutine -> 0x000252d8 (arch_local_save_flags)\n", + "0x0002338d lexical_block -> 0x000252ea ()\n", + "0x000233c3 lexical_block -> 0x0002532c ()\n", + "0x000233de lexical_block -> 0x0002533a ()\n", + "0x000233f6 inlined_subroutine -> 0x00025286 (arch_local_irq_disable)\n", + "0x00023419 lexical_block -> 0x00025294 ()\n", + "0x0002344a inlined_subroutine -> 0x0002594f (get_current)\n", + "0x00023470 lexical_block -> 0x00025960 ()\n", + "0x00023492 lexical_block -> 0x000259b5 ()\n", + "0x000234b7 inlined_subroutine -> 0x00024f4b (do_write_seqcount_begin)\n", + "0x000234ea inlined_subroutine -> 0x00024f65 (do_write_seqcount_begin_nested)\n", + "0x00023527 inlined_subroutine -> 0x00024fa6 (do_raw_write_seqcount_begin)\n", + "0x0002355a inlined_subroutine -> 0x0002594f (get_current)\n", + "0x00023580 lexical_block -> 0x00025960 ()\n", + "0x000235a2 lexical_block -> 0x000259b5 ()\n", + "0x000235c7 inlined_subroutine -> 0x0002594f (get_current)\n", + "0x000235ed lexical_block -> 0x00025960 ()\n", + "0x0002360f lexical_block -> 0x000259b5 ()\n", + "0x00023634 inlined_subroutine -> 0x00024f2c (do_write_seqcount_end)\n", + "0x00023667 inlined_subroutine -> 0x00024f8c (do_raw_write_seqcount_end)\n", + "0x00023699 inlined_subroutine -> 0x000251b9 (arch_local_irq_restore)\n", + "0x000236cc inlined_subroutine -> 0x000251d2 (arch_irqs_disabled_flags)\n", + "0x00023700 inlined_subroutine -> 0x00025234 (arch_local_irq_enable)\n", + "0x00023722 lexical_block -> 0x00025242 ()\n", + "0x00023753 inlined_subroutine -> 0x0002594f (get_current)\n", + "0x00023779 lexical_block -> 0x00025960 ()\n", + "0x0002379b lexical_block -> 0x000259b5 ()\n", + "0x000237c0 inlined_subroutine -> 0x00024ceb (task_unlock)\n", + "0x000237ef inlined_subroutine -> 0x00025019 (spin_unlock)\n", + "0x0002381e call_site -> 0x00025051 (_raw_spin_unlock)\n", + "0x0002382e subprogram kfence_init (external)\n", + "0x00023837 subprogram rest_init (external)\n", + "0x0002387e lexical_block \n", + "0x0002389b lexical_block \n", + "0x000238ae lexical_block \n", + "0x000238c1 lexical_block \n", + "0x000238d4 lexical_block \n", + "0x000238f2 lexical_block \n", + "0x00023902 inlined_subroutine -> 0x00024e80 (rcu_read_lock)\n", + "0x00023929 call_site -> 0x0001bae4 (__rcu_read_lock)\n", + "0x00023937 inlined_subroutine -> 0x00025368 (get_cpu_mask)\n", + "0x0002395f lexical_block \n", + "0x00023969 call_site -> 0x00025e57 (__builtin___ubsan_handle_out_of_bounds)\n", + "0x0002398d inlined_subroutine -> 0x00024e75 (rcu_read_unlock)\n", + "0x000239b4 call_site -> 0x0001badc (__rcu_read_unlock)\n", + "0x000239c2 inlined_subroutine -> 0x00024e80 (rcu_read_lock)\n", + "0x000239e9 call_site -> 0x0001bae4 (__rcu_read_lock)\n", + "0x000239f7 inlined_subroutine -> 0x00024e75 (rcu_read_unlock)\n", + "0x00023a1e call_site -> 0x0001badc (__rcu_read_unlock)\n", + "0x00023a2c call_site -> 0x0001bd57 (rcu_scheduler_starting)\n", + "0x00023a39 call_site -> 0x0001bd37 (user_mode_thread)\n", + "0x00023a64 call_site -> 0x0001bd1b (find_task_by_pid_ns)\n", + "0x00023a7c call_site -> 0x0001bcff (set_cpus_allowed_ptr)\n", + "0x00023a89 call_site -> 0x0001bcf7 (numa_default_policy)\n", + "0x00023a96 call_site -> 0x0001bcd2 (kernel_thread)\n", + "0x00023ab9 call_site -> 0x0001bd1b (find_task_by_pid_ns)\n", + "0x00023ad1 call_site -> 0x0001bcaa (complete)\n", + "0x00023af0 call_site -> 0x0001bca1 (schedule_preempt_disabled)\n", + "0x00023afd call_site -> 0x0001bc8d (cpu_startup_entry)\n", + "0x00023b12 subprogram arch_call_rest_init (external)\n", + "0x00023b31 call_site -> 0x00023837 (rest_init)\n", + "0x00023b3f subprogram start_kernel (external)\n", + "0x00023b82 lexical_block \n", + "0x00023b9f lexical_block \n", + "0x00023bbc lexical_block \n", + "0x00023bdc lexical_block \n", + "0x00023bfc inlined_subroutine -> 0x000252d8 (arch_local_save_flags)\n", + "0x00023c23 lexical_block -> 0x000252ea ()\n", + "0x00023c59 lexical_block -> 0x0002532c ()\n", + "0x00023c74 lexical_block -> 0x0002533a ()\n", + "0x00023c8c inlined_subroutine -> 0x000251d2 (arch_irqs_disabled_flags)\n", + "0x00023cbe lexical_block \n", + "0x00023ce8 call_site -> 0x0001c057 (__warn_printk)\n", + "0x00023d04 lexical_block \n", + "0x00023d21 lexical_block \n", + "0x00023d3e lexical_block \n", + "0x00023d5e lexical_block \n", + "0x00023d7e inlined_subroutine -> 0x000252d8 (arch_local_save_flags)\n", + "0x00023da5 lexical_block -> 0x000252ea ()\n", + "0x00023ddb lexical_block -> 0x0002532c ()\n", + "0x00023dfd lexical_block -> 0x0002533a ()\n", + "0x00023e15 inlined_subroutine -> 0x000251d2 (arch_irqs_disabled_flags)\n", + "0x00023e47 lexical_block \n", + "0x00023e65 call_site -> 0x0001c057 (__warn_printk)\n", + "0x00023e81 inlined_subroutine -> 0x00025286 (arch_local_irq_disable)\n", + "0x00023ea8 lexical_block -> 0x00025294 ()\n", + "0x00023ed8 inlined_subroutine -> 0x000250aa (smp_prepare_boot_cpu)\n", + "0x00023efb inlined_subroutine -> 0x000257a9 (IS_ERR_OR_NULL)\n", + "0x00023f30 inlined_subroutine -> 0x00024a5f (boot_init_stack_canary)\n", + "0x00023f64 inlined_subroutine -> 0x00024b14 (get_random_canary)\n", + "0x00023f8a inlined_subroutine -> 0x00024f18 (get_random_long)\n", + "0x00023fac call_site -> 0x0001bd60 (get_random_u64)\n", + "0x00023fbb lexical_block -> 0x00024a77 ()\n", + "0x00023fd0 inlined_subroutine -> 0x0002594f (get_current)\n", + "0x00023ff6 lexical_block -> 0x00025960 ()\n", + "0x00024018 lexical_block -> 0x000259b5 ()\n", + "0x0002403d lexical_block -> 0x00024af7 ()\n", + "0x00024061 inlined_subroutine -> 0x00025234 (arch_local_irq_enable)\n", + "0x00024088 lexical_block -> 0x00025242 ()\n", + "0x000240b8 inlined_subroutine -> 0x000231b5 (efi_enabled)\n", + "0x000240ec inlined_subroutine -> 0x000257e5 (_test_bit)\n", + "0x00024121 inlined_subroutine -> 0x00025864 (arch_test_bit)\n", + "0x00024155 inlined_subroutine -> 0x000258c2 (constant_test_bit)\n", + "0x0002418d inlined_subroutine -> 0x0001f5be (initcall_debug_enable)\n", + "0x000241c1 inlined_subroutine -> 0x00022eac (register_trace_initcall_start)\n", + "0x000241f6 call_site -> 0x0001bd6d (tracepoint_probe_register)\n", + "0x0002422c inlined_subroutine -> 0x00022d3d (register_trace_initcall_finish)\n", + "0x00024261 call_site -> 0x0001bd6d (tracepoint_probe_register)\n", + "0x00024297 lexical_block -> 0x0001f5d9 ()\n", + "0x000242b9 lexical_block -> 0x0001f5e7 ()\n", + "0x000242e0 call_site -> 0x0001c057 (__warn_printk)\n", + "0x000242fd inlined_subroutine -> 0x000251f0 (__phys_addr_nodebug)\n", + "0x00024325 lexical_block \n", + "0x00024331 inlined_subroutine -> 0x00025286 (arch_local_irq_disable)\n", + "0x00024358 lexical_block -> 0x00025294 ()\n", + "0x00024388 call_site -> 0x0001c0ed (set_task_stack_end_magic)\n", + "0x00024395 call_site -> 0x0001f62c (smp_setup_processor_id)\n", + "0x000243a2 call_site -> 0x0001c0e4 (init_vmlinux_build_id)\n", + "0x000243af call_site -> 0x0001c0d7 (cgroup_init_early)\n", + "0x000243bc call_site -> 0x0001c0ce (boot_cpu_init)\n", + "0x000243c9 call_site -> 0x0001c101 (_printk)\n", + "0x000243e8 call_site -> 0x0001c0c2 (early_security_init)\n", + "0x000243f5 call_site -> 0x0001c0b0 (setup_arch)\n", + "0x0002440d call_site -> 0x00020790 (setup_boot_config)\n", + "0x0002441a call_site -> 0x0001f791 (setup_command_line)\n", + "0x00024427 call_site -> 0x00025081 (setup_nr_cpu_ids)\n", + "0x00024434 call_site -> 0x0001c0a7 (setup_per_cpu_areas)\n", + "0x00024441 call_site -> 0x0001c09e (boot_cpu_hotplug_init)\n", + "0x0002444e call_site -> 0x0001c101 (_printk)\n", + "0x0002446d call_site -> 0x0001c096 (jump_label_init)\n", + "0x0002447a call_site -> 0x00025a52 (parse_early_param)\n", + "0x00024487 call_site -> 0x0001c151 (parse_args)\n", + "0x000244b2 call_site -> 0x0001f281 (print_unknown_bootoptions)\n", + "0x000244bf call_site -> 0x0001c151 (parse_args)\n", + "0x000244fa call_site -> 0x0001c151 (parse_args)\n", + "0x0002452f call_site -> 0x00024f06 (random_init_early)\n", + "0x0002453c call_site -> 0x0002593d (setup_log_buf)\n", + "0x00024553 call_site -> 0x00024bfa (vfs_caches_init_early)\n", + "0x00024560 call_site -> 0x0001c08d (sort_main_extable)\n", + "0x0002456d call_site -> 0x0001f5f8 (trap_init)\n", + "0x0002457a call_site -> 0x0001c085 (mm_core_init)\n", + "0x00024587 call_site -> 0x00024d19 (poking_init)\n", + "0x00024594 call_site -> 0x0001c07c (ftrace_init)\n", + "0x000245a1 call_site -> 0x0001c074 (early_trace_init)\n", + "0x000245ae call_site -> 0x0001c06b (sched_init)\n", + "0x000245bb call_site -> 0x0001c04e (radix_tree_init)\n", + "0x000245c8 call_site -> 0x0001c045 (maple_tree_init)\n", + "0x000245d5 call_site -> 0x000231a3 (housekeeping_init)\n", + "0x000245e2 call_site -> 0x00024dd7 (workqueue_init_early)\n", + "0x000245ef call_site -> 0x0001c03d (rcu_init)\n", + "0x000245fc call_site -> 0x0001c035 (trace_init)\n", + "0x00024609 call_site -> 0x0001c026 (early_irq_init)\n", + "0x00024616 call_site -> 0x0001c01e (init_IRQ)\n", + "0x00024623 call_site -> 0x000231ac (tick_init)\n", + "0x00024630 call_site -> 0x0001c016 (rcu_init_nohz)\n", + "0x0002463d call_site -> 0x0001c00d (init_timers)\n", + "0x0002464a call_site -> 0x0001c004 (srcu_init)\n", + "0x00024657 call_site -> 0x00024cda (hrtimers_init)\n", + "0x00024664 call_site -> 0x0001bffa (softirq_init)\n", + "0x00024671 call_site -> 0x0001bff1 (timekeeping_init)\n", + "0x0002467e call_site -> 0x0001bfe9 (time_init)\n", + "0x0002468b call_site -> 0x00024efe (random_init)\n", + "0x00024698 call_site -> 0x0002382e (kfence_init)\n", + "0x000246a5 call_site -> 0x0001bfe0 (perf_event_init)\n", + "0x000246b2 call_site -> 0x0001bfd2 (profile_init)\n", + "0x000246bf call_site -> 0x00025089 (call_function_init)\n", + "0x000246cc call_site -> 0x00024c03 (kmem_cache_init_late)\n", + "0x000246d9 call_site -> 0x0001bfc8 (console_init)\n", + "0x000246e6 call_site -> 0x0001bfb2 (panic)\n", + "0x00024705 call_site -> 0x0001bfa9 (setup_per_cpu_pageset)\n", + "0x00024712 call_site -> 0x0001bfa1 (numa_policy_init)\n", + "0x0002471f call_site -> 0x0001bf97 (acpi_early_init)\n", + "0x0002472c call_site -> 0x0001bf8e (sched_clock_init)\n", + "0x00024739 call_site -> 0x0001bf86 (calibrate_delay)\n", + "0x00024746 call_site -> 0x0001bf7d (arch_cpu_finalize_init)\n", + "0x00024753 call_site -> 0x0001bf75 (pid_idr_init)\n", + "0x00024760 call_site -> 0x0001bf6d (anon_vma_init)\n", + "0x0002476d call_site -> 0x0001f612 (thread_stack_cache_init)\n", + "0x0002477a call_site -> 0x00024ce3 (cred_init)\n", + "0x00024787 call_site -> 0x0001bf5c (fork_init)\n", + "0x00024794 call_site -> 0x0001bf54 (proc_caches_init)\n", + "0x000247a1 call_site -> 0x0001bf4c (uts_ns_init)\n", + "0x000247ae call_site -> 0x0001bf43 (key_init)\n", + "0x000247bb call_site -> 0x0001bf37 (security_init)\n", + "0x000247c8 call_site -> 0x00023190 (dbg_late_init)\n", + "0x000247d5 call_site -> 0x0001bf2e (net_ns_init)\n", + "0x000247e2 call_site -> 0x00024bf1 (vfs_caches_init)\n", + "0x000247ef call_site -> 0x00024bce (pagecache_init)\n", + "0x000247fc call_site -> 0x0001bf24 (signals_init)\n", + "0x00024809 call_site -> 0x0001bf1b (seq_file_init)\n", + "0x00024816 call_site -> 0x0001bf12 (proc_root_init)\n", + "0x00024823 call_site -> 0x0001bf0a (nsfs_init)\n", + "0x00024830 call_site -> 0x0001befd (cpuset_init)\n", + "0x0002483d call_site -> 0x0001bef0 (cgroup_init)\n", + "0x0002484a call_site -> 0x0001bee7 (taskstats_init_early)\n", + "0x00024857 call_site -> 0x0001bedf (delayacct_init)\n", + "0x00024864 call_site -> 0x0001bed5 (acpi_subsystem_init)\n", + "0x00024871 call_site -> 0x0001f646 (arch_post_acpi_subsys_init)\n", + "0x0002487e call_site -> 0x00023b12 (arch_call_rest_init)\n", + "0x0002488b call_site -> 0x0001c101 (_printk)\n", + "0x000248aa call_site -> 0x0001bf64 (efi_enter_virtual_mode)\n", + "0x000248b7 call_site -> 0x00025e4d (__builtin___ubsan_handle_load_invalid_value)\n", + "0x000248dc subprogram xbc_get_embedded_bootconfig\n", + "0x000248fc subprogram xbc_exit (external)\n", + "0x00024905 subprogram xbc_get_info (external)\n", + "0x00024921 subprogram xbc_init (external)\n", + "0x00024947 subprogram xbc_node_compose_key_after (external)\n", + "0x0002496d subprogram xbc_find_node\n", + "0x0002498b subprogram xbc_node_find_next_key_value (external)\n", + "0x000249ab subprogram xbc_node_find_subkey (external)\n", + "0x000249c6 subprogram xbc_node_get_data (external)\n", + "0x000249dc subprogram xbc_node_get_child (external)\n", + "0x000249f2 subprogram xbc_calc_checksum\n", + "0x00024a32 subprogram memblock_alloc\n", + "0x00024a5f subprogram boot_init_stack_canary\n", + "0x00024a77 lexical_block \n", + "0x00024a7c subprogram __compiletime_assert_353 (external)\n", + "0x00024a85 lexical_block \n", + "0x00024a97 lexical_block \n", + "0x00024aa8 lexical_block \n", + "0x00024ab7 lexical_block \n", + "0x00024ac8 lexical_block \n", + "0x00024ad7 lexical_block \n", + "0x00024ae8 lexical_block \n", + "0x00024af7 lexical_block \n", + "0x00024b04 lexical_block \n", + "0x00024b14 subprogram get_random_canary\n", + "0x00024b20 subprogram trace_trigger_soft_disabled\n", + "0x00024b4d subprogram bpf_prog_array_valid\n", + "0x00024b6c lexical_block \n", + "0x00024b6d subprogram __compiletime_assert_352 (external)\n", + "0x00024b78 subprogram perf_fetch_caller_regs\n", + "0x00024b94 subprogram free_initmem_default\n", + "0x00024bce subprogram pagecache_init (external)\n", + "0x00024bd7 subprogram pgtable_cache_init (external)\n", + "0x00024bf1 subprogram vfs_caches_init (external)\n", + "0x00024bfa subprogram vfs_caches_init_early (external)\n", + "0x00024c03 subprogram kmem_cache_init_late (external)\n", + "0x00024c0c subprogram kzalloc\n", + "0x00024c39 subprogram kmalloc\n", + "0x00024c65 lexical_block \n", + "0x00024c75 subprogram __kmalloc_index\n", + "0x00024ca1 lexical_block \n", + "0x00024ca2 subprogram __compiletime_assert_269 (external)\n", + "0x00024cad subprogram kmalloc_type\n", + "0x00024cda subprogram hrtimers_init (external)\n", + "0x00024ce3 subprogram cred_init (external)\n", + "0x00024ceb subprogram task_unlock\n", + "0x00024d02 subprogram task_lock\n", + "0x00024d19 subprogram poking_init (external)\n", + "0x00024d33 subprogram task_pid_nr\n", + "0x00024d51 subprogram task_pid\n", + "0x00024d6f subprogram get_pid\n", + "0x00024d8d subprogram kcsan_init\n", + "0x00024d96 subprogram hash_64_generic\n", + "0x00024dc5 subprogram workqueue_init_topology (external)\n", + "0x00024dce subprogram workqueue_init (external)\n", + "0x00024dd7 subprogram workqueue_init_early (external)\n", + "0x00024de0 subprogram debug_objects_early_init\n", + "0x00024de9 subprogram ktime_us_delta\n", + "0x00024e13 subprogram ktime_to_us\n", + "0x00024e30 subprogram ktime_divns\n", + "0x00024e58 lexical_block \n", + "0x00024e65 lexical_block \n", + "0x00024e75 subprogram rcu_read_unlock\n", + "0x00024e80 subprogram rcu_read_lock\n", + "0x00024e8b subprogram refcount_inc\n", + "0x00024ea2 subprogram __refcount_inc\n", + "0x00024ec5 subprogram __refcount_add\n", + "0x00024efe subprogram random_init (external)\n", + "0x00024f06 subprogram random_init_early (external)\n", + "0x00024f18 subprogram get_random_long\n", + "0x00024f24 subprogram add_latent_entropy\n", + "0x00024f2c subprogram do_write_seqcount_end\n", + "0x00024f4b subprogram do_write_seqcount_begin\n", + "0x00024f65 subprogram do_write_seqcount_begin_nested\n", + "0x00024f8c subprogram do_raw_write_seqcount_end\n", + "0x00024fa6 subprogram do_raw_write_seqcount_begin\n", + "0x00024fc0 subprogram __seqprop_spinlock_assert\n", + "0x00024fdc subprogram __seqprop_spinlock_preemptible\n", + "0x00024ff8 subprogram __seqprop_spinlock_ptr\n", + "0x00025019 subprogram spin_unlock\n", + "0x00025035 subprogram spin_lock\n", + "0x00025051 subprogram _raw_spin_unlock (external)\n", + "0x00025065 subprogram _raw_spin_lock (external)\n", + "0x00025079 subprogram smp_init (external)\n", + "0x00025081 subprogram setup_nr_cpu_ids (external)\n", + "0x00025089 subprogram call_function_init (external)\n", + "0x00025091 subprogram smp_prepare_cpus\n", + "0x000250aa subprogram smp_prepare_boot_cpu\n", + "0x000250b2 subprogram __preempt_count_dec_and_test\n", + "0x000250c3 lexical_block \n", + "0x000250d0 subprogram __preempt_count_add\n", + "0x000250e8 lexical_block \n", + "0x000250f5 lexical_block \n", + "0x00025107 lexical_block \n", + "0x00025114 lexical_block \n", + "0x00025125 subprogram preempt_count_set\n", + "0x00025154 lexical_block \n", + "0x00025166 lexical_block \n", + "0x00025199 subprogram preempt_count\n", + "0x000251aa lexical_block \n", + "0x000251b9 subprogram arch_local_irq_restore\n", + "0x000251d2 subprogram arch_irqs_disabled_flags\n", + "0x000251f0 subprogram __phys_addr_nodebug\n", + "0x00025216 subprogram arch_local_irq_save\n", + "0x00025234 subprogram arch_local_irq_enable\n", + "0x00025242 lexical_block \n", + "0x00025286 subprogram arch_local_irq_disable\n", + "0x00025294 lexical_block \n", + "0x000252d8 subprogram arch_local_save_flags\n", + "0x000252ea lexical_block \n", + "0x0002532c lexical_block \n", + "0x0002533a lexical_block \n", + "0x0002533b subprogram __compiletime_assert_62 (external)\n", + "0x00025348 subprogram cpu_online\n", + "0x00025368 subprogram get_cpu_mask\n", + "0x00025393 subprogram cpumask_test_cpu\n", + "0x000253c0 subprogram cpumask_check\n", + "0x000253de subprogram cpu_max_bits_warn\n", + "0x00025403 subprogram atomic_fetch_add_relaxed\n", + "0x0002542e subprogram raw_atomic_fetch_add_relaxed\n", + "0x00025457 subprogram arch_atomic_fetch_add\n", + "0x0002547c lexical_block \n", + "0x0002548b subprogram strcpy (external)\n", + "0x000254ee subprogram memcmp (external)\n", + "0x00025547 subprogram fortify_memcpy_chk (external)\n", + "0x000255a7 subprogram strlcat (external)\n", + "0x00025638 subprogram strscpy (external)\n", + "0x00025696 lexical_block \n", + "0x000256be lexical_block \n", + "0x000256cf subprogram __fortify_strlen (external)\n", + "0x00025716 subprogram strnlen (external)\n", + "0x00025774 lexical_block \n", + "0x00025799 lexical_block \n", + "0x000257a9 subprogram IS_ERR_OR_NULL\n", + "0x000257c7 subprogram IS_ERR\n", + "0x000257e5 subprogram _test_bit\n", + "0x00025813 subprogram instrument_atomic_read_write\n", + "0x0002583e subprogram instrument_atomic_read\n", + "0x00025864 subprogram arch_test_bit\n", + "0x0002588d subprogram variable_test_bit\n", + "0x000258c2 subprogram constant_test_bit\n", + "0x000258eb subprogram const_test_bit\n", + "0x0002593d subprogram setup_log_buf (external)\n", + "0x0002594f subprogram get_current\n", + "0x00025960 lexical_block \n", + "0x0002596d lexical_block \n", + "0x0002597f lexical_block \n", + "0x00025991 lexical_block \n", + "0x000259a3 lexical_block \n", + "0x000259b5 lexical_block \n", + "0x000259c5 subprogram __this_cpu_preempt_check\n", + "0x000259e4 subprogram static_key_false\n", + "0x00025a02 subprogram arch_static_branch\n", + "0x00025a35 subprogram parse_early_options (external)\n", + "0x00025a52 subprogram parse_early_param (external)\n", + "0x00025a9c inlined_subroutine -> 0x00025638 (strscpy)\n", + "0x00025ade lexical_block \n", + "0x00025b0a inlined_subroutine -> 0x00025716 (strnlen)\n", + "0x00025b22 lexical_block \n", + "0x00025b3e call_site -> 0x0001c18b (__real_strnlen)\n", + "0x00025b64 call_site -> 0x0001c1aa (fortify_panic)\n", + "0x00025b81 call_site -> 0x0001c1c5 (__real_strscpy)\n", + "0x00025bab inlined_subroutine -> 0x00025a35 (parse_early_options)\n", + "0x00025bdb call_site -> 0x0001c151 (parse_args)\n", + "0x00025c19 subprogram initcall_from_entry\n", + "0x00025c37 subprogram hlist_empty\n", + "0x00025c54 lexical_block \n", + "0x00025c55 subprogram __compiletime_assert_12 (external)\n", + "0x00025c65 subprogram list_empty\n", + "0x00025c84 lexical_block \n", + "0x00025c85 subprogram __compiletime_assert_4 (external)\n", + "0x00025c95 subprogram list_add\n", + "0x00025cba subprogram __list_add\n", + "0x00025cea lexical_block \n", + "0x00025ceb subprogram __compiletime_assert_2 (external)\n", + "0x00025cf5 subprogram __list_add_valid\n", + "0x00025d2b subprogram kcsan_check_access\n", + "0x00025d64 subprogram kcsan_nestable_atomic_end\n", + "0x00025d6d subprogram kcsan_nestable_atomic_begin\n", + "0x00025d76 subprogram kasan_check_write\n", + "0x00025da0 subprogram kasan_check_read\n", + "0x00025dca subprogram offset_to_ptr\n", + "0x00025ded subprogram -> 0x00025a35 (parse_early_options)\n", + "0x00025e16 call_site -> 0x0001c151 (parse_args)\n", + "0x00025e4d subprogram __builtin___ubsan_handle_load_invalid_value (external)\n", + "0x00025e57 subprogram __builtin___ubsan_handle_out_of_bounds (external)\n", + "0x00025e61 subprogram __builtin_strlen (external)\n", + "0x00025e6b subprogram __builtin_memcpy (external)\n", + "0x00025e75 subprogram __stack_chk_fail (external)\n", + "0x00025e7f subprogram __builtin_strcpy (external)\n", + "0x00025e93 subprogram __builtin_memmove (external)\n" + ] + }, + { + "data": { + "text/plain": [ + "[FuncEntry(name='fput', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:console_on_rootfs']),\n", + " FuncEntry(name='filp_open', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:console_on_rootfs']),\n", + " FuncEntry(name='free_reserved_area', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:free_initmem']),\n", + " FuncEntry(name='add_device_randomness', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_one_initcall']),\n", + " FuncEntry(name='__real_strlcat', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='strreplace', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:initcall_blacklisted']),\n", + " FuncEntry(name='sprint_symbol_no_offset', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:initcall_blacklisted']),\n", + " FuncEntry(name='strsep', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:initcall_blacklist']),\n", + " FuncEntry(name='static_key_disable', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:early_randomize_kstack_offset']),\n", + " FuncEntry(name='static_key_enable', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:early_randomize_kstack_offset']),\n", + " FuncEntry(name='kstrtobool', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:early_randomize_kstack_offset']),\n", + " FuncEntry(name='get_option', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:loglevel']),\n", + " FuncEntry(name='bpf_trace_run2', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:__bpf_trace_initcall_finish']),\n", + " FuncEntry(name='bpf_trace_run1', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:__bpf_trace_initcall_start', 'init/main.c:__bpf_trace_initcall_level']),\n", + " FuncEntry(name='trace_handle_return', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:trace_raw_output_initcall_finish', 'init/main.c:trace_raw_output_initcall_start', 'init/main.c:trace_raw_output_initcall_level']),\n", + " FuncEntry(name='trace_event_printf', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:trace_raw_output_initcall_finish', 'init/main.c:trace_raw_output_initcall_start', 'init/main.c:trace_raw_output_initcall_level']),\n", + " FuncEntry(name='trace_raw_output_prep', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:trace_raw_output_initcall_finish', 'init/main.c:trace_raw_output_initcall_start', 'init/main.c:trace_raw_output_initcall_level']),\n", + " FuncEntry(name='__trace_trigger_soft_disabled', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:trace_event_raw_event_initcall_finish', 'init/main.c:trace_event_raw_event_initcall_start', 'init/main.c:trace_event_raw_event_initcall_level']),\n", + " FuncEntry(name='trace_event_buffer_commit', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:trace_event_raw_event_initcall_finish', 'init/main.c:trace_event_raw_event_initcall_start', 'init/main.c:trace_event_raw_event_initcall_level']),\n", + " FuncEntry(name='trace_event_buffer_reserve', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:trace_event_raw_event_initcall_finish', 'init/main.c:trace_event_raw_event_initcall_start', 'init/main.c:trace_event_raw_event_initcall_level']),\n", + " FuncEntry(name='perf_trace_run_bpf_submit', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:perf_trace_initcall_finish', 'init/main.c:perf_trace_initcall_start', 'init/main.c:perf_trace_initcall_level']),\n", + " FuncEntry(name='perf_trace_buf_alloc', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:perf_trace_initcall_finish', 'init/main.c:perf_trace_initcall_start', 'init/main.c:perf_trace_initcall_level']),\n", + " FuncEntry(name='trace_event_raw_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_event_reg', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__SCT__tp_func_initcall_finish', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_one_initcall']),\n", + " FuncEntry(name='__SCT__tp_func_initcall_start', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_one_initcall']),\n", + " FuncEntry(name='__rcu_read_unlock', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init', 'init/main.c:rest_init']),\n", + " FuncEntry(name='__rcu_read_lock', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init', 'init/main.c:rest_init']),\n", + " FuncEntry(name='kernel_execve', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:run_init_process']),\n", + " FuncEntry(name='__dynamic_pr_debug', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:run_init_process', 'init/main.c:run_init_process', 'init/main.c:run_init_process', 'init/main.c:run_init_process', 'init/main.c:initcall_blacklisted', 'init/main.c:initcall_blacklist']),\n", + " FuncEntry(name='mark_rodata_ro', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='rcu_barrier', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='__compiletime_assert_269', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__kmalloc', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_initcalls']),\n", + " FuncEntry(name='kmalloc_trace', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kmalloc_large', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kfree', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_initcalls']),\n", + " FuncEntry(name='init_irq_proc', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='driver_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='cpuset_init_smp', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='__SCT__tp_func_initcall_level', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls']),\n", + " FuncEntry(name='refcount_warn_saturate', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable', 'init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='prepare_namespace', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='wait_for_initramfs', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='page_alloc_init_late', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='sched_init_smp', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='lockup_detector_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='rcu_init_tasks_generic', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='init_mm_internals', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='do_sysctl_args', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='rcu_end_inkernel_boot', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='pti_finalize', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='kgdb_free_init_mem', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='ftrace_free_init_mem', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='kprobe_free_init_mem', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='async_synchronize_full', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='wait_for_completion', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='cpu_startup_entry', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init']),\n", + " FuncEntry(name='schedule_preempt_disabled', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init']),\n", + " FuncEntry(name='complete', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init']),\n", + " FuncEntry(name='kthreadd', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kernel_thread', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init']),\n", + " FuncEntry(name='numa_default_policy', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init', 'init/main.c:rest_init']),\n", + " FuncEntry(name='set_cpus_allowed_ptr', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init']),\n", + " FuncEntry(name='find_task_by_pid_ns', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init', 'init/main.c:rest_init']),\n", + " FuncEntry(name='user_mode_thread', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init']),\n", + " FuncEntry(name='rcu_scheduler_starting', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:rest_init']),\n", + " FuncEntry(name='get_random_u64', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='tracepoint_probe_register', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel', 'init/main.c:start_kernel']),\n", + " FuncEntry(name='ktime_get', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:trace_initcall_finish_cb', 'init/main.c:trace_initcall_start_cb']),\n", + " FuncEntry(name='sprintf', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:print_unknown_bootoptions', 'init/main.c:print_unknown_bootoptions']),\n", + " FuncEntry(name='snprintf', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:xbc_snprint_cmdline', 'init/main.c:xbc_snprint_cmdline']),\n", + " FuncEntry(name='memblock_alloc_try_nid', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:initcall_blacklist', 'init/main.c:initcall_blacklist', 'init/main.c:print_unknown_bootoptions', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:xbc_make_cmdline']),\n", + " FuncEntry(name='memblock_free', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:print_unknown_bootoptions', 'init/main.c:xbc_make_cmdline']),\n", + " FuncEntry(name='__read_overflow', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='parameqn', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:unknown_bootoption']),\n", + " FuncEntry(name='strncmp', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:unknown_bootoption']),\n", + " FuncEntry(name='strnchr', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:unknown_bootoption']),\n", + " FuncEntry(name='sysctl_is_alias', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:unknown_bootoption']),\n", + " FuncEntry(name='__read_overflow2_field', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__write_overflow_field', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__read_overflow2', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='acpi_subsystem_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='delayacct_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='taskstats_init_early', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='cgroup_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='cpuset_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='nsfs_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='proc_root_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='seq_file_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='signals_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='net_ns_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='security_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='key_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='uts_ns_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='proc_caches_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='fork_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='efi_enter_virtual_mode', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='anon_vma_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='pid_idr_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='arch_cpu_finalize_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='calibrate_delay', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='sched_clock_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='acpi_early_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='numa_policy_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='setup_per_cpu_pageset', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='panic', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:do_initcalls', 'init/main.c:initcall_blacklist', 'init/main.c:initcall_blacklist', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:start_kernel']),\n", + " FuncEntry(name='console_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='profile_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='perf_event_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='time_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='timekeeping_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='softirq_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='srcu_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='init_timers', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='rcu_init_nohz', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='init_IRQ', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='early_irq_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='trace_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='rcu_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='maple_tree_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='radix_tree_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='__warn_printk', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_one_initcall', 'init/main.c:start_kernel', 'init/main.c:start_kernel', 'init/main.c:start_kernel']),\n", + " FuncEntry(name='sched_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='early_trace_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='ftrace_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='mm_core_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='sort_main_extable', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='jump_label_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='boot_cpu_hotplug_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='setup_per_cpu_areas', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='setup_arch', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='early_security_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='boot_cpu_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='cgroup_init_early', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='init_vmlinux_build_id', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='set_task_stack_end_magic', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='_printk', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:console_on_rootfs', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:set_debug_rodata', 'init/main.c:run_init_process', 'init/main.c:trace_initcall_finish_cb', 'init/main.c:trace_initcall_start_cb', 'init/main.c:print_unknown_bootoptions', 'init/main.c:print_unknown_bootoptions', 'init/main.c:do_early_param', 'init/main.c:unknown_bootoption', 'init/main.c:setup_boot_config', 'init/main.c:setup_boot_config', 'init/main.c:setup_boot_config', 'init/main.c:setup_boot_config', 'init/main.c:setup_boot_config', 'init/main.c:setup_boot_config', 'init/main.c:setup_boot_config', 'init/main.c:xbc_make_cmdline', 'init/main.c:xbc_make_cmdline', 'init/main.c:start_kernel', 'init/main.c:start_kernel', 'init/main.c:start_kernel']),\n", + " FuncEntry(name='strcmp', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:set_debug_rodata', 'init/main.c:initcall_blacklisted', 'init/main.c:do_early_param', 'init/main.c:do_early_param', 'init/main.c:bootconfig_params']),\n", + " FuncEntry(name='parameq', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_early_param']),\n", + " FuncEntry(name='parse_args', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_initcalls', 'init/main.c:setup_boot_config', 'init/main.c:start_kernel', 'init/main.c:start_kernel', 'init/main.c:start_kernel', 'init/main.c:parse_early_param']),\n", + " FuncEntry(name='__real_strnlen', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_one_initcall', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_boot_config', 'init/main.c:parse_early_param']),\n", + " FuncEntry(name='fortify_panic', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_boot_config', 'init/main.c:parse_early_param']),\n", + " FuncEntry(name='__write_overflow', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__real_strscpy', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:setup_boot_config', 'init/main.c:parse_early_param']),\n", + " FuncEntry(name='console_on_rootfs', external=True, inline=-2, loc='init/main.c:1508', file='init/main.c', caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='IS_ERR', external=False, inline=3, loc='include/linux/err.h:59', file='init/main.c', caller_inline=['init/main.c:console_on_rootfs', 'init/main.c:setup_boot_config'], caller_func=[]),\n", + " FuncEntry(name='init_dup', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:console_on_rootfs', 'init/main.c:console_on_rootfs', 'init/main.c:console_on_rootfs']),\n", + " FuncEntry(name='kernel_init', external=False, inline=-2, loc='init/main.c:1432', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='exit_boot_config', external=False, inline=1, loc='init/main.c:462', file='init/main.c', caller_inline=['init/main.c:kernel_init'], caller_func=[]),\n", + " FuncEntry(name='xbc_exit', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='mark_readonly', external=False, inline=1, loc='init/main.c:1400', file='init/main.c', caller_inline=['init/main.c:kernel_init'], caller_func=[]),\n", + " FuncEntry(name='rodata_test', external=False, inline=3, loc='include/linux/rodata_test.h:15', file='init/main.c', caller_inline=['init/main.c:kernel_init'], caller_func=[]),\n", + " FuncEntry(name='__builtin___ubsan_handle_load_invalid_value', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init', 'init/main.c:early_randomize_kstack_offset', 'init/main.c:setup_boot_config', 'init/main.c:setup_boot_config', 'init/main.c:start_kernel']),\n", + " FuncEntry(name='try_to_run_init_process', external=False, inline=1, loc='init/main.c:1360', file='init/main.c', caller_inline=['init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init'], caller_func=[]),\n", + " FuncEntry(name='run_init_process', external=False, inline=-2, loc='init/main.c:1345', file='init/main.c', caller_inline=[], caller_func=['init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init', 'init/main.c:kernel_init']),\n", + " FuncEntry(name='kernel_init_freeable', external=False, inline=-2, loc='init/main.c:1522', file='init/main.c', caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='free_initmem', external=True, inline=-2, loc='init/main.c:1427', file='init/main.c', caller_inline=[], caller_func=['init/main.c:kernel_init']),\n", + " FuncEntry(name='free_initmem_default', external=False, inline=3, loc='include/linux/mm.h:3139', file='init/main.c', caller_inline=['init/main.c:free_initmem'], caller_func=[]),\n", + " FuncEntry(name='set_debug_rodata', external=False, inline=-2, loc='init/main.c:1383', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='arch_parse_debug_rodata', external=False, inline=3, loc='init/main.c:1380', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='get_current', external=False, inline=3, loc='arch/x86/include/asm/current.h:40', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:trace_initcall_start_cb', 'init/main.c:set_mems_allowed', 'init/main.c:set_mems_allowed', 'init/main.c:set_mems_allowed', 'init/main.c:set_mems_allowed', 'init/main.c:set_mems_allowed', 'init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='task_pid', external=False, inline=3, loc='include/linux/pid.h:210', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='get_pid', external=False, inline=3, loc='include/linux/pid.h:79', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='refcount_inc', external=False, inline=3, loc='include/linux/refcount.h:254', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='__refcount_inc', external=False, inline=3, loc='include/linux/refcount.h:237', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='__refcount_add', external=False, inline=3, loc='include/linux/refcount.h:180', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='atomic_fetch_add_relaxed', external=False, inline=3, loc='include/linux/atomic/atomic-instrumented.h:250', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='raw_atomic_fetch_add_relaxed', external=False, inline=3, loc='include/linux/atomic/atomic-arch-fallback.h:744', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='arch_atomic_fetch_add', external=False, inline=3, loc='arch/x86/include/asm/atomic.h:95', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='smp_prepare_cpus', external=False, inline=3, loc='arch/x86/include/asm/smp.h:67', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='do_pre_smp_initcalls', external=False, inline=1, loc='init/main.c:1336', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='trace_initcall_level', external=False, inline=3, loc='include/trace/events/initcall.h:10', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_initcalls'], caller_func=[]),\n", + " FuncEntry(name='static_key_false', external=False, inline=3, loc='include/linux/jump_label.h:205', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='arch_static_branch', external=False, inline=3, loc='arch/x86/include/asm/jump_label.h:25', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:run_init_process', 'init/main.c:run_init_process', 'init/main.c:run_init_process', 'init/main.c:run_init_process', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall', 'init/main.c:initcall_blacklisted', 'init/main.c:initcall_blacklist'], caller_func=[]),\n", + " FuncEntry(name='cpu_online', external=False, inline=3, loc='include/linux/cpumask.h:1102', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='cpumask_test_cpu', external=False, inline=3, loc='include/linux/cpumask.h:502', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='_test_bit', external=False, inline=3, loc='include/asm-generic/bitops/instrumented-non-atomic.h:139', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall', 'init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='arch_test_bit', external=False, inline=3, loc='arch/x86/include/asm/bitops.h:236', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall', 'init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='variable_test_bit', external=False, inline=3, loc='arch/x86/include/asm/bitops.h:223', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='__preempt_count_add', external=False, inline=3, loc='arch/x86/include/asm/preempt.h:77', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='__preempt_count_dec_and_test', external=False, inline=3, loc='arch/x86/include/asm/preempt.h:92', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls', 'init/main.c:do_one_initcall', 'init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='initcall_from_entry', external=False, inline=3, loc='include/linux/init.h:121', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls'], caller_func=[]),\n", + " FuncEntry(name='offset_to_ptr', external=False, inline=3, loc='include/linux/compiler.h:220', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls'], caller_func=[]),\n", + " FuncEntry(name='do_one_initcall', external=True, inline=-2, loc='init/main.c:1226', file='init/main.c', caller_inline=[], caller_func=['init/main.c:kernel_init_freeable', 'init/main.c:do_initcalls']),\n", + " FuncEntry(name='do_basic_setup', external=False, inline=1, loc='init/main.c:1327', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='do_ctors', external=False, inline=1, loc='init/main.c:1084', file='init/main.c', caller_inline=['init/main.c:kernel_init_freeable'], caller_func=[]),\n", + " FuncEntry(name='do_initcalls', external=False, inline=-2, loc='init/main.c:1301', file='init/main.c', caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='set_mems_allowed', external=False, inline=-2, loc='include/linux/cpuset.h:164', file='init/main.c', caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='workqueue_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='smp_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='workqueue_init_topology', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='padata_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='init_eaccess', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='integrity_load_keys', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:kernel_init_freeable', 'init/main.c:kernel_init_freeable']),\n", + " FuncEntry(name='__compiletime_assert_514', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_516', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_518', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_520', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='do_initcall_level', external=False, inline=1, loc='init/main.c:1286', file='init/main.c', caller_inline=['init/main.c:do_initcalls'], caller_func=[]),\n", + " FuncEntry(name='__builtin___ubsan_handle_out_of_bounds', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_initcalls', 'init/main.c:do_initcalls', 'init/main.c:do_initcalls', 'init/main.c:do_initcalls', 'init/main.c:do_initcalls', 'init/main.c:rdinit_setup', 'init/main.c:init_setup', 'init/main.c:unknown_bootoption', 'init/main.c:unknown_bootoption', 'init/main.c:unknown_bootoption', 'init/main.c:unknown_bootoption', 'init/main.c:unknown_bootoption', 'init/main.c:set_init_arg', 'init/main.c:set_init_arg', 'init/main.c:rest_init']),\n", + " FuncEntry(name='strcpy', external=True, inline=3, loc='include/linux/fortify-string.h:729', file='init/main.c', caller_inline=['init/main.c:do_initcalls', 'init/main.c:initcall_blacklist', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:perf_trace_initcall_level', 'init/main.c:trace_event_raw_event_initcall_level'], caller_func=[]),\n", + " FuncEntry(name='__fortify_strlen', external=True, inline=3, loc='include/linux/fortify-string.h:203', file='init/main.c', caller_inline=['init/main.c:do_initcalls', 'init/main.c:initcall_blacklist', 'init/main.c:initcall_blacklist', 'init/main.c:print_unknown_bootoptions', 'init/main.c:print_unknown_bootoptions', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:unknown_bootoption', 'init/main.c:unknown_bootoption', 'init/main.c:repair_env_string', 'init/main.c:repair_env_string', 'init/main.c:perf_trace_initcall_level', 'init/main.c:trace_event_raw_event_initcall_level'], caller_func=[]),\n", + " FuncEntry(name='__builtin_strlen', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_initcalls', 'init/main.c:initcall_blacklist', 'init/main.c:initcall_blacklist', 'init/main.c:print_unknown_bootoptions', 'init/main.c:print_unknown_bootoptions', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:unknown_bootoption', 'init/main.c:unknown_bootoption', 'init/main.c:repair_env_string', 'init/main.c:repair_env_string', 'init/main.c:perf_trace_initcall_level', 'init/main.c:trace_event_raw_event_initcall_level']),\n", + " FuncEntry(name='__builtin_memcpy', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_initcalls', 'init/main.c:setup_command_line']),\n", + " FuncEntry(name='kzalloc', external=False, inline=3, loc='include/linux/slab.h:709', file='init/main.c', caller_inline=['init/main.c:do_initcalls'], caller_func=[]),\n", + " FuncEntry(name='kmalloc', external=False, inline=3, loc='include/linux/slab.h:581', file='init/main.c', caller_inline=['init/main.c:do_initcalls'], caller_func=[]),\n", + " FuncEntry(name='ignore_unknown_bootoption', external=False, inline=-2, loc='init/main.c:1280', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='arch_local_save_flags', external=False, inline=3, loc='arch/x86/include/asm/paravirt.h:685', file='init/main.c', caller_inline=['init/main.c:do_one_initcall', 'init/main.c:set_mems_allowed', 'init/main.c:start_kernel', 'init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='arch_irqs_disabled_flags', external=False, inline=3, loc='arch/x86/include/asm/irqflags.h:120', file='init/main.c', caller_inline=['init/main.c:do_one_initcall', 'init/main.c:set_mems_allowed', 'init/main.c:start_kernel', 'init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='preempt_count', external=False, inline=3, loc='arch/x86/include/asm/preempt.h:24', file='init/main.c', caller_inline=['init/main.c:do_one_initcall', 'init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='trace_initcall_start', external=False, inline=3, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=['init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='trace_initcall_finish', external=False, inline=3, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=['init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='add_latent_entropy', external=False, inline=3, loc='include/linux/random.h:21', file='init/main.c', caller_inline=['init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='strlcat', external=True, inline=3, loc='include/linux/fortify-string.h:319', file='init/main.c', caller_inline=['init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='strnlen', external=True, inline=3, loc='include/linux/fortify-string.h:161', file='init/main.c', caller_inline=['init/main.c:do_one_initcall', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_boot_config', 'init/main.c:parse_early_param'], caller_func=[]),\n", + " FuncEntry(name='arch_local_irq_enable', external=False, inline=3, loc='arch/x86/include/asm/paravirt.h:696', file='init/main.c', caller_inline=['init/main.c:do_one_initcall', 'init/main.c:set_mems_allowed', 'init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='preempt_count_set', external=False, inline=3, loc='arch/x86/include/asm/preempt.h:29', file='init/main.c', caller_inline=['init/main.c:do_one_initcall'], caller_func=[]),\n", + " FuncEntry(name='initcall_blacklisted', external=False, inline=-2, loc='init/main.c:1136', file='init/main.c', caller_inline=[], caller_func=['init/main.c:do_one_initcall']),\n", + " FuncEntry(name='__stack_chk_fail', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:do_one_initcall', 'init/main.c:initcall_blacklisted', 'init/main.c:early_randomize_kstack_offset', 'init/main.c:setup_boot_config', 'init/main.c:xbc_snprint_cmdline', 'init/main.c:loglevel', 'init/main.c:perf_trace_initcall_finish', 'init/main.c:perf_trace_initcall_start', 'init/main.c:perf_trace_initcall_level', 'init/main.c:trace_event_raw_event_initcall_finish', 'init/main.c:trace_event_raw_event_initcall_start', 'init/main.c:trace_event_raw_event_initcall_level']),\n", + " FuncEntry(name='trace_initcall_finish_cb', external=False, inline=-2, loc='init/main.c:1187', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='ktime_us_delta', external=False, inline=3, loc='include/linux/ktime.h:167', file='init/main.c', caller_inline=['init/main.c:trace_initcall_finish_cb'], caller_func=[]),\n", + " FuncEntry(name='ktime_to_us', external=False, inline=3, loc='include/linux/ktime.h:157', file='init/main.c', caller_inline=['init/main.c:trace_initcall_finish_cb'], caller_func=[]),\n", + " FuncEntry(name='ktime_divns', external=False, inline=3, loc='include/linux/ktime.h:146', file='init/main.c', caller_inline=['init/main.c:trace_initcall_finish_cb'], caller_func=[]),\n", + " FuncEntry(name='trace_initcall_start_cb', external=False, inline=-2, loc='init/main.c:1178', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='task_pid_nr', external=False, inline=3, loc='include/linux/pid.h:228', file='init/main.c', caller_inline=['init/main.c:trace_initcall_start_cb'], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_512', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='list_empty', external=False, inline=3, loc='include/linux/list.h:371', file='init/main.c', caller_inline=['init/main.c:initcall_blacklisted'], caller_func=[]),\n", + " FuncEntry(name='initcall_blacklist', external=False, inline=-2, loc='init/main.c:1108', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_510', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='memblock_alloc', external=False, inline=3, loc='include/linux/memblock.h:435', file='init/main.c', caller_inline=['init/main.c:initcall_blacklist', 'init/main.c:initcall_blacklist', 'init/main.c:print_unknown_bootoptions', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:xbc_make_cmdline'], caller_func=[]),\n", + " FuncEntry(name='__builtin_strcpy', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:initcall_blacklist', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:setup_command_line', 'init/main.c:perf_trace_initcall_level', 'init/main.c:trace_event_raw_event_initcall_level']),\n", + " FuncEntry(name='list_add', external=False, inline=3, loc='include/linux/list.h:167', file='init/main.c', caller_inline=['init/main.c:initcall_blacklist'], caller_func=[]),\n", + " FuncEntry(name='__list_add', external=False, inline=3, loc='include/linux/list.h:146', file='init/main.c', caller_inline=['init/main.c:initcall_blacklist'], caller_func=[]),\n", + " FuncEntry(name='print_unknown_bootoptions', external=False, inline=-2, loc='init/main.c:830', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='early_randomize_kstack_offset', external=False, inline=-2, loc='init/main.c:807', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='initcall_debug_enable', external=False, inline=1, loc='init/main.c:1199', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='trap_init', external=True, inline=-2, loc='init/main.c:789', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='thread_stack_cache_init', external=True, inline=-2, loc='init/main.c:780', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='smp_setup_processor_id', external=True, inline=-2, loc='init/main.c:775', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='arch_post_acpi_subsys_init', external=True, inline=-2, loc='init/main.c:773', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='do_early_param', external=False, inline=-2, loc='init/main.c:734', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='setup_command_line', external=False, inline=-2, loc='init/main.c:617', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='rdinit_setup', external=False, inline=-2, loc='init/main.c:593', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='init_setup', external=False, inline=-2, loc='init/main.c:576', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='unknown_bootoption', external=False, inline=-2, loc='init/main.c:528', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='obsolete_checksetup', external=False, inline=1, loc='init/main.c:192', file='init/main.c', caller_inline=['init/main.c:unknown_bootoption'], caller_func=[]),\n", + " FuncEntry(name='repair_env_string', external=False, inline=-2, loc='init/main.c:488', file='init/main.c', caller_inline=[], caller_func=['init/main.c:unknown_bootoption', 'init/main.c:set_init_arg']),\n", + " FuncEntry(name='set_init_arg', external=False, inline=-2, loc='init/main.c:503', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__builtin_memmove', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:repair_env_string']),\n", + " FuncEntry(name='setup_boot_config', external=False, inline=-2, loc='init/main.c:404', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='get_boot_config_from_initrd', external=False, inline=1, loc='init/main.c:263', file='init/main.c', caller_inline=['init/main.c:setup_boot_config'], caller_func=[]),\n", + " FuncEntry(name='memcmp', external=True, inline=3, loc='include/linux/fortify-string.h:660', file='init/main.c', caller_inline=['init/main.c:setup_boot_config'], caller_func=[]),\n", + " FuncEntry(name='xbc_calc_checksum', external=False, inline=3, loc='include/linux/bootconfig.h:38', file='init/main.c', caller_inline=['init/main.c:setup_boot_config'], caller_func=[]),\n", + " FuncEntry(name='strscpy', external=True, inline=3, loc='include/linux/fortify-string.h:237', file='init/main.c', caller_inline=['init/main.c:setup_boot_config', 'init/main.c:parse_early_param'], caller_func=[]),\n", + " FuncEntry(name='xbc_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:setup_boot_config']),\n", + " FuncEntry(name='xbc_get_info', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:setup_boot_config']),\n", + " FuncEntry(name='xbc_make_cmdline', external=False, inline=-2, loc='init/main.c:358', file='init/main.c', caller_inline=[], caller_func=['init/main.c:setup_boot_config', 'init/main.c:setup_boot_config']),\n", + " FuncEntry(name='warn_bootconfig', external=False, inline=-2, loc='init/main.c:398', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='bootconfig_params', external=False, inline=-2, loc='init/main.c:389', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='xbc_find_node', external=False, inline=3, loc='include/linux/bootconfig.h:159', file='init/main.c', caller_inline=['init/main.c:xbc_make_cmdline'], caller_func=[]),\n", + " FuncEntry(name='xbc_node_find_subkey', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:xbc_make_cmdline']),\n", + " FuncEntry(name='xbc_snprint_cmdline', external=False, inline=-2, loc='init/main.c:322', file='init/main.c', caller_inline=[], caller_func=['init/main.c:xbc_make_cmdline', 'init/main.c:xbc_make_cmdline']),\n", + " FuncEntry(name='xbc_node_find_next_key_value', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:xbc_snprint_cmdline', 'init/main.c:xbc_snprint_cmdline']),\n", + " FuncEntry(name='xbc_node_compose_key_after', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:xbc_snprint_cmdline']),\n", + " FuncEntry(name='xbc_node_get_child', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:xbc_snprint_cmdline', 'init/main.c:xbc_snprint_cmdline']),\n", + " FuncEntry(name='xbc_node_get_data', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:xbc_snprint_cmdline', 'init/main.c:xbc_snprint_cmdline']),\n", + " FuncEntry(name='loglevel', external=False, inline=-2, loc='init/main.c:243', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='quiet_kernel', external=False, inline=-2, loc='init/main.c:234', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='debug_kernel', external=False, inline=-2, loc='init/main.c:228', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='set_reset_devices', external=False, inline=-2, loc='init/main.c:180', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kunit_run_all_tests', external=False, inline=3, loc='include/kunit/test.h:347', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__bpf_trace_initcall_finish', external=False, inline=-2, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__bpf_trace_initcall_start', external=False, inline=-2, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__bpf_trace_initcall_level', external=False, inline=-2, loc='include/trace/events/initcall.h:10', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='perf_trace_initcall_finish', external=False, inline=-2, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_event_get_offsets_initcall_finish', external=False, inline=3, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=['init/main.c:perf_trace_initcall_finish', 'init/main.c:trace_event_raw_event_initcall_finish'], caller_func=[]),\n", + " FuncEntry(name='bpf_prog_array_valid', external=False, inline=3, loc='include/linux/trace_events.h:439', file='init/main.c', caller_inline=['init/main.c:perf_trace_initcall_finish', 'init/main.c:perf_trace_initcall_start', 'init/main.c:perf_trace_initcall_level'], caller_func=[]),\n", + " FuncEntry(name='perf_fetch_caller_regs', external=False, inline=3, loc='include/linux/perf_event.h:1440', file='init/main.c', caller_inline=['init/main.c:perf_trace_initcall_finish', 'init/main.c:perf_trace_initcall_start', 'init/main.c:perf_trace_initcall_level'], caller_func=[]),\n", + " FuncEntry(name='hlist_empty', external=False, inline=3, loc='include/linux/list.h:978', file='init/main.c', caller_inline=['init/main.c:perf_trace_initcall_finish', 'init/main.c:perf_trace_initcall_start', 'init/main.c:perf_trace_initcall_level'], caller_func=[]),\n", + " FuncEntry(name='perf_trace_initcall_start', external=False, inline=-2, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_event_get_offsets_initcall_start', external=False, inline=3, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=['init/main.c:perf_trace_initcall_start', 'init/main.c:trace_event_raw_event_initcall_start'], caller_func=[]),\n", + " FuncEntry(name='perf_trace_initcall_level', external=False, inline=-2, loc='include/trace/events/initcall.h:10', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_event_get_offsets_initcall_level', external=False, inline=3, loc='include/trace/events/initcall.h:10', file='init/main.c', caller_inline=['init/main.c:perf_trace_initcall_level', 'init/main.c:trace_event_raw_event_initcall_level'], caller_func=[]),\n", + " FuncEntry(name='trace_event_raw_event_initcall_finish', external=False, inline=-2, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_trigger_soft_disabled', external=False, inline=3, loc='include/linux/trace_events.h:742', file='init/main.c', caller_inline=['init/main.c:trace_event_raw_event_initcall_finish', 'init/main.c:trace_event_raw_event_initcall_start', 'init/main.c:trace_event_raw_event_initcall_level'], caller_func=[]),\n", + " FuncEntry(name='trace_event_raw_event_initcall_start', external=False, inline=-2, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_event_raw_event_initcall_level', external=False, inline=-2, loc='include/trace/events/initcall.h:10', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_raw_output_initcall_finish', external=False, inline=-2, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_raw_output_initcall_start', external=False, inline=-2, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='trace_raw_output_initcall_level', external=False, inline=-2, loc='include/trace/events/initcall.h:10', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__probestub_initcall_finish', external=True, inline=-2, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__traceiter_initcall_finish', external=True, inline=-2, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_502', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_503', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__probestub_initcall_start', external=True, inline=-2, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__traceiter_initcall_start', external=True, inline=-2, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_499', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_500', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__probestub_initcall_level', external=True, inline=-2, loc='include/trace/events/initcall.h:10', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__traceiter_initcall_level', external=True, inline=-2, loc='include/trace/events/initcall.h:10', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_496', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_497', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='register_trace_initcall_finish', external=False, inline=3, loc='include/trace/events/initcall.h:48', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_488', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='register_trace_initcall_start', external=False, inline=3, loc='include/trace/events/initcall.h:27', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_480', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_472', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='context_tracking_init', external=False, inline=3, loc='include/linux/context_tracking.h:108', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='dbg_late_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='housekeeping_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='tick_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='efi_enabled', external=False, inline=3, loc='include/linux/efi.h:892', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='task_lock', external=False, inline=3, loc='include/linux/sched/task.h:221', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='spin_lock', external=False, inline=3, loc='include/linux/spinlock.h:349', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='_raw_spin_lock', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:set_mems_allowed']),\n", + " FuncEntry(name='arch_local_irq_save', external=False, inline=3, loc='arch/x86/include/asm/paravirt.h:701', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='arch_local_irq_disable', external=False, inline=3, loc='arch/x86/include/asm/paravirt.h:691', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed', 'init/main.c:start_kernel', 'init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='do_write_seqcount_begin', external=False, inline=3, loc='include/linux/seqlock.h:493', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='do_write_seqcount_begin_nested', external=False, inline=3, loc='include/linux/seqlock.h:467', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='do_raw_write_seqcount_begin', external=False, inline=3, loc='include/linux/seqlock.h:420', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='do_write_seqcount_end', external=False, inline=3, loc='include/linux/seqlock.h:513', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='do_raw_write_seqcount_end', external=False, inline=3, loc='include/linux/seqlock.h:441', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='arch_local_irq_restore', external=False, inline=3, loc='arch/x86/include/asm/irqflags.h:132', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='task_unlock', external=False, inline=3, loc='include/linux/sched/task.h:226', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='spin_unlock', external=False, inline=3, loc='include/linux/spinlock.h:389', file='init/main.c', caller_inline=['init/main.c:set_mems_allowed'], caller_func=[]),\n", + " FuncEntry(name='_raw_spin_unlock', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:set_mems_allowed']),\n", + " FuncEntry(name='kfence_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='rest_init', external=True, inline=-2, loc='init/main.c:684', file='init/main.c', caller_inline=[], caller_func=['init/main.c:arch_call_rest_init']),\n", + " FuncEntry(name='rcu_read_lock', external=False, inline=3, loc='include/linux/rcupdate.h:746', file='init/main.c', caller_inline=['init/main.c:rest_init', 'init/main.c:rest_init'], caller_func=[]),\n", + " FuncEntry(name='get_cpu_mask', external=False, inline=3, loc='include/linux/cpumask.h:1076', file='init/main.c', caller_inline=['init/main.c:rest_init'], caller_func=[]),\n", + " FuncEntry(name='rcu_read_unlock', external=False, inline=3, loc='include/linux/rcupdate.h:777', file='init/main.c', caller_inline=['init/main.c:rest_init', 'init/main.c:rest_init'], caller_func=[]),\n", + " FuncEntry(name='arch_call_rest_init', external=True, inline=-2, loc='init/main.c:825', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='start_kernel', external=True, inline=-2, loc='init/main.c:874', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='smp_prepare_boot_cpu', external=False, inline=3, loc='arch/x86/include/asm/smp.h:62', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='IS_ERR_OR_NULL', external=False, inline=3, loc='include/linux/err.h:70', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='boot_init_stack_canary', external=False, inline=3, loc='arch/x86/include/asm/stackprotector.h:50', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='get_random_canary', external=False, inline=3, loc='include/linux/stackprotector.h:23', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='get_random_long', external=False, inline=3, loc='include/linux/random.h:44', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='constant_test_bit', external=False, inline=3, loc='arch/x86/include/asm/bitops.h:203', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='__phys_addr_nodebug', external=False, inline=3, loc='arch/x86/include/asm/page_64.h:21', file='init/main.c', caller_inline=['init/main.c:start_kernel'], caller_func=[]),\n", + " FuncEntry(name='setup_nr_cpu_ids', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='parse_early_param', external=True, inline=-2, loc='init/main.c:759', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='random_init_early', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='setup_log_buf', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='vfs_caches_init_early', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='poking_init', external=True, inline=-2, loc='init/main.c:785', file='init/main.c', caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='workqueue_init_early', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='hrtimers_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='random_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='call_function_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='kmem_cache_init_late', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='cred_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='vfs_caches_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='pagecache_init', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=['init/main.c:start_kernel']),\n", + " FuncEntry(name='xbc_get_embedded_bootconfig', external=False, inline=3, loc='include/linux/bootconfig.h:296', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_353', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_352', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='pgtable_cache_init', external=True, inline=-2, loc='init/main.c:787', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__kmalloc_index', external=False, inline=3, loc='include/linux/slab.h:434', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kmalloc_type', external=False, inline=3, loc='include/linux/slab.h:391', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kcsan_init', external=False, inline=3, loc='include/linux/kcsan.h:71', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='hash_64_generic', external=False, inline=3, loc='include/linux/hash.h:74', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='debug_objects_early_init', external=False, inline=3, loc='include/linux/debugobjects.h:103', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__seqprop_spinlock_assert', external=False, inline=3, loc='include/linux/seqlock.h:227', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__seqprop_spinlock_preemptible', external=False, inline=3, loc='include/linux/seqlock.h:227', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__seqprop_spinlock_ptr', external=False, inline=3, loc='include/linux/seqlock.h:227', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_62', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='cpumask_check', external=False, inline=3, loc='include/linux/cpumask.h:148', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='cpu_max_bits_warn', external=False, inline=3, loc='include/linux/cpumask.h:140', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='fortify_memcpy_chk', external=True, inline=3, loc='include/linux/fortify-string.h:504', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='instrument_atomic_read_write', external=False, inline=3, loc='include/linux/instrumented.h:94', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='instrument_atomic_read', external=False, inline=3, loc='include/linux/instrumented.h:66', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='const_test_bit', external=False, inline=3, loc='include/asm-generic/bitops/generic-non-atomic.h:166', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__this_cpu_preempt_check', external=False, inline=3, loc='include/linux/percpu-defs.h:313', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='parse_early_options', external=True, inline=1, loc='init/main.c:752', file='init/main.c', caller_inline=['init/main.c:parse_early_param'], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_12', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_4', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__compiletime_assert_2', external=True, inline=-1, loc=None, file=None, caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='__list_add_valid', external=False, inline=3, loc='include/linux/list.h:128', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kcsan_check_access', external=False, inline=-2, loc='include/linux/kcsan-checks.h:229', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kcsan_nestable_atomic_end', external=False, inline=3, loc='include/linux/kcsan-checks.h:200', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kcsan_nestable_atomic_begin', external=False, inline=3, loc='include/linux/kcsan-checks.h:199', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kasan_check_write', external=False, inline=-2, loc='include/linux/kasan-checks.h:44', file='init/main.c', caller_inline=[], caller_func=[]),\n", + " FuncEntry(name='kasan_check_read', external=False, inline=-2, loc='include/linux/kasan-checks.h:40', file='init/main.c', caller_inline=[], caller_func=[])]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from depsurf import FunctionRecorder, VERSION_DEFAULT\n", + "\n", + "\n", + "def cus_mapper(cus):\n", + " return [\n", + " next(cu for cu in cus if cu.get_top_DIE().get_full_path().endswith(\"main.c\"))\n", + " ]\n", + "\n", + " result = []\n", + " for cu in cus:\n", + " path = cu.get_top_DIE().get_full_path()\n", + " if path.endswith(\"kernel/cpu.c\"):\n", + " result.append(cu)\n", + " if path.endswith(\"arch/x86/kernel/smpboot.c\"):\n", + " result.append(cu)\n", + " if len(result) == 2:\n", + " break\n", + "\n", + " return result\n", + "\n", + "\n", + "recorder = FunctionRecorder.from_path(\n", + " path=VERSION_DEFAULT.vmlinux_path,\n", + " cus_mapper=cus_mapper,\n", + " debug=True,\n", + ")\n", + "\n", + "list(recorder.iter_funcs())" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "__raw_spin_unlock ['__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock.constprop.0', '__raw_spin_unlock.constprop.0', '__raw_spin_unlock.constprop.0', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock', '__raw_spin_unlock.constprop.0', '__raw_spin_unlock.constprop.0']\n", + "clear_bit ['clear_bit', 'clear_bit', 'clear_bit.constprop.0', 'clear_bit.constprop.0']\n", + "unwind_next_frame ['unwind_next_frame.part.0', 'unwind_next_frame.part.0.cold', 'unwind_next_frame']\n", + "kzalloc ['kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc', 'kzalloc.constprop.0', 'kzalloc', 'kzalloc.constprop.0', 'kzalloc', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc', 'kzalloc', 'kzalloc', 'kzalloc', 'kzalloc.constprop.0', 'kzalloc', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0', 'kzalloc.constprop.0']\n", + "wrmsrl ['wrmsrl', 'wrmsrl', 'wrmsrl', 'wrmsrl.constprop.0', 'wrmsrl', 'wrmsrl']\n", + "cpumask_weight ['cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0', 'cpumask_weight', 'cpumask_weight.constprop.0', 'cpumask_weight.constprop.0']\n", + "set_bit ['set_bit', 'set_bit.constprop.0', 'set_bit', 'set_bit', 'set_bit.constprop.0', 'set_bit', 'set_bit', 'set_bit.constprop.0', 'set_bit', 'set_bit', 'set_bit', 'set_bit', 'set_bit', 'set_bit']\n", + "kmalloc_array ['kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array', 'kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array', 'kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array', 'kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array.constprop.0', 'kmalloc_array', 'kmalloc_array.constprop.0', 'kmalloc_array']\n", + "bitmap_zero ['bitmap_zero', 'bitmap_zero.constprop.0', 'bitmap_zero', 'bitmap_zero.constprop.0', 'bitmap_zero.constprop.0']\n", + "hv_send_ipi_mask_allbutself ['hv_send_ipi_mask_allbutself.part.0', 'hv_send_ipi_mask_allbutself', 'hv_send_ipi_mask_allbutself.cold']\n", + "collect_cpu_info ['collect_cpu_info', 'collect_cpu_info', 'collect_cpu_info.cold']\n", + "__nodes_weight ['__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0', '__nodes_weight.constprop.0']\n", + "uv_gam_range ['uv_gam_range', 'uv_gam_range', 'uv_gam_range.cold']\n", + "is_uv3_hub ['is_uv3_hub.part.0', 'is_uv3_hub.part.0', 'is_uv3_hub.part.0']\n", + "is_uv2_hub ['is_uv2_hub.part.0', 'is_uv2_hub.part.0', 'is_uv2_hub.part.0']\n", + "x2apic_acpi_madt_oem_check ['x2apic_acpi_madt_oem_check', 'x2apic_acpi_madt_oem_check.cold', 'x2apic_acpi_madt_oem_check']\n", + "amd_cache_northbridges ['amd_cache_northbridges.part.0', 'amd_cache_northbridges.part.0.cold', 'amd_cache_northbridges']\n", + "gart_map_sg ['gart_map_sg.part.0', 'gart_map_sg.part.0.cold', 'gart_map_sg']\n", + "alloc_iommu ['alloc_iommu', 'alloc_iommu', 'alloc_iommu.cold']\n", + "free_memtype ['free_memtype.part.0', 'free_memtype.part.0.cold', 'free_memtype']\n", + "__raw_spin_unlock_irq ['__raw_spin_unlock_irq.constprop.0', '__raw_spin_unlock_irq', '__raw_spin_unlock_irq']\n", + "ftrace_dump ['ftrace_dump.part.0', 'ftrace_dump.part.0.cold', 'ftrace_dump']\n", + "assert_clock_updated ['assert_clock_updated.isra.0.part.0', 'assert_clock_updated.isra.0.part.0', 'assert_clock_updated.isra.0.part.0']\n", + "print_cpu ['print_cpu', 'print_cpu.cold', 'print_cpu']\n", + "state_store ['state_store', 'state_store', 'state_store', 'state_store', 'state_store.cold', 'state_store']\n", + "do_poweroff ['do_poweroff', 'do_poweroff', 'do_poweroff.cold']\n", + "audit_log_start ['audit_log_start.part.0', 'audit_log_start.part.0.cold', 'audit_log_start']\n", + "trace_module_notify ['trace_module_notify', 'trace_module_notify', 'trace_module_notify.cold']\n", + "out_of_memory ['out_of_memory.part.0', 'out_of_memory.part.0.cold', 'out_of_memory']\n", + "dio_warn_stale_pagecache ['dio_warn_stale_pagecache.part.0', 'dio_warn_stale_pagecache.part.0.cold', 'dio_warn_stale_pagecache']\n", + "elf_map ['elf_map', 'elf_map.cold', 'elf_map', 'elf_map.cold']\n", + "parse_options ['parse_options', 'parse_options', 'parse_options.cold', 'parse_options']\n", + "__jbd2_journal_abort_hard ['__jbd2_journal_abort_hard.part.0', '__jbd2_journal_abort_hard.cold', '__jbd2_journal_abort_hard']\n", + "lzo_init ['lzo_init', 'lzo_init.cold', 'lzo_init']\n", + "start_creating ['start_creating', 'start_creating.cold', 'start_creating']\n", + "allocate_buf_for_compression ['allocate_buf_for_compression.part.0', 'allocate_buf_for_compression.part.0.cold', 'allocate_buf_for_compression', 'allocate_buf_for_compression.cold']\n", + "datablob_parse ['datablob_parse', 'datablob_parse', 'datablob_parse.cold']\n", + "template_desc_init_fields ['template_desc_init_fields.part.0', 'template_desc_init_fields.part.0.cold', 'template_desc_init_fields']\n", + "put_partition ['put_partition', 'put_partition', 'put_partition.part.0', 'put_partition']\n", + "phy_exit ['phy_exit.cold', 'phy_exit', 'phy_exit']\n", + "phy_init ['phy_init.cold', 'phy_init', 'phy_init']\n", + "unexport_store ['unexport_store', 'unexport_store.cold', 'unexport_store']\n", + "export_store ['export_store', 'export_store.cold', 'export_store']\n", + "pwm_put ['pwm_put.part.0', 'pwm_put.part.0.cold', 'pwm_put']\n", + "pcie_bus_configure_set ['pcie_bus_configure_set.part.0', 'pcie_bus_configure_set.part.0.cold', 'pcie_bus_configure_set']\n", + "get_adapter_status ['get_adapter_status', 'get_adapter_status', 'get_adapter_status', 'get_adapter_status.cold', 'get_adapter_status']\n", + "get_latch_status ['get_latch_status', 'get_latch_status', 'get_latch_status', 'get_latch_status.cold', 'get_latch_status']\n", + "get_attention_status ['get_attention_status', 'get_attention_status', 'get_attention_status.cold', 'get_attention_status']\n", + "get_power_status ['get_power_status', 'get_power_status', 'get_power_status', 'get_power_status.cold', 'get_power_status']\n", + "set_attention_status ['set_attention_status', 'set_attention_status', 'set_attention_status', 'set_attention_status.cold', 'set_attention_status']\n", + "disable_slot ['disable_slot', 'disable_slot.cold', 'disable_slot', 'disable_slot.cold', 'disable_slot', 'disable_slot']\n", + "enable_slot ['enable_slot', 'enable_slot.cold', 'enable_slot', 'enable_slot.cold', 'enable_slot', 'enable_slot']\n", + "efifb_probe ['efifb_probe.part.0', 'efifb_probe', 'efifb_probe.cold']\n", + "acpi_create_platform_device ['acpi_create_platform_device.part.0', 'acpi_create_platform_device.part.0.cold', 'acpi_create_platform_device']\n", + "acpi_os_allocate ['acpi_os_allocate', 'acpi_os_allocate', 'acpi_os_allocate', 'acpi_os_allocate.constprop.0', 'acpi_os_allocate', 'acpi_os_allocate']\n", + "acpi_processor_get_platform_limit ['acpi_processor_get_platform_limit', 'acpi_processor_get_platform_limit', 'acpi_processor_get_platform_limit.cold']\n", + "thermal_zone_device_update ['thermal_zone_device_update.part.0', 'thermal_zone_device_update.part.0.cold', 'thermal_zone_device_update']\n", + "setup_vq ['setup_vq', 'setup_vq.cold', 'setup_vq', 'setup_vq.cold']\n", + "vp_finalize_features ['vp_finalize_features', 'vp_finalize_features.cold', 'vp_finalize_features']\n", + "init_vqs ['init_vqs', 'init_vqs.cold', 'init_vqs']\n", + "__do_SAK ['__do_SAK.part.0', '__do_SAK.part.0.cold', '__do_SAK']\n", + "hpet_acpi_add ['hpet_acpi_add.part.0', 'hpet_acpi_add', 'hpet_acpi_add.cold']\n", + "amd_iommu_add_device ['amd_iommu_add_device.part.0', 'amd_iommu_add_device.part.0.cold', 'amd_iommu_add_device']\n", + "dmar_set_interrupt ['dmar_set_interrupt.part.0', 'dmar_set_interrupt.part.0.cold', 'dmar_set_interrupt']\n", + "uevent_store ['uevent_store', 'uevent_store.cold', 'uevent_store']\n", + "level_show ['level_show', 'level_show', 'level_show.cold', 'level_show']\n", + "sg_write ['sg_write.part.0', 'sg_write.part.0.cold', 'sg_write']\n", + "ata_host_start ['ata_host_start.part.0', 'ata_host_start.part.0.cold', 'ata_host_start']\n", + "ata_read_log_page ['ata_read_log_page.part.0', 'ata_read_log_page.part.0.cold', 'ata_read_log_page']\n", + "cdrom_sysctl_info ['cdrom_sysctl_info.part.0', 'cdrom_sysctl_info.part.0.cold', 'cdrom_sysctl_info']\n", + "level_store ['level_store', 'level_store.cold', 'level_store', 'level_store.cold']\n", + "speed_show ['speed_show', 'speed_show.part.0', 'speed_show']\n", + "xhci_discover_or_reset_device ['xhci_discover_or_reset_device', 'xhci_discover_or_reset_device.part.0', 'xhci_discover_or_reset_device.part.0.cold']\n", + "xhci_add_endpoint ['xhci_add_endpoint', 'xhci_add_endpoint.part.0', 'xhci_add_endpoint.part.0.cold']\n", + "xhci_hc_died ['xhci_hc_died.part.0', 'xhci_hc_died.cold', 'xhci_hc_died']\n", + "i2c_acpi_notify ['i2c_acpi_notify.part.0', 'i2c_acpi_notify', 'i2c_acpi_notify.cold']\n", + "i2c_acpi_find_bus_speed ['i2c_acpi_find_bus_speed.part.0', 'i2c_acpi_find_bus_speed.part.0.cold', 'i2c_acpi_find_bus_speed']\n", + "i2cdev_attach_adapter ['i2cdev_attach_adapter', 'i2cdev_attach_adapter.part.0', 'i2cdev_attach_adapter.part.0.cold']\n", + "__cec_s_phys_addr ['__cec_s_phys_addr.part.0', '__cec_s_phys_addr.part.0.cold', '__cec_s_phys_addr']\n", + "__power_supply_register ['__power_supply_register.part.0', '__power_supply_register', '__power_supply_register.cold']\n", + "edac_pci_do_parity_check ['edac_pci_do_parity_check.part.0', 'edac_pci_do_parity_check.part.0.cold', 'edac_pci_do_parity_check']\n", + "governor_store ['governor_store', 'governor_store', 'governor_store.cold']\n", + "mmc_runtime_resume ['mmc_runtime_resume', 'mmc_runtime_resume', 'mmc_runtime_resume.cold']\n", + "mmc_runtime_suspend ['mmc_runtime_suspend', 'mmc_runtime_suspend', 'mmc_runtime_suspend.cold']\n", + "netdev_rx_csum_fault ['netdev_rx_csum_fault.part.0', 'netdev_rx_csum_fault.cold', 'netdev_rx_csum_fault']\n", + "ipv6_add_dev ['ipv6_add_dev.part.0', 'ipv6_add_dev.part.0.cold', 'ipv6_add_dev']\n" + ] + } + ], + "source": [ + "from depsurf import VERSION_DEFAULT\n", + "\n", + "for group in VERSION_DEFAULT.img.func_groups.iter_groups():\n", + " if group.has_suffix:\n", + " if len(group.symbols) > 2:\n", + " print(group.name, [sym.name for sym in group.symbols])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/95_test_relo.ipynb b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/95_test_relo.ipynb new file mode 100644 index 00000000..ad9daa73 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/95_test_relo.ipynb @@ -0,0 +1,93 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%reload_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing tmp.bpf.c\n" + ] + } + ], + "source": [ + "%%writefile tmp.bpf.c\n", + "struct task_struct {\n", + " int i;\n", + " int j;\n", + " int k;\n", + " struct inner {\n", + " int a;\n", + " int b;\n", + " } s;\n", + "} __attribute__((preserve_access_index));\n", + "\n", + "int f(struct task_struct* foo) { \n", + " return foo->s.b;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "tmp.bpf.o:\tfile format elf64-bpf\n", + "\n", + "Disassembly of section .text:\n", + "\n", + "0000000000000000 :\n", + "; return foo->s.b;\n", + " 0:\t61 10 10 00 00 00 00 00\tr0 = *(u32 *)(r1 + 0x10)\n", + "\t\t0000000000000000: CO-RE [2] struct task_struct::s.b (0:3:1)\n", + " 1:\t95 00 00 00 00 00 00 00\texit\n" + ] + } + ], + "source": [ + "!clang -g -O2 -target bpf -c tmp.bpf.c -o tmp.bpf.o\n", + "!llvm-objdump --disassemble --reloc --source tmp.bpf.o\n", + "!rm tmp.bpf.c tmp.bpf.o" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/README.md b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/README.md new file mode 100644 index 00000000..48d4a60d --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/README.md @@ -0,0 +1,3 @@ +This directory contains archived code that has been deprecated from the main repository. + +While some of this code may no longer be functional, it is preserved here for reference and potential future use. \ No newline at end of file diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/depsurf/bpftool.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/depsurf/bpftool.py new file mode 100644 index 00000000..bfb173f8 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/depsurf/bpftool.py @@ -0,0 +1,18 @@ +def get_linux_tools_path(): + parent = Path("/usr/lib/linux-tools") + versions = [x for x in parent.iterdir() if x.is_dir()] + if len(versions) == 0: + raise Exception("No linux-tools found") + versions.sort() + return parent / versions[-1] + + +def get_bpftool_path(): + bpftool_path = BPFTOOL_SRC_PATH / "bpftool" + if bpftool_path.exists(): + return bpftool_path + + path = get_linux_tools_path() / "bpftool" + if not path.exists(): + raise Exception("bpftool not found") + return path diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/depsurf/relo.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/depsurf/relo.py new file mode 100644 index 00000000..e473ac8e --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/depsurf/relo.py @@ -0,0 +1,299 @@ +import json +from dataclasses import dataclass +from enum import Enum + +from elftools.construct import Struct, ULInt8, ULInt16, ULInt32 +from elftools.elf.elffile import ELFFile + +from depsurf.btf import Kind +from depsurf.linux import get_cstr + + +class RawBTF: + def __init__(self, raw_types): + self.raw_types = raw_types + + @classmethod + def load(cls, path): + with open(path) as f: + return cls(json.load(f)["types"]) + + def get_raw(self, type_id): + elem = self.raw_types[type_id - 1] + assert elem["id"] == type_id + return elem + + def __len__(self): + return len(self.raw_types) + + def __repr__(self): + return f"RawBTF({len(self.raw_types)} types)" + + +btf_header_t = Struct( + "btf_header", + ULInt16("magic"), + ULInt8("version"), + ULInt8("flags"), + ULInt32("hdr_len"), + # type + ULInt32("type_off"), + ULInt32("type_len"), + # string + ULInt32("str_off"), + ULInt32("str_len"), +) + +btf_ext_header_t = Struct( + "btf_ext_header", + ULInt16("magic"), + ULInt8("version"), + ULInt8("flags"), + ULInt32("hdr_len"), + # func + ULInt32("func_info_off"), + ULInt32("func_info_len"), + # line + ULInt32("line_info_off"), + ULInt32("line_info_len"), + # core + ULInt32("core_relo_off"), + ULInt32("core_relo_len"), +) + +rec_size_t = ULInt32("rec_size") + +btf_ext_info_sec_t = Struct( + "btf_ext_info_sec", + ULInt32("sec_name_off"), + ULInt32("num_info"), +) + +bpf_core_relo_t = Struct( + "bpf_core_relo", + ULInt32("insn_off"), + ULInt32("type_id"), + ULInt32("access_str_off"), + ULInt32("kind"), +) + + +@dataclass +class BTFStrtab: + strtab: bytes + + def __init__(self, elf: ELFFile): + btf = elf.get_section_by_name(".BTF") + + data = btf.data() + header = btf_header_t.parse(data) + + off = header.hdr_len + header.str_off + self.strtab = data[off : off + header.str_len] + + def get(self, off): + return get_cstr(self.strtab, off) + + +class BTFCoreReloKind(Enum): + FIELD_BYTE_OFFSET = 0 # field byte offset + FIELD_BYTE_SIZE = 1 # field size in bytes + FIELD_EXISTS = 2 # field existence in target kernel + FIELD_SIGNED = 3 # field signedness (0 - unsigned, 1 - signed) + FIELD_LSHIFT_U64 = 4 # bitfield-specific left bitshift + FIELD_RSHIFT_U64 = 5 # bitfield-specific right bitshift + TYPE_ID_LOCAL = 6 # type ID in local BPF object + TYPE_ID_TARGET = 7 # type ID in target kernel + TYPE_EXISTS = 8 # type existence in target kernel + TYPE_SIZE = 9 # type size in bytes + ENUMVAL_EXISTS = 10 # enum value existence in target kernel + ENUMVAL_VALUE = 11 # enum value integer value + TYPE_MATCHES = 12 # type match in target kernel + + @property + def name(self): + return { + BTFCoreReloKind.FIELD_BYTE_OFFSET: "byte_off", + BTFCoreReloKind.FIELD_BYTE_SIZE: "byte_sz", + BTFCoreReloKind.FIELD_EXISTS: "field_exists", + BTFCoreReloKind.FIELD_SIGNED: "signed", + BTFCoreReloKind.FIELD_LSHIFT_U64: "lshift_u64", + BTFCoreReloKind.FIELD_RSHIFT_U64: "rshift_u64", + BTFCoreReloKind.TYPE_ID_LOCAL: "local_type_id", + BTFCoreReloKind.TYPE_ID_TARGET: "target_type_id", + BTFCoreReloKind.TYPE_EXISTS: "type_exists", + BTFCoreReloKind.TYPE_SIZE: "type_size", + BTFCoreReloKind.ENUMVAL_EXISTS: "enumval_exists", + BTFCoreReloKind.ENUMVAL_VALUE: "enumval_value", + BTFCoreReloKind.TYPE_MATCHES: "type_matches", + }[self] + + +@dataclass(eq=True, frozen=True, order=True, repr=False) +class Dep: + kind: Kind + name: str + member: str = "" + + @classmethod + def from_t(cls, t, member=""): + return cls(t["kind"], t["name"].split("___")[0], member) + + def __repr__(self): + s = f"{self.kind.lower()} {self.name}" + if self.member != "": + s += f"::{self.member}" + return s + + +class BTFReloEntry: + def __init__(self, data, strtab: BTFStrtab, btf_types: RawBTF): + header = bpf_core_relo_t.parse(data) + + self.insn_off = header.insn_off + self.type_id = header.type_id + self.access_str = strtab.get(header.access_str_off) + self.kind = BTFCoreReloKind(header.kind) + self.btf_types = btf_types + + t = btf_types.get_raw(header.type_id) + self.string = f"{Dep.from_t(t)}" + + access_nums = [int(num) for num in self.access_str.split(":")] + + if t["kind"] == Kind.ENUM: + assert len(access_nums) == 1 + num = access_nums[0] + value = t["values"][num] + name = value["name"] + self.string += f".{name}" + self.deps = [Dep.from_t(t, name)] + return + + assert access_nums[0] == 0 + if len(access_nums) == 1: + self.deps = [Dep.from_t(t)] + return + + deps = [] + for num in access_nums[1:]: + t = self.handle(num, t, deps) + + self.deps = self.normalize_deps(deps) + + def normalize_deps(self, deps): + new_deps = [] + + for dep in deps: + is_type_anon = dep.name == "(anon)" + is_member_anon = dep.member == "(anon)" + + if is_member_anon and is_type_anon: + continue + + if is_type_anon: + new_deps.append(Dep(named_dep.kind, named_dep.name, dep.member)) + named_dep = None + continue + else: + named_dep = dep + + if is_member_anon: + continue + + new_deps.append(dep) + + return new_deps + + def handle(self, num, t, deps): + if "members" in t: + member = t["members"][num] + name = member["name"] + self.string += f".{name}" + deps.append(Dep.from_t(t, name)) + return self.btf_types.get_raw(member["type_id"]) + elif t["kind"] == Kind.ARRAY: + self.string += f"[{num}]" + return self.btf_types.get_raw(t["type_id"]), None + elif t["kind"] == Kind.TYPEDEF: + deps.append(Dep.from_t(t)) + real_t = self.btf_types.get_raw(t["type_id"]) + return self.handle(num, real_t, deps) + + assert False, f"Unhandled type: {t['kind']}" + + def __repr__(self): + return f"{self.insn_off:04x}: CO-RE <{self.kind.name}> [{self.type_id}] {self.string} ({self.access_str})\n\t\t deps on {self.deps}" + + +class BTFReloSection: + def __init__(self, data, strtab: BTFStrtab, btf_types: RawBTF): + header = btf_ext_info_sec_t.parse(data) + + self.sec_name = strtab.get(header.sec_name_off) + self.relocations = [ + BTFReloEntry(data[self.get_off(i) : self.get_off(i + 1)], strtab, btf_types) + for i in range(header.num_info) + ] + + def get_off(self, i): + return btf_ext_info_sec_t.sizeof() + i * bpf_core_relo_t.sizeof() + + @property + def size(self): + return self.get_off(len(self.relocations)) + + def __repr__(self): + s = f"Relocation for {self.sec_name}:\n\t" + s += "\n\t".join(map(str, self.relocations)) + return s + + +class BTFReloInfo: + def __init__(self, data, strtab: BTFStrtab, btf_types: RawBTF): + self.relo_sections = [] + + if len(data) == 0: + return + + assert rec_size_t.parse(data) == bpf_core_relo_t.sizeof() + data = data[rec_size_t.sizeof() :] + while len(data) > 0: + sec = BTFReloSection(data, strtab, btf_types) + self.relo_sections.append(sec) + data = data[sec.size :] + + def get_deps(self): + return sorted( + { + dep + for sec in self.relo_sections + for relo in sec.relocations + for dep in relo.deps + } + ) + + def __repr__(self): + return "\n".join(map(str, self.relo_sections)) + + +@dataclass +class BTFExtSection: + func_info: bytes + line_info: bytes + relo_info: bytes + + @classmethod + def from_elf(cls, elf: ELFFile): + btf_ext = elf.get_section_by_name(".BTF.ext").data() + header = btf_ext_header_t.parse(btf_ext) + + def get_slice(off, size): + off += header.hdr_len + return btf_ext[off : off + size] + + return cls( + get_slice(header.func_info_off, header.func_info_len), + get_slice(header.line_info_off, header.line_info_len), + get_slice(header.core_relo_off, header.core_relo_len), + ) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/.gitignore b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/.gitignore new file mode 100644 index 00000000..8e8b287e --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/.gitignore @@ -0,0 +1,3 @@ +cmake-build-* +.idea +build diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/CMakeLists.txt b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/CMakeLists.txt new file mode 100644 index 00000000..aa4a76d2 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/CMakeLists.txt @@ -0,0 +1,78 @@ +cmake_minimum_required(VERSION 3.16) +project(ebpf) +set(CMAKE_CXX_STANDARD 20) + +# Tell cmake where to find BpfObject module +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/libbpf-bootstrap/tools/cmake) + +# Build vendored libbpf +include(ExternalProject) +ExternalProject_Add(libbpf + PREFIX libbpf + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libbpf-bootstrap/libbpf/src + CONFIGURE_COMMAND "" + BUILD_COMMAND make + BUILD_STATIC_ONLY=1 + OBJDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf + DESTDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf + INCLUDEDIR= + LIBDIR= + UAPIDIR= + install install_uapi_headers + BUILD_IN_SOURCE TRUE + INSTALL_COMMAND "" + STEP_TARGETS build + ) + +ExternalProject_Add(bpftool + PREFIX bpftool + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libbpf-bootstrap/bpftool/src + CONFIGURE_COMMAND "" + BUILD_COMMAND make bootstrap + OUTPUT=${CMAKE_CURRENT_BINARY_DIR}/bpftool/ + BUILD_IN_SOURCE TRUE + INSTALL_COMMAND "" + STEP_TARGETS build + ) + +# Set BpfObject input parameters -- note this is usually not necessary unless +# you're in a highly vendored environment (like libbpf-bootstrap) +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") + set(ARCH "x86") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") + set(ARCH "arm") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64") + set(ARCH "arm64") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc64le") + set(ARCH "powerpc") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips") + set(ARCH "mips") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "riscv64") + set(ARCH "riscv") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "loongarch64") + set(ARCH "loongarch") +endif() + +set(BPFOBJECT_BPFTOOL_EXE ${CMAKE_CURRENT_BINARY_DIR}/bpftool/bootstrap/bpftool) +set(BPFOBJECT_VMLINUX_H ${CMAKE_CURRENT_SOURCE_DIR}/libbpf-bootstrap/vmlinux/${ARCH}/vmlinux.h) +set(LIBBPF_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/libbpf) +set(LIBBPF_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf.a) +find_package(BpfObject REQUIRED) + +# Generate BPF skeleton +bpf_object(ebpf ebpf.bpf.c) +add_dependencies(ebpf_skel libbpf-build bpftool-build) + +# Add BPF skeleton to target +add_executable(ebpf ebpf.cpp) +target_link_libraries(ebpf ebpf_skel pthread) + +# For highlighting in IDE +add_library(ebpf_bpf OBJECT ${BPF_C_FILE}) +target_include_directories(ebpf_bpf PRIVATE ${GENERATED_VMLINUX_DIR}) +target_include_directories(ebpf_bpf SYSTEM PRIVATE ${LIBBPF_INCLUDE_DIRS}) +set_target_properties(ebpf_bpf PROPERTIES EXCLUDE_FROM_ALL TRUE) + + +# add_executable(main main.cpp) + diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/Makefile b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/Makefile new file mode 100644 index 00000000..cc8d4781 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/Makefile @@ -0,0 +1,15 @@ +.DEFAULT_GOAL := ebpf +.PHONY: config all clean ebpf + +config: + cmake -B build -S . -DCMAKE_BUILD_TYPE=Release + +all: config + cmake --build build + +ebpf: config + cmake --build build --target ebpf + sudo ./build/ebpf + +clean: + rm -rf build diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/README.md b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/README.md new file mode 100644 index 00000000..5c37bd1d --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/README.md @@ -0,0 +1,44 @@ +## Install Dependencies + +Install + +```sh +sudo apt install make cmake clang-12 llvm-12 pkg-config libelf-dev binutils-dev libcap-dev g++ +``` + +Set clang-12 and clang++-12 to be the default clang +``` +sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-12 100 +sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-12 100 +``` + + +Install `bpftrace` on Ubuntu: + +```sh +sudo apt install bpftrace +``` + +# Hello World for `bpftrace`: + +```sh +sudo bpftrace -e 'BEGIN { printf("Hello eBPF!\n"); }' +``` + +```sh +sudo bpftrace --unsafe -e 'BEGIN {system("echo \"hello\"");}' +``` + +```sh +sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("Hi! %s %s\n", comm, str(args->filename)) }' +``` + + +Cheat Sheet: https://www.brendangregg.com/BPF/bpftrace-cheat-sheet.html + +List all tracepoints: + +```sh +sudo bpftrace -l +sudo bpftrace -lv 'tracepoint:*enter_read' +``` diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/ebpf.bpf.c b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/ebpf.bpf.c new file mode 100644 index 00000000..31a75ac2 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/ebpf.bpf.c @@ -0,0 +1,106 @@ +#include "vmlinux.h" + +#include +#include +#include + +char LICENSE[] SEC("license") = "GPL"; + +// struct task_struct___foo { +// union { +// struct { +// struct { +// int foo; +// int bar; +// unsigned int __state; +// }; +// }; +// }; +// } __attribute__((preserve_access_index)); + +// SEC("kprobe/close_fd") +// int prog(struct pt_regs* ctx) { +// struct task_struct___foo* t = (void*)PT_REGS_PARM1(ctx); // get the 1st +// arg return t->__state; +// } + +// static __always_inline int strncmp(const char *s1, const char *s2, +// unsigned long n) { +// int i; +// for (i = 0; i < n; i++) { +// if (s1[i] != s2[i]) { +// return s1[i] - s2[i]; +// } +// } +// return 0; +// } + +// SEC("lsm/inode_setxattr") +// int prog(struct pt_regs *ctx) { +// const char *name = (const char *)PT_REGS_PARM2(ctx); + +// char name_buf[32]; // copy name to stack +// bpf_probe_read_str(name_buf, 32, name); + +// if (strncmp(name_buf, "user.malicious", 14) == 0) +// return -EACCES; // reject "user.malicious" xattr +// return 0; +// } +// setfattr -n user.malicious -v val /tmp/test + +// struct { +// __uint(type, BPF_MAP_TYPE_RINGBUF); +// __uint(max_entries, 1024); +// } fds SEC(".maps"); + +// SEC("kprobe/close_fd") +// int prog(struct pt_regs *ctx) { +// int fd = PT_REGS_PARM1(ctx); // get the 1st arg +// bpf_ringbuf_output(&fds, &fd, sizeof(fd), 0); +// return 0; // not used +// } + +// struct { +// __uint(type, BPF_MAP_TYPE_RINGBUF); +// __uint(max_entries, 1024); +// } rb SEC(".maps"); + +// SEC("kprobe/vfs_statx") +// int prog(struct pt_regs *ctx) { +// struct filename *fnp = (void *)PT_REGS_PARM2(ctx); // get the 1st arg +// char *filename = BPF_CORE_READ(fnp, name); + +// char buf[32] = {'h', 'e', 'l'}; +// // bpf_probe_read_str(buf, sizeof(buf), filename); +// bpf_ringbuf_output(&rb, &buf, 32, 0); +// return 0; // not used +// } + +// SEC("kprobe/do_execveat_common") +// int prog(struct pt_regs *ctx) { +// // unsigned long arg1 = ctx->di; +// unsigned long arg1 = PT_REGS_PARM2(ctx); +// struct filename *f = (void *)arg1; +// const char *str; +// bpf_probe_read(&str, sizeof(str), &f->name); +// bpf_printk("execve: %s", name); +// } + +SEC("kprobe/do_unlinkat") +int prog(struct pt_regs *ctx) { + struct filename *f = (void *)PT_REGS_PARM1(ctx); + const char *str; + bpf_probe_read(&str, sizeof(str), &f->name); + bpf_printk("unlinkat: %s", str); + return 0; +} + +// SEC("fentry/do_unlinkat") +// int BPF_PROG(bar) { +// void*** arg1 = (void*)ctx[0]; + +// bpf_printk("arg1 = %pK, *arg1 = %pK (%s)", arg1, *arg1, *arg1); + +// // bpf_printk("filename = %p", *((void **)ctx[1] + 1000)); +// return 0; +// } diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/ebpf.cpp b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/ebpf.cpp new file mode 100644 index 00000000..624a7efd --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/ebpf.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "ebpf.skel.h" + +struct BPF { + BPF() { + libbpf_set_print( + [](enum libbpf_print_level level, const char* format, va_list args) { + switch (level) { + case LIBBPF_DEBUG: + fprintf(stderr, "\033[1;30m[DEBUG]\033[0m "); + break; + case LIBBPF_INFO: + fprintf(stderr, "\033[1;32m[INFO] \033[0m "); + break; + case LIBBPF_WARN: + fprintf(stderr, "\033[1;33m[WARN] \033[0m "); + break; + } + return vfprintf(stderr, format, args); + }); + + skel = ebpf_bpf__open(); + if (!skel) throw std::runtime_error("Failed to open BPF skeleton"); + + if (ebpf_bpf__load(skel)) + throw std::runtime_error("Failed to load BPF skeleton"); + + if (ebpf_bpf__attach(skel)) + throw std::runtime_error("Failed to attach BPF skeleton"); + } + + ~BPF() { ebpf_bpf__destroy(skel); } + + struct ebpf_bpf* skel; +}; + +extern "C" __attribute__((noinline)) int uprobed_sub(int a, int b) { + asm volatile(""); + return a - b; +} + +void print_trace() { + int fd = open("/sys/kernel/debug/tracing/trace_pipe", O_RDONLY); + if (fd < 0) throw std::runtime_error("Failed to open trace_pipe"); + while (1) { + char buf[4096]; + ssize_t n = read(fd, buf, sizeof(buf) - 1); + if (n <= 0) break; + buf[n] = '\0'; + char* curr = buf; + char* next = strchr(curr, '\n'); + while (next != NULL) { + *next = '\0'; + printf("\033[1;32m[TRACE]\033[0m %s\n", curr); + curr = next + 1; + next = strchr(curr, '\n'); + } + } +} + +void print_ringbuf(struct bpf_map* rb) { + auto handle_event = [](void* ctx, void* data, size_t data_sz) -> int { + char* event = (char*)data; + event[30] = '\0'; + printf("\033[1;32m[EVENT]\033[0m %s\n", event); + }; + + struct ring_buffer* ringbuffer = + ring_buffer__new(bpf_map__fd(rb), handle_event, NULL, NULL); + + if (!ringbuffer) throw std::runtime_error("Failed to create ring buffer"); + + while (1) { + if (ring_buffer__poll(ringbuffer, 100 /* timeout, ms */) < 0) break; + } +} + +int main() { + if (getuid() != 0) throw std::runtime_error("Run as root"); + + BPF bpf; + + std::thread t1(print_trace); + t1.detach(); + + // std::thread t3([bpf]() { print_ringbuf(bpf.skel->maps.rb); }); + // t3.detach(); + + std::thread t2([]() { system("bash"); }); + t2.join(); + + // for (int i = 0;; i++) { + // uprobed_sub(i * i, i); + // sleep(1); + // } +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/count.bpf.c b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/count.bpf.c new file mode 100644 index 00000000..0b7cb3f8 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/count.bpf.c @@ -0,0 +1,35 @@ + +#include "vmlinux.h" +// Must be included first + +#include +#include + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __type(key, u32); + __type(value, u32); + __uint(max_entries, 1); +} enter_open_map SEC(".maps"); + +static __always_inline void count(void *map) { + u32 key = 0; + u32 *ptr = bpf_map_lookup_elem(map, &key); + + if (ptr) { + *ptr += 1; // non-atomic increment + if (*ptr < 1000) { + bpf_printk("count %d", *ptr); + } + } else { + u32 init_val = 1; + bpf_map_update_elem(map, &key, &init_val, BPF_NOEXIST); + bpf_printk("init %d", init_val); + } +} + +SEC("tracepoint/syscalls/sys_enter_sched_getparam") +int trace_enter_open_at(void *ctx) { + count(&enter_open_map); + return 0; +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/dents.bpf.c b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/dents.bpf.c new file mode 100644 index 00000000..6b72f382 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/dents.bpf.c @@ -0,0 +1,65 @@ +#pragma once + +#include "vmlinux.h" +// Must be included first + +#include +#include + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 8192); + __type(key, tid_t); + __type(value, u64); +} dir_entries SEC(".maps"); + +SEC("tracepoint/syscalls/sys_enter_getdents64") +int enter_getdents64(struct trace_event_raw_sys_enter *ctx) { + tid_t tid = bpf_get_current_pid_tgid(); + + struct linux_dirent64 *d_entry = (struct linux_dirent64 *)ctx->args[1]; + if (d_entry == NULL) return 1; + + bpf_map_update_elem(&dir_entries, &tid, &d_entry, BPF_ANY); + return 0; +} + +#define MAX_D_NAME_LEN 128 +SEC("tracepoint/syscalls/sys_exit_getdents64") +int exit_getdents64(struct trace_event_raw_sys_exit *ctx) { + tid_t tid = bpf_get_current_pid_tgid(); + + struct linux_dirent64 **dir_addr = + (struct linux_dirent64 **)bpf_map_lookup_elem(&dir_entries, &tid); + if (dir_addr == NULL) return 1; + + bpf_map_delete_elem(&dir_entries, &tid); + + // return write_user(*dir_addr); + + long offset = 0; + // limitation for now, only examine the first 256 entries + for (int i = 0; i < 256; i++) { + struct linux_dirent64 *d_entry = + (struct linux_dirent64 *)((char *)*dir_addr + offset); + + // read d_name + char d_name[MAX_D_NAME_LEN]; + long err = bpf_probe_read_user(&d_name, MAX_D_NAME_LEN, d_entry->d_name); + if (!err) { + bpf_printk("d_name \"%s\"", d_name); + long ret = bpf_probe_write_user(d_entry, "x", sizeof(char)); + if (ret) { + bpf_printk("getdents: bpf_probe_write_user failed: %ld", ret); + } + } + + // read d_reclen + unsigned short int d_reclen; + bpf_probe_read_user(&d_reclen, sizeof(d_reclen), &d_entry->d_reclen); + offset += d_reclen; + if (offset >= ctx->ret) return 0; + } + + return 0; +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/fault.bpf.c b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/fault.bpf.c new file mode 100644 index 00000000..d8f55355 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/fault.bpf.c @@ -0,0 +1,145 @@ +#include "vmlinux.h" +// Must be included first + +#include +#include + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +static void print_flags(unsigned int f) { + if (f & FAULT_FLAG_WRITE) bpf_printk("WRITE"); + if (f & FAULT_FLAG_MKWRITE) bpf_printk("MKWRITE"); + if (f & FAULT_FLAG_ALLOW_RETRY) bpf_printk("ALLOW_RETRY"); + if (f & FAULT_FLAG_RETRY_NOWAIT) bpf_printk("RETRY_NOWAIT"); + if (f & FAULT_FLAG_KILLABLE) bpf_printk("KILLABLE"); + if (f & FAULT_FLAG_TRIED) bpf_printk("TRIED"); + if (f & FAULT_FLAG_USER) bpf_printk("USER"); + if (f & FAULT_FLAG_REMOTE) bpf_printk("REMOTE"); + if (f & FAULT_FLAG_INSTRUCTION) bpf_printk("INSTRUCTION"); + if (f & FAULT_FLAG_INTERRUPTIBLE) bpf_printk("INTERRUPTIBLE"); +} + +static void print_fault_reason(vm_fault_t f) { + if (f & VM_FAULT_OOM) bpf_printk("OOM"); + if (f & VM_FAULT_SIGBUS) bpf_printk("SIGBUS"); + if (f & VM_FAULT_MAJOR) bpf_printk("MAJOR"); + if (f & VM_FAULT_WRITE) bpf_printk("WRITE"); + if (f & VM_FAULT_HWPOISON) bpf_printk("HWPOISON"); + if (f & VM_FAULT_HWPOISON_LARGE) bpf_printk("HWPOISON_LARGE"); + if (f & VM_FAULT_SIGSEGV) bpf_printk("SIGSEGV"); + if (f & VM_FAULT_NOPAGE) bpf_printk("NOPAGE"); + if (f & VM_FAULT_LOCKED) bpf_printk("LOCKED"); + if (f & VM_FAULT_RETRY) bpf_printk("RETRY"); + if (f & VM_FAULT_FALLBACK) bpf_printk("FALLBACK"); + if (f & VM_FAULT_DONE_COW) bpf_printk("DONE_COW"); + if (f & VM_FAULT_NEEDDSYNC) bpf_printk("NEEDDSYNC"); + if (f & VM_FAULT_HINDEX_MASK) bpf_printk("HINDEX_MASK"); +} + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 8192); + __type(key, tid_t); + __type(value, unsigned long); +} address_map SEC(".maps"); + +SEC("kprobe/handle_mm_fault") +int BPF_KPROBE(handle_mm_fault, struct vm_area_struct *vma, + unsigned long address, unsigned int flags, + struct pt_regs *regs) { + // only record the first fault + if (flags & FAULT_FLAG_TRIED) return 0; + + if (!is_target_proc()) return 0; + + char *d_iname = get_dname(vma); + if (!is_target_name(d_iname)) return 0; + + print_flags(flags); + + tid_t tid = bpf_get_current_pid_tgid(); + + bpf_printk("handle_mm_fault: tid %d, address %px, name %s", tid, address, + d_iname); + + bpf_map_update_elem(&address_map, &tid, &address, BPF_ANY); + return 0; +} + +SEC("kretprobe/handle_mm_fault") +int BPF_KRETPROBE(handle_mm_fault_ret, vm_fault_t fault_ret) { + // ignore retry + if (fault_ret & VM_FAULT_RETRY) return 0; + + if (!is_target_proc()) return 0; + + tid_t tid = bpf_get_current_pid_tgid(); + unsigned long *val = bpf_map_lookup_elem(&address_map, &tid); + if (val == NULL) return 0; + bpf_map_delete_elem(&address_map, &tid); + + void *address = (void *)(*val & 0xfffffffffffff000); + + bpf_printk("handle_mm_fault_ret: tid %d, address %px, ret %d", tid, address, + fault_ret); + + static char page[4096]; + { + long ret = bpf_probe_read_user(page, sizeof(page), address); + if (ret != 0) { + bpf_printk("handle_mm_fault_ret: read_kernel(%px) failed: %d", address, + ret); + } else { + bpf_printk("handle_mm_fault_ret: read_kernel(%px) succeeded", address); + } + } + + for (int i = 0; i < sizeof(page); i++) { + if (page[i] == '\n') continue; + page[i] = page[i] + 1; + } + + { + long ret = bpf_probe_write_user(address, page, sizeof(page)); + if (ret != 0) { + bpf_printk("handle_mm_fault_ret: write_user(%px) failed: %d", address, + ret); + } else { + bpf_printk("handle_mm_fault_ret: write_user(%px) succeeded", address); + } + } + + return 0; +} + +SEC("fentry/handle_mm_fault") +int BPF_PROG(handle_mm_fault, struct vm_area_struct *vma, unsigned long address, + unsigned int flags, struct pt_regs *regs) { + // only record the first fault + if (flags & FAULT_FLAG_TRIED) return 0; + + if (!is_target_proc()) return 0; + + char *d_iname = get_dname_from_file(vma->vm_file); + if (!is_target_name(d_iname)) return 0; + + struct inode *inode = get_inode_from_file(vma->vm_file); + int ino = get_ino_from_inode(inode); + + bpf_printk("handle_mm_fault: \"%s\", ino %d, address %px", d_iname, ino, + address); + + return 0; +} + +SEC("fentry/add_to_page_cache_lru") +int BPF_PROG(add_to_page_cache_lru, struct page *page, + struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask) { + if (!is_target_proc()) return 0; + + int ino = get_ino_from_inode(mapping->host); + + bpf_printk("add_to_page_cache_lru: ino %d, pgoff %d", ino, offset); + + return 0; +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/helper.bpf.c b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/helper.bpf.c new file mode 100644 index 00000000..47f949bb --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/helper.bpf.c @@ -0,0 +1,34 @@ +#include "vmlinux.h" + +#include +#include + +char LICENSE[] SEC("license") = "GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_INODE_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, 0); +} inode_storage_map SEC(".maps"); + +// SEC("xdp") +// SEC("lwt_in") +// SEC("socket") +// SEC("cgroup/dev") +// SEC("lsm/file_open") +// SEC("kprobe/vfs_open") +SEC("uprobe//proc/self/exe:uprobed_sub") +int prog(void* ctx) { + char buf; + void* ptr = (void*)0xffffa1b713b5d788; + int rc = bpf_probe_read_kernel(&buf, 1, ptr); + bpf_printk("rc: %d", rc); + return 0; + + // return bpf_skb_load_bytes(ctx, 0, &buf, 1) == 0; + // bpf_inode_storage_get(&inode_storage_map, 0x0, 0x0, 0); + // return 0; + + // return XDP_PASS; +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/hex_dump.h b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/hex_dump.h new file mode 100644 index 00000000..20b11cf4 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/hex_dump.h @@ -0,0 +1,12 @@ +#include +#include + +void hexdump(const void* data, size_t size) { + const auto* p = (const uint8_t*)data; + for (size_t i = 0; i < size; i++) { + if (i % 32 == 0) printf("%04zx: ", i); + printf("%02x", p[i]); + if (i % 4 == 3) printf(" "); + if (i % 32 == 31) printf("\n"); + } +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/relocation.bpf.c b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/relocation.bpf.c new file mode 100644 index 00000000..178983e1 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/test-bpf/tests/relocation.bpf.c @@ -0,0 +1,16 @@ +// #define BPF_NO_PRESERVE_ACCESS_INDEX +#include "vmlinux.h" +// + +#include +#include + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +SEC("kprobe/vfs_read") +int BPF_KPROBE(vfs_read_entry, struct file* file) { + struct path path; + path = BPF_CORE_READ(file, f_path); + struct dentry* dentry = path.dentry; + return BPF_CORE_READ(dentry, d_flags); +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/.gitignore b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/.gitignore new file mode 100644 index 00000000..5bd4a0fe --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/.gitignore @@ -0,0 +1,2 @@ +init +init.cpio diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/Makefile b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/Makefile new file mode 100644 index 00000000..310c5479 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/Makefile @@ -0,0 +1,24 @@ +.PHONY: run clean + +run: init.cpio + qemu-system-aarch64 \ + -machine virt \ + -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \ + -cpu cortex-a53 \ + -m 256M \ + -kernel vmlinuz-5.4.0-26-generic \ + -initrd $< \ + -nographic \ + -append "nokaslr" + +init: init.c + gcc -Wall -Werror -static -o $@ $< + +init.cpio: init + echo $< | cpio -o -H newc > $@ + +kill: + sudo kill -9 $(ps aux | grep 'qemu' | awk '{print $2}') + +clean: + rm -f init init.cpio diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/README.md b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/README.md new file mode 100644 index 00000000..90ddba2e --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/README.md @@ -0,0 +1,13 @@ +``` +sudo apt install qemu-kvm genisoimage +``` + +Add /etc/fstab entry for 9p mount +``` +hostshare /path/to/mount 9p trans=virtio,version=9p2000.L 0 0 +``` + +sudo mount -a + +awk -F\' '$1=="menuentry " || $1=="submenu " {print i++ " : " $2}; /\tmenuentry / {print "\t" i-1">"j++ " : " $2};' /boot/grub/grub.cfg +sudo grub-reboot "1>2" && sudo reboot diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/prep.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/prep.py new file mode 100755 index 00000000..25e4f6ee --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/prep.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 + +import os +from pathlib import Path + +from utils.arch import Arch, get_arch +from utils.system import system + +VM_DATA_PATH = Path("data") / "vm" +KEY_PATH = VM_DATA_PATH / "id_rsa" +TMP_PATH = VM_DATA_PATH / "tmp" +DISK_IMG_PATH = TMP_PATH / "cloudimg.img" +SEED_IMG_PATH = TMP_PATH / "cloud-init-config.iso" + + +def download( + url, + data_path=TMP_PATH, +): + path = data_path / Path(url).name + + if path.exists(): + print(f"{path} already exists, skipping download") + else: + import urllib.request + + print(f"Downloading {url} to {path}") + path.parent.mkdir(parents=True, exist_ok=True) + urllib.request.urlretrieve(url, path) + + return path + + +def get_disk_img_url( + minimal=False, + version="20.04", +): + arch = { + Arch.X86_64: "amd64", + Arch.ARM64: "arm64", + }[get_arch()] + + if minimal: + return f"https://cloud-images.ubuntu.com/minimal/releases/{version}/release/ubuntu-{version}-minimal-cloudimg-{arch}.img" + else: + return f"https://cloud-images.ubuntu.com/releases/{version}/release/ubuntu-{version}-server-cloudimg-{arch}.img" + + +def prep_disk_img( + raw_img_path, + img_path=DISK_IMG_PATH, + size_gb=64, +): + if not img_path.exists(): + print(f"Copying {raw_img_path} to {img_path}") + system(f"cp {raw_img_path} {img_path}") + + print(f"Resizing {img_path} to {size_gb}G") + system(f"qemu-img resize {img_path} +{size_gb}G") + else: + print(f"Disk image {img_path} already exists") + + return img_path + + +def get_pub_key_local(key_path=KEY_PATH): + if not key_path.exists(): + print(f"Creating {key_path}") + system(f"ssh-keygen -q -t rsa -N '' -f {key_path} <</dev/null 2>&1") + + public_key_path = key_path.with_suffix(".pub") + return public_key_path.read_text().strip().split("\n") + + +def get_pub_key_gh(username): + import json + + import requests + + url = f"https://api.github.com/users/{username}/keys" + resp = requests.get(url) + + if resp.status_code != 200: + print(f"Failed to get public key from GitHub: {resp.status_code}") + return [] + + return [f"{k['key']} {username}@github/{k['id']}" for k in json.loads(resp.text)] + + +def prep_user_data( + public_keys, + path=TMP_PATH / "user-data", +): + import yaml + + if path.exists(): + print(f"{path} already exists, skipping creation") + return path + + print(f"Creating {path}") + + password = os.urandom(4).hex() + with open(path, "w") as f: + f.write("#cloud-config\n") + data = { + "ssh_authorized_keys": public_keys, + "ssh_pwauth": True, + "password": password, + "chpasswd": {"expire": False}, + } + yaml.dump(data, f) + + return path + + +def prep_meta_data( + path=TMP_PATH / "meta-data", +): + if path.exists(): + print(f"{path} already exists, skipping creation") + return path + + print(f"Creating {path}") + with open(path, "w") as f: + f.write("{'instance-id': 'iid-local01'}") + return path + + +def prep_seed_img( + user_data, + meta_data, + seed_path=SEED_IMG_PATH, +): + if seed_path.exists(): + print(f"{seed_path} already exists, skipping creation") + return seed_path + + print(f"Creating {seed_path}") + system( + f"mkisofs -output {seed_path} " + f"-volid cidata -joliet -rock {user_data} {meta_data}" + ) + + return seed_path + + +if __name__ == "__main__": + img_url = get_disk_img_url() + raw_img_path = download(img_url) + prep_disk_img(raw_img_path) + + public_keys = get_pub_key_local() + get_pub_key_gh("ShawnZhong") + user_data = prep_user_data(public_keys) + meta_data = prep_meta_data() + prep_seed_img(user_data, meta_data) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/run.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/run.py new file mode 100755 index 00000000..b069fe03 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/run.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +import argparse +import os + +from prep import DISK_IMG_PATH, SEED_IMG_PATH, VM_DATA_PATH +from utils.arch import Arch, get_arch +from utils.system import system + + +def get_qemu_path(): + return { + Arch.X86_64: "qemu-system-x86_64", + Arch.ARM64: "qemu-system-aarch64", + }[get_arch()] + + +def run_qemu(img_path, core_count, port, debug=False): + if os.system(f"nc -z localhost {port}") == 0: + print(f"Port {port} is already in use. Please close the process and try again.") + exit(1) + + accel = "kvm" if get_arch() == Arch.X86_64 else "hvf" + + cmd = ( + f"sudo {get_qemu_path()} " + f"-smp {core_count} " # use all host cores + f"-cpu max " # use host CPU + f"-accel {accel} " # try to use HVF acceleration + f"-m 16G " + f"-nographic " + f"-device virtio-net-pci,netdev=net0 " # virtio network device + f"-netdev user,id=net0,hostfwd=tcp::{port}-:22 " # ssh port forwarding + f"-drive if=virtio,format=qcow2,file={img_path} " + f"-cdrom {SEED_IMG_PATH} " + f"-virtfs local,path=..,security_model=passthrough,mount_tag=host0" + ) + + if get_arch() == Arch.ARM64: + cmd += f"-machine virt " # use virt machine + cmd += f"-bios support/AAVMF_CODE.fd " # specify UEFI image + + if debug: + cmd += "-s " # shorthand for -gdb tcp::1234 + cmd += "-S " # freezes CPU at startup (use 'c' in gdb to continue) + + system(cmd) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("index", type=int, default=0, nargs="?") + args = parser.parse_args() + idx = args.index + + if idx == 0: + img_path = DISK_IMG_PATH + else: + img_path = VM_DATA_PATH / f"cloudimg-{idx}.img" + if not img_path.exists(): + system(f"cp {DISK_IMG_PATH} {img_path}") + else: + print(f"Using existing image {img_path}") + + core_count = os.cpu_count() // 4 + run_qemu( + img_path=img_path, + core_count=core_count, + port=2222 + idx, + ) + + +if __name__ == "__main__": + main() diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/ssh.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/ssh.py new file mode 100755 index 00000000..2310468f --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/distro/ssh.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 + +import argparse + +from prep import KEY_PATH +from utils.system import system + + +def ssh(port, key_path): + system( + f'ssh -p {port} -i {key_path} -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" ubuntu@localhost' + ) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("idx", type=int, default=0, nargs="?") + args = parser.parse_args() + idx = args.idx + + ssh(2222 + idx, KEY_PATH) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/init.c b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/init.c new file mode 100644 index 00000000..95380a4e --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/archive/vm/init.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PANIC(msg) \ + do { \ + perror(msg); \ + exit(1); \ + } while (0) + +#define DEBUGFS "/debug" + +void list_dir(const char *path, int max_depth) { + if (max_depth == 0) return; + + DIR *dir = opendir(path); + if (dir == NULL) PANIC("opendir"); + + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + if (entry->d_type == DT_DIR) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + char new_path[4096]; + snprintf(new_path, sizeof(new_path), "%s/%s", path, entry->d_name); + printf("%s\n", new_path); + list_dir(new_path, max_depth - 1); + } + } + + closedir(dir); +} + +void print_file(const char *path) { + FILE *fp = fopen(path, "r"); + if (fp == NULL) PANIC("fopen"); + + char buf[4096]; + while (fgets(buf, sizeof(buf), fp) != NULL) { + printf("%s", buf); + } + fclose(fp); +} + +void mount_fs(const char *fs, const char *path) { + if (mkdir(path, 0755) == -1 && errno != EEXIST) PANIC("mkdir"); + if (mount(NULL, path, fs, 0, NULL) == -1) PANIC("mount"); +} + +int main() { + mount_fs("devtmpfs", "/dev"); + // mknod -m 640 /dev/kmem c 1 2 + + // mount_fs("debugfs", DEBUGFS); + // print_file(DEBUGFS "/tracing/available_events"); + list_dir("/", -1); + pause(); +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/data/.gitignore b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/data/.gitignore new file mode 100644 index 00000000..724f2d70 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/data/.gitignore @@ -0,0 +1,3 @@ +/download +/intermediate +/output diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/__init__.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/__init__.py new file mode 100644 index 00000000..2aa0127a --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/__init__.py @@ -0,0 +1,22 @@ +import logging + +from .bpf_program import * +from .btf import * +from .dep import * +from .diff import * +from .funcs import * +from .issues import * +from .linux import * +from .linux_image import * +from .paths import * +from .prep import * +from .report import * +from .utils import * +from .version import * +from .version_group import * +from .version_pair import * + +logging.basicConfig( + level=logging.INFO, + format="[%(filename)16s:%(lineno)-3d] %(levelname)s: %(message)s", +) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/bpf_program.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/bpf_program.py new file mode 100644 index 00000000..739d50d4 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/bpf_program.py @@ -0,0 +1,611 @@ +from functools import cached_property +from pathlib import Path +from typing import Dict, List + +from elftools.elf.elffile import ELFFile + +from depsurf.btf import Kind, Types, dump_btf_json, gen_min_btf +from depsurf.dep import Dep, DepKind + + +class BPFProgram: + DEP_MAPPING: Dict[Dep, List[Dep]] = {} + + def __init__(self, path: Path): + self.path = path + self.file = open(path, "rb") + self.elffile = ELFFile(self.file) + + def __del__(self): + self.file.close() + + @property + def name(self): + return self.path.name.removesuffix(".o").removesuffix(".bpf") + + @property + def btf_file(self): + return self.path.with_suffix(".min.btf") + + @property + def btf_json_file(self): + return self.path.with_suffix(".min.btf.json") + + @property + def btf_txt_file(self): + return self.path.with_suffix(".min.btf.txt") + + @property + def hook_names(self): + return [ + section.name + for section in self.elffile.iter_sections() + if not section.name.startswith(".") + and section.name != "license" + and section.header.sh_type == "SHT_PROGBITS" + ] + + @property + def deps_hook(self) -> List[Dep]: + results = [] + for hook_name in self.hook_names: + kind = DepKind.from_hook_name(hook_name) + if "/" in hook_name: + name = hook_name.rsplit("/", 1)[-1] + else: + name = "" + + for prefix in ["sys_enter_", "sys_exit_"]: + if kind == DepKind.SYSCALL and name.startswith(prefix): + name = name[len(prefix) :] + + results.append(Dep(kind, name)) + + return results + + @property + def deps_struct(self) -> list[Dep]: + gen_min_btf( + self.path, + result_path=self.btf_file, + slient=True, + overwrite=True, + ) + dump_btf_json( + self.btf_file, + result_path=self.btf_json_file, + slient=True, + overwrite=True, + ) + struct_types = Types.from_btf_json(self.btf_json_file, Kind.STRUCT) + + results = [] + for name, struct in struct_types.items(): + name = name.split("___")[0] + if name == "user_pt_regs": + continue + if name == "pt_regs": + continue + results.append(DepKind.STRUCT(name)) + for member in struct["members"]: + results.append(DepKind.FIELD(f"{name}::{member['name']}")) + + return results + + @cached_property + def deps(self) -> list[Dep]: + deps = [] + for dep in set(self.deps_hook + self.deps_struct): + if dep in BPFProgram.DEP_MAPPING: + deps.extend(BPFProgram.DEP_MAPPING[dep]) + else: + deps.append(dep) + return sorted(deps) + + +BPFProgram.DEP_MAPPING = { + # Used by fsdist and fsslower + # Ref: https://github.com/iovisor/bcc/blob/fef9003e2e2f29c893543d49b762dd413a352f05/libbpf-tools/fsdist.c#L42-L81 + DepKind.FUNC("dummy_file_read"): [DepKind.FUNC("ext4_file_read_iter")], + DepKind.FUNC("dummy_file_write"): [DepKind.FUNC("ext4_file_write_iter")], + DepKind.FUNC("dummy_file_open"): [DepKind.FUNC("ext4_file_open")], + DepKind.FUNC("dummy_file_sync"): [DepKind.FUNC("ext4_sync_file")], + DepKind.FUNC("dummy_getattr"): [DepKind.FUNC("ext4_file_getattr")], + # Used by ksnoop + DepKind.FUNC("foo"): [], + # Used by funclatency + DepKind.FUNC("dummy_fentry"): [], + DepKind.FUNC("dummy_fexit"): [], + DepKind.FUNC("dummy_kprobe"): [], + DepKind.FUNC("dummy_kretprobe"): [], + # Used by readahead + # https://github.com/iovisor/bcc/blob/1d8daaa395f066b328a56a36fbd40a0de3a7b3c1/libbpf-tools/readahead.c#L79 + DepKind.FUNC("do_page_cache_ra"): [ + DepKind.FUNC("do_page_cache_ra"), + DepKind.FUNC("__do_page_cache_readahead"), + ], + # Used by tracee + # https://github.com/aquasecurity/tracee/blob/4fc1bbb2b99333be869e49a333fc3dd17c176137/pkg/ebpf/probes/probe_group.go + # https://github.com/aquasecurity/tracee/blob/4fc1bbb2b99333be869e49a333fc3dd17c176137/pkg/events/core.go + # https://github.com/aquasecurity/tracee/blob/4fc1bbb2b99333be869e49a333fc3dd17c176137/pkg/ebpf/c/tracee.bpf.c + DepKind.FUNC("__kernel_write_tail"): [DepKind.FUNC("__kernel_write")], + DepKind.FUNC("vfs_read_tail"): [DepKind.FUNC("vfs_read")], + DepKind.FUNC("vfs_readv_tail"): [DepKind.FUNC("vfs_readv")], + DepKind.FUNC("vfs_write_tail"): [DepKind.FUNC("vfs_write")], + DepKind.FUNC("vfs_writev_tail"): [DepKind.FUNC("vfs_writev")], + DepKind.FUNC("empty_kprobe"): [], + DepKind.FUNC("execute_finished"): [ + DepKind.SYSCALL("execve"), + DepKind.SYSCALL("execveat"), + ], + DepKind.FUNC("send_bin"): [], + DepKind.FUNC("trace_execute_failed1"): [], + DepKind.FUNC("trace_execute_failed2"): [], + DepKind.TRACEPOINT("send_bin_tp"): [], + DepKind.TRACEPOINT("exec_test"): [], + DepKind.TRACEPOINT("cgroup_mkdir_signal"): [DepKind.TRACEPOINT("cgroup_mkdir")], + DepKind.TRACEPOINT("cgroup_rmdir_signal"): [DepKind.TRACEPOINT("cgroup_rmdir")], + DepKind.TRACEPOINT("sched_process_exec_event_submit_tail"): [ + DepKind.TRACEPOINT("sched_process_exec") + ], + DepKind.TRACEPOINT("syscall__accept4"): [DepKind.SYSCALL("accept4")], + DepKind.TRACEPOINT("sys_dup"): [DepKind.SYSCALL("dup")], + DepKind.TRACEPOINT("sys_execve"): [DepKind.SYSCALL("execve")], + DepKind.TRACEPOINT("sys_execveat"): [DepKind.SYSCALL("execveat")], + DepKind.TRACEPOINT("sys_init_module"): [DepKind.SYSCALL("init_module")], + DepKind.TRACEPOINT("sys_enter_init"): [], + DepKind.TRACEPOINT("sys_exit_init"): [], + DepKind.TRACEPOINT("sys_enter_submit"): [], + DepKind.TRACEPOINT("sys_exit_submit"): [], + # DepKind.TRACEPOINT("sys_enter"): [], + # DepKind.TRACEPOINT("sys_exit"): [], + DepKind.TRACEPOINT("trace_sys_enter"): [], + DepKind.TRACEPOINT("trace_sys_exit"): [ + DepKind.SYSCALL("read"), + DepKind.SYSCALL("write"), + DepKind.SYSCALL("open"), + DepKind.SYSCALL("close"), + DepKind.SYSCALL("stat"), + DepKind.SYSCALL("fstat"), + DepKind.SYSCALL("lstat"), + DepKind.SYSCALL("poll"), + DepKind.SYSCALL("lseek"), + DepKind.SYSCALL("mmap"), + DepKind.SYSCALL("mprotect"), + DepKind.SYSCALL("munmap"), + DepKind.SYSCALL("brk"), + DepKind.SYSCALL("rt_sigaction"), + DepKind.SYSCALL("rt_sigprocmask"), + DepKind.SYSCALL("rt_sigreturn"), + DepKind.SYSCALL("ioctl"), + DepKind.SYSCALL("pread64"), + DepKind.SYSCALL("pwrite64"), + DepKind.SYSCALL("readv"), + DepKind.SYSCALL("writev"), + DepKind.SYSCALL("access"), + DepKind.SYSCALL("pipe"), + DepKind.SYSCALL("select"), + DepKind.SYSCALL("sched_yield"), + DepKind.SYSCALL("mremap"), + DepKind.SYSCALL("msync"), + DepKind.SYSCALL("mincore"), + DepKind.SYSCALL("madvise"), + DepKind.SYSCALL("shmget"), + DepKind.SYSCALL("shmat"), + DepKind.SYSCALL("shmctl"), + DepKind.SYSCALL("dup"), + DepKind.SYSCALL("dup2"), + DepKind.SYSCALL("pause"), + DepKind.SYSCALL("nanosleep"), + DepKind.SYSCALL("getitimer"), + DepKind.SYSCALL("alarm"), + DepKind.SYSCALL("setitimer"), + DepKind.SYSCALL("getpid"), + DepKind.SYSCALL("sendfile"), + DepKind.SYSCALL("socket"), + DepKind.SYSCALL("connect"), + DepKind.SYSCALL("accept"), + DepKind.SYSCALL("sendto"), + DepKind.SYSCALL("recvfrom"), + DepKind.SYSCALL("sendmsg"), + DepKind.SYSCALL("recvmsg"), + DepKind.SYSCALL("shutdown"), + DepKind.SYSCALL("bind"), + DepKind.SYSCALL("listen"), + DepKind.SYSCALL("getsockname"), + DepKind.SYSCALL("getpeername"), + DepKind.SYSCALL("socketpair"), + DepKind.SYSCALL("setsockopt"), + DepKind.SYSCALL("getsockopt"), + DepKind.SYSCALL("clone"), + DepKind.SYSCALL("fork"), + DepKind.SYSCALL("vfork"), + DepKind.SYSCALL("execve"), + DepKind.SYSCALL("exit"), + DepKind.SYSCALL("wait4"), + DepKind.SYSCALL("kill"), + DepKind.SYSCALL("uname"), + DepKind.SYSCALL("semget"), + DepKind.SYSCALL("semop"), + DepKind.SYSCALL("semctl"), + DepKind.SYSCALL("shmdt"), + DepKind.SYSCALL("msgget"), + DepKind.SYSCALL("msgsnd"), + DepKind.SYSCALL("msgrcv"), + DepKind.SYSCALL("msgctl"), + DepKind.SYSCALL("fcntl"), + DepKind.SYSCALL("flock"), + DepKind.SYSCALL("fsync"), + DepKind.SYSCALL("fdatasync"), + DepKind.SYSCALL("truncate"), + DepKind.SYSCALL("ftruncate"), + DepKind.SYSCALL("getdents"), + DepKind.SYSCALL("getcwd"), + DepKind.SYSCALL("chdir"), + DepKind.SYSCALL("fchdir"), + DepKind.SYSCALL("rename"), + DepKind.SYSCALL("mkdir"), + DepKind.SYSCALL("rmdir"), + DepKind.SYSCALL("creat"), + DepKind.SYSCALL("link"), + DepKind.SYSCALL("unlink"), + DepKind.SYSCALL("symlink"), + DepKind.SYSCALL("readlink"), + DepKind.SYSCALL("chmod"), + DepKind.SYSCALL("fchmod"), + DepKind.SYSCALL("chown"), + DepKind.SYSCALL("fchown"), + DepKind.SYSCALL("lchown"), + DepKind.SYSCALL("umask"), + DepKind.SYSCALL("gettimeofday"), + DepKind.SYSCALL("getrlimit"), + DepKind.SYSCALL("getrusage"), + DepKind.SYSCALL("sysinfo"), + DepKind.SYSCALL("times"), + DepKind.SYSCALL("ptrace"), + DepKind.SYSCALL("getuid"), + DepKind.SYSCALL("syslog"), + DepKind.SYSCALL("getgid"), + DepKind.SYSCALL("setuid"), + DepKind.SYSCALL("setgid"), + DepKind.SYSCALL("geteuid"), + DepKind.SYSCALL("getegid"), + DepKind.SYSCALL("setpgid"), + DepKind.SYSCALL("getppid"), + DepKind.SYSCALL("getpgrp"), + DepKind.SYSCALL("setsid"), + DepKind.SYSCALL("setreuid"), + DepKind.SYSCALL("setregid"), + DepKind.SYSCALL("getgroups"), + DepKind.SYSCALL("setgroups"), + DepKind.SYSCALL("setresuid"), + DepKind.SYSCALL("getresuid"), + DepKind.SYSCALL("setresgid"), + DepKind.SYSCALL("getresgid"), + DepKind.SYSCALL("getpgid"), + DepKind.SYSCALL("setfsuid"), + DepKind.SYSCALL("setfsgid"), + DepKind.SYSCALL("getsid"), + DepKind.SYSCALL("capget"), + DepKind.SYSCALL("capset"), + DepKind.SYSCALL("rt_sigpending"), + DepKind.SYSCALL("rt_sigtimedwait"), + DepKind.SYSCALL("rt_sigqueueinfo"), + DepKind.SYSCALL("rt_sigsuspend"), + DepKind.SYSCALL("sigaltstack"), + DepKind.SYSCALL("utime"), + DepKind.SYSCALL("mknod"), + DepKind.SYSCALL("uselib"), + DepKind.SYSCALL("personality"), + DepKind.SYSCALL("ustat"), + DepKind.SYSCALL("statfs"), + DepKind.SYSCALL("fstatfs"), + DepKind.SYSCALL("sysfs"), + DepKind.SYSCALL("getpriority"), + DepKind.SYSCALL("setpriority"), + DepKind.SYSCALL("sched_setparam"), + DepKind.SYSCALL("sched_getparam"), + DepKind.SYSCALL("sched_setscheduler"), + DepKind.SYSCALL("sched_getscheduler"), + DepKind.SYSCALL("sched_get_priority_max"), + DepKind.SYSCALL("sched_get_priority_min"), + DepKind.SYSCALL("sched_rr_get_interval"), + DepKind.SYSCALL("mlock"), + DepKind.SYSCALL("munlock"), + DepKind.SYSCALL("mlockall"), + DepKind.SYSCALL("munlockall"), + DepKind.SYSCALL("vhangup"), + DepKind.SYSCALL("modify_ldt"), + DepKind.SYSCALL("pivot_root"), + DepKind.SYSCALL("sysctl"), + DepKind.SYSCALL("prctl"), + DepKind.SYSCALL("arch_prctl"), + DepKind.SYSCALL("adjtimex"), + DepKind.SYSCALL("setrlimit"), + DepKind.SYSCALL("chroot"), + DepKind.SYSCALL("sync"), + DepKind.SYSCALL("acct"), + DepKind.SYSCALL("settimeofday"), + DepKind.SYSCALL("mount"), + DepKind.SYSCALL("umount2"), + DepKind.SYSCALL("swapon"), + DepKind.SYSCALL("swapoff"), + DepKind.SYSCALL("reboot"), + DepKind.SYSCALL("sethostname"), + DepKind.SYSCALL("setdomainname"), + DepKind.SYSCALL("iopl"), + DepKind.SYSCALL("ioperm"), + DepKind.SYSCALL("create_module"), + DepKind.SYSCALL("init_module"), + DepKind.SYSCALL("delete_module"), + DepKind.SYSCALL("get_kernel_syms"), + DepKind.SYSCALL("query_module"), + DepKind.SYSCALL("quotactl"), + DepKind.SYSCALL("nfsservctl"), + DepKind.SYSCALL("getpmsg"), + DepKind.SYSCALL("putpmsg"), + DepKind.SYSCALL("afs"), + DepKind.SYSCALL("tuxcall"), + DepKind.SYSCALL("security"), + DepKind.SYSCALL("gettid"), + DepKind.SYSCALL("readahead"), + DepKind.SYSCALL("setxattr"), + DepKind.SYSCALL("lsetxattr"), + DepKind.SYSCALL("fsetxattr"), + DepKind.SYSCALL("getxattr"), + DepKind.SYSCALL("lgetxattr"), + DepKind.SYSCALL("fgetxattr"), + DepKind.SYSCALL("listxattr"), + DepKind.SYSCALL("llistxattr"), + DepKind.SYSCALL("flistxattr"), + DepKind.SYSCALL("removexattr"), + DepKind.SYSCALL("lremovexattr"), + DepKind.SYSCALL("fremovexattr"), + DepKind.SYSCALL("tkill"), + DepKind.SYSCALL("time"), + DepKind.SYSCALL("futex"), + DepKind.SYSCALL("sched_setaffinity"), + DepKind.SYSCALL("sched_getaffinity"), + DepKind.SYSCALL("set_thread_area"), + DepKind.SYSCALL("io_setup"), + DepKind.SYSCALL("io_destroy"), + DepKind.SYSCALL("io_getevents"), + DepKind.SYSCALL("io_submit"), + DepKind.SYSCALL("io_cancel"), + DepKind.SYSCALL("get_thread_area"), + DepKind.SYSCALL("lookup_dcookie"), + DepKind.SYSCALL("epoll_create"), + DepKind.SYSCALL("epoll_ctl_old"), + DepKind.SYSCALL("epoll_wait_old"), + DepKind.SYSCALL("remap_file_pages"), + DepKind.SYSCALL("getdents64"), + DepKind.SYSCALL("set_tid_address"), + DepKind.SYSCALL("restart_syscall"), + DepKind.SYSCALL("semtimedop"), + DepKind.SYSCALL("fadvise64"), + DepKind.SYSCALL("timer_create"), + DepKind.SYSCALL("timer_settime"), + DepKind.SYSCALL("timer_gettime"), + DepKind.SYSCALL("timer_getoverrun"), + DepKind.SYSCALL("timer_delete"), + DepKind.SYSCALL("clock_settime"), + DepKind.SYSCALL("clock_gettime"), + DepKind.SYSCALL("clock_getres"), + DepKind.SYSCALL("clock_nanosleep"), + DepKind.SYSCALL("exit_group"), + DepKind.SYSCALL("epoll_wait"), + DepKind.SYSCALL("epoll_ctl"), + DepKind.SYSCALL("tgkill"), + DepKind.SYSCALL("utimes"), + DepKind.SYSCALL("vserver"), + DepKind.SYSCALL("mbind"), + DepKind.SYSCALL("set_mempolicy"), + DepKind.SYSCALL("get_mempolicy"), + DepKind.SYSCALL("mq_open"), + DepKind.SYSCALL("mq_unlink"), + DepKind.SYSCALL("mq_timedsend"), + DepKind.SYSCALL("mq_timedreceive"), + DepKind.SYSCALL("mq_notify"), + DepKind.SYSCALL("mq_getsetattr"), + DepKind.SYSCALL("kexec_load"), + DepKind.SYSCALL("waitid"), + DepKind.SYSCALL("add_key"), + DepKind.SYSCALL("request_key"), + DepKind.SYSCALL("keyctl"), + DepKind.SYSCALL("ioprio_set"), + DepKind.SYSCALL("ioprio_get"), + DepKind.SYSCALL("inotify_init"), + DepKind.SYSCALL("inotify_add_watch"), + DepKind.SYSCALL("inotify_rm_watch"), + DepKind.SYSCALL("migrate_pages"), + DepKind.SYSCALL("openat"), + DepKind.SYSCALL("mkdirat"), + DepKind.SYSCALL("mknodat"), + DepKind.SYSCALL("fchownat"), + DepKind.SYSCALL("futimesat"), + DepKind.SYSCALL("newfstatat"), + DepKind.SYSCALL("unlinkat"), + DepKind.SYSCALL("renameat"), + DepKind.SYSCALL("linkat"), + DepKind.SYSCALL("symlinkat"), + DepKind.SYSCALL("readlinkat"), + DepKind.SYSCALL("fchmodat"), + DepKind.SYSCALL("faccessat"), + DepKind.SYSCALL("pselect6"), + DepKind.SYSCALL("ppoll"), + DepKind.SYSCALL("unshare"), + DepKind.SYSCALL("set_robust_list"), + DepKind.SYSCALL("get_robust_list"), + DepKind.SYSCALL("splice"), + DepKind.SYSCALL("tee"), + DepKind.SYSCALL("sync_file_range"), + DepKind.SYSCALL("vmsplice"), + DepKind.SYSCALL("move_pages"), + DepKind.SYSCALL("utimensat"), + DepKind.SYSCALL("epoll_pwait"), + DepKind.SYSCALL("signalfd"), + DepKind.SYSCALL("timerfd_create"), + DepKind.SYSCALL("eventfd"), + DepKind.SYSCALL("fallocate"), + DepKind.SYSCALL("timerfd_settime"), + DepKind.SYSCALL("timerfd_gettime"), + DepKind.SYSCALL("accept4"), + DepKind.SYSCALL("signalfd4"), + DepKind.SYSCALL("eventfd2"), + DepKind.SYSCALL("epoll_create1"), + DepKind.SYSCALL("dup3"), + DepKind.SYSCALL("pipe2"), + DepKind.SYSCALL("inotify_init1"), + DepKind.SYSCALL("preadv"), + DepKind.SYSCALL("pwritev"), + DepKind.SYSCALL("rt_tgsigqueueinfo"), + DepKind.SYSCALL("perf_event_open"), + DepKind.SYSCALL("recvmmsg"), + DepKind.SYSCALL("fanotify_init"), + DepKind.SYSCALL("fanotify_mark"), + DepKind.SYSCALL("prlimit64"), + DepKind.SYSCALL("name_to_handle_at"), + DepKind.SYSCALL("open_by_handle_at"), + DepKind.SYSCALL("clock_adjtime"), + DepKind.SYSCALL("syncfs"), + DepKind.SYSCALL("sendmmsg"), + DepKind.SYSCALL("setns"), + DepKind.SYSCALL("getcpu"), + DepKind.SYSCALL("process_vm_readv"), + DepKind.SYSCALL("process_vm_writev"), + DepKind.SYSCALL("kcmp"), + DepKind.SYSCALL("finit_module"), + DepKind.SYSCALL("sched_setattr"), + DepKind.SYSCALL("sched_getattr"), + DepKind.SYSCALL("renameat2"), + DepKind.SYSCALL("seccomp"), + DepKind.SYSCALL("getrandom"), + DepKind.SYSCALL("memfd_create"), + DepKind.SYSCALL("kexec_file_load"), + DepKind.SYSCALL("bpf"), + DepKind.SYSCALL("execveat"), + DepKind.SYSCALL("userfaultfd"), + DepKind.SYSCALL("membarrier"), + DepKind.SYSCALL("mlock2"), + DepKind.SYSCALL("copy_file_range"), + DepKind.SYSCALL("preadv2"), + DepKind.SYSCALL("pwritev2"), + DepKind.SYSCALL("pkey_mprotect"), + DepKind.SYSCALL("pkey_alloc"), + DepKind.SYSCALL("pkey_free"), + DepKind.SYSCALL("statx"), + DepKind.SYSCALL("io_pgetevents"), + DepKind.SYSCALL("rseq"), + DepKind.SYSCALL("pidfd_send_signal"), + DepKind.SYSCALL("io_uring_setup"), + DepKind.SYSCALL("io_uring_enter"), + DepKind.SYSCALL("io_uring_register"), + DepKind.SYSCALL("open_tree"), + DepKind.SYSCALL("move_mount"), + DepKind.SYSCALL("fsopen"), + DepKind.SYSCALL("fsconfig"), + DepKind.SYSCALL("fsmount"), + DepKind.SYSCALL("fspick"), + DepKind.SYSCALL("pidfd_open"), + DepKind.SYSCALL("clone3"), + DepKind.SYSCALL("close_range"), + DepKind.SYSCALL("openat2"), + DepKind.SYSCALL("pidfd_getfd"), + DepKind.SYSCALL("faccessat2"), + DepKind.SYSCALL("process_madvise"), + DepKind.SYSCALL("epoll_pwait2"), + DepKind.SYSCALL("mount_setattr"), + DepKind.SYSCALL("quotactl_fd"), + DepKind.SYSCALL("landlock_create_ruleset"), + DepKind.SYSCALL("landlock_add_rule"), + DepKind.SYSCALL("landlock_restrict_self"), + DepKind.SYSCALL("memfd_secret"), + DepKind.SYSCALL("process_mrelease"), + DepKind.SYSCALL("waitpid"), + DepKind.SYSCALL("oldfstat"), + DepKind.SYSCALL("break"), + DepKind.SYSCALL("oldstat"), + DepKind.SYSCALL("umount"), + DepKind.SYSCALL("stime"), + DepKind.SYSCALL("stty"), + DepKind.SYSCALL("gtty"), + DepKind.SYSCALL("nice"), + DepKind.SYSCALL("ftime"), + DepKind.SYSCALL("prof"), + DepKind.SYSCALL("signal"), + DepKind.SYSCALL("lock"), + DepKind.SYSCALL("mpx"), + DepKind.SYSCALL("ulimit"), + DepKind.SYSCALL("oldolduname"), + DepKind.SYSCALL("sigaction"), + DepKind.SYSCALL("sgetmask"), + DepKind.SYSCALL("ssetmask"), + DepKind.SYSCALL("sigsuspend"), + DepKind.SYSCALL("sigpending"), + DepKind.SYSCALL("oldlstat"), + DepKind.SYSCALL("readdir"), + DepKind.SYSCALL("profil"), + DepKind.SYSCALL("socketcall"), + DepKind.SYSCALL("olduname"), + DepKind.SYSCALL("idle"), + DepKind.SYSCALL("vm86old"), + DepKind.SYSCALL("ipc"), + DepKind.SYSCALL("sigreturn"), + DepKind.SYSCALL("sigprocmask"), + DepKind.SYSCALL("bdflush"), + DepKind.SYSCALL("afs_syscall"), + DepKind.SYSCALL("llseek"), + DepKind.SYSCALL("old_select"), + DepKind.SYSCALL("vm86"), + DepKind.SYSCALL("old_getrlimit"), + DepKind.SYSCALL("mmap2"), + DepKind.SYSCALL("truncate64"), + DepKind.SYSCALL("ftruncate64"), + DepKind.SYSCALL("stat64"), + DepKind.SYSCALL("lstat64"), + DepKind.SYSCALL("fstat64"), + DepKind.SYSCALL("lchown16"), + DepKind.SYSCALL("getuid16"), + DepKind.SYSCALL("getgid16"), + DepKind.SYSCALL("geteuid16"), + DepKind.SYSCALL("getegid16"), + DepKind.SYSCALL("setreuid16"), + DepKind.SYSCALL("setregid16"), + DepKind.SYSCALL("getgroups16"), + DepKind.SYSCALL("setgroups16"), + DepKind.SYSCALL("fchown16"), + DepKind.SYSCALL("setresuid16"), + DepKind.SYSCALL("getresuid16"), + DepKind.SYSCALL("setresgid16"), + DepKind.SYSCALL("getresgid16"), + DepKind.SYSCALL("chown16"), + DepKind.SYSCALL("setuid16"), + DepKind.SYSCALL("setgid16"), + DepKind.SYSCALL("setfsuid16"), + DepKind.SYSCALL("setfsgid16"), + DepKind.SYSCALL("fcntl64"), + DepKind.SYSCALL("sendfile32"), + DepKind.SYSCALL("statfs64"), + DepKind.SYSCALL("fstatfs64"), + DepKind.SYSCALL("fadvise64_64"), + DepKind.SYSCALL("clock_gettime32"), + DepKind.SYSCALL("clock_settime32"), + DepKind.SYSCALL("clock_adjtime64"), + DepKind.SYSCALL("clock_getres_time32"), + DepKind.SYSCALL("clock_nanosleep_time32"), + DepKind.SYSCALL("timer_gettime32"), + DepKind.SYSCALL("timer_settime32"), + DepKind.SYSCALL("timerfd_gettime32"), + DepKind.SYSCALL("timerfd_settime32"), + DepKind.SYSCALL("utimensat_time32"), + DepKind.SYSCALL("pselect6_time32"), + DepKind.SYSCALL("ppoll_time32"), + DepKind.SYSCALL("io_pgetevents_time32"), + DepKind.SYSCALL("recvmmsg_time32"), + DepKind.SYSCALL("mq_timedsend_time32"), + DepKind.SYSCALL("mq_timedreceive_time32"), + DepKind.SYSCALL("rt_sigtimedwait_time32"), + DepKind.SYSCALL("futex_time32"), + DepKind.SYSCALL("sched_rr_get_interval_time32"), + ], +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/__init__.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/__init__.py new file mode 100644 index 00000000..1b85a808 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/__init__.py @@ -0,0 +1,4 @@ +from .bpftool import * +from .dump import * +from .kind import * +from .types import * diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/bpftool.patch b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/bpftool.patch new file mode 100644 index 00000000..cd6e3f25 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/bpftool.patch @@ -0,0 +1,13 @@ +diff --git a/src/gen.c b/src/gen.c +index b3979dd..5eaeb1c 100644 +--- a/src/gen.c ++++ b/src/gen.c +@@ -2355,8 +2355,6 @@ static int btfgen_record_obj(struct btfgen_info *info, const char *obj_path) + + err = bpf_core_calc_relo_insn(sec_name, relo, relo_idx, btf, cands, + specs_scratch, &targ_res); +- if (err) +- goto out; + + /* specs_scratch[2] is the target spec */ + err = btfgen_record_reloc(info, &specs_scratch[2]); diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/bpftool.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/bpftool.py new file mode 100644 index 00000000..7850d07f --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/bpftool.py @@ -0,0 +1,30 @@ +from functools import partial +from pathlib import Path + +from depsurf.utils import manage_result_path, system + +CURR_PATH = Path(__file__).parent +BPFTOOL_SRC_PATH = CURR_PATH / "bpftool" / "src" +BPFTOOL_PATCH_PATH = CURR_PATH / "bpftool.patch" +BPFTOOL_BIN_PATH = BPFTOOL_SRC_PATH / "bpftool" + + +@manage_result_path +def gen_min_btf(obj_file, result_path): + system( + f"{BPFTOOL_BIN_PATH} gen min_core_btf {obj_file} {result_path} {obj_file}", + linux=True, + ) + + +@manage_result_path +def dump_btf(raw_btf_path: Path, cmd: str, result_path: Path): + system( + f"{BPFTOOL_BIN_PATH} btf dump file {raw_btf_path} {cmd} > {result_path}", + linux=True, + ) + + +dump_btf_header = partial(dump_btf, cmd="format c") +dump_btf_txt = partial(dump_btf, cmd="format raw") +dump_btf_json = partial(dump_btf, cmd="--json") diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/dump.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/dump.py new file mode 100644 index 00000000..d988fe3c --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/dump.py @@ -0,0 +1,207 @@ +import json +import logging +from functools import cached_property +from pathlib import Path +from typing import Dict + +from depsurf.utils import manage_result_path + +from .kind import Kind + + +class BTFNormalizer: + def __init__(self, path: Path): + assert path.suffix == ".json" + self.path = path + + @cached_property + def raw_types(self): + with open(self.path) as f: + return json.load(f)["types"] + + def get_raw(self, type_id): + elem = self.raw_types[type_id - 1] + assert elem["id"] == type_id + return elem + + RECURSE_KINDS = { + Kind.CONST, + Kind.VOLATILE, + Kind.RESTRICT, + Kind.PTR, + Kind.FUNC, + Kind.FUNC_PROTO, + Kind.ARRAY, + } + + def normalize_int(self, elem, recurse): + assert elem["bits_offset"] == 0 + del elem["bits_offset"] + del elem["encoding"] + del elem["nr_bits"] + if not recurse: + del elem["size"] + + @staticmethod + def uint2sint(u, nbytes): + nbits = nbytes * 8 + u &= (1 << nbits) - 1 + if u >= (1 << (nbits - 1)): + return u - (1 << nbits) + return u + + def normalize_enum(self, elem, recurse): + assert elem["vlen"] == len(elem["values"]) + del elem["vlen"] + + if recurse: + if elem["encoding"] == "UNSIGNED": + elem["values"] = [ + {**v, "val": self.uint2sint(v["val"], elem["size"])} + for v in elem["values"] + ] + else: + del elem["values"] + del elem["encoding"] + + def normalize_type_id(self, elem, recurse): + for type_key in ["type", "ret_type"]: + type_id = f"{type_key}_id" + + if type_id not in elem: + continue + + if recurse: + elem[type_key] = self.normalize(elem[type_id], recurse=False) + del elem[type_id] + + def get_new_list(self, old_list, expand_anon): + new_list = [] + + anon_count = 0 + for elem in old_list: + t = self.normalize(elem["type_id"], recurse=False) + is_anon = elem["name"] == "(anon)" + + if is_anon and expand_anon and (t["kind"] in (Kind.STRUCT, Kind.UNION)): + t = self.get_raw(elem["type_id"]) + sub_list = self.get_new_list(t["members"], expand_anon=True) + for sub_item in sub_list: + sub_item["bits_offset"] += elem["bits_offset"] + new_list.append(sub_item) + continue + + name = elem["name"] + if is_anon: + if anon_count > 0: + name = f"(anon-{anon_count})" + anon_count += 1 + + new_list.append( + { + "name": name, + **{k: v for k, v in elem.items() if k not in ["name", "type_id"]}, + "type": t, + } + ) + + return new_list + + def normalize_list(self, elem, recurse): + for list_key in ["params", "members"]: + if list_key not in elem: + continue + + assert len(elem[list_key]) == elem["vlen"] + del elem["vlen"] + + if recurse: + expand_anon = list_key == "members" + elem[list_key] = self.get_new_list(elem[list_key], expand_anon) + else: + del elem[list_key] + if list_key == "members": + del elem["size"] + + def normalize(self, type_id, recurse): + if type_id == 0: + return {"name": "void", "kind": Kind.VOID.value} + + elem = self.get_raw(type_id) + + kind = elem["kind"] + + # Recurse into types for certain kinds + recurse = recurse or kind in self.RECURSE_KINDS + + elem = elem.copy() + + del elem["id"] + + if kind == Kind.INT: + self.normalize_int(elem, recurse) + elif kind == Kind.ARRAY: + del elem["index_type_id"] + elif kind in (Kind.ENUM, Kind.ENUM64): + self.normalize_enum(elem, recurse) + elif kind == Kind.FUNC: + assert elem["linkage"] == "static" + del elem["linkage"] + elif kind in (Kind.PTR, Kind.FUNC_PROTO): + assert elem["name"] == "(anon)" + del elem["name"] + + self.normalize_type_id(elem, recurse) + self.normalize_list(elem, recurse) + + return elem + + @cached_property + def data(self): + results: Dict[str, Dict[str, Dict]] = {k.value: {} for k in Kind} + + anon_enum_values = [] + for i in range(1, len(self.raw_types) + 1): + t = self.normalize(i, recurse=True) + + name = t.get("name") + if name is None: + continue + + if name == "(anon)": + if t["kind"] == Kind.ENUM.value: + anon_enum_values += t["values"] + continue + + kind = t["kind"] + group = results.get(kind) + if group is None: + results[kind] = {name: t} + else: + if name in group: + logging.debug(f"Duplicate type {name}") + else: + group[name] = t + + if anon_enum_values: + results[Kind.ENUM.value]["(anon)"] = { + "kind": "ENUM", + "name": "(anon)", + "size": 4, + "values": anon_enum_values, + } + return results + + @manage_result_path + def dump_types(self, kind: Kind, result_path: Path): + with open(result_path, "w") as f: + for k, v in self.data[kind].items(): + print(json.dumps(v), file=f) + + +def dump_types( + btf_json_path: Path, result_paths: Dict[Kind, Path], overwrite: bool = False +): + normalizer = BTFNormalizer(btf_json_path) + for kind, path in result_paths.items(): + normalizer.dump_types(kind, result_path=path, overwrite=overwrite) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/kind.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/kind.py new file mode 100644 index 00000000..ecdb4bb6 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/kind.py @@ -0,0 +1,24 @@ +from enum import StrEnum + + +class Kind(StrEnum): + VOID = "VOID" + INT = "INT" + PTR = "PTR" + ARRAY = "ARRAY" + STRUCT = "STRUCT" + UNION = "UNION" + ENUM = "ENUM" + FWD = "FWD" + TYPEDEF = "TYPEDEF" + VOLATILE = "VOLATILE" + CONST = "CONST" + RESTRICT = "RESTRICT" + FUNC = "FUNC" + FUNC_PROTO = "FUNC_PROTO" + VAR = "VAR" + DATASEC = "DATASEC" + FLOAT = "FLOAT" + DECL_TAG = "DECL_TAG" + TYPE_TAG = "TYPE_TAG" + ENUM64 = "ENUM64" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/types.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/types.py new file mode 100644 index 00000000..7343626a --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/btf/types.py @@ -0,0 +1,47 @@ +import json +import logging +from pathlib import Path +from typing import Dict + +from .kind import Kind + + +class Types: + def __init__(self, data: Dict): + assert isinstance(data, Dict) + self.data: Dict[str, Dict] = data + + @classmethod + def from_dump(cls, path: Path): + assert path.exists() + assert path.suffix == ".jsonl" + with open(path, "r") as f: + logging.info(f"Loading types from {path}") + + data = {} + for line in f: + info = json.loads(line) + data[info["name"]] = info + + return cls(data) + + @classmethod + def from_btf_json(cls, path: Path, kind: Kind): + assert path.exists() + assert path.suffix == ".json" + from .dump import BTFNormalizer + + data = BTFNormalizer(path).data + return cls(data[kind]) + + def __getitem__(self, name: str): + return self.data[name] + + def get(self, name: str): + return self.data.get(name) + + def items(self): + return self.data.items() + + def __iter__(self): + return iter(self.data) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/dep.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/dep.py new file mode 100644 index 00000000..6c6535e9 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/dep.py @@ -0,0 +1,152 @@ +from dataclasses import dataclass +from enum import StrEnum +from pathlib import Path +from typing import Callable, Dict, List, Optional + +from .diff import ( + BaseChange, + diff_config, + diff_enum, + diff_func, + diff_nop, + diff_struct, + diff_struct_field, + diff_tracepoint, +) +from .funcs import FuncGroup +from .issues import IssueEnum +from .utils import OrderedEnum +from .version import Version + + +class DepKind(OrderedEnum, StrEnum): + FUNC = "Function" + STRUCT = "Struct" + FIELD = "Field" + TRACEPOINT = "Tracepoint" + LSM = "LSM" + KFUNC = "kfunc" + SYSCALL = "Syscall" + + UNION = "Union" + ENUM = "Enum" + + UPROBE = "uprobe" + USDT = "USDT" + PERF_EVENT = "Perf Event" + CGROUP = "cgroup" + + CONFIG = "Config" + + REGISTER = "Register" + + @staticmethod + def from_hook_name(name: str): + if name.startswith("tracepoint/syscalls/"): + return DepKind.SYSCALL + + prefix = name.split("/")[0] + return { + "kprobe": DepKind.FUNC, + "kretprobe": DepKind.FUNC, + "fentry": DepKind.FUNC, + "fexit": DepKind.FUNC, + "tp_btf": DepKind.TRACEPOINT, + "raw_tp": DepKind.TRACEPOINT, + "raw_tracepoint": DepKind.TRACEPOINT, + "tracepoint": DepKind.TRACEPOINT, + "lsm": DepKind.LSM, + "uprobe": DepKind.UPROBE, + "uretprobe": DepKind.UPROBE, + "usdt": DepKind.USDT, + "perf_event": DepKind.PERF_EVENT, + "cgroup_skb": DepKind.CGROUP, + }[prefix] + + @property + def differ(self) -> Callable[[Dict, Dict], List[BaseChange]]: + return { + DepKind.STRUCT: diff_struct, + DepKind.FIELD: diff_struct_field, + DepKind.FUNC: diff_func, + DepKind.TRACEPOINT: diff_tracepoint, + DepKind.LSM: diff_func, + DepKind.KFUNC: diff_func, + DepKind.UNION: diff_struct, + DepKind.ENUM: diff_enum, + DepKind.SYSCALL: diff_nop, + DepKind.CONFIG: diff_config, + }[self] + + def __call__(self, name): + return Dep(self, name) + + def __repr__(self): + return self.value + + +@dataclass(frozen=True, order=True) +class Dep: + kind: DepKind + name: str + + def __str__(self): + return f"{self.kind.value} {self.name}" + + @classmethod + def from_dict(cls, data: Dict) -> "Dep": + return cls(DepKind(data["kind"]), data["name"]) + + @classmethod + def from_report_path(cls, path: Path) -> "Dep": + return cls(DepKind(path.parent.parent.name), path.stem) + + +@dataclass +class DepStatus: + version: Version + t: Optional[Dict] + func_group: Optional[FuncGroup] = None + + @property + def issues(self) -> List[IssueEnum]: + if not self.exists: + return [IssueEnum.ABSENT] + + if self.func_group: + return self.func_group.issues + + return [] + + @property + def exists(self) -> bool: + return self.t is not None or self.func_group is not None + + @classmethod + def from_dict(cls, data: Dict) -> "DepStatus": + return cls( + version=Version.from_dict(data["version"]), + t=data["t"], + func_group=( + FuncGroup.from_dict(data["func_group"]) if data["func_group"] else None + ), + ) + + +@dataclass +class DepDelta: + v1: Version + v2: Version + t1: Optional[Dict] + t2: Optional[Dict] + changes: List[BaseChange] + + @classmethod + def from_dict(cls, data: Dict) -> "DepDelta": + return cls( + v1=Version.from_dict(data["v1"]), + v2=Version.from_dict(data["v2"]), + t1=data["t1"], + t2=data["t2"], + changes=[BaseChange.from_dict(change) for change in data["changes"]], + ) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/__init__.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/__init__.py new file mode 100644 index 00000000..cc7efbdd --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/__init__.py @@ -0,0 +1,7 @@ +from .change import * +from .diff_common import * +from .diff_config import * +from .diff_enum import * +from .diff_func import * +from .diff_struct import * +from .diff_tracepoint import * diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/change.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/change.py new file mode 100644 index 00000000..a0b39375 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/change.py @@ -0,0 +1,148 @@ +import dataclasses +from dataclasses import dataclass +from typing import Dict + +from depsurf.issues import IssueEnum + + +class BaseChange: + issue_map = {} + issue: IssueEnum + + def __init_subclass__(cls): + cls.issue_map[cls.issue] = cls + + @classmethod + def from_dict(cls, data: Dict): + return cls.issue_map[data["issue"]](**data) + + def to_dict(self) -> Dict: + return dataclasses.asdict(self) + + +####################### +# Struct changes +####################### + +# @dataclass +# class StructLayoutChange(BaseChange): +# issue: IssueEnum = IssueEnum.STRUCT_LAYOUT + + +@dataclass +class FieldAdd(BaseChange): + name: str + type: dict + issue: IssueEnum = IssueEnum.FIELD_ADD + + +@dataclass +class FieldRemove(BaseChange): + name: str + type: dict + issue: IssueEnum = IssueEnum.FIELD_REMOVE + + +@dataclass +class FieldType(BaseChange): + name: str + old: dict + new: dict + issue: IssueEnum = IssueEnum.FIELD_TYPE + + +####################### +# Function changes +####################### +@dataclass +class FuncReturn(BaseChange): + old: str + new: str + issue: IssueEnum = IssueEnum.RETURN_TYPE + + +@dataclass +class ParamRemove(BaseChange): + name: str + type: dict + issue: IssueEnum = IssueEnum.PARAM_REMOVE + + +@dataclass +class ParamAdd(BaseChange): + name: str + type: dict + issue: IssueEnum = IssueEnum.PARAM_ADD + + +@dataclass +class ParamReorder(BaseChange): + old: dict + new: dict + issue: IssueEnum = IssueEnum.PARAM_REORDER + + +@dataclass +class ParamType(BaseChange): + name: str + old: dict + new: dict + issue: IssueEnum = IssueEnum.PARAM_TYPE + + +####################### +# Tracepoint changes +####################### +@dataclass +class TraceEventChange(BaseChange): + issue: IssueEnum = IssueEnum.TRACE_EVENT_CHANGE + + +@dataclass +class TraceFuncChange(BaseChange): + issue: IssueEnum = IssueEnum.TRACE_FUNC_CHANGE + + +@dataclass +class TraceFormatChange(BaseChange): + old: str + new: str + issue: IssueEnum = IssueEnum.TRACE_FMT_CHANGE + + def format(self): + return f"\n{self.old}\n{self.new}" + + +####################### +# Enum changes +####################### +@dataclass +class EnumValAdd(BaseChange): + name: str + val: int + issue: IssueEnum = IssueEnum.VAL_ADD + + +@dataclass +class EnumValRemove(BaseChange): + name: str + val: int + issue: IssueEnum = IssueEnum.VAL_REMOVE + + +@dataclass +class EnumValChange(BaseChange): + name: str + old_val: int + new_val: int + issue: IssueEnum = IssueEnum.VAL_CHANGE + + +####################### +# Config changes +####################### +@dataclass +class ConfigChange(BaseChange): + old: str + new: str + issue: IssueEnum = IssueEnum.CONFIG_CHANGE diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_common.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_common.py new file mode 100644 index 00000000..39026c27 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_common.py @@ -0,0 +1,14 @@ +from typing import Dict, Tuple + + +def diff_nop(old, new): + return [] + + +def diff_dict( + old: Dict, new: Dict +) -> Tuple[Dict[str, Dict], Dict[str, Dict], Dict[str, Tuple[Dict, Dict]]]: + added = {k: v for k, v in new.items() if k not in old} + removed = {k: v for k, v in old.items() if k not in new} + common = {k: (old[k], new[k]) for k in old.keys() if k in new} + return added, removed, common diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_config.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_config.py new file mode 100644 index 00000000..170663a3 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_config.py @@ -0,0 +1,7 @@ +from .change import ConfigChange + + +def diff_config(old, new): + if old != new: + return [ConfigChange(old, new)] + return [] diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_enum.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_enum.py new file mode 100644 index 00000000..cf070d07 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_enum.py @@ -0,0 +1,34 @@ +from typing import List + +from depsurf.btf import Kind +from depsurf.diff import BaseChange, EnumValAdd, EnumValChange, EnumValRemove + +from .diff_common import diff_dict + + +def diff_enum(old, new) -> List[BaseChange]: + assert old["kind"] == Kind.ENUM + assert new["kind"] == Kind.ENUM + + result = [] + + old_values = {v["name"]: v for v in old["values"]} + new_values = {v["name"]: v for v in new["values"]} + + added, removed, common = diff_dict(old_values, new_values) + + for name, value in added.items(): + result.append(EnumValAdd(name=name, val=value["val"])) + + for name, value in removed.items(): + result.append(EnumValRemove(name=name, val=value["val"])) + + changed_values = [ + (name, old_value["val"], new_value["val"]) + for name, (old_value, new_value) in common.items() + if old_value["val"] != new_value["val"] + ] + for name, old_val, new_val in changed_values: + result.append(EnumValChange(name=name, old_val=old_val, new_val=new_val)) + + return result diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_func.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_func.py new file mode 100644 index 00000000..2f8588e6 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_func.py @@ -0,0 +1,56 @@ +from typing import List + +from depsurf.btf import Kind + +from .change import ( + BaseChange, + FuncReturn, + ParamAdd, + ParamRemove, + ParamReorder, + ParamType, +) +from .diff_common import diff_dict + + +def diff_func(old, new) -> List[BaseChange]: + assert old["kind"] == Kind.FUNC + assert new["kind"] == Kind.FUNC + + result = [] + + old_params = {p["name"]: p for p in old["type"]["params"]} + new_params = {p["name"]: p for p in new["type"]["params"]} + + added, removed, common = diff_dict(old_params, new_params) + + # params added + for name, value in added.items(): + result.append(ParamAdd(**value)) + + # params removed + for name, value in removed.items(): + result.append(ParamRemove(**value)) + + # params reordered + old_idx = {n: i for i, n in enumerate(old_params) if n in common} + new_idx = {n: i for i, n in enumerate(new_params) if n in common} + if old_idx != new_idx: + result.append(ParamReorder(old_params, new_params)) + + # params changed type + changed_types = [ + (name, old_value["type"], new_value["type"]) + for name, (old_value, new_value) in common.items() + if old_value["type"] != new_value["type"] + ] + for name, old_value, new_value in changed_types: + result.append(ParamType(name, old_value, new_value)) + + # changed return value + old_ret = old["type"]["ret_type"] + new_ret = new["type"]["ret_type"] + if old_ret != new_ret: + result.append(FuncReturn(old_ret, new_ret)) + + return result diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_struct.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_struct.py new file mode 100644 index 00000000..467fe014 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_struct.py @@ -0,0 +1,52 @@ +from typing import List + +from depsurf.btf import Kind + +from .change import ( + BaseChange, + FieldAdd, + FieldRemove, + FieldType, +) +from .diff_common import diff_dict + + +def diff_struct_field(old, new) -> List[BaseChange]: + assert old["name"] == new["name"] + + if old["type"] != new["type"]: + return [FieldType(name=old["name"], old=old["type"], new=new["type"])] + + return [] + + +def diff_struct(old, new) -> List[BaseChange]: + assert old["kind"] == new["kind"] + assert old["kind"] in (Kind.STRUCT, Kind.UNION), f"{old['kind']}" + + changes = [] + + old_members = {m["name"]: m for m in old["members"]} + new_members = {m["name"]: m for m in new["members"]} + + added, removed, common = diff_dict(old_members, new_members) + + for name, value in added.items(): + changes.append(FieldAdd(name=name, type=value["type"])) + + for name, value in removed.items(): + changes.append(FieldRemove(name=name, type=value["type"])) + + for name, (old_value, new_value) in common.items(): + if old_value["type"] != new_value["type"]: + changes.append( + FieldType(name=name, old=old_value["type"], new=new_value["type"]) + ) + + # def offsets(members): + # return [(name, member["bits_offset"]) for name, member in members.items()] + + # if offsets(old_members) != offsets(new_members) or old["size"] != new["size"]: + # changes.append(StructLayoutChange()) + + return changes diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_tracepoint.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_tracepoint.py new file mode 100644 index 00000000..c891cad7 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/diff/diff_tracepoint.py @@ -0,0 +1,32 @@ +from typing import Dict, List + +from .change import ( + BaseChange, + TraceEventChange, + TraceFormatChange, + TraceFuncChange, +) +from .diff_func import diff_func +from .diff_struct import diff_struct + + +def diff_tracepoint(old: Dict, new: Dict) -> List[BaseChange]: + result = [] + + result_struct = diff_struct(old["struct"], new["struct"]) + # result_struct = [r for r in result_struct if r.issue != IssueEnum.STRUCT_LAYOUT] + if result_struct: + result.append(TraceEventChange()) + for r in result_struct: + result.append(r) + + result_func = diff_func(old["func"], new["func"]) + if result_func: + result.append(TraceFuncChange()) + for r in result_func: + result.append(r) + + # if old.fmt_str != new.fmt_str: + # result.append(TraceFormatChange(old.fmt_str, new.fmt_str)) + + return result diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/__init__.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/__init__.py new file mode 100644 index 00000000..9a397a9d --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/__init__.py @@ -0,0 +1,6 @@ +from .dwarf import * +from .dwarf_dump import * +from .entry import * +from .group import * +from .groups import * +from .symbol import * diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/dwarf.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/dwarf.py new file mode 100644 index 00000000..f13b2e7f --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/dwarf.py @@ -0,0 +1,156 @@ +import logging +from dataclasses import dataclass +from pathlib import Path +from typing import Callable, Optional + +from elftools.dwarf.die import DIE +from elftools.dwarf.enums import ENUM_DW_TAG + +KERNEL_DIR = { + "arch", + "block", + "certs", + "crypto", + "drivers", + "fs", + "include", + "init", + "kernel", + "lib", + "mm", + "net", + "security", + "sound", + "virt", + "rust", +} + + +def get_name(die: DIE): + name = die.attributes.get("DW_AT_name") + if name is None: + return None + return name.value.decode("ascii") + + +def normalize_compile_path(s: str) -> str: + d = Path(s) + if not d.is_absolute(): + if d.parts[0] not in KERNEL_DIR: + logging.warning(f"Suspicious path {d}") + return str(d) + + d = d.resolve() + if len(d.parts) >= 4 and d.parts[3].startswith("linux-"): + return str(Path(*d.parts[4:])) + else: + if d.parts[1] not in ("usr", "tmp"): + logging.warning(f"Suspicious path {d}") + return str(d) + + +@dataclass(frozen=True) +class DIEHandler: + rec: bool + fn: Optional[Callable[[DIE, "Traverser"], None]] = None + + +class Traverser: + def __init__(self, top_die: DIE, handler_map: dict[str, DIEHandler]): + assert top_die.tag == "DW_TAG_compile_unit" + self.top_die = top_die + + for tag in handler_map: + assert tag in ENUM_DW_TAG, tag + self.handler_map = handler_map + + self.path = normalize_compile_path(self.top_die.get_full_path()) + self.lang = self.top_die.attributes["DW_AT_language"].value + + line_prog = top_die.dwarfinfo.line_program_for_CU(top_die.cu) + self.version = line_prog.header.version + self.file_entry = line_prog.header.file_entry + self.include_directory = [ + normalize_compile_path(b.decode("ascii")) + for b in line_prog.header.include_directory + ] + + self.num_indent = 0 + + def traverse(self): + self.traverse_impl(self.top_die) + + def traverse_impl(self, die: DIE): + handler = self.handler_map.get(die.tag) + if handler is None: + return + + if handler.fn: + handler.fn(die, self) + + if handler.rec: + for child in die.iter_children(): + self.traverse_impl(child) + + def traverse_debug(self): + self.traverse_debug_impl(self.top_die) + + def traverse_debug_impl(self, die: DIE): + tag = die.tag + + handler = self.handler_map.get(tag) + if handler is None: + return + + if handler.fn: + handler.fn(die, self) + + name = get_name(die) + external = die.attributes.get("DW_AT_external") + if external is not None and external.value == 1: + assert name is not None + name += " (external)" + if "DW_AT_abstract_origin" in die.attributes: + die_ao = die.get_DIE_from_attribute("DW_AT_abstract_origin") + die_ao_name = get_name(die_ao) or "" + assert name is None + name = f"-> {die_ao.offset:#010x} ({die_ao_name})" + if "DW_AT_call_origin" in die.attributes: + die_co = die.get_DIE_from_attribute("DW_AT_call_origin") + die_co_name = get_name(die_co) or "" + assert name is None + name = f"-> {die_co.offset:#010x} ({die_co_name})" + tag = tag.removeprefix("DW_TAG_").removeprefix("GNU_") + print(f"{die.offset:#010x} {' ' * self.num_indent}{tag} {name or ''}") + + if handler.rec: + self.num_indent += 1 + for child in die.iter_children(): + self.traverse_debug_impl(child) + self.num_indent -= 1 + + def get_decl_location(self, die: DIE): + if "DW_AT_decl_file" not in die.attributes: + if self.lang not in [0x8001]: + logging.warning(f"Die at {die.offset:#x} does not have DW_AT_decl_file") + return self.path + + file_idx = die.attributes["DW_AT_decl_file"].value + # To handle the inconsistency between DWARF4 and DWARF5 + if self.version < 5: + file_idx -= 1 + + entry = self.file_entry[file_idx] + + dir_idx = entry.dir_index + if self.version < 5: + dir_idx -= 1 + + directory = self.include_directory[dir_idx] + name = entry.name.decode("ascii") + + # return f"{directory}/{name}" + + line = die.attributes["DW_AT_decl_line"].value + # column = die.attributes["DW_AT_decl_column"].value + return f"{directory}/{name}:{line}" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/dwarf_dump.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/dwarf_dump.py new file mode 100644 index 00000000..b3e9c61c --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/dwarf_dump.py @@ -0,0 +1,220 @@ +import dataclasses +import json +import logging +from pathlib import Path +from typing import Dict, List, Optional, Tuple + +from elftools.dwarf.compileunit import CompileUnit +from elftools.dwarf.die import DIE +from elftools.dwarf.dwarfinfo import DWARFInfo +from elftools.elf.elffile import ELFFile + +from depsurf.utils import manage_result_path + +from .dwarf import DIEHandler, Traverser, get_name +from .entry import FuncEntry, InlineStatus + + +def get_pc(die: DIE) -> int: + attrs = ["DW_AT_low_pc", "DW_AT_entry_pc", "DW_AT_high_pc"] + for attr in attrs: + val = die.attributes.get(attr) + if val is not None: + return val.value + return 0 + + +class FunctionRecorder: + def __init__(self): + self.data: Dict[str, Dict[Tuple[Optional[str], Optional[str]], FuncEntry]] = {} + self.curr_prog = None + + def iter_funcs(self): + for name, group in self.data.items(): + for loc, func in group.items(): + if func.name.startswith("__compiletime_assert_"): + continue + yield func + + def get_or_create_entry(self, die: DIE, traverser: Traverser) -> FuncEntry: + name = get_name(die) + assert name is not None, f"{die.offset:#x}" + + group = self.data.setdefault(name, {}) + + external = die.attributes.get("DW_AT_external") + external = False if external is None else external.value == 1 + + if external: + (loc, file) = (None, None) + else: + loc = traverser.get_decl_location(die) + file = traverser.path + + key = (loc, file) + + entry = group.get(key) + if entry is not None: + return entry + + entry = FuncEntry( + addr=0, + name=name, + external=external, + loc=loc, + file=file, + ) + group[key] = entry + + return entry + + def record_prog(self, die: DIE, traverser: Traverser): + assert die.tag == "DW_TAG_subprogram" + + # ignore inlined subprograms as they will be accounted at the call site + if "DW_AT_abstract_origin" in die.attributes: + assert "DW_AT_inline" not in die.attributes + assert "DW_AT_name" not in die.attributes + self.curr_prog = None + origin_die = die.get_DIE_from_attribute("DW_AT_abstract_origin") + entry = self.get_or_create_entry(origin_die, traverser) + if entry.addr == 0: + entry.addr = get_pc(die) + return + + entry = self.get_or_create_entry(die, traverser) + + decl = die.attributes.get("DW_AT_declaration") + decl = False if decl is None else decl.value == 1 + if decl: + # declaration-only subprograms + return + + self.curr_prog = entry.name + + # set inline attribute + inline = die.attributes.get("DW_AT_inline") + if entry.inline in (InlineStatus.UNSEEN, InlineStatus.SEEN_UNKNOWN): + if inline is not None: + entry.inline = InlineStatus.from_num(inline.value) + else: + entry.inline = InlineStatus.SEEN_UNKNOWN + else: + if inline is not None and entry.inline.num != inline.value: + logging.warning( + f"Conflicting inline status: {entry.inline} vs {inline.value} at {die.offset:#x}" + ) + + if entry.loc is None: + entry.loc = traverser.get_decl_location(die) + if entry.file is None: + entry.file = traverser.path + + if entry.addr == 0: + entry.addr = get_pc(die) + + def record_call_gnu(self, die: DIE, traverser: Traverser): + if "DW_AT_abstract_origin" not in die.attributes: + return # indirect call + die = die.get_DIE_from_attribute("DW_AT_abstract_origin") + if "DW_AT_abstract_origin" in die.attributes: + die = die.get_DIE_from_attribute("DW_AT_abstract_origin") + self.record_call_impl(die, traverser, is_inline=False) + + def record_call(self, die: DIE, traverser: Traverser): + if "DW_AT_call_origin" not in die.attributes: + return # indirect call + die = die.get_DIE_from_attribute("DW_AT_call_origin") + if "DW_AT_abstract_origin" in die.attributes: + die = die.get_DIE_from_attribute("DW_AT_abstract_origin") + self.record_call_impl(die, traverser, is_inline=False) + + def record_inline(self, die: DIE, traverser: Traverser): + fn_die = die.get_DIE_from_attribute("DW_AT_abstract_origin") + entry = self.record_call_impl(fn_die, traverser, is_inline=True) + if entry.addr == 0: + entry.addr = get_pc(die) + + def record_call_impl(self, die: DIE, traverser: Traverser, is_inline: bool): + entry = self.get_or_create_entry(die, traverser) + + caller_name = self.curr_prog + # this may happen when a subprogram has abstract_origin + if caller_name is None: + return entry + + caller_loc = f"{traverser.path}:{caller_name}" + + if is_inline: + assert entry.name != caller_name, f"{entry.addr:#x}" + entry.caller_inline.append(caller_loc) + else: + # it is possible that entry.name == caller_name (e.g., recursive call) + entry.caller_func.append(caller_loc) + + return entry + + @classmethod + def from_cus(cls, cus: List[CompileUnit], debug=False): + obj = cls() + handler_map = { + "DW_TAG_compile_unit": DIEHandler(rec=True), + "DW_TAG_lexical_block": DIEHandler(rec=True), + "DW_TAG_subprogram": DIEHandler(rec=True, fn=obj.record_prog), + "DW_TAG_inlined_subroutine": DIEHandler(rec=True, fn=obj.record_inline), + # We don't want to recurse into call sites to avoid double counting + "DW_TAG_GNU_call_site": DIEHandler(rec=False, fn=obj.record_call_gnu), + "DW_TAG_call_site": DIEHandler(rec=False, fn=obj.record_call), + } + + cus = list(cus) + for i, cu in enumerate(cus): + top_die = cu.get_top_DIE() + lang = top_die.attributes["DW_AT_language"].value + if lang == 0x001C: # # ignore DW_LANG_Rust + logging.info(f"Ignoring {i + 1}/{len(cus)}: {traverser.path}") + continue + + traverser = Traverser(top_die, handler_map) + logging.debug(f"Traversing {i + 1}/{len(cus)}: {traverser.path}") + if debug: + traverser.traverse_debug() + else: + traverser.traverse() + + return obj + + @classmethod + def from_path(cls, path: Path, cus_mapper=None, debug=False): + logging.info(f"Dumping functions from {path}") + with path.open("rb") as f: + elffile = ELFFile(f) + dwarfinfo = elffile.get_dwarf_info(relocate_dwarf_sections=False) + cus = dwarfinfo.iter_CUs() + if cus_mapper is not None: + cus = cus_mapper(cus) + obj = cls.from_cus(cus, debug=debug) + del dwarfinfo + del elffile + return obj + + def dump(self, path: Path): + with open(path, "w") as f: + for func in self.iter_funcs(): + print(json.dumps(dataclasses.asdict(func)), file=f) + + +def disable_dwarf_cache(): + def _get_cached_DIE(self: CompileUnit, offset): + top_die_stream = self.get_top_DIE().stream + return DIE(cu=self, stream=top_die_stream, offset=offset) + + CompileUnit._get_cached_DIE = _get_cached_DIE + DWARFInfo._cached_CU_at_offset = DWARFInfo._parse_CU_at_offset + + +@manage_result_path +def dump_func_entries(path: Path, result_path: Path): + disable_dwarf_cache() + + FunctionRecorder.from_path(path).dump(result_path) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/entry.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/entry.py new file mode 100644 index 00000000..342507f6 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/entry.py @@ -0,0 +1,59 @@ +import dataclasses +from dataclasses import dataclass +from enum import StrEnum +from typing import List, Optional + + +class InlineStatus(StrEnum): + NOT_DECL_NOT_INLINE = "not declared, not inlined" + NOT_DECL_INLINE = "not declared, inlined" + DECL_NOT_INLINE = "declared, not inlined" + DECL_INLINE = "declared, inlined" + UNSEEN = "not seen" + SEEN_UNKNOWN = "seen, unknown" + + @classmethod + def from_num(cls, n: int) -> "InlineStatus": + return [ + cls.NOT_DECL_NOT_INLINE, + cls.NOT_DECL_INLINE, + cls.DECL_NOT_INLINE, + cls.DECL_INLINE, + ][n] + + @property + def num(self) -> int: + return { + self.NOT_DECL_NOT_INLINE: 0, + self.NOT_DECL_INLINE: 1, + self.DECL_NOT_INLINE: 2, + self.DECL_INLINE: 3, + }[self] + + +@dataclass +class FuncEntry: + addr: int + name: str + external: bool + loc: Optional[str] = None + file: Optional[str] = None + inline: InlineStatus = InlineStatus.UNSEEN + caller_inline: List[str] = dataclasses.field(default_factory=list) + caller_func: List[str] = dataclasses.field(default_factory=list) + + @property + def inline_declared(self) -> bool: + return self.inline in (InlineStatus.DECL_NOT_INLINE, InlineStatus.DECL_INLINE) + + @property + def inline_actual(self) -> bool: + return self.inline in (InlineStatus.NOT_DECL_INLINE, InlineStatus.DECL_INLINE) + + @property + def has_inline_caller(self) -> bool: + return bool(self.caller_inline) + + @property + def has_func_caller(self) -> bool: + return bool(self.caller_func) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/group.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/group.py new file mode 100644 index 00000000..fc613bf9 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/group.py @@ -0,0 +1,176 @@ +import dataclasses +import logging +from dataclasses import dataclass +from enum import StrEnum +from typing import Dict, List + +from depsurf.issues import IssueEnum + +from .entry import FuncEntry +from .symbol import FuncSymbol + + +class CollisionType(StrEnum): + UNIQUE_GLOBAL = "Unique Global" + UNIQUE_STATIC = "Unique Static" + INCLUDE_DUP = "Static Duplication" + STATIC_STATIC = "Static-Static Collision" + STATIC_GLOBAL = "Static-Global Collision" + + +def get_collision_type(funcs: List[FuncEntry]) -> CollisionType: + if len(funcs) == 1: + if funcs[0].external: + return CollisionType.UNIQUE_GLOBAL + else: + return CollisionType.UNIQUE_STATIC + + # Functions with the same location + # => defined in the header file and included in multiple source files + if len({func.loc for func in funcs}) == 1: + return CollisionType.INCLUDE_DUP + + if all(not func.external for func in funcs): + # Static functions have name collision with other static functions + return CollisionType.STATIC_STATIC + else: + # External functions have name collision with static functions + return CollisionType.STATIC_GLOBAL + + +class InlineType(StrEnum): + NO = "No" + FULL = "Full" + SELECTIVE = "Selective" + + +def get_inline_type(funcs: List[FuncEntry], in_symtab: bool) -> InlineType: + name = funcs[0].name + + for func in funcs: + if func.has_inline_caller: + # having inline caller must implies inline + if not func.inline_actual: + logging.warning( + f"{name} at {func.loc} has inline caller but not inline." + ) + else: + # if the function is inlined, there could be inline caller miss-counted + if func.inline_actual: + logging.debug( + f"{name} at {func.loc} is inline but has no inline caller. " + f"maybe it is declared w/ __attribute__((always_inline))" + ) + + if not in_symtab: + # Check if any one of the functions has func caller + # This case should be very rare + if any(func.has_func_caller for func in funcs): + if name.startswith("__builtin_") or name.startswith("__real_"): + logging.debug(f"{name} is a builtin function") + elif name in { + "__switch_to_asm", + "asm_call_irq_on_stack", + "asm_call_sysvec_on_stack", + "relocate_kernel", + "restore_image", + "rewind_stack_and_make_dead", + "rewind_stack_do_exit", + "soft_restart_cpu", + "start_cpu0", + "swsusp_arch_suspend", + "xen_cpu_bringup_again", + "xen_pvh_early_cpu_init", + "__efi64_thunk", + }: + logging.debug(f"{name} is an assembly function") + elif name.startswith("efi_"): + logging.debug(f"{name} is an EFI function") + else: + logging.warning(f"{name} has func caller but no sym entry. ") + return InlineType.FULL + + if any(func.inline_actual for func in funcs): + # Any of the functions is inlined + return InlineType.SELECTIVE + else: + return InlineType.NO + + +@dataclass(frozen=True) +class FuncGroup: + name: str + collision_type: CollisionType + inline_type: InlineType + funcs: List[FuncEntry] + symbols: List[FuncSymbol] + + @classmethod + def from_funcs(cls, funcs: List[FuncEntry], symbols: List[FuncSymbol]): + assert len(funcs) > 0, "There must be at least one function in a group" + assert all(func.name == funcs[0].name for func in funcs), ( + "All functions must have the same name" + ) + assert sum(func.external for func in funcs) <= 1, ( + "There should be at most one external function in a group" + ) + + return cls( + name=funcs[0].name, + collision_type=get_collision_type(funcs), + inline_type=get_inline_type(funcs, len(symbols) > 0), + funcs=funcs, + symbols=symbols, + ) + + @classmethod + def from_dict(cls, data: Dict) -> "FuncGroup": + return cls( + name=data["name"], + funcs=[FuncEntry(**func) for func in data["funcs"]], + collision_type=CollisionType(data["collision_type"]), + inline_type=InlineType(data["inline_type"]), + symbols=[FuncSymbol(**sym) for sym in data["symbols"]], + ) + + def to_dict(self) -> Dict: + return dataclasses.asdict(self) + + @property + def num_funcs(self): + return len(self.funcs) + + @property + def has_suffix(self): + return any(sym.has_suffix for sym in self.symbols) + + @property + def issues(self) -> List[IssueEnum]: + result = [] + + # collision + if self.collision_type == CollisionType.INCLUDE_DUP: + result.append(IssueEnum.DUPLICATE) + elif self.collision_type in ( + CollisionType.STATIC_STATIC, + CollisionType.STATIC_GLOBAL, + ): + result.append(IssueEnum.COLLISION) + + # inline + if self.inline_type == InlineType.FULL: + result.append(IssueEnum.FULL_INLINE) + elif self.inline_type == InlineType.SELECTIVE: + result.append(IssueEnum.SELECTIVE_INLINE) + + # transformation + if self.has_suffix: + result.append(IssueEnum.TRANSFORMATION) + + return result + + def __getitem__(self, index): + return self.funcs[index] + + def __iter__(self): + return iter(self.funcs) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/groups.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/groups.py new file mode 100644 index 00000000..fc98c009 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/groups.py @@ -0,0 +1,73 @@ +import dataclasses +import json +import logging +from collections import defaultdict +from dataclasses import dataclass +from pathlib import Path +from typing import Dict, Iterator, List, Optional + +from depsurf.linux import SymbolTable +from depsurf.utils import manage_result_path + +from .entry import FuncEntry +from .group import FuncGroup +from .symbol import FuncSymbol, get_func_symbols + + +@dataclass(frozen=True) +class FuncGroups: + data: Dict[str, FuncGroup] + + @property + def num_groups(self) -> int: + return len(self.data) + + def get_group(self, name) -> Optional[FuncGroup]: + return self.data.get(name) + + def iter_groups(self) -> Iterator[FuncGroup]: + for group in self.data.values(): + yield group + + def iter_funcs(self) -> Iterator[FuncEntry]: + for group in self.data.values(): + for func in group.funcs: + yield func + + def iter_symbols(self) -> Iterator[FuncSymbol]: + for group in self.data.values(): + for symbol in group.symbols: + yield symbol + + def __str__(self): + return f"FuncGroups({self.num_groups} groups)" + + @classmethod + def from_dump(cls, path: Path): + logging.info(f"Loading funcs from {path}") + result: Dict[str, FuncGroup] = {} + with open(path, "r") as f: + for line in f: + group = FuncGroup.from_dict(json.loads(line)) + result[group.name] = group + return cls(data=result) + + +@manage_result_path +def dump_func_groups(func_entries_path: Path, symtab_path: Path, result_path: Path): + functions: Dict[str, List[FuncEntry]] = defaultdict(list) + with open(func_entries_path, "r") as f: + for line in f: + func = FuncEntry(**json.loads(line)) + functions[func.name].append(func) + + func_symbols = get_func_symbols(SymbolTable.from_dump(symtab_path)) + + data = { + name: FuncGroup.from_funcs(funcs, func_symbols.get(name) or []) + for name, funcs in functions.items() + } + + with open(result_path, "w") as f: + for group in data.values(): + print(json.dumps(group.to_dict()), file=f) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/symbol.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/symbol.py new file mode 100644 index 00000000..49dbf365 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/funcs/symbol.py @@ -0,0 +1,68 @@ +import logging +from collections import defaultdict +from dataclasses import dataclass +from enum import StrEnum +from typing import Dict, List + +from depsurf.linux import SymbolTable + + +class TransformType(StrEnum): + ISRA = "isra" + CONSTPROP = "constprop" + PART = "part" + COLD = "cold" + LOCALALIAS = "localalias" + MULTIPLE = "≥2" + + +@dataclass +class FuncSymbol: + addr: int + name: str + section: str + bind: str + size: int + + @property + def stem(self) -> str: + return self.name.split(".")[0] + + @property + def has_suffix(self) -> bool: + return "." in self.name + + @property + def suffixes(self) -> List[str]: + return [s for s in self.name.split(".")[1:] if not s.isdigit()] + + @property + def transform_type(self) -> TransformType: + assert self.has_suffix, "Symbol has no suffix" + suffixes = self.suffixes + if len(suffixes) > 1: + return TransformType.MULTIPLE + return TransformType(suffixes[0]) + + +def get_func_symbols(symtab: SymbolTable) -> Dict[str, List[FuncSymbol]]: + result: Dict[str, List[FuncSymbol]] = defaultdict(list) + for sym in symtab.data: + if sym["type"] != "STT_FUNC": + continue + name: str = sym["name"] + # Ref: https://github.com/torvalds/linux/commit/9f2899fe36a623885d8576604cb582328ad32b3c + if name.startswith("__pfx"): + continue + if sym["visibility"] != "STV_DEFAULT": + logging.debug(f"Symbol {name} is not default visibility: {sym}") + func_sym = FuncSymbol( + addr=sym["value"], + name=sym["name"], + section=sym["section"], + bind=sym["bind"], + size=sym["size"], + ) + result[func_sym.stem].append(func_sym) + + return result diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/issues.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/issues.py new file mode 100644 index 00000000..77cfae59 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/issues.py @@ -0,0 +1,90 @@ +from enum import StrEnum + + +class Consequence(StrEnum): + # Rank by severity, don't change the order + MISS = "Missing invocation" + STRAY = "Stray read" + ERROR = "Error" + OK = "OK" + UNKNOWN = "Unknown" + + +class IssueEnum(StrEnum): + # Not really an issue, defined for convenience + OLD = "Old" + NEW = "New" + + # Generic status + OK = "OK" + ABSENT = "Absent" + + # Generic changes + ADD = "Added" + REMOVE = "Removed" + CHANGE = "Changed" + NO_CHANGE = "No change" + BOTH_ABSENT = "Both absent" + + # Function status + SELECTIVE_INLINE = "Selective Inline" + FULL_INLINE = "Full Inline" + TRANSFORMATION = "Transformation" + DUPLICATE = "Duplicate" + COLLISION = "Collision" + + # Function changes + FUNC_ADD = "Function added" + FUNC_REMOVE = "Function removed" + FUNC_CHANGE = "Function changed" + PARAM_ADD = "Param added" + PARAM_REMOVE = "Param removed" + PARAM_REORDER = "Param reordered" + PARAM_TYPE = "Param type changed" + RETURN_TYPE = "Return type changed" + + # Struct changes + STRUCT_ADD = "Struct added" + STRUCT_REMOVE = "Struct removed" + STRUCT_CHANGE = "Struct changed" + # STRUCT_LAYOUT = "Struct layout changed" + FIELD_ADD = "Field added" + FIELD_REMOVE = "Field removed" + FIELD_TYPE = "Field type changed" + + # Enum changes + ENUM_ADD = "Enum added" + ENUM_REMOVE = "Enum removed" + ENUM_CHANGE = "Enum changed" + VAL_ADD = "Value added" + VAL_REMOVE = "Value removed" + VAL_CHANGE = "Value changed" + + # Tracepoint changes + TRACE_EVENT_CHANGE = "Event changed" + TRACE_FMT_CHANGE = "Format changed" + TRACE_FUNC_CHANGE = "Func changed" + + # Config changes + CONFIG_CHANGE = "Config changed" + + @property + def consequence(self): + d = { + self.OK: Consequence.OK, + self.ABSENT: Consequence.ERROR, + self.PARAM_ADD: Consequence.STRAY, + self.PARAM_REMOVE: Consequence.STRAY, + self.PARAM_TYPE: Consequence.STRAY, + self.PARAM_REORDER: Consequence.STRAY, + self.RETURN_TYPE: Consequence.STRAY, + self.SELECTIVE_INLINE: Consequence.MISS, + self.FULL_INLINE: Consequence.ERROR, + self.TRANSFORMATION: Consequence.ERROR, + self.DUPLICATE: Consequence.MISS, + self.FIELD_TYPE: Consequence.STRAY, + } + return d.get(self, Consequence.UNKNOWN) + + def __repr__(self): + return f"'{self.value}'" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/__init__.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/__init__.py new file mode 100644 index 00000000..ec88ca92 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/__init__.py @@ -0,0 +1,8 @@ +from .comment import * +from .config import * +from .extract import * +from .filebytes import * +from .struct import * +from .symtab import * +from .syscalls import * +from .tracepoint import * diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/comment.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/comment.py new file mode 100644 index 00000000..daa58c2f --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/comment.py @@ -0,0 +1,20 @@ +from pathlib import Path + +from elftools.elf.elffile import ELFFile + +from depsurf.utils import manage_result_path + + +def get_comment(vmlinux_path: Path) -> str: + with open(vmlinux_path, "rb") as f: + elf = ELFFile(f) + section = elf.get_section_by_name(".comment") + if section is None: + return "" + return section.data().decode().replace("\0", "\n") + + +@manage_result_path +def dump_comment(vmlinux_path: Path, result_path: Path): + with open(result_path, "w") as f: + f.write(get_comment(vmlinux_path)) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/config.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/config.py new file mode 100644 index 00000000..6cd68ea4 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/config.py @@ -0,0 +1,32 @@ +import logging +import re +from pathlib import Path +from typing import Dict, Optional + + +def get_configs(path: Path) -> Dict[str, Optional[str]]: + with open(path, "r") as f: + lines = f.readlines() + + configs = {} + for line in lines: + line = line.strip() + if not line: + continue + + groups = re.match(r"# CONFIG_(\w+) is not set", line) + if groups: + configs[groups[1]] = None + continue + + groups = re.match(r"CONFIG_(\w+)=(.*)", line) + if groups: + configs[groups[1]] = groups[2] + continue + + if line[0] == "#": + continue + + logging.warning(f"Unrecognized line in {path}: {line}") + + return configs diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/extract.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/extract.py new file mode 100644 index 00000000..8c01fc93 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/extract.py @@ -0,0 +1,48 @@ +import logging +from pathlib import Path + +from elftools.elf.elffile import ELFFile + +from depsurf.utils import manage_result_path, system + + +def list_deb(deb_path: Path): + system(f"dpkg -c {deb_path}") + + +@manage_result_path +def extract_deb(deb_path: Path, file_path: str, result_path: Path): + system( + f"dpkg --fsys-tarfile {deb_path} | tar -xO .{file_path} > {result_path}", + linux=True, + ) + + +@manage_result_path +def extract_btf(vmlinux_path: Path, result_path: Path): + with open(vmlinux_path, "rb") as f: + elf = ELFFile(f) + + if elf.has_dwarf_info(): + # Ref: https://github.com/torvalds/linux/blob/master/scripts/Makefile.btf + system( + f"pahole " + # f"--btf_gen_floats " + f"--lang_exclude=rust " + # f"--btf_gen_optimized " + f"--btf_encode_detached {result_path} " + f"{vmlinux_path}" + ) + return + + btf = elf.get_section_by_name(".BTF") + if btf: + logging.info(f"Extracting .BTF from {vmlinux_path} to {result_path}") + with open(result_path, "wb") as f: + f.write(btf.data()) + # system( + # f"objcopy -I elf64-little {self.path} --dump-section .BTF={result_path}" + # ) + return + + raise ValueError(f"No BTF or DWARF in {vmlinux_path}") diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/filebytes.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/filebytes.py new file mode 100644 index 00000000..4fc3cddd --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/filebytes.py @@ -0,0 +1,122 @@ +import logging +import shutil +from functools import cached_property +from pathlib import Path +from typing import Dict, Literal + +from elftools.elf.dynamic import DynamicSection +from elftools.elf.elffile import ELFFile +from elftools.elf.relocation import RelocationSection + +from depsurf.utils import system + + +def get_objdump_path(): + canidates = ["llvm-objdump-18", "llvm-objdump", "objdump"] + for prog in canidates: + path = shutil.which(prog) + if path: + return path + else: + raise FileNotFoundError(f"None of {canidates} found") + + +def objdump(path: Path): + system( + f"{get_objdump_path()} --disassemble --reloc --source {path}", + ) + + +def hexdump(path: Path): + system(f"hexdump -C {path}") + + +def get_cstr(data: bytes, off: int) -> str: + end = data.find(b"\x00", off) + return data[off:end].decode() + + +class FileBytes: + def __init__(self, vmlinux_path: Path): + self.file = open(vmlinux_path, "rb") + self.elf = ELFFile(self.file) + self.stream = self.elf.stream + self.ptr_size = self.elf.elfclass // 8 + self.byteorder: Literal["little", "big"] = ( + "little" if self.elf.little_endian else "big" + ) + + def __del__(self): + self.file.close() + + def addr_to_offset(self, addr): + offsets = list(self.elf.address_offsets(addr)) + if len(offsets) == 1: + return offsets[0] + elif len(offsets) == 0: + raise ValueError(f"Address {addr:x} not found") + else: + raise ValueError(f"Multiple offsets found for address {addr:x}") + + def get_bytes(self, addr, size=8) -> bytes: + if addr in self.relocations: + assert size == 8 + return self.relocations[addr] + offset = self.addr_to_offset(addr) + self.stream.seek(offset) + return self.stream.read(size) + + def get_int(self, addr, size) -> int: + b = self.get_bytes(addr, size) + return int.from_bytes(b, self.byteorder) + + def get_cstr(self, addr, size=4096) -> str: + data = self.get_bytes(addr, size) + return get_cstr(data, 0) + + @cached_property + def relocations(self) -> Dict[int, bytes]: + arch = self.elf["e_machine"] + if arch not in ("EM_AARCH64", "EM_S390"): + return {} + + relo_sec = self.elf.get_section_by_name(".rela.dyn") + if not isinstance(relo_sec, RelocationSection): + logging.warning("No .rela.dyn found") + return {} + + if arch == "EM_S390": + dynsym = self.elf.get_section_by_name(".dynsym") + if not isinstance(dynsym, DynamicSection): + logging.warning("No .dynsym found") + return {} + + constant = 1 << self.elf.elfclass + + result = {} + for r in relo_sec.iter_relocations(): + info_type = r["r_info_type"] + if info_type == 0: + continue + elif arch == "EM_AARCH64": + # Ref: https://github.com/torvalds/linux/blob/a2c63a3f3d687ac4f63bf4ffa04d7458a2db350b/arch/arm64/kernel/pi/relocate.c#L19-L23 + if info_type != 1027: # R_AARCH64_RELATIVE + continue + val = constant + r["r_addend"] + elif arch == "EM_S390" and info_type in (12, 22): + # R_390_RELATIVE and R_390_64 + # Ref: + # - https://github.com/torvalds/linux/blob/a2c63a3f3d687ac4f63bf4ffa04d7458a2db350b/arch/s390/boot/startup.c#L145 + # - https://github.com/torvalds/linux/blob/a2c63a3f3d687ac4f63bf4ffa04d7458a2db350b/arch/s390/kernel/machine_kexec_reloc.c#L5 + val = r["r_addend"] + info = r["r_info"] + sym_idx = info >> 32 + if sym_idx != 0: + sym = dynsym.get_symbol(sym_idx) + val += sym["st_value"] + else: + raise ValueError(f"Unknown relocation type {r} for arch {arch}") + addr = r["r_offset"] + result[addr] = val.to_bytes(8, self.byteorder) + + return result diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/struct.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/struct.py new file mode 100644 index 00000000..e091fb2d --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/struct.py @@ -0,0 +1,55 @@ +from depsurf.btf import Kind, Types + +from .filebytes import FileBytes + + +class StructInstance: + def __init__( + self, + struct_types: Types, + int_types: Types, + filebytes: FileBytes, + name: str, + ptr: int, + ): + self.int_types = int_types + self.filebytes = filebytes + self.name = name + self.ptr = ptr + + t = struct_types.get(name) + assert t is not None, f"Could not find struct {name}" + + self.size = t["size"] + self.members = {m["name"]: m for m in t["members"]} + + def get_offset(self, member_name): + bits_offset = self.members[member_name]["bits_offset"] + assert bits_offset % 8 == 0 + return bits_offset // 8 + + def get(self, name, size=None) -> int: + m = self.members[name] + t = m["type"] + kind = t["kind"] + + addr = self.ptr + self.get_offset(name) + + if size is None: + if kind == Kind.PTR: + size = self.filebytes.ptr_size + elif kind == Kind.INT: + size = self.int_types[t["name"]]["size"] + else: + raise NotImplementedError + + return self.filebytes.get_int(addr, size) + + def __getitem__(self, name) -> int: + return self.get(name) + + def get_bytes(self): + return self.filebytes.get_bytes(self.ptr, self.size) + + def __repr__(self): + return f"StructInstance({self.name}, {self.ptr:x}): {self.get_bytes().hex()}" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/symtab.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/symtab.py new file mode 100644 index 00000000..002fb884 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/symtab.py @@ -0,0 +1,66 @@ +import json +import logging +from pathlib import Path +from typing import Dict, List + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection + +from depsurf.utils import manage_result_path + + +@manage_result_path +def dump_symtab(vmlinux_path: Path, result_path: Path): + with open(vmlinux_path, "rb") as fin: + elffile = ELFFile(fin) + + symtab = elffile.get_section_by_name(".symtab") + if symtab is None: + raise ValueError( + "No symbol table found. Perhaps this is a stripped binary?" + ) + assert type(symtab) == SymbolTableSection + + sections = [s.name for s in elffile.iter_sections()] + + with open(result_path, "w") as fout: + for sym in symtab.iter_symbols(): + entry = { + "name": sym.name, + "section": ( + sections[sym.entry.st_shndx] + if isinstance(sym.entry.st_shndx, int) + else sym.entry.st_shndx + ), + **sym.entry.st_info, + **sym.entry.st_other, + "value": sym.entry.st_value, + "size": sym.entry.st_size, + } + fout.write(json.dumps(entry) + "\n") + + +class SymbolTable: + def __init__(self, data: List[Dict]): + self.data: List[Dict] = data + + @classmethod + def from_dump(cls, path): + data = [] + logging.info(f"Loading symtab from {path}") + with open(path) as f: + for line in f: + data.append(json.loads(line)) + return cls(data) + + def get_symbols_by_name(self, name: str): + return [sym for sym in self.data if sym["name"] == name] + + def get_symbols_by_addr(self, addr: int): + return [sym for sym in self.data if sym["value"] == addr] + + def __repr__(self): + return f"SymbolTable({len(self.data)} symbols)" + + def __iter__(self): + return iter(self.data) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/syscalls.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/syscalls.py new file mode 100644 index 00000000..896638be --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/syscalls.py @@ -0,0 +1,72 @@ +import json +import logging +from typing import Iterable, Tuple, TYPE_CHECKING + +from depsurf.utils import manage_result_path + +from .filebytes import FileBytes +from .symtab import SymbolTable + +if TYPE_CHECKING: + from ..linux_image import LinuxImage + +SYSCALL_PREFIXES = ["stub_", "sys_", "ppc_", "ppc64_", "sys32_x32_"] + + +class SyscallExtracter: + def __init__(self, symtab: SymbolTable, filebytes: FileBytes): + self.symtab = symtab + self.filebytes = filebytes + + self.table_addr = None + self.table_size = None + self.addr_to_name = {} + + for sym in self.symtab.data: + if sym["name"] == "sys_call_table": + assert self.table_addr is None + assert self.table_size is None + self.table_addr = sym["value"] + self.table_size = sym["size"] + if self.table_size == 0: + logging.warning("sys_call_table size is 0. Using hardcoded size") + # https://github.com/torvalds/linux/blob/219d54332a09e8d8741c1e1982f5eae56099de85/include/uapi/asm-generic/unistd.h#L855 + self.table_size = 436 * self.filebytes.ptr_size + + if ( + sym["type"] in ("STT_FUNC", "STT_NOTYPE") + and any(p in sym["name"] for p in SYSCALL_PREFIXES) + and ( + sym["value"] not in self.addr_to_name or sym["bind"] == "STB_GLOBAL" + ) + ): + self.addr_to_name[sym["value"]] = sym["name"] + + def iter_syscall(self) -> Iterable[Tuple[str, int]]: + assert self.table_addr is not None + assert self.table_size is not None + + for i, ptr in enumerate( + range( + self.table_addr, + self.table_addr + self.table_size, + self.filebytes.ptr_size, + ) + ): + val = self.filebytes.get_int(ptr, self.filebytes.ptr_size) + name = self.addr_to_name.get(val) + if name is None: + logging.warning(f"Unknown syscall at {i}: {ptr:x} -> {val:x}") + else: + for prefix in SYSCALL_PREFIXES: + name = name.split(prefix, 1)[-1] + logging.debug(f"{i}: {ptr:x} -> {val:x} -> {name}") + yield name, i + + +@manage_result_path +def dump_syscalls(img: "LinuxImage", result_path): + extractor = SyscallExtracter(img.symtab, img.filebytes) + syscalls = {i: name for name, i in extractor.iter_syscall()} + with open(result_path, "w") as f: + json.dump(syscalls, f, indent=2) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/tracepoint.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/tracepoint.py new file mode 100644 index 00000000..5485214c --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux/tracepoint.py @@ -0,0 +1,143 @@ +import dataclasses +import json +import logging +from dataclasses import dataclass +from pathlib import Path +from typing import TYPE_CHECKING, Dict, Iterator, Optional + +from depsurf.utils import manage_result_path + +from .struct import StructInstance + +if TYPE_CHECKING: + from depsurf.linux_image import LinuxImage + + +@dataclass +class Tracepoint: + class_name: str + event_name: str + func_name: str + struct_name: str + fmt_str: str + func: dict + struct: dict + + +class TracepointsExtractor: + def __init__(self, img: "LinuxImage"): + self.struct_types = img.struct_types + self.func_types = img.func_types + self.int_types = img.int_types + + self.filebytes = img.filebytes + self.symtab = img.symtab + + self.event_names = {} + self.class_names = {} + for sym in self.symtab: + t = sym["type"] + name: str = sym["name"] + if t == "STT_NOTYPE": + # Ref: https://github.com/torvalds/linux/blob/49668688dd5a5f46c72f965835388ed16c596055/kernel/module.c#L2317 + if name == "__start_ftrace_events": + self.start_ftrace_events = sym["value"] + elif name == "__stop_ftrace_events": + self.stop_ftrace_events = sym["value"] + elif t == "STT_OBJECT": + if name.startswith("event_class_"): + self.class_names[sym["value"]] = name.removeprefix("event_class_") + elif name.startswith("event_"): + self.event_names[sym["value"]] = name.removeprefix("event_") + + for e in img.enum_types["(anon)"]["values"]: + if e["name"] == "TRACE_EVENT_FL_TRACEPOINT": + self.FLAG_TRACEPOINT = e["val"] + elif e["name"] == "TRACE_EVENT_FL_IGNORE_ENABLE": + self.FLAG_IGNORE_ENABLE = e["val"] + + def iter_event_ptrs(self) -> Iterator[int]: + ptr_size = self.filebytes.ptr_size + for ptr in range(self.start_ftrace_events, self.stop_ftrace_events, ptr_size): + event_ptr = self.filebytes.get_int(ptr, ptr_size) + if event_ptr == 0: + logging.warning(f"Invalid event pointer: {ptr:x} -> {event_ptr:x}") + continue + yield event_ptr + + def get_tracepoint(self, ptr: int) -> Optional[Tracepoint]: + # Ref: https://github.com/torvalds/linux/blob/2425bcb9240f8c97d793cb31c8e8d8d0a843fa29/include/linux/trace_events.h#L272 + event = StructInstance( + struct_types=self.struct_types, + int_types=self.int_types, + filebytes=self.filebytes, + name="trace_event_call", + ptr=ptr, + ) + class_name = self.class_names[event["class"]] + flags = event["flags"] + + if flags & self.FLAG_IGNORE_ENABLE: + # Ref: https://github.com/torvalds/linux/blob/6fbf71854e2ddea7c99397772fbbb3783bfe15b5/kernel/trace/trace_export.c#L172-L189 + logging.debug(f"Ignoring event {class_name}") + return + + if not (flags & self.FLAG_TRACEPOINT): + # Ref: https://github.com/torvalds/linux/blob/6fbf71854e2ddea7c99397772fbbb3783bfe15b5/include/linux/syscalls.h#L144 + return + + func_name = f"trace_event_raw_event_{class_name}" + struct_name = f"trace_event_raw_{class_name}" + + func = self.func_types.get(func_name) + struct = self.struct_types.get(struct_name) + + if func is None: + logging.warning(f"Could not find function for {func_name}") + return + if struct is None: + logging.warning(f"Could not find struct for {struct_name}") + return + + return Tracepoint( + class_name=class_name, + event_name=self.event_names[ptr], + func_name=func_name, + struct_name=struct_name, + func=func, + struct=struct, + fmt_str=self.filebytes.get_cstr(event["print_fmt"]), + ) + + def iter_tracepoints(self) -> Iterator[Tracepoint]: + for ptr in self.iter_event_ptrs(): + info = self.get_tracepoint(ptr) + if info: + yield info + + +@manage_result_path +def dump_tracepoints(img: "LinuxImage", result_path): + extractor = TracepointsExtractor(img) + with open(result_path, "w") as f: + for info in extractor.iter_tracepoints(): + json.dump(dataclasses.asdict(info), f) + f.write("\n") + + +@dataclass +class Tracepoints: + data: dict[str, Dict] + + @classmethod + def from_dump(cls, path: Path): + data = {} + with open(path) as f: + for line in f: + info = json.loads(line) + data[info["event_name"]] = info + + return cls(data=data) + + def __repr__(self): + return f"Tracepoints ({len(self.data)}): {list(self.data.keys())}" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux_image.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux_image.py new file mode 100644 index 00000000..181c7676 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/linux_image.py @@ -0,0 +1,164 @@ +import json +from functools import cached_property +from typing import Dict, Optional + +from depsurf.btf import Types +from depsurf.dep import Dep, DepKind, DepStatus +from depsurf.funcs import FuncGroups +from depsurf.linux import FileBytes, SymbolTable, Tracepoints, get_configs +from depsurf.version import Version + + +class LinuxImage: + cache_enabled = True + cache = {} + + def __init__(self, version: Version): + if LinuxImage.cache_enabled and version in self.cache: + raise ValueError("Please use LinuxImage.from_* to get an instance") + self.version = version + + @classmethod + def from_version(cls, version: Version): + if not cls.cache_enabled: + return cls(version) + if version not in cls.cache: + cls.cache[version] = cls(version) + return cls.cache[version] + + @staticmethod + def disable_cache(): + LinuxImage.cache_enabled = False + LinuxImage.cache.clear() + + @staticmethod + def enable_cache(): + LinuxImage.cache_enabled = True + + def get_all_by_kind(self, kind: DepKind) -> Dict: + if kind == DepKind.STRUCT: + return self.struct_types.data + elif kind == DepKind.FUNC: + return self.func_types.data + elif kind == DepKind.TRACEPOINT: + return self.tracepoints.data + elif kind == DepKind.LSM: + return self.lsm_hooks + elif kind == DepKind.UNION: + return self.union_types.data + elif kind == DepKind.ENUM: + return self.enum_types.data + elif kind == DepKind.SYSCALL: + return self.syscalls + elif kind == DepKind.CONFIG: + return self.configs + elif kind == DepKind.KFUNC: + return self.kfuncs + raise ValueError(f"Unknown DepKind: {kind}") + + def get_dep(self, dep: Dep) -> Optional[Dict]: + if dep.kind == DepKind.FIELD: + struct_name, field_name = dep.name.split("::") + struct = self.struct_types.get(struct_name) + if struct is None: + return None + for field in struct["members"]: + if field["name"] == field_name: + return field + return None + else: + return self.get_all_by_kind(dep.kind).get(dep.name) + + def get_dep_status(self, dep: Dep) -> DepStatus: + if dep.kind == DepKind.FUNC: + func_group = self.func_groups.get_group(dep.name) + if func_group is None: + return DepStatus(version=self.version, t=None) + + return DepStatus( + version=self.version, + t=self.get_dep(dep), + func_group=func_group, + ) + else: + return DepStatus( + version=self.version, + t=self.get_dep(dep), + ) + + @cached_property + def filebytes(self): + return FileBytes(self.version.vmlinux_path) + + @cached_property + def syscalls(self) -> Dict[str, int]: + with open(self.version.syscalls_path) as f: + syscalls = json.load(f) + return {v: 0 for v in syscalls.values()} + + @cached_property + def func_groups(self) -> FuncGroups: + return FuncGroups.from_dump(self.version.func_groups_path) + + @cached_property + def func_types(self) -> Types: + return Types.from_dump(self.version.func_types_path) + + @cached_property + def struct_types(self) -> Types: + return Types.from_dump(self.version.struct_types_path) + + @cached_property + def union_types(self) -> Types: + return Types.from_dump(self.version.union_types_path) + + @cached_property + def enum_types(self) -> Types: + return Types.from_dump(self.version.enum_types_path) + + @cached_property + def int_types(self) -> Types: + return Types.from_dump(self.version.int_types_path) + + @cached_property + def symtab(self) -> SymbolTable: + return SymbolTable.from_dump(self.version.symtab_path) + + @cached_property + def tracepoints(self) -> Tracepoints: + return Tracepoints.from_dump(self.version.tracepoints_path) + + @cached_property + def lsm_hooks(self): + func_names = { + f"security_{e['name']}" + for e in self.struct_types["security_hook_heads"]["members"] + } + return { + k.removeprefix("security_"): v + for k, v in self.func_types.items() + if k in func_names + } + + @cached_property + def kfuncs(self): + prefix = "__BTF_ID__func__" + func_names = [ + sym["name"].removeprefix(prefix).rsplit("__", 1)[0] + for sym in self.symtab.data + if sym["name"].startswith(prefix) + if "bpf_lsm_" not in sym["name"] + ] + return {k: v for k, v in self.func_types.items() if k in func_names} + + @cached_property + def configs(self): + return get_configs(self.version.config_path) + + @cached_property + def comment(self): + with open(self.version.comment_path) as f: + return f.readline().strip() + + def __repr__(self): + return f"LinuxImage({self.version.name})" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/paths.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/paths.py new file mode 100644 index 00000000..b89a9733 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/paths.py @@ -0,0 +1,9 @@ +from pathlib import Path + +PROJ_PATH = Path(__file__).parent.parent + +DATA_PATH = PROJ_PATH / "data" + +DOWNLOAD_PATH = DATA_PATH / "download" +DATASET_PATH = DATA_PATH / "dataset" +INTERMEDIATE_PATH = DATA_PATH / "intermediate" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/prep.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/prep.py new file mode 100644 index 00000000..f5c800fe --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/prep.py @@ -0,0 +1,118 @@ +from depsurf.btf import ( + Kind, + dump_btf_header, + dump_btf_json, + dump_btf_txt, + dump_types, +) +from depsurf.funcs import dump_func_entries, dump_func_groups +from depsurf.linux import ( + dump_comment, + dump_symtab, + dump_syscalls, + dump_tracepoints, + extract_btf, + extract_deb, +) +from depsurf.linux_image import LinuxImage +from depsurf.version import Version + + +def prep(v: Version): + LinuxImage.disable_cache() + + # Extract the Linux image with debug info + extract_deb( + deb_path=v.dbgsym_download_path, + file_path=f"/usr/lib/debug/boot/vmlinux-{v.short_name}", + result_path=v.vmlinux_path, + ) + + # Extract the boot image + if v.image_download_path.exists(): + extract_deb( + deb_path=v.image_download_path, + file_path=( + f"/boot/vmlinux-{v.short_name}" + if v.arch == "ppc64el" + else f"/boot/vmlinuz-{v.short_name}" + ), + result_path=v.vmlinuz_path, + ) + + # Extract the config file + if v.buildinfo_download_path.exists(): # from buildinfo + extract_deb( + deb_path=v.buildinfo_download_path, + file_path=f"/usr/lib/linux/{v.short_name}/config", + result_path=v.config_path, + ) + elif v.modules_download_path.exists(): # from modules + extract_deb( + deb_path=v.modules_download_path, + file_path=f"/boot/config-{v.short_name}", + result_path=v.config_path, + ) + else: # from image + extract_deb( + deb_path=v.image_download_path, + file_path=f"/boot/config-{v.short_name}", + result_path=v.config_path, + ) + + # Extract BTF + extract_btf( + vmlinux_path=v.vmlinux_path, + result_path=v.btf_path, + ) + dump_btf_json( + raw_btf_path=v.btf_path, + result_path=v.btf_json_path, + ) + dump_btf_txt( + raw_btf_path=v.btf_path, + result_path=v.btf_txt_path, + ) + dump_btf_header( + raw_btf_path=v.btf_path, + result_path=v.btf_header_path, + ) + + # Dump type info + dump_types( + btf_json_path=v.btf_json_path, + result_paths={ + Kind.FUNC: v.func_types_path, + Kind.STRUCT: v.struct_types_path, + Kind.UNION: v.union_types_path, + Kind.ENUM: v.enum_types_path, + Kind.INT: v.int_types_path, + }, + ) + + # Dump symbol table, tracepoints, functions, syscalls, and comment + dump_symtab( + vmlinux_path=v.vmlinux_path, + result_path=v.symtab_path, + ) + dump_func_entries( + v.vmlinux_path, + result_path=v.func_entries_path, + ) + dump_func_groups( + func_entries_path=v.func_entries_path, + symtab_path=v.symtab_path, + result_path=v.func_groups_path, + ) + dump_tracepoints( + img=v.img, + result_path=v.tracepoints_path, + ) + dump_syscalls( + img=v.img, + result_path=v.syscalls_path, + ) + dump_comment( + vmlinux_path=v.vmlinux_path, + result_path=v.comment_path, + ) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/report.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/report.py new file mode 100644 index 00000000..d3cc183b --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/report.py @@ -0,0 +1,347 @@ +import dataclasses +import json +import sys +from dataclasses import dataclass +from io import StringIO +from pathlib import Path +from typing import Dict, List, TextIO, Tuple + +from depsurf.btf import Kind +from depsurf.dep import Dep, DepDelta, DepKind, DepStatus +from depsurf.diff import ( + BaseChange, + ConfigChange, + EnumValAdd, + EnumValChange, + EnumValRemove, + FieldAdd, + FieldRemove, + FieldType, + FuncReturn, + ParamAdd, + ParamRemove, + ParamReorder, + ParamType, + TraceFormatChange, +) +from depsurf.funcs import FuncGroup +from depsurf.issues import IssueEnum +from depsurf.version import Version +from depsurf.version_group import VersionGroup + +IssuesDict = Dict[Tuple[VersionGroup, Version], List[IssueEnum]] + + +def code_inline(text) -> str: + return f"{text}" + + +@dataclass(frozen=True) +class DepReport: + dep: Dep + status_dict: Dict[VersionGroup, List[DepStatus]] + delta_dict: Dict[VersionGroup, List[DepDelta]] + + @classmethod + def from_groups(cls, dep: Dep, groups: List[VersionGroup]) -> "DepReport": + return cls( + dep=dep, + status_dict={ + group: [version.img.get_dep_status(dep) for version in group.versions] + for group in groups + }, + delta_dict={ + group: [pair.diff_dep(dep) for pair in group.pairs] for group in groups + }, + ) + + @classmethod + def from_group(cls, dep: Dep, group: VersionGroup) -> "DepReport": + return cls.from_groups(dep, [group]) + + @classmethod + def from_dict(cls, dict: Dict) -> "DepReport": + return cls( + dep=Dep.from_dict(dict["dep"]), + status_dict={ + VersionGroup(group): [ + DepStatus.from_dict(status) for status in status_list + ] + for group, status_list in dict["status_dict"].items() + }, + delta_dict={ + VersionGroup(group): [DepDelta.from_dict(delta) for delta in delta_list] + for group, delta_list in dict["delta_dict"].items() + }, + ) + + def to_dict(self) -> Dict: + return dataclasses.asdict(self) + + @classmethod + def from_dump(cls, path: Path): + with path.open("r") as f: + return cls.from_dict(json.load(f)) + + def dump_json(self, path: Path): + path.parent.mkdir(exist_ok=True, parents=True) + with path.open("w") as f: + json.dump(self.to_dict(), f) + + def dump_md(self, path: Path): + path.parent.mkdir(exist_ok=True, parents=True) + with path.open("w") as f: + self.print(file=f) + + @property + def issues_dict(self) -> IssuesDict: + issues_dict = { + (group, status.version): status.issues + for group, status_list in self.status_dict.items() + for status in status_list + } + for group, delta_list in self.delta_dict.items(): + has_changes = False + for delta in delta_list: + if delta.changes: + has_changes = True + if has_changes and delta.t2 is not None: + issues_dict[(group, delta.v2)].append(IssueEnum.CHANGE) + return issues_dict + + def print(self, file: TextIO = sys.stdout): + print(f"# {self.dep.kind}: {code_inline(self.dep.name)}\n", file=file) + + print("## Status", file=file) + + for group, status_list in self.status_dict.items(): + print(f"{group.name}", file=file) + print("
    ", file=file) + for status in status_list: + print("
  • ", file=file) + print_status(group, self.dep, status, file=file) + print("
  • ", file=file) + print("
", file=file) + + print("", file=file) + + print("## Differences", file=file) + + for group, delta_list in self.delta_dict.items(): + if all(not delta.t1 and not delta.t2 for delta in delta_list): + continue + print(f"{group.name}", file=file) + print("
    ", file=file) + for delta in delta_list: + print_delta(group, self.dep, delta, file=file) + print("
", file=file) + + def _repr_markdown_(self): + output = StringIO() + self.print(file=output) + return output.getvalue() + + +def type_to_str(obj) -> str: + assert "kind" in obj, obj + kind: str = obj["kind"] + + if kind in (Kind.STRUCT, Kind.UNION, Kind.ENUM): + return f"{kind.lower()} {obj['name']}" + if kind in (Kind.VOLATILE, Kind.CONST, Kind.RESTRICT): + return f"{kind.lower()} {type_to_str(obj['type'])}" + elif kind in (Kind.TYPEDEF, Kind.INT, Kind.VOID): + return obj["name"] + elif kind == Kind.PTR: + t = obj["type"] + if t["kind"] == Kind.FUNC_PROTO: + return type_to_str(t) + elif t["kind"] == Kind.PTR: + return f"{type_to_str(t)}*" + else: + return f"{type_to_str(t)} *" + elif kind == Kind.ARRAY: + return f"{type_to_str(obj['type'])}[{obj['nr_elems']}]" + elif kind == Kind.FUNC_PROTO: + return f"{type_to_str(obj['ret_type'])}(*)({', '.join(type_to_str(a['type']) for a in obj['params'])})" + elif kind == Kind.FWD: + return f"{obj['fwd_kind']} {obj['name']}" + elif kind == Kind.FUNC: + result = type_name_to_str(obj["type"]["ret_type"], obj["name"]) + result += "(" + result += ", ".join( + type_name_to_str(p["type"], p["name"]) for p in obj["type"]["params"] + ) + result += ");" + return result + else: + raise ValueError(f"Unknown kind: {obj}") + + +def type_name_to_str(t, name) -> str: + kind = t["kind"] + if kind == Kind.PTR: + if t["type"]["kind"] == Kind.FUNC_PROTO: + result = type_to_str(t["type"]["ret_type"]) + result += f" (*{name})" + result += "(" + result += ", ".join(type_to_str(a["type"]) for a in t["type"]["params"]) + result += ")" + return result + else: + return f"{type_to_str(t)}{name}" + elif kind == Kind.ARRAY: + return f"{type_to_str(t['type'])} {name}[{t['nr_elems']}]" + else: + return f"{type_to_str(t)} {name}" + + +def print_dep_val(kind: DepKind, val, file: TextIO): + print("", file=file) + + if isinstance(val, int): + return + + if kind == DepKind.TRACEPOINT: + print("Event:", file=file) + print_dep_val(DepKind.STRUCT, val["struct"], file=file) + print("Function:", file=file) + print_dep_val(DepKind.FUNC, val["func"], file=file) + return + + if "kind" not in val: + print(f"{type_to_str(val['type'])}{val['name']}", file=file) + return + + if kind in (DepKind.STRUCT, DepKind.UNION): + print("```c", file=file) + print(type_to_str(val) + " {", file=file) + for field in val["members"]: + print(f" {type_name_to_str(field['type'], field['name'])};", file=file) + print("};", file=file) + print("```", file=file) + return + + print("```c", file=file) + print(type_to_str(val), file=file) + print("```", file=file) + + +def print_func_group(g: FuncGroup, file: TextIO): + print("", file=file) + print(f"**Collision:** {g.collision_type}\n", file=file) + print(f"**Inline:** {g.inline_type}\n", file=file) + print(f"**Transformation:** {g.has_suffix}\n", file=file) + + print("**Instances:**\n", file=file) + for f in g.funcs: + print("```", file=file) + print(f"In {f.file} ({f.addr:x})", file=file) + print(f"Location: {f.loc}", file=file) + # print(f"External: {f.external}", file=file) + print(f"Inline: {f.inline_actual}", file=file) + if f.caller_inline: + print("Inline callers:", file=file) + for caller in f.caller_inline: + print(f" - {caller}", file=file) + if f.caller_func: + print("Direct callers:", file=file) + for caller in f.caller_func: + print(f" - {caller}", file=file) + print("```", file=file) + + if g.symbols: + print("**Symbols:**\n", file=file) + print("```", file=file) + for s in g.symbols: + print(f"{s.addr:x}-{s.addr + s.size:x}: {s.name} ({s.bind})", file=file) + print("```", file=file) + + +def print_status(group: VersionGroup, dep: Dep, status: DepStatus, file: TextIO): + issues_str = ( + ", ".join([issue.value for issue in status.issues]) + " ⚠️" + if status.issues + else "✅" + ) + + v = code_inline(group.to_str(status.version)) + title = f"In {v}: {issues_str}" + if not status.t and not status.func_group: + print(title, file=file) + return + + print("
", file=file) + print(f"{title}", file=file) + + if status.t: + print_dep_val(dep.kind, status.t, file=file) + + if status.func_group: + print_func_group(status.func_group, file=file) + + print("
", file=file) + + +def print_change(change: BaseChange, file: TextIO): + if isinstance(change, (FieldAdd, FieldRemove)): + print(code_inline(f"{type_name_to_str(change.type, change.name)}"), file=file) + elif isinstance(change, (FieldType, ParamType)): + print( + code_inline(f"{type_name_to_str(change.old, change.name)}") + + " ➡️ " + + code_inline(f"{type_name_to_str(change.new, change.name)}"), + file=file, + ) + elif isinstance(change, FuncReturn): + print( + code_inline(f"{type_to_str(change.old)}") + + " ➡️ " + + code_inline(f"{type_to_str(change.new)}"), + file=file, + ) + elif isinstance(change, (ParamRemove, ParamAdd)): + print(code_inline(f"{type_name_to_str(change.type, change.name)}"), file=file) + elif isinstance(change, ParamReorder): + print( + code_inline(", ".join(change.old.keys())) + + " ➡️ " + + code_inline(", ".join(change.new.keys())), + file=file, + ) + elif isinstance(change, (TraceFormatChange, ConfigChange)): + print( + code_inline(change.old) + " ➡️ " + code_inline(change.new), + file=file, + ) + elif isinstance(change, (EnumValAdd, EnumValRemove)): + print(f"{change.name} = {change.val}", file=file) + elif isinstance(change, EnumValChange): + print(f"{change.name} = {change.old_val} -> {change.new_val}", file=file) + + +def print_delta(group: VersionGroup, dep: Dep, delta: DepDelta, file: TextIO): + v1 = code_inline(group.to_str(delta.v1)) + v2 = code_inline(group.to_str(delta.v2)) + + if delta.t1 and delta.t2 and not delta.changes: + print("
  • ", file=file) + print(f"No changes between {v1} and {v2} ✅", file=file) + print("
  • ", file=file) + return + + if not delta.changes: + return + + print("
  • ", file=file) + print("
    ", file=file) + print(f"Changed between {v1} and {v2} ⚠️", file=file) + print("
      ", file=file) + for change in delta.changes: + print("
    • ", file=file) + print(f"{change.issue}. ", file=file) + print_change(change, file=file) + print("
    • ", file=file) + print("
    ", file=file) + print("
    ", file=file) + print("
  • ", file=file) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/__init__.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/__init__.py new file mode 100644 index 00000000..4225da28 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/__init__.py @@ -0,0 +1,4 @@ +from .color import * +from .decorator import * +from .enum import * +from .system import * diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/color.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/color.py new file mode 100644 index 00000000..252a3487 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/color.py @@ -0,0 +1,13 @@ +class TermColor: + HEADER = "\033[95m" + OKBLUE = "\033[94m" + OKCYAN = "\033[96m" + OKGREEN = "\033[92m" + WARNING = "\033[93m" + FAIL = "\033[91m" + ENDC = "\033[0m" + BOLD = "\033[1m" + UNDERLINE = "\033[4m" + + +__all__ = ["TermColor"] diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/decorator.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/decorator.py new file mode 100644 index 00000000..fd85d070 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/decorator.py @@ -0,0 +1,39 @@ +import logging +from pathlib import Path + +from .color import TermColor + + +def manage_result_path(fn): + def wrapper(*args, **kwargs): + fn_name = fn.__name__ + + def log_info(msg: str, path: Path): + if slient: + return + logging.info(f"{fn_name:<18} {msg} {path}") + + for kwarg in ("result_path",): + assert kwarg in kwargs, f"Missing '{kwarg}' in kwargs for {fn_name}" + + overwrite: bool = kwargs.pop("overwrite", False) + slient: bool = kwargs.pop("slient", False) + result_path: Path = kwargs.pop("result_path") + + if not overwrite and result_path.exists(): + log_info(f"{TermColor.WARNING}Skipped{TermColor.ENDC}", result_path) + return + + tmp_path = result_path.parent / f"{result_path.name}.tmp" + tmp_path.unlink(missing_ok=True) + tmp_path.parent.mkdir(parents=True, exist_ok=True) + + log_info(f"{TermColor.OKBLUE}Writing{TermColor.ENDC}", result_path) + fn(*args, **kwargs, result_path=tmp_path) + tmp_path.rename(result_path) + log_info(f"{TermColor.OKGREEN}Written{TermColor.ENDC}", result_path) + + return wrapper + + +__all__ = ["manage_result_path"] diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/enum.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/enum.py new file mode 100644 index 00000000..dc211a46 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/enum.py @@ -0,0 +1,34 @@ +from enum import Enum + + +class OrderedEnum(Enum): + def __init__(self, *args): + try: + super().__init__(*args) + except TypeError: + pass + ordered = len(self.__class__.__members__) + 1 + self._order = ordered + + def __ge__(self, other): + if self.__class__ is other.__class__: + return self._order >= other._order + return NotImplemented + + def __gt__(self, other): + if self.__class__ is other.__class__: + return self._order > other._order + return NotImplemented + + def __le__(self, other): + if self.__class__ is other.__class__: + return self._order <= other._order + return NotImplemented + + def __lt__(self, other): + if self.__class__ is other.__class__: + return self._order < other._order + return NotImplemented + + +__all__ = ["OrderedEnum"] diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/system.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/system.py new file mode 100644 index 00000000..6bd4b4e5 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/utils/system.py @@ -0,0 +1,19 @@ +import logging +import subprocess +import sys + +from .color import TermColor + + +def system(cmd, linux=False): + if linux: + if sys.platform == "darwin": + cmd = f"orbctl run bash -c '{cmd}'" + elif sys.platform != "linux": + raise RuntimeError("Running linux command on non-Linux platform") + + logging.info(f'Running command: "{TermColor.OKGREEN}{cmd}{TermColor.ENDC}"') + subprocess.run(cmd, shell=True, check=True, executable="/bin/bash") + + +__all__ = ["system"] diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version.py new file mode 100644 index 00000000..d4ddce52 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version.py @@ -0,0 +1,179 @@ +import dataclasses +from dataclasses import dataclass +from functools import cached_property +from pathlib import Path +from typing import TYPE_CHECKING, Dict + +if TYPE_CHECKING: + from .linux_image import LinuxImage + +from .paths import DATASET_PATH, DOWNLOAD_PATH, INTERMEDIATE_PATH + + +@dataclass(order=True, frozen=True) +class Version: + version_tuple: tuple[int, int, int] + flavor: str + arch: str + revision: int + + @classmethod + def from_path(cls, path: Path | str): + return cls.from_str(Path(path).stem) + + @classmethod + def from_str(cls, name: str): + name = ( + name.removeprefix("linux-image-") + .removeprefix("unsigned-") + .replace("_", "-") + ) + + version, revision, flavor, *others, arch = name.split("-") + return cls( + version_tuple=cls.version_to_tuple(version), + revision=int(revision), + flavor=flavor, + arch=arch, + ) + + @classmethod + def from_dict(cls, data: Dict) -> "Version": + return cls( + version_tuple=tuple(data["version_tuple"]), + revision=data["revision"], + flavor=data["flavor"], + arch=data["arch"], + ) + + @staticmethod + def version_to_str(version_tuple: tuple) -> str: + return ".".join(map(str, version_tuple)) + + @staticmethod + def version_to_tuple(version: str) -> tuple: + t = tuple(map(int, version.split("."))) + if len(t) == 2: + return t + (0,) + return t + + @property + def version(self): + return self.version_to_str(self.version_tuple) + + @property + def short_version(self): + assert self.version_tuple[-1] == 0 + return self.version_to_str(self.version_tuple[:-1]) + + @property + def name(self): + return f"{self.version}-{self.revision}-{self.flavor}-{self.arch}" + + @property + def short_name(self): + return f"{self.version}-{self.revision}-{self.flavor}" + + @property + def dbgsym_download_path(self): + return DOWNLOAD_PATH / "dbgsym" / f"{self.name}.deb" + + @property + def image_download_path(self): + return DOWNLOAD_PATH / "image" / f"{self.name}.deb" + + @property + def modules_download_path(self): + return DOWNLOAD_PATH / "modules" / f"{self.name}.deb" + + @property + def buildinfo_download_path(self): + return DOWNLOAD_PATH / "buildinfo" / f"{self.name}.deb" + + @property + def config_path(self): + return DATASET_PATH / "config" / f"{self.name}.config" + + @property + def vmlinux_path(self): + return INTERMEDIATE_PATH / "vmlinux" / self.name + + @property + def vmlinuz_path(self): + return INTERMEDIATE_PATH / "vmlinuz" / self.name + + @property + def btf_path(self): + return INTERMEDIATE_PATH / "btf" / f"{self.name}" + + @property + def btf_json_path(self): + return INTERMEDIATE_PATH / "btf" / f"{self.name}.json" + + @property + def btf_header_path(self): + return INTERMEDIATE_PATH / "btf" / f"{self.name}.h" + + @property + def btf_txt_path(self): + return INTERMEDIATE_PATH / "btf" / f"{self.name}.txt" + + @property + def func_types_path(self): + return DATASET_PATH / "types_func" / f"{self.name}.jsonl" + + @property + def struct_types_path(self): + return DATASET_PATH / "types_struct" / f"{self.name}.jsonl" + + @property + def union_types_path(self): + return DATASET_PATH / "types_union" / f"{self.name}.jsonl" + + @property + def enum_types_path(self): + return DATASET_PATH / "types_enum" / f"{self.name}.jsonl" + + @property + def int_types_path(self): + return DATASET_PATH / "types_int" / f"{self.name}.jsonl" + + @property + def symtab_path(self): + return DATASET_PATH / "symtab" / f"{self.name}.jsonl" + + @property + def tracepoints_path(self): + return DATASET_PATH / "tracepoints" / f"{self.name}.jsonl" + + @property + def func_entries_path(self): + return INTERMEDIATE_PATH / "func_entries" / f"{self.name}.jsonl" + + @property + def func_groups_path(self): + return DATASET_PATH / "func_groups" / f"{self.name}.jsonl" + + @property + def syscalls_path(self): + return DATASET_PATH / "syscalls" / f"{self.name}.json" + + @property + def comment_path(self): + return DATASET_PATH / "comment" / f"{self.name}.txt" + + @cached_property + def img(self) -> "LinuxImage": + from depsurf.linux_image import LinuxImage + + return LinuxImage.from_version(self) + + def __repr__(self): + return self.name + + def __getstate__(self): + # avioid pickling the img attribute + return dataclasses.asdict(self) + + def __setstate__(self, state): + self.__dict__.update(state) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version_group.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version_group.py new file mode 100644 index 00000000..293c6ce7 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version_group.py @@ -0,0 +1,119 @@ +from enum import StrEnum +from typing import Dict, Iterator, List + +from .paths import DATASET_PATH +from .version import Version +from .version_pair import DiffPairResult, VersionPair + +VERSION_DEFAULT = Version( + version_tuple=(5, 4, 0), flavor="generic", arch="amd64", revision=26 +) +VERSIONS_ALL = sorted(set(Version.from_path(p) for p in DATASET_PATH.rglob("*.jsonl"))) +VERSIONS_REV = [ + v + for v in VERSIONS_ALL + if v.version_tuple == VERSION_DEFAULT.version_tuple + and v.arch == VERSION_DEFAULT.arch + and v.flavor == VERSION_DEFAULT.flavor +] +VERSIONS_REGULAR = sorted( + [ + v + for v in VERSIONS_ALL + if v.arch == VERSION_DEFAULT.arch + and v.flavor == VERSION_DEFAULT.flavor + and v.version_tuple != VERSION_DEFAULT.version_tuple + ] + + [VERSION_DEFAULT] +) +VERSIONS_LTS = [ + v + for v in VERSIONS_REGULAR + if v.version_tuple + in [ + (4, 4, 0), + (4, 15, 0), + (5, 4, 0), + (5, 15, 0), + (6, 8, 0), + ] +] +VERSIONS_ARCH = [ + v + for v in VERSIONS_ALL + if v.arch != VERSION_DEFAULT.arch + and v.version_tuple == VERSION_DEFAULT.version_tuple +] +VERSIONS_FLAVOR = [ + v + for v in VERSIONS_ALL + if v.flavor != VERSION_DEFAULT.flavor + and v.version_tuple == VERSION_DEFAULT.version_tuple +] + + +class VersionGroup(StrEnum): + ALL = "All" + LTS = "LTS" + REGULAR = "Regular" + REV = "Revision" + ARCH = "Arch" + FLAVOR = "Flavor" + + @property + def name(self): + return self.value + + @property + def versions(self) -> List[Version]: + return { + VersionGroup.ALL: VERSIONS_ALL, + VersionGroup.LTS: VERSIONS_LTS, + VersionGroup.REGULAR: VERSIONS_REGULAR, + VersionGroup.REV: VERSIONS_REV, + VersionGroup.ARCH: VERSIONS_ARCH, + VersionGroup.FLAVOR: VERSIONS_FLAVOR, + }[self] + + @property + def pairs(self) -> List[VersionPair]: + if self in (VersionGroup.ARCH, VersionGroup.FLAVOR): + return [VersionPair(VERSION_DEFAULT, v) for v in self.versions] + if self in (VersionGroup.LTS, VersionGroup.REGULAR, VersionGroup.REV): + return [ + VersionPair(v1, v2) for v1, v2 in zip(self.versions, self.versions[1:]) + ] + raise ValueError(f"Unknown group: {self}") + + def to_str(self, v: Version) -> str: + if self == VersionGroup.ARCH: + return v.arch + if self == VersionGroup.FLAVOR: + return v.flavor + if self == VersionGroup.REV: + return str(v.revision) + if self in (VersionGroup.REGULAR, VersionGroup.LTS): + return v.short_version + return str(v) + + def __iter__(self) -> Iterator[Version]: + return iter(self.versions) + + def __len__(self) -> int: + return len(self.versions) + + def __getitem__(self, key) -> Version: + return self.versions[key] + + def __repr__(self): + return f"Versions({self.name})" + + def __add__(self, other) -> List[Version]: + return self.versions + other.versions + + def __radd__(self, other) -> List[Version]: + return other + self.versions + + +DiffGroupResult = Dict[VersionPair, DiffPairResult] +DiffResult = Dict[VersionGroup, DiffGroupResult] diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version_pair.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version_pair.py new file mode 100644 index 00000000..a615f23a --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/depsurf/version_pair.py @@ -0,0 +1,110 @@ +from dataclasses import dataclass, field +from typing import Dict, Iterator, List, Tuple + +from depsurf.dep import Dep, DepDelta, DepKind +from depsurf.diff import BaseChange, diff_dict +from depsurf.issues import IssueEnum +from depsurf.version import Version + + +@dataclass(frozen=True) +class DiffKindResult: + kind: DepKind + old_len: int + new_len: int + added: Dict[str, Dict] + removed: Dict[str, Dict] + changed: Dict[str, List[BaseChange]] + + @property + def issues(self) -> Dict[IssueEnum, int]: + issues = {change: 0 for change in IssueEnum} + for changes in self.changed.values(): + for issue in set(change.issue for change in changes): + issues[issue] += 1 + # for change in changes: + # reasons[change.issue] += 1 + + issues[IssueEnum.OLD] = self.old_len + issues[IssueEnum.NEW] = self.new_len + issues[IssueEnum.ADD] = len(self.added) + issues[IssueEnum.REMOVE] = len(self.removed) + issues[IssueEnum.CHANGE] = len(self.changed) + + return issues + + def iter_issues(self) -> Iterator[Tuple[IssueEnum, int]]: + return iter(self.issues.items()) + + +@dataclass(frozen=True) +class DiffPairResult: + v1: Version + v2: Version + kind_results: Dict[DepKind, DiffKindResult] = field(default_factory=dict) + + def iter_kinds(self) -> Iterator[Tuple[DepKind, "DiffKindResult"]]: + return iter(self.kind_results.items()) + + +@dataclass(frozen=True, order=True) +class VersionPair: + v1: Version + v2: Version + + def diff(self, kinds: List[DepKind]) -> DiffPairResult: + return DiffPairResult( + self.v1, self.v2, {kind: self.diff_kind(kind) for kind in kinds} + ) + + def diff_kind(self, kind: DepKind) -> DiffKindResult: + dict1 = self.v1.img.get_all_by_kind(kind) + dict2 = self.v2.img.get_all_by_kind(kind) + added, removed, common = diff_dict(dict1, dict2) + + changed: Dict[str, List[BaseChange]] = {} + + for name, (old, new) in common.items(): + if old == new: + continue + + result = kind.differ(old, new) + # For debugging only + # if len(result) == 0: + # if kind in (DepKind.TRACEPOINT, DepKind.SYSCALL): + # continue + # logging.error(f"Diff found but no changes: {name}") + # logging.error(f"Old: {old}") + # logging.error(f"New: {new}") + # continue + + # result = [c for c in result if c.issue != IssueEnum.STRUCT_LAYOUT] + if result: + changed[name] = result + + return DiffKindResult( + kind=kind, + old_len=len(dict1), + new_len=len(dict2), + added=added, + removed=removed, + changed=changed, + ) + + def diff_dep(self, dep: Dep) -> DepDelta: + t1 = self.v1.img.get_dep(dep) + t2 = self.v2.img.get_dep(dep) + changes = [] + if t1 and t2: + changes = dep.kind.differ(t1, t2) + # changes = [c for c in changes if c.issue != IssueEnum.STRUCT_LAYOUT] + return DepDelta( + v1=self.v1, + v2=self.v2, + t1=t1, + t2=t2, + changes=changes, + ) + + def __repr__(self): + return f"({self.v1}, {self.v2})" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/pyproject.toml b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/pyproject.toml new file mode 100644 index 00000000..2609ae01 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/pyproject.toml @@ -0,0 +1,15 @@ +[project] +name = "depsurf" +version = "0.1.0" +description = "depsurf" +readme = "README.md" +authors = [{ name = "Shawn Zhong", email = "me@shawnzhong.com" }] +urls = { "Homepage" = "https://github.com/ShawnZhong/DepSurf" } +requires-python = ">=3.11" +dependencies = [ + "launchpadlib>=2.1.0", + "matplotlib>=3.10.0", + "notebook>=7.3.2", + "pandas>=2.2.3", + "pyelftools>=0.31", +] diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/__init__.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/__init__.py new file mode 100644 index 00000000..1ab1b009 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/__init__.py @@ -0,0 +1,6 @@ +from .consts import * +from .paths import * +from .utils_latex import * +from .utils_matplotlib import * +from .utils_pandas import * +from .utils_pickle import * diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/consts.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/consts.py new file mode 100644 index 00000000..6b473b00 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/consts.py @@ -0,0 +1,17 @@ +FLAVOR_NAMES = { + "generic": "Generic", + "lowlatency": "low-lat", + "aws": "AWS", + "azure": "Azure", + "gcp": "GCP", + "oracle": "Oracle", +} + +ARCH_NAMES = { + "amd64": "x86", + "arm64": "arm64", + "armhf": "arm32", + "ppc64el": "ppc", + "s390x": "s390", + "riscv64": "riscv", +} diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/fonts/Inconsolata_ExtraCondensed-Medium.ttf b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/fonts/Inconsolata_ExtraCondensed-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e79c127e79b42bc3e06b1407ce559f3cd9614204 GIT binary patch literal 101928 zcmd442Yi)9_BTE=&&^Hm$xS8qCN~LzK)AW-NJ*!+kYGa1O(TIcQwU(g0%GhP%PL|4 z3vf|HM8vW#vUXk9bzKXh>$hFqIY(?3Pa&cpat9wDys1=OGZeT2+xN%LN&GL`n z1B{9JsQ;#=du7M5xH}g!mVJb=&>L5}db@!SL;GXfMfGb@pWh0EZ?ex_C|9GL+S<{#_KQDXb_HW8&w!s_dsn0DNaB@N#(Z;;Hg&kx zcKfamdlU31Gh3&tqxtRF$_b2>EM+V@th=kXZ(Ho6`xxtMWi0)+?w;oE%;P;1VI0U4 zPcqK<&=3p7ktxry9c(P?Wj;(m;|c6GQ2ZtI5~kpf>X!_aqFwyZkrNw~p9$mr53LEK zu+keg2L`POo%90>R6Zk$cVo;8Qnc+>ewKJMq^SR(1M`!mD4C}+F|e|=5A66r zQ(r45zF`2Uc z{{x^6iIvq=Rj_A({Eyl<y_)#l*47Eftt+$6x3***w>D=DS(^YiW=*v=j32VP z#tm8P$2D13WHwosXCAjM%N(*U#c|2l)FJCE9B10MTW8pZtkdnst<&t) z*2dZdhnvuTUIy$|{nx2plw=^xG(3)zBk6UVw8?vVO z14y<`g{Y}kYhJ8nX;SQ1>!_F^YocYlH6bT1bxG_*%e*D=1jP^(9amv-Esk_X)Py_3 zY9i{w>VmU^YJAQ&)dba<>OxIc(^S(u(}kwHOkbOPLz_Zs0;dMl_&UusaEO|ax~>o& zP-m_SHBU9qGp{gTXuivAW_6)#9=z`^_B9rWEWaA%d{N_v@&8)z*98w1Rxwq~6BmlR zggJ~U#l=2+Kfl&pojGg2?@-k&xBvVlZob)_wvh7T1&iJ0&2Cn+cuDOZ&abZ9c-2*G zROu}DwF_$>!Q2^DTDM1tvIVt!Ov=@DrMe&UgQEHA-aYUda7 z>-oL>asDEIpMN7vB3a~!R4X;ucXDjYO1Q-mqrG~QHfa+!Kf8%?*E z_LzQade`)WPmqt@XQIzsAD2(B&nBNOJ`edE@_EDOOS8W@!93o)-n_;9rFqCV+}G}# z?>pUhiSMBAZ++kP{ml1gzeK+*zhb{CzZSoBemD7T_dDSCvfqb(-}?Lb$M}!&clr1F z-{-&Ie<&a!pdp|y;NgI$1KteyYv827d4U%O-XHix;75Vq1^EQU28|7x9JDUz%Ah-g z{uK20pr3<-gHwa21}_Tk2);CUOYlR%F9aV8{vpISBtB$($kdRkkfxAZVk4Xp zILkQ86ic&ZlVywL zLCaH?*DS{@-^cjI#K(+_Ss2qCGZ1rm%pEZ=#b(A%j-40V5_?hXme}2~hhyJ~{W>ln zE;+6+ZeCnNTz}l=xZC0$jyn|hdfc(NAL7H~?eRO~pH7HQXh_(Ra3JC3gbxyaN(@L$ zOkA7z;iyHU+D4r>>Y7pSjruByB}F8SOPZ2YlhmDbS<;u5N_t9R%A%Ckl=UfB zrreeCNXly|AEkV6H``wQpWokUylhGlQzaNX6=~4F?Wo4e9Rxld^NUv z?9-XinN68@X1X(<%lu>JXPG~bn=@|3xSny3j*l5XW_-=c=4R_|Gto%QjgtVz2jJwEA~Nk=A~nCv?_ zbaKq(`pM@`-a7e}DLzvwru0v_XUdOLr%!E|dhyhqQ(rH(7Z()IDqdK8LGk^?uav}= zG?uI{xvu2yk_So-l)O~(hmyaPd|dKf$uFhFrJG7$F8#hNv203NeOZ6mVA)M&?y@J# z-YXa7g(v-ODu25otKyQ%z{;M=cczV-Hg(!{)BZT^{pl&wmrcKR#`GDt&UkNT^31Dd zK0nKMmUC9std?0@W^J8yXx3}9zMnmAcIE7z*;mfqKKtd_-_D7jlQw7RoUS=n&G~6= z#oY7ezA*QTc|r5?=T*(yG2eIo1q(73oVQ@(f~ywnS@70^e^td-O{r?A+E}%t>ivbL zg?S5CFWkEDorOPD$5aEuhWL;HVQ{9Dich|jA_toOi z#TkpM7q3~oW$~WHpDhVrGG)o~CFd^LvSiPa!%IG1^3&4jrFl!|E^S6+nM?CN!GcKyb+ z)Af|=E!T;LaSf9imNi_^a81K~4No<^(eT%X9~&)=6B?&Cu57%x@s7qP8voe%O;cFY zgr<2-?M;_AJ<#-Q)B8>TYz}TtZa%AdVe{(d3!86geyI87=D)Rw7H3O!%bJ#(TXwe` zX*t&N)5?&QXRTbe^1_wJTi3L{-Imn0uI zdamx-*Yiow_q~a|rM+`{m-lw}uI;_O_fYTay+?b$>HVpX_4)OM^~Lt(^;Pw)?c31z zSl?59U-bQ}e^h^I|I+^E{?7jE`)})is{e5RYyBVg|7}g=n(=E&)+}1HX3e#09$NFp zfN3CTAaP*UK#kdO9nQhHyk!CWi1>+#^2*uO{N{F7 zUndLUP0X)kafOXfDJ!YA@z}DeY8(4@R>@);dwI^h**126)x0@2wgI=RHnzCBYL<=R zeh_zdxU&RLfx9OkW@aI{(+gwaxT=q2Q7oESSj;J?f`1iN(66Ej{8dx|zlzHLS5f)> zDk|U8P=!i+DVn`bwifQ%rNvY_-L5Co#kySWeLSPl)!WQd8XG&hdA!WSn%dh|@_?q! zt`2T$>2Wo(L^J6l9Pv&pS{B@bX*xBFF!=CTzY3gJLdm)AG>+N-9 zGdFT4dk}dJySKN$p_kp++uz;GwybaN>0;N*ekIF1O6HL=Pm_77%~MQxdN^}xX&l<1W_&aF#r>k?(?lr zqNy9#j@XA#F2$dpcwX$o-;Ma&VEna;T#+tfas8Rj5At33>*jO$IOS5@$KS@z!(S7d z3x34Y4~cde;Qyjblp9!qJ7^#Ni3k@FB2q+o;e&9uKUQoOmjkDWRIyg9_o@v;tB*yr zu!tBD3%n2iGyg09n*UpnzvvPdp>H#BZ##~qV6F)kguCH(XppURAje%KGbyVjq}Hth z+@rKXUbk8+rV)nd#B>AeBa%cmD0)P%mn_nqdTCOYGKDt^y2s|M3rW>RV8)yHANkvq zhz@Bj?x7oD7qWaRb}ndd=NBZp)2DW$kPEgJG*ol!q#E3VOFC8Zl%XFrUg;XI2-MO} z0r5&8>%&6WE0Nq1y|~58x_=9G{J9AB;%XkEdwni&e=j*v9~Z%wJf-Q(W|YWV1BC*g z@DXO=EBu7N2oQlHNWjiaV3dxbvmK%X8hSXGF*2l`tR03YX`B}sIB7+;lReIFd<)-ZP;l(N_>QnCjZGGk>R*9?XrF^@8n0pLh}9lB7b%qUd0u0?3bfO)Qv#m^ zj}YdEy%nK6pd3QJO?e9WJ)lm6Rl-<+vLEG3l*f^8RQ4f1Pk9Xa`Cb$UCB>7H;((-h zLQ=rfl?#=Nl>4MMawm?bvsmnJ+zmPRDEBJ&DfcVel^u}%pz@INu(DIxrR>Je#~$So zBxPeKDxOc| zGyli(1@q-a7&XRc@ELNi<`T%bT)CVDDK{v$uwdm@udNf0$A+JouS?dTpfc>!h*&SHZH{)KtkF8?$Y%#0G zo?sU&%vh;}h{Ecn@UOA<#bBk05EkU&A{r~jSNta- zL=d1a`M(4gfq=f?Kf)LRfd0XM;6uV6(C7SnenR*G`aA!Q|3~-&`iy_ee-UOtf8+n; zKMNl~pYm_`abaR+{xSc=qXEXZMA}0g@m1KTrS*ws*dO^!tX7z3X!%cY{0@?S;6L(z zL9;Pfn}bD#s1&Pdjs72d2**w*t$&!kSOaJ9Mw-L?IRBad!vDihpl>iZ`k#W8f3(0E z18WA(02qyPF`v#?F2Fq5fSGbJX4>T#?;Eibc(ZZ~#{4$rcI6I?`T^xhco(g#G?EPC zPJTm2Qvmk=c?b%=@HfVSvAB}2(lvXy+LKgmBSG$|%&R8n$MT2f}xgrtI` zvyx^cElgUH)RxqhbZ*kdq-&CHNV*00>;JX|+QMwnws>2TEyb2@bJ%ih6K&!m)q{P-D}%!d%(8S_K58<+X35C$&tyH|s~Zr9JXs55J_Kq^P9CBwJEy(%7V|r2M3bNu^1%lNKi}PijwEo3tV6 z>ZI$XJ+|6>VUGw~tS!-IllE}hiljaIq&+sk9{1Sphdmy$?SVa>upJy`k86`Zg*|+v zJ;J3u;tYEKe_>b-+Wa2QS(QSF!s?CACZ@{kM5xS*tBDn$Fh&^{iycX1S%iB z7^>ImoMz;yJ?6Wk;)yPB@CI#1Fqcy8P%|U%&_=Jd3gS6OiKG!}Y;?U%v16 z-Y4%Jd+($7^4`Nb{3p{}k+@Ex*~2)Vx$tzpOT3QzBKc2QtSnWQEA>i~(xSBDyyRB# zS}n>rHyu)rD6f0twb~bzmz6h_ca(RP_mmHmqslSm6XjFody_Dkuy1KIrJEckC(+`F zD+kkOrmsxjn&|n?DgK#0A*AV;3FivarzZKtOD8jZVEP7F+0yjAr2E#W`$C00Er^p3 zqQ}+a(sp- zEj~PmNAPiY!jem8BR-qY!+!8$te%_rW;|250nbvl^F#b;{yhI3e@%>6&K6l%H|Jmj zy-GBRYSE(9D)X^kF5rK}mijv3RH~HUDAi&OU9TxOi%XPwB1O4VnE2bGScHlY5hjvx zJ{HU$cM)N@n~2BiP=t-|2{@0|;@MOc&UR_=^G$3WJD1(eE*72aM)oXwl0C(qW`AaP z@H^SR+27eWaG!s%6P$BDo{YWh7@ow-_*r~1pUQ)I13!m1@fLm&?+{(s-`>S{@CW(B z{4l?aAHm)6FIc@l$F;(LSQ0n06nLSX2Qn-7W$8SGjpm_j5>I90coZw(RyLK7X5)D@ ztK<$=&a>Eb?qt(=Hk-o>*essMmhtIq39n=e_$0QJPh*StM7Dy@VlF<1&t=VgK3j=r zSS@@3Yvl`BJ3pIs^Chf@FJtHMrL3RVvupXeY&~ygSMzo3HolSF#Ru8l{7S5uSFr8; zM)okjl|96_um||fxIW#+9^-ejy?iTsjUQw$@%`)|)|6NIlkE3=AA5x#U~lnf*}MD& z_80asf1Ul6zsWw~Z?Mh0m;Dw`yG!t>p^2^HHLQY9U^nm!a8EbH61ZSD@eQ~R`4MNe zpIIIs#m?e(wvbO@i+KgRh_|zA_i5Tr&Pz{mK@cN!KYoc#6=gti?I?Mx0ge!g=);dG@^!XWdJ2_B|Kp zolWLxEQ?#%44%X0@(Ipb`PEq-p8+FyZG&FH@}1J;5V@c`7O-Nf5Z0k z``8owe)c+lioMLAU~lu^vOn-=*dO_G>^(de{uECX!`V;RSviht;D6$}{X3l1zQ@@f zPr})^xZ3;&t~$SDzU(X9v*DQ&`+^m68=J^eSTP^N96T1+LGdhyC$LXaqIj%$#mcs_czSb}Gwi$$YYCYFl^aV?&+Un#B@*NYp(b>a$fmAFRS zg1hyb#LbFJoQFqe7vT!3Ra`9kMIW9HH7N~BfcQj-5&u-e#OF%5_=gfK{-%V8&lG?0 zj(AgijJy7~vC1D)EV!=86yM<4(gbCU_)3XaCM#pbAC!sW&x%8Quf!>nlnn8PQY8MQ zWQp$-U-6@oDE=s3Q>^0O;v*$W{7V_7jK`BHn>a4MRAR+XN|JJxk}lp-3dJu3j~K$$h!3vN6eSQ>XrYQ({8fA*{w|K4OwV}E&q`*@o z@^k9zuSuusE9sH+e<0D=P@*|Tc1%4(BEO}6S&(!ersIF}!~ehaI&bom0wl7x?*FGc zj^oRRhCoBdqv{dYOUqA6s6PpJDmub>_j5GLdZKykowBrYh<41wF;+_??^KEAxQ>ql z{Qp9tbxxm`q|cPoq);z>4B%7w@R@M5?q(p-@l?rs{W~3eI(watUdNLU2b?0&ocp!w z<*C*M(nt3R8dp0K*?@eP<`wx4*_Mt}Pv;#S)@?N#xTQ#Qk>(@KLt22e5UEZp6a0UR zj{ID=9nx_C?ZcqTjk+Pd9*InRL%q6d7+vGK-}&RnC@ZK$7@yvSC)FFekPL78YxO#f zH!rCd(NiM5bl9u^I!G-rtq z;b`uYk5U~&3PPf}7)Wantwl&Hkus55fnSS6>tZ`n0}`!WeMltxQlw2t=OU5(o3X!F zfwT#!841sXjZ}iP5UCXjPq!q#0osHCUWY_H&PVD&0$$b=J*C-@ zQ-MTsn~|F(<6XkWdmt#xHfb5mo3tA54uWlNVVuB$zJQBC#21@q_4 zoilsZ%o)?CRc2Vj0{qAEJ%Isb_Oj-H@#EN@fIxtO?$k zwxT>CIk_&up6o7mo6;&MxtazW^@=*MKr6Hbi&+cpvlc9_wN(t(%T~Zt4=btlg~Ul#RoA*JGl7>iYI&M0gHSC_A5lF+ueRIVZ2sV2(;lXzflYD39xef&vMcJ)lRCS* zA=930uWbgaJ$@`Gxw^g#P>>FB+cZe9?GIxONR4OP_j3(eT8EeI1_MwDsF>H zouN_tp(c!K@W`Aqm<~Fq|6nByWO0B`v0t%&aS)zQVk`*t2rvh*{p`=#qe0kgPS^vU z=mF6C`G!6I#RSEUtYt2#Z{T%t28~|HhB2 z*dyj<+C6T)pcVsIv4_vitcPpQLQzSpu)(d}#S3eRwmtzqpIld0K7Jf|m#x;`oM5lp z6BRYsU9l%DtZdd`85|wHCLL^#%bZ@HIauo^mm^2BhfRdrDrqws?UnT)v18ic{|ulS z7uo9F4fUA-ZDEyzsJ1n_h?-gU2qkR~H>F|scna)h4sr+Bn@in+_EMu}Dx0d-n5o9s zUh3u+)#?@Y3R`U3V57YO9#}lTc4b0KoeR9(#deq5WG_wFV`8P4U9lWps@TKkW}SC2Sr7lBpyEw zDhyWGUA87H9_TJCx6n?%23Sl|su$M|1~u86?67cg@t_OcPOvrBB@EUzN{d4ssK&;R z^YN@s+TtW=4M=NjL56A3P;YNg5i~nT;#Q7Cw1CPRXP-&ppzKW28ppwz_KGG@P;xc7 z6?kE?tqDI-AeUkD<+^cNBCs%sY#39?d@$@R@*66lUY1b6|3UZ4;l);?Scz&lgDEXb z^%b`%ojk8L*}W>k-CjrjqLR4W8yakbwlModJ7v<(rlEFPz1t^kntMZ|3;n>F1m6Q< zCJ?sT2KX`ySR&Z~aZ>z7f)z<@ylR|QW&FzDu zt;I#oMa%Ad$jATrSo?8s4K74mMiVH(?Ta%&i>uk5jKv+eI%!uqe2_j99#ZRO34??7 zK{tnrX_X)b`*gQCeFh!yzdO_JYQ`XvJe#XowylJ^(mJGHLWMoK4kRLt>`sQmYSBPh z;~>1zy$rL>CoOz1V$fDJh*fJD7F<($z+?S>A$c158#|kw}>f3B@Ga-!uo+#0Ru(G z^GTZl^A^MP5~#J!EpRH6i-y{M1~pC4Fj_NUPS5P!|kYrWId=dCUb$a-ziO@Nm7Lernv(_MO{!4Y95g0#(#7Q zI#Zo$IEVmB>PvDo>p?3j!E(}W(sa~7NxO^&0+Upmcg+dz*1F6lm6=&R%&=ia#me2d zKwfPu!ECT6`(hn~1+bvm+zT^t5|MqoOtwgei_;Q9Udb!%tP(z?0eG0|X7=fLx@gA> zd~R-^?iMH-ko^(7{p4paq=Ub`aF5`=SnaU}+rxr`u+R@S);FmqYFL>SCQPDBCD;Q4 zjsF%;I0&^HGpQ>+Ff``$;9#Q*S6ItJ zXod!*hXWshJ{6&BMOxoroAc1``6L}Wpu@6QT}#~$gcC^T2}DI0?D(we+JUGHL&u-R zf~M)ce`tsds8Oq?gMGnI`ngsuCk8R2b_1DpfGR1~gQ}8}Hj@IiSsFBA)z{doW9mP= z(rz%L6TRKwNToeI2p7Yq1RqFDw}ru66XnpQqbDd2PTa$N(=`HkWEi?Rad0ruuAWlt zwERDTyACEVE?FH`=ivzV`55}aLBHTr*Z7U350(vR@?(^PjU#cd|jTrQN^-8S1&EQ&bQ z?`Lxo>jnpLN*%P*ebpkm(Lqj?c>ltYNY@8+Eo0D+O2oaIHzEiO(6{|V4<*u#lSl4F zhTH+jB@G63!TZ_DQ;H>*<4Y))|7BPAGn|d>sv@RzP4?i@!Ns^;Oy19uNW7*Gl|vF~ z8J7y(KngL&+I=i|FNT}^0q+g1)L{IQI~1?(OFZ6}4*5}o6}Bj3s|Mq0+@SGc@gbWu zyqOh;=zRQGen^;x_h-|Ck7#fpyE=HH1_!b0gLY_eFt-J6*5DA98(6KuVSsHK9L|CQ z<(rr$+>8PCQ}Ku^5D;)eg9UR2ysW_r%LuqvgH3E)z*-IVVPga4YOtAQ1!(-~eIWni z8s3jN{9n{yyqn^`O@jlN)4yAT1A(8e!9i@Cf1(Blv$1~PYH$e4@_Sx`Ls`1tof;g* z9Dbb|9L_TQG`sN#z)2cDk|p^u4US?dz8`3CG_(00(qIcq^}S7lV_2f^1sWX7(tT?+ zIF2RxYBtAvDGp!xTLIWGfu);2(P$FcSn~l59>p@u^iDH;gD0_Z<`xaMvQ%@a2HRMc zSs#mJ{OaQ?4WGiIeBRYyI}7l6U4v6SzJzysJmZ+o!hD|5Xht(XpZyw~!6JO_*WfYW zbB6|xWm!JD-7;CK&rA(Jj%E0yXz+NJZlZU-NdGK0*7T+ZPhcq~w+1`dIMbyXoXt{A z^&0F%TisSUEYYNoMJ}@`Cp4NomZTij;Cz;XH~Cdr1uS0C{jHFt;=LvnU&IoXCJmm* z97?VRpT*LZ5DlKh#tMBbCbJCeL#l13uyNvA4W7#IhM)!)vn(-1gG(5GNu$A~cy95T z2AAQP^K%+pj=j_^8eDe%Os{dA(%VbMdZb4{BVHq0^KBr%LF={w&Ek8RL+o4Az_N6@> zPNwomE`^@$(C$pszlKKd_phOyBkj?~`eCy($*lt2N>EXcdd^5W8>6xk9@uwADo?LH z^d8*FR`S^LOjMpaz3(2(sd%dPJ`>GITb_y5+m>gd8*a-pQT{sHcsLBF_nt4_-bnPr z>pUF1?KYg|^fjll(eSn-Ei=6KWP1#+KU1$fntP~peNOJD$BRx+ z-zmLqq_;Y`2g7Z3db(d@4Np%!)E*0YYIWW9qb^l1ds=(icyK!P$!n*#Po9a&!&R4f zChA{9qqqMxw5J-EQ}yN4BXcUsUuPRnuRZjq;^rB#Q`LI7=zTpE)tTx>+Uiv8y=`== z`r)=Y6~&qR=;?)r&VxG@KaW+;Oy{Z9ZQ#M2n(xSS#;K@A+U(3cy{&g<%HeiAGwrXn zl!uF_h387(RK4@q_RMr1&bn>SO#kbsM%wnwJiTpuX3F8VJu~gEwUoyKo)%~0`ltz4 zN3HB^TvO@SO5S?Tz}0G_yk_l{SA;H5yO_=E>iFbQq3f+aoYg1dS3eVQmD`A`v^JFc z0B0e!;mR!w+JVKtD!?1>TD>{6>=Y-g@9TB4an=fW?)o`b{rd_uYLt> z!?mD#P2B?;>J8B@#5)SJahwOqMC;9&Ea2fV4t0w_(<5~w={A-P4Jp~YG#f5g*T%)x zKtJk}3vY3>OW6Y`lO8r{t4h2{u|UFou!#-$|G9mJw;6y<2A~~DTLW3tzbrXU9pHc7 zNiuZ$M!a{@18TY>(MRA^^e)(}8`fx%qeNHPeUQ?NoJNrRp<_fZbP4~vG$KvND@guI zz+K2mmaa_|`qV8gKHJMCG_qx0eWr4$v;gr^M|vT8)**XKmF=$8Y3*~|k`^vOEtSAlnV{#WGoTO<4)M5k)^{obCY= z(AwkOeSm4+PdJU#G4l7R0odm#XEI(73sK|s;9U~@!*81f4)`5^hpT5bi|tt5v0DE6 z8+$aUQDhx{AS$LKLPa5dHD<;x26iP;N59-uqXHmG#VBXu=fr6genX!43AM%V&mT0X zIo?ql#BTvPer*=S(xOu>Zp7_)kG;)aXD_nn*&%F9Kf)en_gn5{TM;GYMs_tK2V5L~ zEcWvRGv@gk^syV3Yr?NXYoqfm2U%78+iZ6Hi{SW(LXl3~N)qx%#p^QPgM7c@L$IE!HA`NNkh%M&$d%`N;Q* zeaIgZS0R5?EJfceq7d+N*xTal6^h2m?htq5_n$1W2?=kCCDtNUA%cWJ?~@=2h7iql(`r zZpN0AcSKZuT*((^2)NiU zBpocG)xs_sgdS?pTLy$4dvIFYBL?m{13G9x`wYmfL!_V9_CXyNd#?fAX+T?a$g4-! z>$un}4QP`NsdTUji`{^g1 ziTOmw#e85u?-&sJrRp5>vH=~|A>yLdKBGe(>&6^lEC!>9e3t?3FraM)M09sZx|!ZM(#^U=%)&sRz8+fT|5>t^rLqpi%>xWI*`_1b#6N$#1NI zOEsV*1Bx{uj|Ltn0$hS*FU-n0&!~1dF7^u@XE{bt{9%$y zoC%6?NC^r`^?7yAXZh&`g?EQbtezYfLj(;>?v2K2B2-LFIOdkuaM>Nv|*9irNi`klE& z>?WhdZ8{WtrvZ6tZ`5&?t98gD%>#Ma#nX1P-okRR0iCBq(#~t7?TvBs%%d}pVC+86 z$k3dYqjje@j=TgT-HnmOyau$&fSL?wxdGK05L#HOWQ*CuaFr5QJPbEc$5|xgv4-9c zORfjfJyFHQ#zT&*mEJBP>EkMnd>oJ^3!|Dr{%k-$8PHn>w9kOtIz(;Zf7JFt9T$7A z4p~y-cUclG7Dx#*Ai@PmoJq$;pD>`GbjWg>&ISIW>$gRRED!6Dm-g4|IC!1b!g8Yy zd1f+=R`j>hrWh?1ipJP#(5D7;REIom$h~(OAa9CRA^4C66&n!s;|S43KZkTM8r~XB8mJISQz4S(!QCn8JUG%o zt-aoWt~4OhO06ZF+IEA1TdzZwM|3E<&wx4&i1bt2wi>tw16pc8iwwxqqxlAIrU8{3 z&=f$0(gsd_#z&6>E?wem284N_;ixvss8yj5qt;J{5~f58TKS`X84l4oK*dG3ks=TS+3V^0A^7`PwSm1@zXqc=!Q|aS-Ro<9co6 z_XhNp0ez-JUb+}uB9Eaxt^$z1Z9uOZ(2HpMrmO`N`MiV<>1UG2{gIE5uOUMD{RZU0 z0gBuzYXOn}fesM)AE4Wi-zfPJbhU&w1G-p3=NZr%1ESh)S-WZ&uE}V-Ttc;aZNiku zs`$?%XG2=00Tmn2L<7n-AmCygvPG7G%P^o614=X?ivfk543P#JzW}4wq(i6D@60VC zPUvkTelnnM4d@F4`qY4q>X1j82lCj(i}SmB3yi8}zlgUC=v92^;|SR~;yL)n2NF7H zK>G{`wGnPv``|F#y%KllFx(c2^YFVq;>w6kXul!ibkKUEwogKx!&%BsYB6=bSQ$_j+1TE4V+DfqUs~!BcdWgz}ZiSBu)@6{1+V;{-XhX zV?dwlT*5ywpbre_9UYPyNbSSl)N$c28_;1LQr8!BB*=pG1Uc4`@O*;89iaGJLSreX zf8nX>QO(1XO1S7T*?Ok0cbK0poAnrwe8|`v&f9&Q^Z9U*oa!>0pwL%OllJ%Hu zyIbZrVtO4z$PV7TDwDG13BVX@O^@Ccnq79ik;8k``xANY49YFZRj4KOuSUllng) z^?ymW+9x%CLiS>hq}(Gh$0f!s>D@{=$z^|q+yyFL+y=}{3Gb3L(+R_?r00At?XVAD z=Esxy2Uk=OAg;kP27^hZn^)sRHUJH zp_IN&+H;%i*ER*a-8?|rWSi{W?jiEeZBoPY`E!8ji%=X<)m}!vSK8-RIXZ{s=7S{;_H4ol4sa`LF3CFW<@yWLW^XB67G z-6bB8IrV*)xCr^9;y1`|6n7xsE$WbOLzHg73auWy1g#0X#KX|UBC;i(Jb9E@o zce|8CNwXRGGg8keDg8c~@8Z7${wYcMl*BwH;m0KWfZShyOkii7r-*k!`G~~-M()RN zQ>FoPt)#g_w)ze2%JcEklW{gc?Qi6Y_Xb&yPnGaPh@A%wRVi}kekXY#PnP_5O6xtQ z&}z9)J_mSAsU=wM_wSP&=1I;EDrA#g3VHHwg>1DAF`o(Efc&6*O0ZX%4tSSxuFP+h zIcc?9xmo6Ml#9P1KY}=VoCgc)(Ju9Qf|R~nj`eOiN3NAR%#r$EB**Sr(udELns1j{ z9g`aFQ2fAWhty%Gw9@U;N^aTf9g_ccWesSylWo}@3Z886D9LAsoUJ>gte+&$9g^p9 zYRk`-G{@y^IxaOiE@}QDX`YsH4@v$9q*XH|{nN59PfN}?n?vH$lKycyjt?s2b&pHC zJuW#sE;Tx72?(-jODl^he}A!1pOM*LEvgkl%^8%YdbxM>IUG zsJms4EK-x*$OWT083%~IMHk2DTXZRSHdqWieT!}qp8qwn#f;u#Sc3OlSF?IN*S!_b zh3Q*#SIckFU4t3+DZ590i|!pnNDX5Dl;5KJnd4h@Jc{F6blgJUqT`b|zD36;BVOtX zK83zT$1CYubbJ+ki;l16_!b>vkm6f(ypO&`#~+|?(eVfATXcLUeTxn;Z}BZUzMH;9 z$FahTX8wqRZ_)8b=__=6FMb~8#@PthJG>UD3TZY{B~mfcM5J7#EF`MSKuSSML?Rl( z;Y`Z$odQHR6*$8Sb^_@qJe&L$$1h|up|_L}xK~T>;`o-9Ud2&QM*$y&eUE@I$yKdRyBZ1sSI56T?hI0I&{%-zVyYG*)(|Ne-Lf82@y6dJcf;Cf9J70j>qG-7a6RXC-PDFg~btW^N-u z8a#F~JasC(XFM-KoS{-)#wPG`UIEXYhFIk@a5kOAj^Wn=vk{>bk!ukRcs{OJs`x^@ z=ix+j)N1wyuYuQ}4X>}`ixJg!317;WAy(>g%z}E%f(FD6ZsN^|yt|UO@;1aWy^gO& z%%FDOf#|Sqyshvh-sR8ZUHG=gIlPDWVs`W+*2@}1IQ;|>PJia>_v%9NH~AzpCg9ZKlm4jVD=><{(sH2Nc-$##D@7EG0n7i`}nFVV&k*5cw1y0{{?Yt zykg|D^Mw4~23tSkiyOg+-W)2z=-VpnZV}1O$JYk%#T2#&Z&H1QcQ|V3+bM`t9WNtQ zk3uwSD_evRAIa>mB8B~eShJ}j4e_l|0%}xc#*|w*#%+(+aMh5B3wsZ zD4a50Z5|@l7KlPbteq%h)=ozB+Nq)#Z@DZMC88A3vdgiOFJ)hd3allSVw#wan71>< zEVfL{W`9GR>bYVbMZy;I#R5d{)xV2GU$BX12`mv&tQU%EMBJtbxV2c77b6btQW*nx zg{Y^M84+=tur{}dm56rRCRXA51nr1?+bOybiTfP-W{c=U4BRzh0CBO`A-49p>>%FN z_<{Y1D7oj03lJ%H17hV~EG}W;h^#z{CE*(dCY)hXaPRqBb{Pv6m*PEu2sTx0#Qjnr zuH7h(H+}In4A=XQ;0hGqLlA>FgFVlF$M&+v@P&iN*#o#9Kg6C!q~QQW=e-i~d9Ox< z-fP8mOp!5rWu#tqskjAEvwabH_EvU3`xm}6aJ#re{6^e~4_|H-cZ+S}9<~wp6E`D9 z?fr;ZyF)yHcUZn=-{7qh8@q-j<10Ql;hmBj*mj&H@5OsJ*NX@7hQ>p<;=K)L&ilkp zwgnN74~t!5x4@m1ctkuZ_KL^wZJ)=*el7m(K}5ejgfARCBc2t{A^Ps~;&+Jd{{o`% z{vOeGUqZCqR}hu=HSxN5195`?Al^c(-?zn|5H?e!gOp$;1TlTX@U4LeB~pn(Y+{QNqr@T>aXh|0kcfE0 zNs3jmDalHTV#n7R(v)<>AI?z5C}WjOL>eBCuMn>Ws8lO8$|B`# z#8$6EH2fuqhrbLF@mDDIiVJa;8xd`}8L{zKB07GXvPxO4v@0D-Cn9ZkE9WRZxZ3f@ zJ3yP*6>N}Q$u2>}?LJ)ne8w(T`q^`c#yx-t-0Scr%gJB9xD?U1Hz}7XoAC~k{*~XW z={vv5b;|W#U&Wwk-s*QTexuxpINn=N_dOY0RlSF|(yn43BL4hGh(`WCBDlZHK43>j zd}(Gc&b<4S$Cds1mp1fo&nV9-&ndrEo>zXS99CXH)c@ZrFDfq~%Kt0MtLBo1p5`^p zzWtqT*%c)f>ajFmJ36$ZQ#uK!oXlZX=8&KBN)#qw#Z0_tc zmp8h=0EeC~SDz}^q3PqOFjvTKnJXlbTAQuamTJ8$)3h$rv@6qkStff2Epr1Z3~?%p zQmuofdI$4;E3}SCZL>9&*}1+IYR9y8QnVwxw9q_FY7{ul(hI!x0W zTsJM)abw)Upxz?s82 zJF;_RM;zHjYSZkp0`qJ+D(2aSML|_+nhl**1@$JXwCsu;O?s}=JXdWx*Q;r6p4uu` zbEVvTrJ{4ChATABGrE;sQLc?oxz@dMZJf%rrsb-xPIdGhPNz0FIr_M2<6c(bGq1I) zr&ASDuBlg{bJM8GHRDw{g6FmN!zX+CJKA0SvXd}jh3`D?0ngJ~=Sf)(OrgMez3r~v zRxcOM)i~!$&d{&ST%{VM%F7^mS}(FSt@E^AWa|d<|cuDw17TX{v^QnXA3jP-z{`Y|T9Rn)3M-<{D#6P_2ot(2w~(H6GhmXo4y= z1uAq~Ys@Mtf@@B;EhbNmw`~hbd}~xU^{JuN!CWJqRUN*9Li5?u9D!$hy6=B>Q(JRS zb8lO(`RtWFt~Jepb)HJKU7=iBUAH_;8vaZ05M4riX^gLSmXyi#fy zxYE-*X}oM_PQc0$(w*6+R?j+G8rV9#4c5^-bDJ@q=zylJv(mpUi#{re4~DA!D3khQ zMOF21I!b-pw0^W{D{7nJqz-3JLEx(4van_r1g&1#)7;$I?&@r6Yc#jZQ8Tw21_w!* zsU2NVMdnD;II>ldSXMO^a&yd`YST`yrn%COvn!0{wLob$menG2m(fcstJ?6DYrQSk zhOu1p(sEU>Q*{n3TiV#==)G3j1p4N+OP3t_Z7X{ieTbHD9$t^ec8uKW- zB40B`enDXGh>>(=Ylh3$Sm$f3@{3G;w5;}dsiD?k-PFueq&a-P)`|Q|bH6b*Ak)NF z=*I$|evgeSG{Kdc;0oR58ncSZ;Qo_sOmocJ#$*9)dF_|WYro;S*%bvv<^gGjzyVLU z{RfQYbwFKS*Lf;cZ!Oe@xiZhZ&U<;)Mj=NtQDu>Ny<{J-e#BfY%2E2W+K8FcQ6QN) zvz@vA^pVyq%2bHH<*L#Y%2Nz3eWWdL)bUah%JKw-qqHQBa)RI}HNsJzs&Fh)In$SC z{cuH^C4s(yE(rwmwPMOj(7&atzej`G)@XFSZEID!UR+Ces$g^5%GN%Wu(M5LsLG%( z)Jho=AQ=Q`G6+;F?@mZfaNjdrYe(yQorVo?!I+kD-qdF)eoEwc|;%b0%(r6H+Q%9_lCN#2&yMIY5g!+R@VS^ zI9xqFT?75yDzBn~09o##nV_Kx{UxfYYd~IyL$M+i)85>o)8wm|hOWL=73%M9(x@v` z+h?m+n9giUEa zDn+lv1vYiIy4qVL9MRO-f{Ex|9i=tV*r;v5N6t=fLjRWj_I8zHf49LgxWC&=olxq% zS2>Kz-U>z&;v^M=32U&7qS8n;Ek?s(ib{SbsTv|j%3v5Ki(YEMYQzqlntEKFeW6XA zl0q+s^mlt#C#XfW%?Q$Hy>1u-twn#g#10phsJ1ZbhBXY;(7GmIe`*$9*by29VBWX( z;l>TO!yU~{ZT%e*_HV*Z( zWWA(T5%AyEX4jf^#9rD1jdUC}({a%n9pRufSq_w#60)^qs3R@jNDr;fLG8az3|SH+ z`I40?U*brXjzen$2M(mNDqmuyd>sk-9;Am>=b*~hiD4iZf~3Q4;HZ{KvRa10P%rtb zh)CHIFr9g{K^cbA#w|dl>jcjb4b-UhA_*ahTCJ3Ua*!-*v}!@4w8$DNc>0G1Q4&oP z!Aqs#NKL0;NvR7`N&0%ay}L3TIjk@J-9}$j8+sKr4a21XZOogf?`rQno~?FB;~OT) zsi1Y&gBZq;D0Hpkspixk7E4v0E^2N7B}P-Xsw0awloi&LkS9lyuGV`>M z-O~J2R%w)~FR3mHcHy#xtEUm_styt1!RVbfh@koiB9Cb!WxElc>5U_e42ex`u9etG z?d=67PNf1y<*zN2BWiTTRRz@5Q;u^`fR}s8*}@B}kTa|CR-f(qa@mLjoP5 zBzmNO4?}7_3zkS-klJpfe@hY_skKx4BK=#nv^G>;z4LgyWMGVg+B?r6sJ+wphDll~ z=>BaWv@WaSh(gyoUNf^a0a1CpHC9#`6<+>5yu#B$WoEP>IZ^{yRb?hiB*n|WB{QSK z%fE+L$ZqNWEvqzAm7OjJCu+DP^VsAZy2%VDx!wpS52lS_r6k@q=C!+PU%%HaYd zz0}Z^uxL0b#$&fAZ?sNJ7bfbjsoO(mk$-PT8wg#E%|UIQYm9`JH_q1_T?;Q%%O-Yms%^hu>crs<~ZEn<{N)anSBu=>)~>GAu7<8P7#V|)x|Nrs zZuvQK)F&u7mIh(7siC>OYrsS7%vFV}!{E?{2S-hD^;w!DN8RvV4z2rwm{V&`7lbh7wqtYi@e|*4aQ>)gPvfW zo?xAx;G8g(zoeJKy%3I(h@z2*9EmW^t(lFt?eK0|0A5L}##`SCpoHRJlUZ;7{YVwgxy zN~{_0QiG>ix#wHP0{4kPU(VwfvCLeGbE47&8Z_IX1871)lQx`YP^Cc(ThI`f+Uk#use{eW?v`k1Y;T5+r*O9>Dqjp|{*5C^Og4=80jFe3flO z|HL~rx~#U7Ws${{Cr7l}h&OS5l&zAXVa{n<-9Mt$-l4DY206(}LaUb3w2D_-p-1$l zw`S95Z+qdZ=LXGFL-;``I7S9?e(NG>e@W|YDUG9HDdJ0(ih-q~7oE;h+YA}>J|)SB zfQ)NSmLV;)-JpK@KPq(`sF(j&>Sr|G7EnKM8tN*Ix398k=sR{F3w~UY9UVDrlw_kW$J{p0(?Yw+2Qh|W!ty^jZdN#MoN;aP`tWss5XhhYm}+d zCRpjLs42sn!iaQ^w_8UQhXf`k+We6Jz`7TKb+0!($C)Ieqs(UCBqcg3MA%2; zS|vX(H$B~M&r`uHVYgc^OvxV|9Wu%ikrW*qHD>DAiDe0+qoXrZ3iDFZ!u%tXER#f6 zL|RcsdO=En->5Opq|DNBF=a8%jMRKvNnB=PR7!jZR?dW>ANefNhxc)li^I~>(vp+M z`1gc|goVWf;(e@4C+wpd3D!9~B}?SxPEm54mKa~((Yd*!p;Sr;v`rGESwW21Y=6N% z#gPzYAD*81AHoioOU=Vp)d_3?`c zjSWkhw7g_$eQ|PFQnWL33@j@(la?K&S{BQE;66SU)6}MWn@W=iUr=f850y0IK{Luj zGm&~|&|GDfG(}?=3m8VD%Yrw82CLsakcd@BluD7@XrX$#Dw|d|RrY-$hJFbizOb%B zGfSnp+e1?#Y2d3V_y%<)ydxCvb%s4252pyzodPC@J6J3+@Q4sa^@P#V6H->C=ck8+ zMEdiXtQk3@MvW^-(IdsFE{It`^Wf}o_?q-Y5$X<4I2jV(xs z%N=8%G6lc9DCMT8oG1=2pxgv}PU!^-rz+8&fF^>fi>bJ1~2I zLJJe1{*pmK-YaVdzkNkCD<7TrN3Yl1q;FL5`Q`%UXCr`7O+bbC|z@b|#D}pf20b#=>9?jNt#c zY+wWx+}k0%u;EgSAx5LXCU1w+K{lMfe#=*>J*5Hk_=W|4E4rbeNdJY&fTw>@KI_K5)f^YHxy~HO-+u1Sn(v zmo5Gh$E3?G7;fh`@W_&q_4nQ1u`qGlVZo4{=d|C1dTX-HBC(O{5DSXzJcqgkR);~+ ztZ%WX!sy4DHsVk>qW;-}dgDf@PjXyBRc27kHvbNF(L%%19&yT^`u?*6sT zt3L<7qMKLuG7E|ZApEzHCbIdQ=MQt9(|TePLmIBO_DgXH8ZL*vlzdz9R4cOA8_DI% z<$|=DbHkW1W8a(@)R`@-RA9@bW>c$>1&c;u!CGTu)s{|HOdf@j)16Nb%op_DR=zho zm<>hB@kq++wu!PkrB4;!{@p*jc-l9xuQjl9G(9W%vaQ~}v4r2}4>}$8b}=nYEG#|l z0n5=fB8X$qIc`C3drh6wrF6SAjxr)jU--ZWpl+UC==?LDjlw=JNmmO)q_t~(eV*bF zx6d(8mwgU1y>&(bW2!Lw%nfv<3Rj^JfFD5ydRA(ULal2U-v2YYt5?*D1A|(o+2iSP zIApggq6d|1T=fK!W!M-D?ekHdU~!;ApNvY8x)v<-)Oki!fE zCT`*Byg*#BU~bb$*NZblq=Q~CEds|xE0tsV5cduU)0~Bg_{-J=!8jr9A-*OE>L7!{ zEadQSvyd%~tcFun1x0hgYQS{X8np)J{yvD3!=Y)go9qXrNPlw6PMdTa{k8R-uwhO| zK>4=lq;JRmMyzzuvL<0CCy4ujT}E$5t{v39V4T;c#a*j@Th}YDgOfTmyl*tGl~4F8 zn|NyHE8VXXUu?IpKmLuFtK8Zi@%7B2ZfA4#ZfwrMzoEzcFCSVuZ}B_kW&p+JgAP;$laeC#%aaFsq9mUP#vi|HE~qy=y1WVaV!on1^0rFd@JUne=iP zk}eMOAcye*#u^j64lyf}y&xE}7ykp9V3q)24MN521;<7Do8!6Xx-%85RUkTQ@?Plw(b;{dOJdO%@dNey)r5 zckN(QMZ5KW6Z|j8d#&+3{!)>6Kr?z3!von$t^G<|fNZ5;n>@ahdo>ykt8CejWYMmr zQf;+#c+pJ9kBu5q7RBD`=4>mHwK-(jU>92mJQvpWnAzEDgWJ)yDJa9!0RM^J3=# z8_|)54#YdaoAVhRw}Ek3c?Fr)@b|gDD+yUpvKxK>Ir!U|wo(dbocV%H$c1A**bib; ztuY63=0J}@i?PAeij_*WP$2sOLe-Y)%o1tY)=*t{1stNy=7Ap|xwLfeL}km~-cRr5 zbbfEo#WQh9KE>m3OM%MDRr|ju&h6-2O-hbg?+MJ6M+iLO^ne+h0PEdY`uVt!I5n%u96N+I~O{ZL|X&?{=Yc<-oV5@4(c1FUsh3%EuTn{Ul z>#EYkrdq=rzLFc$`s||Ql>K2}IPTx^E>X$XKey9nyWlTUi8;H=?XtNY>7_~WCkyRP zc;@tx7|tR<%T?&uuNH{&eHh9F(?u6D&Oh)kOakZ_0KT3;F@u54SD0LSrhewSLXpr0l`nLX{O%qgI4LrWoVV|cqX(% z@7i8*2IpM3Fek%8wjHWhDw(WfRd-`Y#xJTizfFLtiWq}otM-af=V*&|<(M(229L3&Ik6)iC=_9WpG#mKQc#HYXi-Og5;^91Gz*f8gBW^!oElZw!p8F$7zDf&e5g#dY< zK1uWjT&pssh`BC^ebM4mp?%1CQHrus%+B8@&S0gt9)@A>oGE_P@K(OqVG%Eek4gV! z?5#ZRE(R^>2W1?F{5%fx5$Go9$S`!1wad>!V)?F~!x$2qM6jhxVmT(VB^>HQYYbBm zm@F%pWqcsn=P(8zG=|CYL9%Ph@EOTYB-?>#N|)m}uwfNWR@f~-Obw+x4=tf7Sd2w7 z8_>!Wd;?Q3C!#!WOE>dMKA5!I9k}#QbANcQ{b8sEulLxaOQ)9ofn~|%cBEzo#7}k* ze(Rh`vy_G8b&u1KyikC~$tBO?80~QQ7RuESvX4J5NdByhTvF6rNX=`(2OR2PFB-Nv7J*i}GG}`NJ-@bbJ?Td@I zU%q;KdtvC(^UuDl(YWmF^Di9&RqTyyuHV`<*HX^a6{FxV*6pJ|3}n^@T9t7cwT|Sn0bXNfZmB_Y!jAyM+)YA7qh~EUXMxOXUZ$o88AC$=c%>- zV5^(OjyW9^li=?#^9uBikDcHh;I~Yk8;3UY3Il+?<|NP*!Qjx(fEMhQp91fh=fP>>>um$KE!kP8+{j`O3Hk0h z-zAgR$+=)a%aZXV_@K3vBRqosPKBAm3aTrdy zJj7yGTuwGn&Y?Kvn=ujRh;o8)$|mLV@NtyOw5mBKzN%#sAU1iVA2{84z;JGU79tGxFlIaEZRSGq?TPv#z|Y9Sp~jV*9~DA{<<*=EU=hX68Vf#|D6b_e? zK-9Nqyk}t`*7=3FH#wXu4#$mmY{NSuu(H{9P*byR6@LWlJ>B_2r5TMdN6<98#iC|p z=_p}W-XS{0J;Uu>Zoav5N4gkN%9*XwWe8i!e$N?$r!*S7`~Tv*>EU!{7>*8QX)Y6Y zBHEXMM~z5RZ$Mtn#_aA@Fkd)42RqM9{jvi*XQ?=Ba(I5miTzH?Sw)O*bcDtHSV&XU z^26C+WwMy;pGf5<>akFEAR{@|a7(&g$;ASpL@uP|W4>tLyCr{atm<99@%86jx00cm z*!7kjb+?vNARxrSAtSNM=fccq za)-pJ7G*vmJegTOISx6M4~ zPcK}L|CBLX-PjB}m}A(u-)YfKnww*@a`1%AikXz*C3fR7vRBCMSY9H0`8=YPZJY<% zCh1QqSzp_|TF@VgdJ4r|9@!c7M`D3w zH6BRBVu?UvVxcs$TnuIPc|=h(zZ&pFb6O~wh$jN!YHcvp*hk(a8x5OP%oWA-cr0!{ z+m*fLFn54^G@liM0py1qhe(@A%K-hKW zs2AY@4gN4?iWq|T{WnJ;Cg$eIuVZ*vru%Uw-Nbq9fxXz#Ssp|L`CZV58Rjs^?-Gm- z<_o5*M3~N6hcWia5vCbZD)}f5OD2!XTmdRnC*@kwH zVV4<*xmQ&)3&GUOsF~l0L|Y9+Q=4qJ{E6KQONbfd`|A0{-29;TO_zutX5pz@w(S&8 z*(%=OIdAuQb>a)d&Q|?r`KpJ%i!sM-UAmmZ(4LaR@I9rN4tGWJISj2c4)Y-AFX6Ew z`5cBcIl-)Ja*4feU6XS-+N*F}e3!+c*!G)wSCs1jUo0qt$5~{+&0VH7zI9yp|B8Ild zPw$h8-TX|0a*m0^-1|B?FoWTQ!%=bOuIe?-h{07e!i;bIP=yj0=|aHNjYGn8T1%a+v#I1u4r$KHZi#ej-Et^eF`RN^#rW|)zG5&NdAx;oB-njQTWf{lF!E1!Wwr|ag9 zlUJEA|F7V1BEQA9r&@6|Am7oNiuKQwz0pKK^u}Y}cr_Vthcv%liu*#PoZh46W7DO= zXh~gk>&dit=Xh(KLMwUfSw3rB|!fw5PslL2DrAC{{bfj^{;>&Y-I^@87G5RHn z)c%Og*L5%bj`Z_*O%!`f{mfx*uwbtLErXc`jAcg{46`;I&!+)H`;4vAqIl7M(Sqf> zfedDDLNYLtSN(g^`-GS3;#L@9ah9!}t{C*@cRcY2-hr8s7c8ouG@y5bqRUS}5kZqp z<@7)GYfk?TK!5PW&|O?RBD`X9&5GO;wdcwu3*%>g$1%>0i{e}NGY&J@ZjKo9U~z=- z5=WN6k^26Vab(hZ$7j3Var+70@hfpfE?dx_LnM^uXbUI;M`+GBP(&OVwV#gUtT@jGT~EJ0#E374chES%SL)}b!2JQpS%;@2%GNC&O!Zh1I?n)gDFiv9ySg}Y>H)(e+9XFyE#DID2I-WRb0t@C|Xk@@FH1K^L z20WFXv|!$j`67!k1l|3VDMN()Aq)EruP`cU z?eQ8##E2b`%Cp6Pg}z$E*}@a;)bi3&!96{lFBF7rsZ`7#ajuSxkM|4>nYxP^0jg%F z-5XRG{b5>+sj(InRhudc8qL_RBD33F+D@5k6cSKGk(Ug%jOQE|<@zF_!f4qY2?yhz zRIoQ0%ETN_Jr&6JsJFU;deEx|9qC|STq!2q&RE79QEcf#(51X(uPfvaL_FT&Y^5?@ z*5tm4R9G3(6Tx^WlnC^nxm0lsr3MONcgQmojR%s7k_^n%b_|G-o?Idu_%B<}SRy?J zNn$*aKJGxuhU-8!bMh{XQ zmsC$!by_tlR2O1agIj?{N-jd}|82OGa{F-Pq7Ct$M9P;QMAd(JIN=SYHJ>MvQuLDM zR?`u0C>x!W?slPY;d%V()>~&UZ8>i|w&X7@wVI1P;qva;dbE>RZWjkwR)hoH2 z5Odj)^z@TGGVAV$N;AC0swm8euaWp{brlwzED2f->UuDwN0AJ@;xbBxUUtQ%Wau|z zN;no*LUiv#30$1VdDlJUXXkpN9_MNgnMm$s7+n$+@z@+~!)IofL}j`bjrULHYjfd( z-GM3xe@0XC$xt9sj)qc6Z&sf!cylucCTGu{Ojn8{F4?8}0^V@%!chNWpXP~%r_xl{ zz-W=Mrx6kOf%Uo0E75xGMO}kcb;)5Kw_uK{3}yf@L*|+;ArgTxSunS|*t#F@!M6=C z=DV<>0b{(8^zS@-rD#3DSMz52j>H&VqOX4)FZd}zpBiJhHf)XI3%V+OdNcl;bg_4Rm#UPL4md4U!aUo!}bvaoyN10_u>4JEZg z%rTERhGd_&*(6sYAMvY6)ve@XYD)D)3Q>H^a2_2ec5cfc|6;y>Cs9vrKDmWPeR?TEqXLPupCMUR@5mK9ux8%MI{yW zxr33IPs!?jzn=9a$IqIbJ!dBER00`9^_vMlLUUn%N=-NQ?BdP?BP$2z((|F7Eu*FJ z-h@v@iezx9Mr)EPYEQ$BGI`WAZxxDdB|S2d_r^WbqoV=AkLqNnFbBmt*BpFyj(#8w zYbGkpiO}UpbbTU>?2Oq(r1DBAXO$w?Sl44?e-bIBf`L?7PZsRcZaen#l5G;lU^}#U z(67V;fmp~N4LIF_i1)AXr3Eu+^zwMcutys?fBVX7Mk9ryQE>aMa53ywG_RUd7K*!P z=XMo?rMaQW?L8ssqEuXKjHc8;GUfLMBZ@*<2a>sSrMn@QR2Srw-y`f2euC8{jX`>w zru3%Z1-30H2X#kKY-JjegsweP3X!*Ns5>ME)nZUa{Sj5`y$tL74Izg-9J*s;f|}0@ zRg!K)zrc8H5%GIclV{De&zVZcMo*vdgk12^6;C8ki)4agrqIZT0@()b<{4$oy3lS6dWP+Y zq&hfJH95gy{uKP;FxRtM9cc(KU9~zGp@i-N1Li1<6*x-O)~x7(ziSdO1|HHgh)=?= z1~%v!d4-{qreNM!{}$IXo9R1Z?+{+1uhvc9g>tX;?$6-egt1vCUv?eV#7N#f*;9-L zRNRUyUK}#vr3#aAhFEGa@1DomS%nFsL!PzX@!76-+PG9FP_$7YBf&ss19dvW(1afqk#c3F(O>*=_3)4-kYffr{B&)NP(|xlAbIUqK zR$nWJxx#|E5hl`*3Ff9-axHJ+Fqmb)Ffa8L-m@YPfw$*#-m+&**?<%u_tfFFV}IbO z>;?|q`$GrOGYZoC7#EqH`!(||qVR2zS#?#bgM&ggh_Xu4T$r7rXYj0E>(#xVW~0&4 z%>8*Z`e5%|K9~+`dVajnSS*&8htrjaT1tiEK5tC5yBrRe%N~d+ZYAp$%ZvS~{;VTB zltLxk*d=>TdE>}@Vb|R3u9A|8DCrGWoO8}Dm$q(g?V0P%_q#nw-Pvjh zXP!OhTs_;lstQ3y5sIMEiK0)?)+Ri`zM1xyyw3GLT^^trkU=;9m$Xa9$)YFY^D z=z7KRXmP9>QBt9tC+P6$IW1LGyqQ$2uNduJo1*sG|=STFuf(Dm7Zf-|3N} z8u$6)DvGXsiB&xU;nJ%g4`%9_R4wC*c%#_*#1vOJqec^cyFZ$VCWf`7HxzWE(^bjV z6RAdzF0S;f3=OaJ^sEdIuTnr`7OQ2__1OKDR7!5!e3(zhMdnkY#2MP}ZWdX# zoi}G}QAu7o4A~+MbChLsZ5IK?iW+ekvH~3D$V+5b7#=GU$YA8U1@ouJeoZiM1Rg8W z$?=c|<#?`rk=6#ov&Yn+9ES82hq>`33+8OTenj+-3*snta2c!~zXGvzMx$P=9l_Xt zu*!0?ke_E=DFMrTT^aSgb@Fa~xw4w8>+`;-;)`jDdx7uBew-?)rPH={ek4W*#^e52 zp`PgcW)1)GcY-cTGr$j8`zzrEP%mb^bT|f#1aY&D6$Hu*D2M!RSU$u%vKxAe*1k`; z;vEDl*0|cAhu_~~QE(HT93(WhD&=@dx>hAY!Z;LzIoh#ckB90#?Zy5OB&odYv zEADK;+-kvG|2sxQ05E$^&Tu@BS};ez8H||l@DmG&du%N0FgL#>v6u=0t;bY2CbHIi z#P0(|6nP;i793$S!Jyx~jpil~a#2r+3I=1X8xBLhARqB9 z<{WoLZ8^+U7R-&J^)4%iFo$j<_^BSo82g5A&qkyP+cK3ABiJer8lx@}Iy?{p;*a6_}hj_v!)1||C?k|0jW5#Fsw zlo;n?h(eWR2vOrHq}q@I)|cd1wF&4Ie#4zRzCQdQ*BhPpeU&9*Q%Y-W+N|0h5 z&ZfiE08Q`&G#F40`8E&JjnqkL)}6uk8vuqSPAU0*A&&>zY7@P@*K}QH!C=FTBi4k_ z*TAlAw;fcpbS4tXq}x)Wjd6&2HX6-kbuCA0w~4jeO^2aZLyQh1*CY!8$m=xdh@%pB zP$;(}nXIsyPbLv==_`@+`V5bw@l{0Oy1MMp)zj5uM_oNtOSyLU_k1Eftd!8&=;aCf9Q{7i58b-T8yiG->qlaD5&%QlzW=eF7O)&OhiY3=CO9yLZK^_#6dd{hTF zjEe8AMe4^gJ1igvaIf(?baCnjAb_=UGZ(&^;c>fJNI`sHZue8FOdqxj5 z8mE6?YU)7yYl+>7-_Lh`kUb^)lQs~dMn=GWgWrG+E4Nj->`f+v!Lrl2Dmqs4QH~g^ ziUppzwSk@C(Pb87Mm45so>}`1EHw-6D6wg$67>b5LD{LLg5(v6vo?>@r+TK{A&1}R z5TC6psNlq0rxhhvPj&7Ww^Yi$TqD`}C$T+N4kRjx&U2Xa80H)lLiWxCt%y(X&ag&) zJwAbPFuwxh!2NP5omrM}?JR-?vf>L1m^#YPra%7PZ|y^uydi_vl&+aZW?EJ&=sEBo5Fb_%^u z=*PMYWmL83TunJvlOB`~7`}IxF6XhBQKJx-oG#)U51v!;+f(6cFmAIsLjgVMcLh|R zFBT2C7Z=@H99@6qWGGzd|3omfD7wAw;!@+kD~*(ooUwT4H{fg}ivU(_$N2Z!XSU*u zr-&?d^WqLfZZU#Hm-Jh_puHLA#SJpkQfYA2+MC7KeuMiozs@4=uv8&L+t(vcR<`8i zEk>W{U#e7=`s<6;>S8@!ibP8Bcv;iRuI9yi_gykFa>>5E7dPA0T~mmVmUm50?Wz*} z?5!+LaUqw9UlL`kyTkIrIShFL9Oim<<_fEtw{o|e@f;CZ1c>@gtZXL1oW~+S9M5Nv zlcNX<>dYwuWWjR#AIHksVp0a50ooGlhwz#`M)mzh*UNWUc@OiU7#%DE#NYARu6G~; zblf|BBW`CAAP)UGSP!CT02CntbOPutECR%#p9UWYx(4WHPYi9+56W+TiN|&bDPt}3 z7CGO@r{p-V0R?9N$$B=EkIKcNzzaaZ+T94v@n@9HV;x3AMu!o9%H$zrN?w2NTI9&h z=ZJFZFq+_$?7xE3 zD|gB{;IUxd@uMGO1u^M*YV8wdogIfF-31E|ZeGXaRPHsI$=^m2Lzp-Wr&}I88QmO; z)4drJ_$CqE9EQ^^4;@c8t!WN(!*6M9az9{rrqtrmQ-I;)e;ccw;++R`!@n2}RQY11SNFvGZUj$H*lZogO~h>=|>mNk%q5 zbr`)Xul`hdT}A}>@+luO6!EpMfNwVZ)ZIq}drW;qtd8aXvXAJjfqxr3dJ@Gp7Lh7i z$9+=u#`sV4kklOMmKy3K+N9lR9yw?EJTm#)IFIuA7H0utaQ1Pg0mg?!LFRou?3r%P zu55aWR`}y=)yjAb=K!w1%82*!d8}@Fj#j(%Hncc(KZa|l1sif*2auI7i7D=a1j{BcZ$gU(gi!6tz`BJ)>d=Iv;nma!Y_>rtzX zjLoI^oY|GxU3s+IJ}6 zfHwl4D@%0>nTMW_FT<2@^c~q}bOox}n zXAcK5{n=nLK8M~J6_t45>P-EYWL?-hnJ#$;*Ch&RX)y(TZ+XughP-DEb2QFi@_@0t z=UI5qpxuJG4VxHvj6F%Ru0JsC-R8I53?G|fO%&)^k4VjukJN?hR-E4gTm^=UpUnqu z1rZzEFFuDIE_N4%fgpL$j%XBteM{vFbMC}44yY#`^{Eu3>ST+7Ftg|FQ`+B^8ZBh5x@oG~Z~=tN<%K_`Er zgAk@C<8(M;F`si40S;3<23Z@)A+(RkCzBHW@9sINoIE@~FBVTMDyW7<9=QqWoTA!f zrIi@8P1Q5bRsWQseAzyimG^8o83&nTt5*z5s4JgACkU{kAgNU>+w2KZLzvwgti+?) zuv1Az%43=Ic&}c~#XWge&k`tvvxQ(OUmeu*IPudT51|*#srdYXa6amfstD*;MoPu8 zoC_^wV{RKn-S5lA!^uQQE%cZA=ku5oHV!87@8c2=%LR#_#&MCB#4{M?(*p)R$8~^o z%GV-#@jZpA*pW&8~W2SY&F(2ia=K*D{6OI|xlmr9JfFaDF>%9!~;S$5$d{ zC5G@P&cgAyQ3f1Mc$9$G;ZkD3Xg0W%pRDxG6uo*F2i|(~6CR&`*6WRy8|magQJr&# zQS%V*%_{XhW1Z8*kDm3WK{S}An!SEkraoDnJG}-wQ^Q)Bk+um5o>R#PF41)~=~z`0 ze6b{+eT`Aa(o(TnkcD*WPAD(KB`IR{7XK9~D7WO=>K1KIh=@b-#8kZ$3dKfK55FY- z!jqV~aGSUlEeFnka=q`KEvFXa!I_vQK08l-Q;$J`3FIfK;ngYn_l1S$PfiphoVc<_`ZDC|UMBUI3D*ck+7)GCNuFB!kZC1q zs2c`G3>JC4H%7HHP%m_$tAF|OCh|CwrE+M?BIUTDRv@)A^ zslh7UkttPSgUAbo0riA%0f#2-kg-X+Q2#xX<=C7Sg5(!(naQSSV9 za3bSX%X9=s=UP-Cc~#XLN~j*P=Z1Q;uS#Cb&fb3XpJvHBa#3V`Nm0U7+JnrQM(IMgj%259Om--KhL{W*uZ zk;hgE#>#>*7gpO+x5E10swEL8zB8F%4_WW0s&I3@>FoD2xSgpd1VJ&^ zIj7)hi-NZ!9>HV>V_`)(U1Oo$E~oPb%qFCQ(9UxVKpc5*8*0vAJ*A}W-K>?@GO8$WhF-cT9HodYC?(2?>)5mnqVWO*yilf(01|J z&h4KbJHMxPaH4YzxIFOTP6e(A`S-Fzl?6Z6^=jA%h(FupE)?&GgAp5T1|%oi;^!5Xb?_7=AOzrbboCB_R4 z(E)4yZ-zM{u(hp;U2B`e(5mHlu36)pC!qCJyBX8r-)wpt#+?Qoix@ZcJ_n2*Imv-I zH_s39lMAnCRjEVHsiQ+Ked(K)c5H1Qykg6q9Y22lo_oIkKOg=utg3<>(hTsVgdAat z=io7>v@~)@DIPKBnBaqMIGnMin$rVE6U=p<6RiYeHuPor>|T3V3%Tb!DoQ*w-zmy? zac1dtrAJkDk{nBqBqc{GVsPNBfq@GKI$u~Cm#*pDbS`n3(ZVvLU*cS5xo9a5iLxp2T@U<>r z>q*L|x=zB~Ow-{G<(5xGH`!_awwtis089_YX6a9k=PC>4MhC}(v00jd!;tpmcy3r@ zFlB31LN;=sbry4K_1Jk>j~#7kSQd~X8q{M)I~t?MF84Q&c0ThLXt8s3{=hoOZ5`gDMVllvlS$05f4~9S%btFo*dwfk`#tvG~nS zsb&1;Fvc!*Q;!|#{TRkqAdffUInEit8JQ?&KB+VC_DCVFxWze?A|qd;dfJk0ikyLv zmiWWYfP_5t2av_Q8sA$&y&Y*m^AE<*g70(+1IP^Ld)P4_I81Sn{AsFPQJU9Lc6=X8 z0aFe*%3JYxM2x%H8~R!_){5suW!jxR_3T8+rQl3QmlAgAS;Z6f24g{&C$6EvBo*#Y z7Y1VEj-VR3^p#gcd8*crQe|0cBG2zn$56l(Dm05DEiIt*Y0=d7EnldIB0k%|4EeL> zNa&opB6#U3=5p95(}8u66pX;4`&An^h|W*sak)V=pKGMkjhqq(UlmsK{YDUFtL|+t zoLZ@zy3pQRZKWpb0~4v##6W#A^|~3XF(adih~Qa}2nm!3;xalYebDKJb|~yep?5HZ z(;YqVTHNT_1wZ*+7x)2!O!scEK2bP-x}K-b(c%{U$E;oSKOXNZ#!)Agf3zT}ZSJ-mFU$kCySx4OO)jC+VKOOw+ zY4y2cajssUD-`DHvAhz_#q@kQT=NZrg5r}7{a@>9^bfsHP>U()xFnj>G0HziUbhq95r{Itd_KUuZb#p7@UWC z+j>8ar*`9Pomf^0W@@QIkLGj*GzebQGZ>pLmc}x{bTn3q&~ zhSFZ!jG9MBMnU&^wNSBAEp2J!#(RC<+FWgHABy_;30Bmj?}3+s6Wwt{JzCKHZZ{6o zU1d{JLxsl#?@*)Klp<|C=uE9@bM#xE{<~JA@%W`5m=N#nT)c4Sw|+{qOB|syODQ)U z$VH>2Qp(rwU(Kf21oMhoYxiw&#Mpu}MySB=q^YAIFWB%{@3v?I-SIAeMpY6Kk0+8; zf{Cc7FYtp0oNi6`rTcSAVXo$_4^`}TSJ01(NXldR(pX8wPTVifEq>hTu_s1%jVzrr zgfZ8#mux|^@gA5!vf0dLT{AuYRSn%-Oq!^wg(QkXQX8vjDK-FU>Y|Rv$JytS(}7Ld zll`-~%GTk0GhDXYCE0EF`=Q44h)?pyvr4=#tK=rCk{>yC4@xS0XwgHgI+6~17H&NM z>brJi(qm4WGl+SxdEx^*#zIkFYIMiY?0F-L;nGO4)GUNNY9iFLeX0O%lcPBdZu_a0 z%Y}15!DSx?!B@l;2vCy!1H~6;J+;`!k3~xPY~Z}lJbBJiZR@+=^WGh#AFANTxO7O! zLsKr3cT{u5M{L4O$i7;zdfVtE0+StR1X|Y*@G~>)%qG@|2(hjP@M|=xQYeL~d)AWo zSl>)OQckGpU}~(=I}%3|Vn|JC?)*%jp23LF>!K^}a4zFhd=7s+9FBQiA>GrrbGT=5 zG#sprWd@e3<;A*Q@5%do#abiN+}*d37|O+a^GUZWQRs=~hEw90JCV*S@k&%H$D)O# zP7+D;O?qPzyJ}yyr>EhY#9TMJ=9&$y%kcx-80qUZ%2b%V9?vJ80-ycf{Df9SbkXkd zXud>IbBn=jJQxeRJu1RMxwy~nPnGoKP*IH(2U7#nnfzkYlS+=E#yaG4I_f*lZJc$< zP^d6c%Jk=zU?I6(%Y+h*E%l*YBgvVo54`>Uol=+n_F_lDs?^~N`brV|D(W!S<<&I2 zy!Pr36;3}&-GkvoLOF>Z7yZdF)joxjogbZCnM;;!G0%YQYKL5x7p{ca34HwKCh%YcK zCbbR`0RlW>(&`ZZhy89+>JXu*@$Ve|2t1M(+3!1rpNV1VFbn{37E}r^3;%@M;T*(Q z{JvXwS@g4iC$560fOoUsK_hgS#813W_&J`x4!;vOK_B2f z?B9u(^!(4op!7EUJ8{y4Cwjm~tOJ8S=EvlbFZSU~8Qkn-JCr16rq=jjgB@d!_QVr- zFzdP~ddX4Gk;zOw9AlX1#vq;?kLYgWGov zFBJ+)!@IUalNcPqi8j%;N0#7635S@K{3*-@b3wS{a?hA&Px)nWTJIU_T!-fj&f%`6 zNZT!BGL=Ja%^;bc+BYkk9pBtN;8?#~b9L!u|_^M+lx^Tp<>1cysWTxyl+ zjc=h1&68rbzA)NIM3MmDMyCq!R&c1SIb%YDY;#{EqN=5aFWop) zB4U2noFltOw)qg>2Akdr@y>8oy8Uv0@}zO^H6m>qPy4TM61FkpJ^@&f0d~AS8mO(Ji_YgH?~; zi6mNeIyZ!N`bb9gK>P}=9NAQ3?PB+$JPEf$I7E&IM2P$0hSwoE4+WB$&{dxd=Tm`~ zCojKjd^k6G<<+xT!NyugJf<#8(^_`+Yh_znI5ZmQTFaOZ8aVeixM4Fzj(Zy@P#_x} zjUpA>wZdUpMgnogue$3!y?yR*AguZHS~{S4P!j43dwg01V?&D88*+KWKc5_c6XEqF z^5NRpXm7Zb_INYZSbi`$6iBMbY}k7#5qVh9X{<3n$_`W4it-#tm28fo zTd6orvL8A3V$`3%rt$d=RBkQ({onR&z5Iet8&nD4=2_AwP}?#k%%TQqrk!rj%}q7O z#wI4FXGVsHr$$Dm7Ut*GzKC2J8Y&S_5yqvE3VtvN;v8n)9SM`En_fjHGnG(8;LA{l zMO^Dmq_0FPz65T5a=2_>M@aQ2G$rb_Iel(V*p>E`)J!!T3hTY4|HVdE7aOO;zgIcobMg#+-eN}g41aHu-`k^ehg3TYWOe_ z_%Odc@h6tg0T^gQ)5Zr8`3*i15)SEnPxeEuoz2}C^S_}2y4L(-C$#84JDD+O)Vu`x z$h$+q$r|;FSbmzM!2!YV7IlEY`Y@>@PrR43H5{Lm?@$rGIP*W)s^{@9uC3^Hk@c+- z^MJcZ{v;wkUQa0KKOyPjM?%m~A+J|?@??V$g{#p;^)2B%#K%34qkEUgV174V$|?9L z@4v|Sa#1ZuU!=XST00Y`-kgt`M9*If&-jGF#IvLgxCt>I4M-m-MiRKyBpuQ6s73l{ zIx&h=VOaAgvz3ZgA82B}{siy;p7;RXuM2@s!#hF65nW#aD!TcA?TCri@v%q-T>{yR z#wg2X#POUKWu$eUM!X=)nnNVva?togU{-}Ja$=E$@Qk16Bn8t&sWD1N_Y2-vM1<4t z4WO(ek3*h~*R7Kujt481f1QW!XrePm#8RS@2Z`e zduxrup|8RVkj>-eWr&qU!+SK3h7)_ddelJuMe+U7bTF7tcCPpuHQTUBC;X2A|9*x) z_$dMCF;Rm}h8j1nP@si`Rb{O^_z^F7PrvSs1pJz(Zcr@V(zzm;4+b-ubdd8dnx$1+ zN2TQm>i8jP^|Q7K-&; z?Qhqmo^EZr8L^TYsB8-1C(30I>5G%nC7lm>jRb7Q`ASI2(Z!3j<)`%v!bh7pD;Nfv zGp6}Pzoth)VLTKq1UQAkDyLA3Mg6mREuGdP>2ySFmq)6F5~ne&1%ghey^6}OJ| zjQ19c{n@_1#Uy3HO>h$HS=5DZiEoD#x;_czGPr3S8LK(n)kY=aww>DubkC`BWJC~Uhmx&yf}K**`q6m2L60_>*B{g)?Oa`^TE4l zB)6?yC;Uvf4fhwKN=SGHy-kD7#8*i>jT(A;)FAFQJ&y2Xx}J#l-!MLu)5`i-cBWpN z&Ox#i!GpSwRp{F+ta?@r27S;FZnsZQrEoMrLXzx0{IP{`Jpl7cSZm<#?T6hlqyRhL0_=_`#D&K(L;Kkbh1O??CJ4i(i^FN>`|30F_;E9| zb?r{EDt#Xs*7vyEg|Zb+%`%VfA>zd@>eR)+^jX70XHF&yD5%qWCyN*N-0mx>DQ3P19UDz{*~swDB) zs1+Q#PVqUs&q=O!Qxo0Itz`)%*J>!Jr27D7@*Vl~B(irjJl*)s|r?8sxD0GCk^WY)O_=sQbi8S;g+2lqH5pTLzv0G#JS?W$8B_Kl_6IYsmIs8e|hiw z4oJUVJa$`~pmzW|Yd|A<$%zL$K{nk_CuaZkz3=wQbMS|WbCUMi>`H*ebC)u2m zbKKN+{)3oYUM3%j|2t%Ln91r8ejnNlpV!b2Ko1Z`Cm_x^9>OV}!XSXtzyX|176~$* z!0(86pWvPP+9TrDwV!s=cm@(=I?fYYr1MiRS-U{^u5d9tJxt=U7ob;4YZr)B;bO>s zRfs%^CSRziJRFQ>;#q2rBp-vPBrKzZqaikbvYe-#f53}E{=8DWIv>>7Z(0Pu-J1@V z3qhO}p$1~Po_un8p>o_Opkqip1j~7Z(SfK02+8}OK`{xfYLEiU1a=!|Wmx8Cj31N1 zmJ>HfV@FL==;fu47lP}Am82tSrCg-=1g9l6y-+^x6GqFGpyfJ~7EHDldB&eNX<=;H zcN`P=*;q_xaF5gRL-zKdhqL7|i!ESMNxU)>E)^MH{BiIlH9cQF?i0w!RpKGxM~p9l zPmBI%7()`zo{$+|E(DO@3VKsoq@bK=uq1Pr0N-~_d~hXcP~b0^d)$C-Gnt1od6lAg zh?5r#M*Q(?6$CGk$I~l}qxRtaFpz$%Ij4to`5+4+RY%D{>ipZ?Z+Ua+v;${e_NMaw zv&TQ4xU>JQx7YD);LvTr(GMK+>p0K=Y~dhNi|Yy4w|}mjbz1SwFILVvz5J%}`t5J+ zzccai{@V@>+=-S-;e2FMe=Ghu=x}|K(LiQ^QSi@ixwLxPffn92c=fG-JR6X|G$7fV zOoO4_*n8mgo;SA!Z@qf(&IDG=KJiY`E8S(QNK0QP3$rvy9K2n;Q}}1tIPy#o-yM7o zylbL;)L9&mZ(kCT>gtp1Xk)o+dS$pjm+K$eMk{q2aB0#9fosd>3D=ee;d&=}io$!Ot88b1mzT7@L=yFP`f_oXl;+^hdtG_3bN~Ke=(G}uL1x>1--JUCh|kJ>dmw1HR`Q=K1*2aml=yti`dKRmVfXH9gu!fD8@ z-7No3T7mXJjWB5HZKM5P@cEFpLyXsMM*2nPWH0 z-~RnQ(ocVXkNoXxH0k5|W6R55SYH18(h}%Su6+h)em{VB^-~tREFd+S6oa&Xe6ETA zp?E-gm3NMqof;z}Rf|On%2TXYRgqTc0vAj1;je9E^oB)9235o!`!fGFqbs!%8~wNt}B~_deIL z|M8Siu~1J0U^U6Qu`mx)j71!{ZgsY7>Lg)BsR(pYVC!>Z3nL?c%(;@=q^FL3@(-OY z398n4=j8VhIpyAA|Eg%us%-yF-T%zNq!Z!s)%s(&c=YZ08_u{Pcf+}VEHD3fe)bCY zA@3Lwir8=X9xvtUjFFgPIBLv2r{&FjbR8;#IqKwDvyE7l2XxK+X*9a4RB^lAo@%KS z$SJ|Rzf`Vz@q49Q^yfoLE;y$p1A(LlXU3nruhLfgqI#b?*E8SV zsFeeO+X17J-#{27A>(1Hh9GPAm{}^{(c)z4(^>7aSu(4X5aaao(y@M@8@5=3vIzB!%H4q52 z(&_S1LB`n0RTyODL%0c!27L(LmLYSj?gTwwxW!br%CqU9PYSV^YZ;y?`t6EiKl|Bh zA~48Gx{6vS)jk3(CfY|)6ywwqA+MUiysE)y$Qew9%U}4y#KcA6`i}AOZ8cc)@V_{m z(auUB?Z@pkZXD1%nwcFMoXG?-jpD?7Qhaa<+E&BvdY|lSFv3h85tYJH=}iIz(%@=HcbvkRKqtEJy3KTi~a{aTZh~w zPgKl%GVbEwNFqNHQk^aj?$rtBFt+=`??(yfjo~*tQV7QZB)=D2c(s7-jkASc9hM8ykcnQ9-BSe%*A??IHo{y z`2wy`)Gyn1o}$RP!N-EZ?V{V`N=@{MmH7iZ_Lp^im)+qF`5ejF(cSZ%Z|pv!2)l=^ z8P-1CYy)=z6_xK<`|R44R98&ZUGHVJg3!1cticv$4F(0u$kl4Lgop%4NnmwZ%p%aP z!n6v|8nZUaLFrC539Qh9@t#fx!Hv21G=n3%d&NkhHV{qM^HEn8$sE){;24asCpnl7 z#&vJu-0U*53e($ef8D98IBqnMC}>l%8pClJh4E9zPrqs!sgZXtzLL*l1-NiV&)JY3 zvW{t?r>&x5%AQ0cAkISZCVaNll$RC*E9{w=Kw&fK1HMPdgC_k1w~F8OkMe#!U=dsQfqc-$Qn zkt2DIyah}kbOZFFOz{r$q!Ls>P#YokXV8uBn@H6b%afsMAzukf(tKh5wbJ;pe-K~j zJ9tLtZt?Y_+bWfnX6FgF*J&3o-gi+QZ$-{rJcErtEKuc^=m?{z(H0E*R#7WO`v*QH zl-9s-^IBeQsu(<^1VrEpVUM`0^LTOcjxo1g9{#|%xN}TAu<3ebJGx$fffIJAO0fr8 z@dDvZINdyX+DiXKKkn-7t=IE;e~-V%cR|0u-{*THROeh{4(ILCnY;LlxP2I|LoD<~ za`4P(6fQ!fcwc1>dt=fXNY!laV8TDM)EU1wj%!UgK}JlAS^-BY%qgNm65a_|luhkg z)Z#Pcp;&CN=o@*Tp72OE5$A`Z70M<`Frup4?@xwKz07{;6R75nNDkS7^Q%05oHQ9o zWtCJ|&jq4(8>+edPK1#oTHII7KNZE1l<}xbx~zApr+=ld^Ce$=V)(7jDRgl?qVmPmf|-4MC!*xC_#ph<&e-ILtON@Ii}J z#I}s@5NclcxarPGw|LsL_a9x;;%QU9XI<%cHWugx%Hp=g6u*H|{AypHDDI}eI!8}* z9VI9v&9=i>cbbqBayV@RWo~j5{l+=0I$CnP$`6yzi9>rBG=cLZMESRE`|?BlGR)DU zbs44@SX_MD;^G}Aq=M`+t^P}q>!XT(&=5gwa^|Qz9`_||t5HS+xRm(bvwYji;zMM4 zi=(;`cH|d88s2;P>~t|0ET+#sV`MR}_atApa^7iTy7N3rg!Ux{Guff^O1!pxs4zD` zmq7-_!pzJEW>8&>*c{hOI8VFQj(T%BSFso#9P_Wn!?xAFsVR{gS5U#qRH4kl7Bjp6 z<2u^xl4{G{(_xyJL+EghG3&}aYWTA-TyTdnUYos^lceHwG1-VzeDRc$K(uJz3hh-~ zN+y|tB>U8GSqzOP2h^d|LNFVgIi-?FOsI)ev*^!;7ZQV!*kEr&@&tW8 z-<%Q(D1pcZ{Sp!?*bxQoP7n5tHl$PSw$*@*G%F&HWN@Kfp=C&?Vwcr@DHExfV^d@K zvBX%aF_oE`77O)y=X=Lp&tw-U5WO9BsOBClCXBWdXce+aK?Hj};g}|?l1D87+ieY)&qN&uKdo- z%+=G=uM>;nu9tt+d4kQQa3kz-_5W8S{Kn(rtowyWMXz}2tHtL(5$lb|d*k>!*86Cp zo=nsd_&-VQOmrL0L2(uy=Lxd+r;WWZ_Q9b10cd`lPypZ=@gKp-h=CCmb#26w4P1NvtDc6egYLUElp;?55 zH!<-;!w0K8NJ1eO(Q(?o-u?S)r=C_naK<}tJleSB9V2hQe)!f~$y*pg1ZW7gbTVck zNme=(6_0vw;}%6fVW$!yQ;$}=5>ay3&j?_?Eg01UA$B!GEQl)_L~X~8zl@;+Afbd} zohRd=F#W`Qf-EBT^XOe6c@BKahQJ6>&7%FZN+@8E6$_p3i3RcPi;G{waH%^#kNx+V z>=`d?I^8+#a-kL*&ms!JBM?v|WL0T8=XJR%8^~}k`o9c9EfGfP%*3(h!tC&>PonF{_=8C?we3onQ@ zSLeH8@yb2#KDy^qBc1QeACHNX02+?ED855MT2B5!P73i;TmU(>7hYhvzBKZwJxAaD z=se-d3Vu*E$6`BaR2o4{MFe+*XK=nJa6Jc9%JJe#w)DMMTrqd~<$o;}?|y2_Ll13v z>h`T$u?7Yx8$)+f;D+imB?ta~6dW56?fCRMti4p*hw2l%AES1K;it|~L>aH)mWV5H zikgxm54%Lc++V3_UGoOx-hOwysHy3w<_oC)UT-2P+C$Nh7SBaXQ6;Lx64gW=$0MSi zJL8BVsL5hvC)u#R6f&aSa@U}0}EKZ82i+R{;2P7V~3b+i;l0?`e%AxG5 z!Yg!E-_&?h>b&NRczRT{b&l!x0;5a#EAdS6F|3w8R8CjhVRZjEn<>ra$%ez8md#f6 z(9)s(J`@b!{6i*r9+?L*EO(73BC+YW)DGhWqcT8-o9 zP)`D-++XtQ0iWV_Q@K{)PPgJkB%6FLw;!hv_TxP3Ql(Tz=RGcD&GnW`xv5Gq6-uc} zIuuN);dIcSLa9MONs}J%Kws_0A!#yXm1UN&#tH$*J1ws!Bmu(#Bda1Vbf>rlpCvjb zZ}aIbeL1l|`w((saD>MTg$YV&O%(Jp4qQx@^=O&GG37U8#QQRx*A`|@>F+;fx=@&= z?=ywTc>h#BKS?F1lllBqKi%Rouoi-@`wgVk_qZOS2rH<8qX0*El$VQ*(pG`?u$sY0 zI+gXpVBGITJsP?MMvB3h*Q0wC-J5Ct-0A#3<$VcwT-BB4yYH#?_0_9=UnG@ODy^kb zNtSGDvGF1=*s`%9*aRVBjKL-*U<`I*ViVS22PcpOV>%%nAPI47W1CFa`kT;gLLf`i zAsGn7LneD?I%MlOR%!lo-+QIf0wkHv_s#c>WmTzO-R0bK&vwtf=iJ3cbFk1LUfaLA z!E9UvM?tZDd_R;wQHB#QYq9cd6tIpKXaSv0$K$CKj+fHX0i;Sl>M;%&=tbtZGi{UUc)RFlOO>iehfnH z0a!rEh~i5X6-8>7Ub(jXjSuWvbAfnh{NDBsar5}2?5#2lO~_0PBHn%*c;0=|j6Gy* zlL~Y}Fkw_qkAhQK`JuNjGOlIS`e;0o>j)O=HIaAgmGtnVfyO0=W39CM& zy=68WOoqh+g@I)*hh<$+ArYJ@DN+_2PPgC2^5fBu+!>|Vg zc0jT?JDQ!&M%(sK%BCPW0H%tpFz5q}s}oCD%$nwdRTBgFNx-PaBR?yN?V|c@R5bcr zaF>e%CZv1B@}^(1nk}9hgWr+#I0MM>89}sB)MsQ5$^EO>uf{%U`QPgcF-NMe5f`C< z(Hn92?T)?}+zN^>;zG1W2*szf&SsE0L4NDdIlx2XfuXni@xXPNTmzh78}Lb)jOw0Q!y){)Nk%T{;b&L@X#Z(p8wI)|LLuB{{U zZ@PMBoS-^4B1P7SH$pm4wzh(>0P8PLXKn3VvA%GIg?(CnWF`5HFM|(RCSRDTVj^)`Pg|dMC7-{-<=55`Tg)H;qsq4KNh4W zr_JKR`tj3#dX6wJP|NJdvDrH z|5Nne~W7QC7r$M6wOFKoklnUeCE>6zK&Fk2iCy-kfXeG_xbfmm04eOEkLs;%#e z7G3c`AntO-f_N?Bn@lO0pzo)C!`>6?%GQ-)aeP&Zb~zJ)K+NStr3B=T1lxNPJn4+@ zp%#R2zoXF6m~U-1S|L^9Tw&_RY2HP>l&UP}BdP9OAdu@$CA)F80N#U*agUrJjgye& zM1x`R;>LvwHzi8L`TTGxp}*%tO}*(%4?O?*o=m#8DHOggw`EK2I1naW2>+cS%cp~D-pzuLL3t`f`JYd;Ytxz zTakxJ+c(WvzrQK}`G*_FUSY$#bI-<3wd_z^sYNS4)?krpOlAvC(=a3KKoypel9DZP zc&yFel6zzFYlfZd$%gU^51PwA4b=~EA9Pyq05cm@%)p@p&0$7eoajkuvh!wmpofX9g0n~IwOoUt?Utzow6m9fUp|6_g=8^*b< zQ?X}r6r*AhJ^;T?r-qvv37aO^DXhZHrQavuc&i=9(;W^YZO)PsHNqT5STkR(6PC0;fh@k?t%F#|{^osGG|&Cayp~Oy zTIN4AkNx~a{IRBMu4#HKexmLMkSx(>9#M;V^dz5h8jOevu~eq3e%a)3SZZ7@^nfixr%@je zNOdZ;!bg`uhIB>Fl&~Y2kuN>GQ(<^CrjDw$ z-*0f@zHS+#vLjKTMHbyImxMeD`grtrnU4z;39lucQV+l@hpkVXJzB>Hw&`GM-_7xZ z?9MkfzYzK6mH91(M?d4Zl4gB!p2*W~LV%y4#>_>D?pZ^tWZ0ouws`5GrTZ23DNF=S z2-TmQ1?+Gekew5u=VpFrlI%L9G9ZCOE(?xu70q9IgX4Eb?`E@vb-gM)^xlc`aEuB+ zY%y>L0Nx~&U0psnv-cVcX5OMrd!_fwb)@LXxaUh82~=MwU&A&|B%o(19+OqH^4(az z=E#xC_b*kxhj?Bkr)2sbzn|4h2)k!1Av(r?tCwK;SxY=QPIfGZg1tIh32Do@Pv|AY zJ7z0U6aMp0^b%6ftRLxFAa8{Rsnj#01jm=uqvK1+ zPj8_h=gZgdE>tLl^)pMXpITzy%o6*imN+uA#F42bUY%Lu)hQ*gi#T(vCas7%D}`A~ z6e=aq;dE?_fKrd>fZ!6rnI#5Lf)$#kKq4HOP9JEcd<{oBaK`(YT0-wfpBH>P8%DH= ztD1d-M(LcAiLX>>#}`aeBF1b&Ded&r2$)|jMRn0A6fb&sA-v z&@=H7waBRtIG7!q+8`j!E7&9-ATnHV3jvaXxUvuu)xi*eDwq`x$A}0@t#_2w#;x_8 z6RhQ1*&69P;0^V}k^*lAosiDpG-H#{ij@nUT9_{k;a1FH#M+G@Kh}E?C32atN!TLL zogh1en}iPudxcwtJB9tiLE%1Rr+iR&NO)Kf=yWId+2S3ttnznV)!+XwJh#@btY2C8 zavfgl%P0R!Kit~I|Be0q-f+d9z{)$>2I-Cezh{y4^!D`i{0zUnJ>}2+mwwo}n*SU7 z`@IRY=b~}>-@s|BU}(_($ZWrpe3$Xj?#XPwun6IR%lNQX1eYQw%irm}x%%JQIcpAPlo@(_wqH{R@^xGb0Phk?a7K2E5`8qH@uKEjR}`wN5z2ExcMlz zdSTp6TX%msUTpCD8;bEnu^|v>C|;K8S=Q9FtS6n*CQ0MYW*X(gaAw{bm0h=HAfB~ zet`Y)%$YL;;ba-oH3sCgpn@<(aMo;7{p_S*xu-)_6;qKjBR768wbpS|kk?|ly*kBQTu|9ja{v_WTQ zu{uX+zvQr*Om>_Uz=9b1juM2?`45UNAY}#%oxu#tjeh;SuaA~L&R&9AEsc(E5Ikni#baju8$9Z)|k*ywOqKo>(G`j6bhp1MPNl zyMT6Dtytq5jodyU)M|~P5$I^Vb~7u`O3jFGoO|YxQEG|sp}|HoDxlAHTrA8G`gn#TwJ8afUH?;h$>H~9tgq=#S>?*a>Ur+1vUbYeZ;C$RT*`Fi8xZp9cZ^M|&knpj=60W8FP#9W>rbB^e?-HFa0WGI!5qqlc+qn|nu0s^H4VyHD&rO?X>>T3mnbN9ckHyE)#}9;V@KHwyt6DXGFzg*W#J13V@= z+SDF2tnKbNy_b(bN{&B56{leh$3v=Mn~pVtPpu9B)%vOyAniiy94}5UOi=@R3q*IM zP*e>5RMRIFUBaONCXaGXK?_DMib*qR^9Bnn1^k>)v08!%g954GN3Dk}CzI+!qb{<_ zWWv-5!qoukjXzJ?I4_(=hWi6Er6gQSd_9$4zYf!ke^h#SBEb~y3*qs5>QNEC_Y1s| zAQ?u%GvvS#pX6>FjgE<{bWaf31iU2CI`M=iT{L<_+76=g3Z+(aYBjwvMWZ*Zyo#Tc z&Z+B9b9&SGZC1Kb`Aw%A=)=>{poEEv$BNV*R2>Z-Pzt9xjnDW#RQaCQCwU_ok@$!9 zU&%>Ft&mOJP1rwux?`*ZXA^DcZA8O6StH(4c5DJwv=rikAmQ{m(AT)OLEoSszvxi? zN9Qny%ZD&0Px2Y0mJ=Uf~S#z{|18_ftGjqW2;xdtt9DQ~q_%Tit15TwNS z!+S9>QW7LktL2>vHBNm^3Oh~CP+zE})qxvHgNa~QDZFBksr=0Q;k_7cP`l7M8#Nq) z`xLWVOrS@aRoY9NG@n!mp((3C?5NUYpewQ)Ak{RpqaqDCUqKoYV{u4%wW^u6&&3$%b`R@d~J8F0%HMu!e>C$ z?strJ=sHuQ1cI?jMHAQSiw{0;5ExL+k3jxb>!@jUCb3yH+gztl({7G;7#(Q{(rkNm z-Aky^bt7coMr25^9y6L;#F&7Sl6V2sjyT=ax!a3d>$|(_7If$QW4pu6Y44an*S(;Q zd+Jr~t=6}hIb#E_2q-|D4km-*1<$C(ySu3>5bRJ}qE`9Hg|osLP?8(6!D<0PP~rr% zfkPxti9><7tliaZNIx6@?UXjKmvENz9<_nwtB{Op8*~hXpumwKxp1a>9PHJ}frwZn zlD<3(eM#DkxBwE40#w!Wa=Nr8jd^wq|ETr`ax zsxjd}DbDCqN9s|+RYitG0R=1yn2$9U%dh;d{7R8EmS6s=^vAEBv+$R%630%qgf$`M zMpRE~4QMsBTCj%ni30<<;T_aXgz)iR(NN6rG0460`5 zoJx9-%rR2zr@3Z73(c-lh^CLR!-!)+*nY3lh+HQU3F~AtUCDD2;$&2Vu^s{yP3m}L z26xzzL|4Ev$nqHK{8}xf6BKzqeKHn8lgc(R4eFo^<M}622<%l(_@$s zZf|Oy30}k34IzJ4T@Y2v9->LDw5~}|k{6^^VMV@hdx4mT=eGfz1>bHo2%fkeGC|`T z^j|d^nm6Jbb-!?`Zhz+$Tty>ITfuRBaZNqB{F~HeR0}wvI;w8x5?aFvl2>x*H62Fq zLo;x_2i?weLBBW;BW)i>4pAZwen-`nU+&Q+vq|0CbKyvDyjSwpjdC8E?2~)~8qB75;}UJqQ@BLy zS<~dR$N^NUmIIni&aKfZla1^U%^9d#P!*pKxB0oe(bo~v<;ULBlk$W6hAgcl3U%iB%12*QXxOV-Q&i+ml~gew<>u`q+{EGJt>V6*DXRp{O68KIqP{BYAW#D; zRj-*UIGWi9@1bH_K7z%QwyMUMXIo>P7@NArqA^+~cbi8v$^hi5gpraJ`2tz|w(BfN zGJTz;`OVR;#3>*C(kj;BUdAfdx9UU3cy*^Y9Nsj7hqq0Ljq$jZ!FS96XE*#V zV-JIb#ggW)(LCH#3)kLN1TL-mIla?98p+%f55uqhJZf?-(khuQsMRSUKnF{#oK9&P%$VR@=z{HdG&$8R52*%40^eIk=0-gRW^2^&E<} zmr=o}4J>U%^olBsv^F?LbFIR;y5fbOp@SF}yMHh2L zRi%p+egYP8k4}S!F&7#9{M?-Sq7A>YyyRQ8+?fcP=8i$^Z4rrbdL#cJUvYAXZHRKP z;_l}f1Ae$`M!$r5YO5HAIuNxbe*Q$aEqEJ}(P}c{Mg1STPIS@9&rSZ5-$dXap7iO3zE`fP@CRv9xsZAQ%)pw3Aj?B#H};n7onvnX6Zuc zlt#psSRz4NEM~+#8sv+mEE%-ju>*lhfed8>SK@$>a_M91Tsek#elpe*boXe1f$JXYaY3;1Hr~%jXjtP;+btlP!5QL zXU}?SuHNyn^qfqlH=R%8e{Uu;Cml=U1rO7)kL|d+hW5(fC_)6>O6>hB$6_JJ6B851 zw&N5_Ye$m|2jYO5Hvo4Bbha2O;VcCNeK8}2AVyNDu#9N)R4O9->wLj_zbTj%S0=k_ z+lJ?Mb@eW4ZeG;e)irmxt+qQEF4Wa^M9`-Vab0V~i@7fsXyYds3JNZ;l8TS`?z_+T zfOv8FCvghgjH9%1;y(~Wu>&@@>!byz;%mrB!`+($$Vo}T0`nv$o#$%nouAm!GB=Q` zkBd9vV~-#DaN*JJEv;95=+hV?q8ccZ!cIiGd2q79Vnstnu2G1_(U54$q9t61&TOlr zD=+DopI({i3Uv2$iaWEnymn-;?YE)vM0(S04Z%k$ofOR(sOQNp18r^1mu{V(nYZ~pkCavhdtHs)wf3I(e(Ce;`&K>tl?~Uk z`eUJOUw>pVwJ1%Dv#sLCFlOXYeq3-Gy+{_N?$_)9jA+#mK*FSw-xFB6sD9Dnl`TE# zp7y3()8|rMtr^D}|B622$oY5ezP@)we$DEUbsOjPeB}NwU)uEf@{jgV`@V_aBL;XU zV#wwpznQl?Uhv7XFODA}ZI!m?1q;QJRg$OjeGQ7#s)~X1Wr{pC6>*Xnpui={)x;$q z1(@-pFZDc>=UbVfVj|W)Hy-b(^Y+>jo=_bklDg`dj2n3x;%;9p(w5b`1O85g8`_Pr zI*)8iF5SK1;+vKx!leuPeirw7(sSz(Tj`bRx|6Ya8~PVtKA3d6dOV*0@YK!COG-mL z-9S9(#kf{sCR&hxVY!g$hXb!U*_m+8GaJtHOWRuwmhCN=rui5e21irBP?Kde3Z8~b z4Md|5PZJ0WG*44#3Q%|wn>D>L!-v?tS7 z8!9x{ISwGtzZ+{kvBR5)DVL-W!upUcp04vCNtK-~umodCcf46idR?_yPU1!MooG7M( zO&Lcsma#}v;j_Df4qUz+ap8(%hu`V*d(wFY-awN(B!`ViDr9m7WvjcCZCH-0FDPsn zH!>kqF%h=O^=)zF$M74K?o8ug7B>mZ!*;Me=&^Z{es2`<{gzN1VRj8ki?5JG`d2?o z8kLa4;rDqgcFE!LSe+q7HXGmxfTu}NAY)`?Bbfu+DR@$d`z$pJ+n!+09__7%^sg9B zT>VhMBhZ4d=PX%C#643@pj{Pi%wr(cblEDGodAWoqX;-@Gc_XDkHzRTSrj*b z!A*&dntE4DJTtd79BG+Xo1WVik>j~y6v|!kg4Lp}wO(&+>rJ^u4av?%e^-+Nap&KWs>42V!-y*OPlc z(rEkqk(f5POlIofS~19s*PCg(b;k!-$XAD;ar2H(;a(eW`GI#D&+;Zd9^99T<7}(N zo1mGz$lv0_4lm9a*c7*fi{o7s7$V_793@zW8t;J)f(L~=HMwho28T40xT!ExMBImO zLFv;yOH=t4qzQG#(6GI=wfsBQd+V*`=bpc0<7wiu<%qHii??CNB?*p|g=cZ00(AgN zfw``lDLgQixMg~Th`KQz$#T)yuBW%*!SUwcgr!xb(1gJ`Z|C z`ch;><lmYiOsl^@-A2g@VdjzL;v0Raf07 zrU##SW^nv<>eq)mzWT&3Adlu8A=xj>4dGHv!eFpm}8^(NhpYlPOw80-tZ5_<}>R8;NSX9Kv3go1>n`Wnxo zd994Z5R@E^vW1mo1v7!QO_hN<2ujYopa@=%Z*H=c#XloZ*)h+Si9fRo*aoa# z5O;YJ=?mi)csOax4fr4vr6ODXAb2iNNr9J&d?jk~eWhz@Hs013YaPy)&$&8cEj>QJ z6H&l#udz_?SaO?3+wG6zw<&qJ15yZ;XJ-8X=HoIm)U_t z9_W?m62HmL6UC(mHf%UR+8~P6G@Uj^Zd$AeaL%!zvC*2!WPH{va{Kd8@d|N|@Qb8q zRRw}9a4SmHiIlns5pjsXGiAS=RL>?O4msQnDUDOE&;K52wg*F86?wD53+Cq z13Cu~E>^;{%UQOx{Ehp!y}petE!^3fPHHwlxsZo@h4((XIx^C%5 z19vUCVf97E-5-?Smw)iV{GwYPXnXU`wg>WuQ{VVTif~;gtYC9Q=pI0!KnuCt9@%NO z*{!&z756a!-7j_^^&S~~BPlsWB02zbA6NxmP1!o;EB~_Yg%?(LhdMe!r4qf0*7AZp z8#}ftym)bV6@R6kaC;k8BUX+(7|Z=WkJl$FHEyfL;j%fA9nxTspeKkRwf@joHh>os zMI-AyZv5phH(Yn*$nee6dVKxZv@UT^JbGMJ-J=uftsTtjHYz^Z<3&O_gij;o3!Okx zM~En6St(^R6mN{tQC`_n;P)3_{HvFThmY)>(&Ou|BY^mtW5>#erVNzUGy;w(y#RdL z1mzUc4&m4=t(TBsg3sEul%hhxUD_b~U*5a++I!dT+Qkkxmq(lN+6*21mvL;zCFQT z@KF0x!8}1P`J%2lCxH;T5zb%?=y> zGPzc^wtm2dcwVP1flJ{M>Yr4mJs)rIukts>^6l;U&Q5xbHR3@-Tz}Bu3^_ZIdjoIG z+KJ2ZoI#f}=-j#Lf8vQNfbZxFJW;OAE8LUt@+PCxGI^cZnPn570G;J6IM z?Y7|BM5GAD@|19iBt1cO0|*RB`2$JV6KY35s#+Xwp@c=A8i`wcb<1;(OD}a^Sodk~ zV88b%_I&x+MW2q|wf>%`FLsYz>0JK@@P-W+Fs^||hODO&zk$|S$|n$gK*0wpY2vz?HhxL}v_J9vQ0h`U~v{{`_tIgq69J!P?5k$%p zXe*1^YjfZLxuQ7WFJQs)&*J4baPzkd`97V#8$*$FIFt#ubh%?*zu91xktV_x4f+$f ze=h<@hXl*ZApM#B3zr=#t?yw1-|{cK)WNSP(NlC$TB+n@HgERfN+xfT@_uo@cqQoG z%5|$>=tj8llnro4$6woip;kOCtSV{)9haM@3*ge>Irv(? zUy3~Ih$;QwtDZRh`60A-1z=pO!C2QXBRiG}hj4guv3_LsA_t@fBw>n_JJ0TAFyL@6 z6W0R7%>cErtN_$=g)^(a@KpH+fVBKM$mkm;9v5CmcG4;fcO5L;2ebJ(%bvjZ*Ry{T z{tdZz6xgV^>S1R7|58Pg+?%v}Y-X#4VIdxNM%h0FUFn3?>~Okmfk-+XD0HE{tFVLp zviL!0K<5eDvy}@Qz)e`okvM_;AwdMk+2cu1(Cx-`x^X!velQYf!-amx_&do)9|*22kPyxL5Vp)2w<({{Oymey?ag zm_AHxYnDHPMb?slM}EWSgzt<0z)yU+1)i2|a^(Rg3~;}$zwk<+-jDxG_F9k>`MFp} zJlP&Aq=T-o3$1(vt^5zI6?haW3x}FMPZgoycGbOktKEgm(^-J>VX^1BP&t?`#M+bb zju=|GNz5}QK1(A!#`ZvDgz2meX6;Dlz(O(qaf0{mi9z8zLVW7H77O1Q8hZLQ`u<+_ z6jnBL^G?;urdW7oV1PaK8pgj+EV79Bi5jDX0DOG@h}bNg5%0!lG>^}hvp?Z3`p5A3 z6a4d?>`%xSPM_};-op3ii)Pj#K7r5oar_Oj39R3afG6OA#>Kced_?RAUCgtPkh!5| zL)lzEs*Kj1$0lm;x~rD*pezy@i;G9qnlSU30d7qLuZiTDTo9A7kjY-Xa8VuVibpqY zL|xQeE{6D;(TVfS=*?u_gR3IAbAd|`qBxKme1qhV@A^fXtC&ia-0haA$L@8BxA`bo z&zFcfBN)#XoLBpk_$0=2KOfJ4*oVA`U!?fqej6IMxcA_kvya*bOnTC~0p10<{ETXz zChqlPrbb6PpoA1?8kf1nnvLRCOxz3T5dR^R%DMb5#iwMNT|PHmrU!a15I%^&{9Jqv7Nq^S+qfq{+Yh9T;2y$tVB`u>HH4lR>gRTsy#sl+>AFH=(2-I+FYWHF&~AZZN&|GD(~|J zCFlKl;&JsVI^3X_w))~yQM*FV>#SU%2hX@0cVt{BrXW>ug0f~0+Tv>ro=T5)TiAv6 zcvP}k#8h!^u$V3oHg`^J6JDP9c8y88Y2vrzgLtxV;yo-f@in7Kx)FEW)C0oZ8!X7W=Q~4LO$fxZSbC@58;*HW_PBWtuA>rSk z@#);Ez`*>}?m83sub|1X_JaKT7f-m(>urceJYlEr(Rt=@HWWru4X>v$>-NTI1j{E@ zvhc*yfcIv=+l411$a89&cnDAS;R)SWJc9JQ9(FP3Za!0hpCsTj$c{E2HMF~ju#BO* zheVy*F;?=Td+c_8yi?_ps#KoUyOHn5CFmafUhN4XM|~(H7GsJMqw8LAGZeNDy-~oS zNe#3+>#c0Z>85mC?r$)Q4}Lf|*^hw3j?-Xj_}yf?9bKS8%z zG%~OFRY)z*NgUz;fFREoJ5<|+#)9r1U6(KQ)FTt-#}gYaP8>w7A<@c0;sMTQxVTHI z*#mbe=QDjSG-*ZD@|9RAlyG9(w^0c?GWDW0+fYi?r|UYgYk*N}5(_aH5yADi-@FI8 zZqbyQ_j;y7qGDwpg{6-F-lW%?ROq5j*pp&SC>Nstjkx(D)WIhllMYJKfO56&kyeGus{P`H6#uK13<)n-hKEfWH-zK2AB?gf-vd@9k zU9#+nSn@T#h@<(Roz6Cw9a)#%7vx1GP^|4l>yJ!?SY$efEu6|>%<+yahA}M=PqHvB z>@Z4SWW;fM#Z$uTQV5^Fbe29}CLR=i!@qy*C-nJR@gOruL45yZt_ugmeQZ!l;`0%X zlRojIEG>nn=)OH%ZBNsE7sWSwwnW#7A8i~PYgmAmd&T`MDMiuJS4<*4FA@(ipJc=5 zqvJ+=z5;giA0*sTE*;}N&lMkIc`1g^d&jp!Li)sB_}O2?${4&P?19$g{?Y;NAcc#{ z$l?~8wWie)7JEBgjrGNWC@5zL;}1!GE)DFs9o2)2PSx1Tw~+-~Ws(J<@YQ&il~7nb zIb9Y2*4u%_9|MafSP&AjXF$#ZZ#MKp91KpM%E5owncONKoO|8|;wBBlyyOgCzs>jl zlz6cIk_E);8tzfjL}x@eukWcayRMgs0g2mRjcv%j8Q;(#?o00KdLMq#S0`pGG&x%k zpEZVQv!x~{I~Ut5Z;4(Yg)v)=bfeo+@e?eFgk47I=JGDUvRR!S&VlyheluslDORIq z?vb+6j{_Xh*-!B#y`24AF7Zl@{c=e38tMpoln@MtAkp4{_%v&int@f~zYhcc^ToMH zW&9;@81m@?dfhT{Qv$I`(?qp?rkf`JnX{+7E+1S%7N;R+uJyVC9+$~%7a#DYa&8}P zQ^6G(c=uA@+`f|9jP<061e3HI6ux(s=ewpnUsNf73p^hm*2<@(I_ str: + return f"\\makebox[{{{width}}}][{align}]{{{text}}}" + + +def colorbox(text: str, color: str) -> str: + return f"\\colorbox{{{color}}}{{{text}}}" + + +def mini_bar( + text: str, + percent: float, + total_width: float, + color: str, + bg_color: Optional[str] = None, +) -> str: + bg_width = f"{(1 - percent) * total_width:.2f}cm" + fg_width = f"{percent * total_width:.2f}cm" + + result = "" + if bg_color: + result += colorbox(makebox(r"\phantom{0}", width=bg_width), color=bg_color) + result += colorbox(makebox(text, width=fg_width), color=color) + + return result + + +def multicolumn(s: str, n: int = 2, format: str = "c"): + return f"\\multicolumn{{{n}}}{{{format}}}{{{s}}}" + + +def center_cell(s: str): + return multicolumn(s, 1, "c") + + +def multirow(s: str, n: int = 2, format: str = "c"): + return f"\\multirow[{format}]{{{n}}}{{*}}{{{s}}}" + + +def shortstack(*s: str, align: str = "l"): + return f"\\shortstack[{{{align}}}]{{{'\\\\'.join(s)}}}" + + +def footnotesize(text: str): + return f"\\footnotesize{{{text}}}" + + +def underline(text: str): + return f"\\underline{{{text}}}" + + +def text_color(text: str, color: str): + return f"\\textcolor{{{color}}}{{{text}}}" + + +def bold(text: str): + return f"\\textbf{{{text}}}" + + +def rotate(text: str, origin="r"): + return f"\\rotatebox[origin={origin}]{{90}}{{{text}}}" + + +def rotate_multirow(latex: str): + return re.sub( + r"\\multirow\[t\]{(\d+)}{\*}{(.*?)}", + r"\\multirow{\1}{*}{\\rotatebox[origin=c]{90}{\2}}", + latex, + ) + + +def center_multirow(latex: str): + return latex.replace("\\multirow[t]", "\\multirow[c]") + + +def fix_multicolumn_sep(latex: str): + return re.sub(r"{c\|}{([^{}]+)} \\\\", r"{c}{\1} \\\\", latex) + + +def save_latex(latex: str, name: str, path: Path = TAB_PATH, rotate=True, midrule=True): + path.mkdir(parents=True, exist_ok=True) + filepath = path / f"{name}.tex" + + latex = latex.replace("#", "\\#") + latex = latex.replace("%", "\\%") + + # Remove double rules + latex = re.sub(r"\\cline{.*?}\n\\bottomrule", r"\\bottomrule", latex) + + # Replace \cline with \midrule or \hline + if midrule: + latex = re.sub(r"\\cline{.*?}", r"\\midrule", latex) + else: + latex = re.sub(r"\\cline{.*?}", r"\\hline", latex) + + # Rotate or center multirow + if rotate: + latex = rotate_multirow(latex) + else: + latex = center_multirow(latex) + latex = fix_multicolumn_sep(latex) + + with open(filepath, "w") as f: + f.write(latex) + logging.info(f"Saved {name} to {filepath}") diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_matplotlib.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_matplotlib.py new file mode 100644 index 00000000..cec3b144 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_matplotlib.py @@ -0,0 +1,86 @@ +import logging +from pathlib import Path + +from matplotlib import pyplot as plt +from matplotlib import transforms +from matplotlib.axes import Axes +from matplotlib.figure import Figure +from matplotlib.text import Text +from matplotlib.ticker import FuncFormatter, MaxNLocator + +from .paths import FIG_PATH + + +def setup_matplotlib(): + # https://matplotlib.org/stable/api/matplotlib_configuration_api.html#default-values-and-styling + plt.rcParams["figure.dpi"] = 200 + plt.rcParams["figure.figsize"] = (10, 5) + plt.rcParams["axes.xmargin"] = 0.01 + plt.rcParams["axes.spines.top"] = False + plt.rcParams["axes.spines.right"] = False + plt.rcParams["legend.frameon"] = False + plt.rcParams["pdf.fonttype"] = 42 + plt.rcParams["ps.fonttype"] = 42 + + logging.getLogger("fontTools").setLevel(logging.WARNING) + + +setup_matplotlib() + + +def get_text_height(ax: Axes): + text = Text(text="0", figure=ax.figure) + return text.get_window_extent().height + + +def get_legend_handles_labels(arg): + if isinstance(arg, Axes): + axes = [arg] + elif isinstance(arg, Figure): + axes = arg.axes + labels_handles = { + label: handle + for ax in axes + for handle, label in zip(*ax.get_legend_handles_labels()) + }.items() + labels, handles = zip(*labels_handles) + return handles, labels + + +def format_yticks(ax: Axes): + locator = MaxNLocator(nbins="auto", steps=[1, 2, 4, 5, 10]) + ax.yaxis.set_major_locator(locator) + yticks = ax.get_yticks() + if all(y % 1000 == 0 for y in yticks): + fn = lambda x, _: f"{x / 1000:.0f}k" if x != 0 else "0" + elif all(y % 100 == 0 for y in yticks) and max(yticks) > 1000: + fn = lambda x, _: f"{x / 1000:.1f}k" if x != 0 else "0" + else: + fn = lambda x, _: f"{x:.0f}" + ax.yaxis.set_major_formatter(FuncFormatter(fn)) + + +def label_multiline_text(ax: Axes, x, y, lines, colors=None, fontsize=8): + if colors is None: + colors = [None for _ in lines] + for i, (line, color) in enumerate(zip(lines, colors)): + ax.text( + x, + y, + line, + color=color, + fontsize=fontsize, + ha="center", + va="top", + transform=transforms.offset_copy( + ax.transData, y=-fontsize * i, units="dots" + ), + ) + + +def save_fig(fig: Figure, name: str, path: Path = FIG_PATH): + path.mkdir(parents=True, exist_ok=True) + filepath = path / f"{name}.pdf" + filepath.unlink(missing_ok=True) + fig.savefig(filepath, bbox_inches="tight", pad_inches=0) + logging.info(f"Saved figure to {filepath}") diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_pandas.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_pandas.py new file mode 100644 index 00000000..de777d82 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_pandas.py @@ -0,0 +1,17 @@ +import os + + +def setup_pandas(): + os.environ["NUMEXPR_NUM_THREADS"] = "1" + + import pandas as pd + + # https://pandas.pydata.org/docs/reference/api/pandas.set_option.html + pd.set_option("display.min_rows", 500) + pd.set_option("display.max_rows", 500) + pd.set_option("display.max_columns", 100) + pd.set_option("display.width", 1000) + pd.set_option("display.max_colwidth", 1000) + + +setup_pandas() diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_pickle.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_pickle.py new file mode 100644 index 00000000..84f98baf --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_pickle.py @@ -0,0 +1,20 @@ +import logging +import pickle +from pathlib import Path + +from .paths import OUTPUT_PATH + + +def save_pkl(obj, name: str, path: Path = OUTPUT_PATH): + path.mkdir(parents=True, exist_ok=True) + filepath = path / f"{name}.pkl" + with open(filepath, "wb") as f: + pickle.dump(obj, f) + logging.info(f"Saved {name} to {filepath}") + + +def load_pkl(name: str, path: Path = OUTPUT_PATH): + filepath = path / f"{name}.pkl" + logging.info(f"Loding {name} from {filepath}") + with open(filepath, "rb") as f: + return pickle.load(f) From dc59d8fc71b6658a472bda9fc6be2753864b8052 Mon Sep 17 00:00:00 2001 From: Bogdan-Alexandru Stoica Date: Wed, 18 Feb 2026 16:19:58 -0600 Subject: [PATCH 2/7] [arteval-bench] feat: adding orchestrator code for oracles --- .../data/benchmark/eurosys25_depsurf/_agent_eval/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/main.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/main.py index e36644af..5cbb5374 100644 --- a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/main.py +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/main.py @@ -43,7 +43,7 @@ def _resolve_workspace_paths() -> tuple[Path, Path]: if not agent_eval_dir.exists() or not agent_eval_dir.is_dir(): raise RuntimeError( f"Invalid _agent_eval dir: {agent_eval_dir}\n" - f"This runner expects _agent_eval/ and DepSurf/ to be located in the same root directory.\n" + f"This expects _agent_eval/ and DepSurf/ to be located in the same root directory.\n" f"Set _AGENT_EVAL_DIR to the directory containing main.py if needed.") depsurf_repo_root = depsurf_home / "DepSurf" From cc87cc92c2a749bcb9a22e34213b0bdc9606bdbd Mon Sep 17 00:00:00 2001 From: Bogdan-Alexandru Stoica Date: Wed, 18 Feb 2026 16:20:20 -0600 Subject: [PATCH 3/7] [arteval-bench] feat: add the environment setup oracle --- .../_agent_eval/oracle_env_setup.py | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_env_setup.py diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_env_setup.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_env_setup.py new file mode 100644 index 00000000..2824ea4d --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_env_setup.py @@ -0,0 +1,149 @@ +"""Environment setup oracle for DEPSURF (EuroSys'25). + +Validates: + - Required system tools are installed and meet minimum versions + - Expected repository paths and bpftool artifacts exist + - bpftool/libbpf versions are compatible +""" + +from __future__ import annotations + +import logging +from pathlib import Path +from typing import Sequence + +from evaluator import utils +from evaluator.oracle_env_setup_primitives import ( + DependencyVersionRequirement, + FilesystemPathRequirement, + OracleEnvSetupBase, + PathType, + VersionCompare, +) + + +class OracleEnvSetup(OracleEnvSetupBase): + """DEPSURF environment setup oracle.""" + + def __init__(self, *, config: utils.EntryConfig, + logger: logging.Logger) -> None: + super().__init__(logger=logger) + self._config = config + self._repo_root = Path( + self._config.repository_paths[self._config.name]).resolve() + + # Required paths (see 00_deps.ipynb) + self._bpftool_src_dir = self._repo_root / "depsurf" / "btf" / "bpftool" / "src" + self._bpftool_bin = self._bpftool_src_dir / "bpftool" + + def requirements(self) -> Sequence[utils.BaseRequirement]: + return ( + # Core dependencies + DependencyVersionRequirement( + name="uv", + cmd=("uv", "--version"), + required_version=(0, 6, 11), + compare=VersionCompare.GEQ, + version_regex=r"uv\s+([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="make", + cmd=("make", "--version"), + required_version=(4, 3, 0), + compare=VersionCompare.GEQ, + version_regex=r"GNU Make\s+([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="patch", + cmd=("patch", "--version"), + required_version=(2, 7, 6), + compare=VersionCompare.GEQ, + version_regex=r"patch\s+([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="pkg-config", + cmd=("pkg-config", "--version"), + required_version=(0, 29, 2), + compare=VersionCompare.GEQ, + version_regex=r"([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="clang", + cmd=("clang", "--version"), + required_version=(14, 0, 0), + compare=VersionCompare.GEQ, + version_regex=r"clang version\s+([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="llvm", + cmd=("llvm-config", "--version"), + required_version=(14, 0, 0), + compare=VersionCompare.GEQ, + version_regex=r"([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="pahole", + cmd=("pahole", "--version"), + required_version=(1, 25, 0), + compare=VersionCompare.GEQ, + version_regex=r"v?([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="libelf", + cmd=("pkg-config", "--modversion", "libelf"), + required_version=(0, 186, 0), + compare=VersionCompare.GEQ, + version_regex=r"([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="libcap", + cmd=("pkg-config", "--modversion", "libcap"), + required_version=(2, 44, 0), + compare=VersionCompare.GEQ, + version_regex=r"([0-9.]+)", + timeout_seconds=10.0, + ), + + # Repository layout + FilesystemPathRequirement( + name="repo root directory exists", + path=self._repo_root, + path_type=PathType.DIRECTORY, + ), + + # bpftool artifacts (see 00_deps.ipynb) + FilesystemPathRequirement( + name="bpftool src directory exists", + path=self._bpftool_src_dir, + path_type=PathType.DIRECTORY, + ), + FilesystemPathRequirement( + name="bpftool binary exists", + path=self._bpftool_bin, + path_type=PathType.FILE, + ), + DependencyVersionRequirement( + name="bpftool", + cmd=(str(self._bpftool_bin), "version"), + required_version=(7, 5, 0), + compare=VersionCompare.GEQ, + version_regex=r"bpftool\s+v([0-9.]+)", + timeout_seconds=10.0, + ), + DependencyVersionRequirement( + name="libbpf", + cmd=(str(self._bpftool_bin), "version"), + required_version=(1, 5, 0), + compare=VersionCompare.GEQ, + version_regex=r"libbpf\s+v([0-9.]+)", + timeout_seconds=10.0, + ), + ) From 72afef30df16e2bd54c0a5b6ad8b2e582f6dbcaa Mon Sep 17 00:00:00 2001 From: Bogdan-Alexandru Stoica Date: Wed, 18 Feb 2026 16:20:31 -0600 Subject: [PATCH 4/7] [arteval-bench] feat: add the artifact build oracle --- .../_agent_eval/oracle_artifact_build.py | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_artifact_build.py diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_artifact_build.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_artifact_build.py new file mode 100644 index 00000000..f2bc1b53 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_artifact_build.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +"""Artifact build oracle for DEPSURF (EuroSys'25). + +Validates: + - Repository working directory exists + - The UV manager and Jupyter run succesfully + - bpftool builds succesfully from source code stored in the repository + - eBPF program artifacts/mini-benchmarks build succesfully +""" + +from __future__ import annotations + +from collections.abc import Mapping, Sequence +from dataclasses import dataclass, field +import logging +from pathlib import Path + +from evaluator.oracle_artifact_build_primitives import ( + BuildCommandRequirement, + OracleArtifactBuildBase, +) +from evaluator.utils import EntryConfig, BaseRequirement + + +@dataclass(frozen=True, slots=True, kw_only=True) +class BuildTarget: + """Declarative description of one build command to run.""" + + name: str + cmd: Sequence[str] + relative_workdir: Path | None = None + optional: bool = False + timeout_seconds: float = 60.0 + env_overrides: Mapping[str, str] = field(default_factory=dict) + + def __post_init__(self) -> None: + if not self.name: + raise ValueError("BuildTarget.name must be non-empty") + + object.__setattr__(self, "cmd", tuple(self.cmd)) + + if self.relative_workdir is not None and not isinstance( + self.relative_workdir, Path): + object.__setattr__(self, "relative_workdir", Path(self.relative_workdir)) + + +class OracleArtifactBuild(OracleArtifactBuildBase): + """The artifact build oracle for DepSurf""" + + _DEFAULT_TARGET_SPECS: tuple[tuple[str, tuple[str, ...], float], ...] = ( + # Check the uv package manager is installed and runs (see README) + ( + "depsurf: uv version", + ("uv", "--version"), + 60.0, + ), + ( + "depsurf: uv run python import depsurf", + ("uv", "run", "python", "-c", + "import depsurf; print('OK depsurf import')"), + 60.0, + ), + ( + "depsurf: uv run python minimal", + ("uv", "run", "python", "-c", "print('OK python')"), + 60.0, + ), + + # Validate Jupyter is installed and runs (see README) + ( + "depsurf: uv run jupyter lab --version (non-interactive)", + ("uv", "run", "jupyter", "lab", "--version"), + 60.0, + ), + # Check bpftool builds (see 00_deps.ipynb) + ( + "depsurf: make bpftool (in-repo)", + ("make", "-C", "depsurf/btf/bpftool/src", "bpftool"), + 1800.0, + ), + ( + "depsurf: bpftool --version", + ("bash", "-lc", "./depsurf/btf/bpftool/src/bpftool --version"), + 60.0, + ), + + # Check eBPF program builds (see 50_programs.ipynb) + ( + "depsurf: make bcc/libbpf-tools", + ("bash", "-lc", "make -C data/software/bcc/libbpf-tools -j $(nproc)"), + 1800.0, + ), + ( + "depsurf: bcc objects exist (*.bpf.o)", + ( + "bash", + "-lc", + "ls -1 data/software/bcc/libbpf-tools/.output/*.bpf.o >/dev/null", + ), + 60.0, + ), + ( + "depsurf: make tracee bpf", + ("bash", "-lc", "make -C data/software/tracee bpf -j $(nproc)"), + 1800.0, + ), + ( + "depsurf: tracee eBPF object exists (tracee.bpf.o)", + ("bash", "-lc", "test -f data/software/tracee/dist/tracee.bpf.o"), + 60.0, + ), + ) + + def __init__( + self, + *, + config: EntryConfig, + logger: logging.Logger, + targets: Sequence[BuildTarget] | None = None, + ) -> None: + super().__init__(logger=logger) + self._config = config + + if targets is None: + targets = self._make_default_targets() + self._targets = tuple(targets) + + names = [t.name for t in self._targets] + if len(names) != len(set(names)): + raise ValueError(f"Duplicate build target names: {names!r}") + + def _make_default_targets(self) -> tuple[BuildTarget, ...]: + targets: list[BuildTarget] = [] + for (name, cmd, timeout_seconds) in self._DEFAULT_TARGET_SPECS: + optional = (name == "depsurf: uv run python minimal") + targets.append( + BuildTarget( + name=name, + cmd=cmd, + timeout_seconds=timeout_seconds, + optional=optional, + )) + return tuple(targets) + + def requirements(self) -> Sequence[BaseRequirement]: + """Returns an ordered list of build requirements to validate.""" + repo_root = self._config.repository_paths.get(self._config.name) + + if repo_root is None: + return (BuildCommandRequirement( + name= + f"config: missing repository_paths entry for {self._config.name!r}", + optional=False, + cwd=Path(self._config.home_dir) / "__MISSING_REPOSITORY_PATH__", + cmd=("true",), + timeout_seconds=1.0, + ),) + + return tuple( + BuildCommandRequirement( + name=target.name, + optional=target.optional, + cwd=repo_root, + cmd=target.cmd, + relative_workdir=target.relative_workdir, + timeout_seconds=target.timeout_seconds, + env_overrides=target.env_overrides, + ) for target in self._targets) From da554ce8f0f311a710d9dab672486908f53a4047 Mon Sep 17 00:00:00 2001 From: Bogdan-Alexandru Stoica Date: Wed, 18 Feb 2026 16:20:41 -0600 Subject: [PATCH 5/7] [arteval-bench] feat: add the benchmark preparation oracle --- .../_agent_eval/oracle_benchmark_prep.py | 295 ++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_benchmark_prep.py diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_benchmark_prep.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_benchmark_prep.py new file mode 100644 index 00000000..77665e56 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_benchmark_prep.py @@ -0,0 +1,295 @@ +"""Benchmark preparation oracle for DEPSURF. + +Validates: + - Dataset directory layout is correct + - Each dataset subdirectory contains the expected raw files +""" + +from __future__ import annotations + +import dataclasses +import logging +from pathlib import Path +from typing import Any, Iterable, Mapping, Sequence + +from evaluator import utils +from evaluator.oracle_benchmark_prep_primitives import ( + BenchmarkRequirement, + FailRequirement, + OracleBenchmarkPrepBase, +) +from evaluator.utils import EntryConfig + + +def _is_within(root: Path, candidate: Path) -> bool: + """Returns True iff candidate is within root after (non-strict) resolution.""" + root_resolved = root.resolve(strict=False) + cand_resolved = candidate.resolve(strict=False) + try: + cand_resolved.relative_to(root_resolved) + return True + except ValueError: + return False + + +def _required_repo_root(config: EntryConfig) -> Path | None: + """Returns the configured repo root (or None if missing).""" + return config.repository_paths.get(config.name) + + +def _format_list(items: Sequence[str], *, max_items: int = 12) -> str: + if not items: + return "" + head = list(items[:max_items]) + more = len(items) - len(head) + suffix = f"\n... ({more} more)" if more > 0 else "" + return "\n".join(f"- {x}" for x in head) + suffix + + +def _as_nonempty_str(value: object, *, label: str) -> str: + if not isinstance(value, str) or not value.strip(): + raise ValueError(f"{label} must be a non-empty string") + return value.strip() + + +def _as_str_list(value: object, *, label: str) -> tuple[str, ...]: + if not isinstance(value, (list, tuple)): + raise ValueError(f"{label} must be a list of strings") + out: list[str] = [] + for i, v in enumerate(value): + if not isinstance(v, str) or not v.strip(): + raise ValueError(f"{label}[{i}] must be a non-empty string") + out.append(v.strip()) + if not out: + raise ValueError(f"{label} must be non-empty") + if len(out) != len(set(out)): + raise ValueError(f"{label} contains duplicates: {out!r}") + return tuple(out) + + +@dataclasses.dataclass(frozen=True, slots=True) +class DatasetSpec: + """Validated dataset layout specification derived from EntryConfig.metadata.""" + dataset_root: Path + subdirs: tuple[str, ...] + basenames: tuple[str, ...] + + +def _parse_dataset_spec( + config: EntryConfig, + *, + repo_root: Path, +) -> DatasetSpec | tuple[utils.BaseRequirement, ...]: + """Parses dataset metadata and returns DatasetSpec, or FailRequirements.""" + md = config.metadata or {} + + try: + rel_raw = md.get("dataset_relpath") + subdirs_raw = md.get("dataset_subdirs") + basenames_raw = md.get("dataset_basenames") + + dataset_relpath = _as_nonempty_str(rel_raw, + label="metadata['dataset_relpath']") + dataset_subdirs = _as_str_list(subdirs_raw, + label="metadata['dataset_subdirs']") + dataset_basenames = _as_str_list(basenames_raw, + label="metadata['dataset_basenames']") + except ValueError as exc: + return (FailRequirement( + name="config:dataset_metadata", + message=str(exc), + ),) + + rel = Path(dataset_relpath) + + if rel.is_absolute(): + return (FailRequirement( + name="config:dataset_relpath", + message=f"dataset_relpath must be relative, got: {dataset_relpath!r}", + ),) + if ".." in rel.parts: + return (FailRequirement( + name="config:dataset_relpath", + message=f"dataset_relpath must not contain '..': {dataset_relpath!r}", + ),) + + dataset_root = (repo_root / rel) + + if not _is_within(repo_root, dataset_root): + return (FailRequirement( + name="config:dataset_relpath", + message= + f"dataset_root escapes repo_root: dataset_root={dataset_root} repo_root={repo_root}", + ),) + + for s in dataset_subdirs: + p = Path(s) + if p.is_absolute() or ".." in p.parts: + return (FailRequirement( + name="config:dataset_subdirs", + message= + f"dataset_subdirs must be relative and not contain '..': bad entry: {s!r}", + ),) + + return DatasetSpec( + dataset_root=dataset_root, + subdirs=dataset_subdirs, + basenames=dataset_basenames, + ) + + +def _path_requirements( + *, + repo_root: Path, + dataset_root: Path, + subdirs: Sequence[str], +) -> list[utils.BaseRequirement]: + """Returns path requirements for dataset layout (existence + type checks).""" + reqs: list[utils.BaseRequirement] = [] + + reqs.append( + BenchmarkRequirement(name="dataset_root_exists", filepath=dataset_root)) + for s in subdirs: + reqs.append( + BenchmarkRequirement( + name=f"dataset_subdir_exists:{s}", + filepath=(dataset_root / s), + )) + + if dataset_root.exists() and not dataset_root.is_dir(): + reqs.append( + FailRequirement( + name="dataset_root_is_dir", + message= + f"dataset_root exists but is not a directory: {dataset_root}", + )) + + for s in subdirs: + p = dataset_root / s + if p.exists() and not p.is_dir(): + reqs.append( + FailRequirement( + name=f"dataset_subdir_is_dir:{s}", + message=f"dataset subdir exists but is not a directory: {p}", + )) + + return reqs + + +def _dirs_ready(*, dataset_root: Path, subdir_paths: Iterable[Path]) -> bool: + """Returns True iff dataset_root and all subdirs exist and are directories.""" + if not dataset_root.exists() or not dataset_root.is_dir(): + return False + for p in subdir_paths: + if not p.exists() or not p.is_dir(): + return False + return True + + +def _present_basenames(dir_path: Path) -> set[str]: + """Returns basenames (file stem) for direct children files under dir_path.""" + out: set[str] = set() + for p in dir_path.iterdir(): + # Ignore hidden files (e.g., .gitignore) + if p.name.startswith("."): + continue + if not p.is_file(): + continue + out.add(p.stem) + return out + + +def _basename_requirements( + *, + dataset_root: Path, + subdirs: Sequence[str], + expected_basenames: Sequence[str], +) -> list[utils.BaseRequirement]: + """Returns requirements ensuring expected basenames exist under each subdir.""" + reqs: list[utils.BaseRequirement] = [] + + expected_set = set(expected_basenames) + if not expected_set: + reqs.append( + FailRequirement( + name="config:dataset_basenames", + message="metadata['dataset_basenames'] must be non-empty", + )) + return reqs + + for s in subdirs: + subdir_path = dataset_root / s + present = _present_basenames(subdir_path) + + missing = sorted(expected_set - present) + extra = sorted(present - expected_set) + + if missing: + reqs.append( + FailRequirement( + name=f"dataset_basenames_missing:{s}", + message= + (f"dataset subdir is missing required basenames: {subdir_path}\n" + f"{_format_list(missing)}"), + )) + + if extra: + reqs.append( + FailRequirement( + name=f"dataset_basenames_extra:{s}", + optional=True, + message= + (f"dataset subdir contains unexpected basenames: {subdir_path}\n" + f"{_format_list(extra)}"), + )) + + return reqs + + +class OracleBenchmarkPrep(OracleBenchmarkPrepBase): + """Validates dataset prerequisites for DEPSURF evaluation bundles.""" + + def __init__(self, *, config: EntryConfig, logger: logging.Logger) -> None: + super().__init__(logger=logger) + self._config = config + + def requirements(self) -> Sequence[utils.BaseRequirement]: + reqs: list[utils.BaseRequirement] = [] + + repo_root = _required_repo_root(self._config) + if repo_root is None: + return [ + FailRequirement( + name="config:repo_root", + message= + f"Missing repository_paths[{self._config.name!r}] in EntryConfig", + ) + ] + + reqs.append( + BenchmarkRequirement(name="repo_root_exists", filepath=repo_root)) + + spec_or_err = _parse_dataset_spec(self._config, repo_root=repo_root) + if not isinstance(spec_or_err, DatasetSpec): + reqs.extend(spec_or_err) + return reqs + + spec = spec_or_err + + reqs.extend( + _path_requirements( + repo_root=repo_root, + dataset_root=spec.dataset_root, + subdirs=spec.subdirs, + )) + + subdir_paths = [spec.dataset_root / s for s in spec.subdirs] + if _dirs_ready(dataset_root=spec.dataset_root, subdir_paths=subdir_paths): + reqs.extend( + _basename_requirements( + dataset_root=spec.dataset_root, + subdirs=spec.subdirs, + expected_basenames=spec.basenames, + )) + + return reqs From 83bd70e462b8abc107003fc7ad378c47e9e80543 Mon Sep 17 00:00:00 2001 From: Bogdan-Alexandru Stoica Date: Wed, 18 Feb 2026 16:20:53 -0600 Subject: [PATCH 6/7] [arteval-bench] feat: add the experimental runs oracle --- .../_agent_eval/oracle_experiment_runs.py | 482 ++++++++++++++++++ 1 file changed, 482 insertions(+) create mode 100644 benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_experiment_runs.py diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_experiment_runs.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_experiment_runs.py new file mode 100644 index 00000000..0782224c --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/_agent_eval/oracle_experiment_runs.py @@ -0,0 +1,482 @@ +"""Experiment runs oracle for DepSurf (EuroSys'25). + +Validates: + - All expected DepSurf CSV result tables can be read and parsed + - Ground-truth reference CSV tables exist and can be read + - Observed tables meet the configured similarity threshold against reference tables +""" + +from __future__ import annotations + +import csv +import dataclasses +import enum +import logging +import math +from collections.abc import Mapping, Sequence +from pathlib import Path + +from evaluator import utils +from evaluator.oracle_experiment_runs_primitives import ( + ExperimentRunsContext, + ListSimilarityRequirement, + OracleExperimentRunsBase, + SimilarityMetric, +) +from evaluator.utils import EntryConfig + + +def _required_path(paths: Mapping[str, Path], key: str, *, label: str) -> Path: + """Returns a required path from a mapping with a clear error message.""" + try: + p = paths[key] + except KeyError as exc: + raise ValueError(f"Missing {label}[{key!r}] in EntryConfig") from exc + return p + + +def _normalize_cell(text: str) -> str: + """Normalizes a CSV cell string for numeric parsing by stripping whitespaces + and treating "missing" symbols as empty cells. + """ + s = text.strip() + if not s: + return "" + if s in {"-", "—", "NA", "N/A", "nan", "NaN"}: + return "" + return s + + +def _as_float_or_zero(text: str, *, label: str) -> float: + """Parses a numeric CSV cell with empty translated to 0.0, or raises error + on non-numeric entries. + """ + s = _normalize_cell(text) + if not s: + return 0.0 + try: + v = float(s) + except ValueError as exc: + raise ValueError(f"{label}: non-numeric cell {text!r}") from exc + if not math.isfinite(v): + raise ValueError(f"{label}: non-finite numeric cell {text!r}") + return v + + +def _load_csv_matrix( + path: Path, + *, + label: str, +) -> tuple[tuple[str, ...], tuple[str, ...], tuple[tuple[str, ...], ...]]: + """Loads a CSV file as (headers, row_keys, rows).""" + try: + with path.open("r", encoding="utf-8", newline="") as f: + reader = csv.reader(f) + raw = list(reader) + except OSError as exc: + raise ValueError(f"{label}: failed to read {path}: {exc}") from exc + + # Drop leading/trailing blank lines + raw = [r for r in raw if any(c.strip() for c in r)] + if not raw: + raise ValueError(f"{label}: empty CSV at {path}") + + headers = tuple(raw[0]) + if len(headers) < 2: + raise ValueError( + f"{label}: expected >=2 columns, got {len(headers)} in {path}") + + out_rows: list[tuple[str, ...]] = [] + row_keys: list[str] = [] + seen: set[str] = set() + + for i, r in enumerate(raw[1:], start=2): + # Pad short rows; ignore extra columns beyond header length + padded = list(r[:len(headers)]) + [""] * max(0, len(headers) - len(r)) + key = padded[0].strip() + if not key: + raise ValueError(f"{label}: empty row key at line {i} in {path}") + if key in seen: + raise ValueError(f"{label}: duplicate row key {key!r} in {path}") + seen.add(key) + row_keys.append(key) + out_rows.append(tuple(padded)) + + return headers, tuple(row_keys), tuple(out_rows) + + +def _discover_numeric_columns( + headers: Sequence[str], + rows: Sequence[Sequence[str]], + *, + label: str, +) -> tuple[str, ...]: + """Returns numeric column header names in order, excluding column 0,""" + numeric: list[str] = [] + for k, header in enumerate(headers): + if k == 0: + continue + + saw_value = False + for i, row in enumerate(rows): + if k >= len(row): + continue + cell = _normalize_cell(row[k]) + if not cell: + continue + saw_value = True + try: + v = float(cell) + except ValueError as exc: + raise ValueError( + f"{label}: column {header!r} has non-numeric cell {row[k]!r} at row {i}" + ) from exc + if not math.isfinite(v): + raise ValueError( + f"{label}: column {header!r} has non-finite cell {row[k]!r} at row {i}" + ) + if saw_value: + numeric.append(header) + if not numeric: + raise ValueError(f"{label}: could not discover any numeric columns") + return tuple(numeric) + + +def _format_missing(items: Sequence[str], *, max_items: int = 10) -> str: + if not items: + return "" + head = list(items[:max_items]) + more = len(items) - len(head) + suffix = f"\n... ({more} more)" if more > 0 else "" + return "\n".join(f"- {k}" for k in head) + suffix + + +def _column_totals( + headers: Sequence[str], + rows: Sequence[Sequence[str]], + *, + numeric_cols: Sequence[str], + label: str, + max_items: int, +) -> list[float]: + """Computes per-column "totals".""" + header_to_idx = {h: i for i, h in enumerate(headers)} + missing_cols = [h for h in numeric_cols if h not in header_to_idx] + if missing_cols: + detail = _format_missing(missing_cols, max_items=max_items) + msg = f"{label}: missing required numeric columns" + if detail: + msg = f"{msg}\nmissing columns:\n{detail}" + raise ValueError(msg) + + totals: list[float] = [] + for col_name in numeric_cols: + j = header_to_idx[col_name] + s = 0.0 + for i, r in enumerate(rows): + cell = r[j] if j < len(r) else "" + s += _as_float_or_zero(cell, label=f"{label}: row[{i}].{col_name}") + totals.append(s) + return totals + + +def _fractions_from_totals(totals: Sequence[float]) -> list[float]: + """Normalizes totals into fractions.""" + den = sum(totals) + if den <= 0.0: + return [0.0 for _ in totals] + return [v / den for v in totals] + + +@enum.unique +class _VectorType(enum.Enum): + """Which aggregated vector to compare for a table under Mode B.""" + + TOTALS = "totals" + FRACTIONS = "fractions" + + +@dataclasses.dataclass(frozen=True, slots=True, kw_only=True) +class CSVTableModeBPearsonRequirement(utils.BaseRequirement): + """Pearson similarity on column totals or column fractions to check + for the same relative number patterns and distribution/shape. + + Attributes: + results_path: Path to the CSV produced by the current run. + reference_path: Path to the reference CSV shipped with the evaluation bundle. + threshold: Minimum acceptable Pearson correlation score. + vector_type: Selects whether to compare raw totals or normalized fractions. + max_mismatches_to_report: Maximum number of missing columns and similar issues to include in error messages. + """ + + results_path: Path + reference_path: Path + threshold: float + vector_type: _VectorType + max_mismatches_to_report: int = 10 + + def check(self, ctx: ExperimentRunsContext) -> utils.CheckResult: + try: + ref_headers, _ref_row_keys, ref_rows = _load_csv_matrix( + self.reference_path, label=f"{self.name} reference") + res_headers, _res_row_keys, res_rows = _load_csv_matrix( + self.results_path, label=f"{self.name} results") + + ref_numeric_cols = _discover_numeric_columns( + ref_headers, ref_rows, label=f"{self.name} reference") + + reference_totals = _column_totals( + ref_headers, + ref_rows, + numeric_cols=ref_numeric_cols, + label=f"{self.name} reference", + max_items=self.max_mismatches_to_report, + ) + observed_totals = _column_totals( + res_headers, + res_rows, + numeric_cols=ref_numeric_cols, + label=f"{self.name} results", + max_items=self.max_mismatches_to_report, + ) + + if self.vector_type == _VectorType.TOTALS: + reference = reference_totals + observed = observed_totals + elif self.vector_type == _VectorType.FRACTIONS: + reference = _fractions_from_totals(reference_totals) + observed = _fractions_from_totals(observed_totals) + else: + raise ValueError(f"unsupported vector_type: {self.vector_type!r}") + except ValueError as exc: + return utils.CheckResult.failure(f"{self.name}: {exc}") + + delegated = ListSimilarityRequirement( + name=self.name, + optional=self.optional, + observed=observed, + reference=reference, + metric=SimilarityMetric.PEARSON, + min_similarity=self.threshold, + ) + return delegated.check(ctx) + + +@dataclasses.dataclass(frozen=True, slots=True, kw_only=True) +class CSVTableModeBPearsonByRowRequirement(utils.BaseRequirement): + """Compute Pearson similarity on a single numeric column aligned by row key. + + Attributes + results_path: Path to the CSV produced by the current run. + reference_path: Path to the reference CSV shipped with the evaluation bundle. + threshold: Minimum acceptable Pearson correlation score. + column_name: Name of the numeric column to extract and compare. + vector_type: Selects whether to compare raw per-row values or normalized per-row fractions. + max_mismatches_to_report: Maximum number of missing rows/columns to include in error messages. + """ + + results_path: Path + reference_path: Path + threshold: float + column_name: str + vector_type: _VectorType + max_mismatches_to_report: int = 10 + + def check(self, ctx: ExperimentRunsContext) -> utils.CheckResult: + try: + ref_headers, ref_row_keys, ref_rows = _load_csv_matrix( + self.reference_path, label=f"{self.name} reference") + res_headers, res_row_keys, res_rows = _load_csv_matrix( + self.results_path, label=f"{self.name} results") + + ref_numeric_cols = _discover_numeric_columns( + ref_headers, ref_rows, label=f"{self.name} reference") + if self.column_name not in ref_numeric_cols: + raise ValueError( + f"reference does not contain required numeric column {self.column_name!r}" + ) + + res_header_to_idx = {h: i for i, h in enumerate(res_headers)} + if self.column_name not in res_header_to_idx: + raise ValueError( + f"results missing required numeric column {self.column_name!r}") + + res_key_to_row: dict[str, Sequence[str]] = { + k: r for k, r in zip(res_row_keys, res_rows, strict=True) + } + missing_rows = [k for k in ref_row_keys if k not in res_key_to_row] + if missing_rows: + detail = _format_missing(missing_rows, + max_items=self.max_mismatches_to_report) + msg = f"results missing required reference rows" + if detail: + msg = f"{msg}\nmissing rows:\n{detail}" + raise ValueError(msg) + + ref_header_to_idx = {h: i for i, h in enumerate(ref_headers)} + ref_j = ref_header_to_idx[self.column_name] + res_j = res_header_to_idx[self.column_name] + + reference: list[float] = [] + observed: list[float] = [] + for row_key, ref_row in zip(ref_row_keys, ref_rows, strict=True): + res_row = res_key_to_row[row_key] + + reference.append( + _as_float_or_zero( + ref_row[ref_j] if ref_j < len(ref_row) else "", + label=f"{self.name} reference: {row_key}.{self.column_name}", + )) + observed.append( + _as_float_or_zero( + res_row[res_j] if res_j < len(res_row) else "", + label=f"{self.name} results: {row_key}.{self.column_name}", + )) + + if self.vector_type == _VectorType.FRACTIONS: + reference = _fractions_from_totals(reference) + observed = _fractions_from_totals(observed) + elif self.vector_type != _VectorType.TOTALS: + raise ValueError(f"unsupported vector_type: {self.vector_type!r}") + except ValueError as exc: + return utils.CheckResult.failure(f"{self.name}: {exc}") + + delegated = ListSimilarityRequirement( + name=self.name, + optional=self.optional, + observed=observed, + reference=reference, + metric=SimilarityMetric.PEARSON, + min_similarity=self.threshold, + ) + return delegated.check(ctx) + + +class OracleExperimentRuns(OracleExperimentRunsBase): + """Validates DepSurf experiment run result tables.""" + + def __init__(self, *, config: EntryConfig, logger: logging.Logger) -> None: + super().__init__(logger=logger) + self._config = config + + def requirements(self) -> Sequence[utils.BaseRequirement]: + if not self._config.results_paths: + raise ValueError("EntryConfig.results_paths must be non-empty") + if not self._config.ground_truth_paths: + raise ValueError("EntryConfig.ground_truth_paths must be non-empty") + + results_config = _required_path(self._config.results_paths, + "39_config", + label="results_paths") + results_programs = _required_path(self._config.results_paths, + "50_programs", + label="results_paths") + results_summary7 = _required_path(self._config.results_paths, + "52_summary_table7", + label="results_paths") + results_summary8 = _required_path(self._config.results_paths, + "52_summary_table8", + label="results_paths") + + reference_config = _required_path(self._config.ground_truth_paths, + "39_config", + label="ground_truth_paths") + reference_programs = _required_path(self._config.ground_truth_paths, + "50_programs", + label="ground_truth_paths") + reference_summary7 = _required_path(self._config.ground_truth_paths, + "52_summary_table7", + label="ground_truth_paths") + reference_summary8 = _required_path(self._config.ground_truth_paths, + "52_summary_table8", + label="ground_truth_paths") + + threshold = self._config.similarity_ratio + + tables: tuple[tuple[str, Path, Path], ...] = ( + ("39_config", results_config, reference_config), + ("50_programs", results_programs, reference_programs), + ("52_summary_table7", results_summary7, reference_summary7), + ) + + reqs: list[utils.BaseRequirement] = [] + for name, results_path, reference_path in tables: + # NOTE: Convert CSVs into compact numeric vectors by summing each + # numeric column across all rows ("column totals"). This captures + # the overall magnitude of each dependency count for individual eBPF + # programs while being less brittle when running on eBPF program + # versions different than those used to evaluate DepSurf. + reqs.append( + CSVTableModeBPearsonRequirement( + name=f"{name}_totals", + results_path=results_path, + reference_path=reference_path, + threshold=threshold, + vector_type=_VectorType.TOTALS, + )) + # NOTE: Compare normalized ratios of total vounts divided by the overall sum. + # This way, the comparison captures the distribution (shape) across dependency + # dependnecy counts for each individual eBPF program and, like above, makes + # the comparison more robust when using different eBPF versions than those + # originally used to evaluate DepSurf. + reqs.append( + CSVTableModeBPearsonRequirement( + name=f"{name}_fractions", + results_path=results_path, + reference_path=reference_path, + threshold=threshold, + vector_type=_VectorType.FRACTIONS, + )) + + # NOTE: For Table 8, row keys represent stable mismatch categories, + # so this compares per-category distributions (per numeric column) + # using Pearson similarity. + try: + ref_headers8, _ref_keys8, ref_rows8 = _load_csv_matrix( + reference_summary8, label="52_summary_table8 reference") + numeric_cols8 = _discover_numeric_columns( + ref_headers8, ref_rows8, label="52_summary_table8 reference") + except ValueError: + numeric_cols8 = () + + if numeric_cols8: + for col in numeric_cols8: + safe_col = col.replace(" ", "_") + reqs.append( + CSVTableModeBPearsonByRowRequirement( + name=f"52_summary_table8_{safe_col}_totals", + results_path=results_summary8, + reference_path=reference_summary8, + threshold=threshold, + column_name=col, + vector_type=_VectorType.TOTALS, + )) + reqs.append( + CSVTableModeBPearsonByRowRequirement( + name=f"52_summary_table8_{safe_col}_fractions", + results_path=results_summary8, + reference_path=reference_summary8, + threshold=threshold, + column_name=col, + vector_type=_VectorType.FRACTIONS, + )) + else: + # NOTE: Fallback to checking aggregated column totals and ratios + reqs.append( + CSVTableModeBPearsonRequirement( + name="52_summary_table8_totals", + results_path=results_summary8, + reference_path=reference_summary8, + threshold=threshold, + vector_type=_VectorType.TOTALS, + )) + reqs.append( + CSVTableModeBPearsonRequirement( + name="52_summary_table8_fractions", + results_path=results_summary8, + reference_path=reference_summary8, + threshold=threshold, + vector_type=_VectorType.FRACTIONS, + )) + + return tuple(reqs) From 91b61d205e814ed464e400750df439623708e932 Mon Sep 17 00:00:00 2001 From: Bogdan-Alexandru Stoica Date: Wed, 18 Feb 2026 18:42:59 -0600 Subject: [PATCH 7/7] feat: enable DepSurf in the task JSON file --- benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl b/benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl index d3ad1586..20cd76a5 100644 --- a/benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl +++ b/benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl @@ -1,4 +1,5 @@ {"artifact_id": "sosp24_wasabi", "artifact_dir": "sosp24_wasabi", "artifact_readme": "sosp24_wasabi/wasabi/README.md", "artifact_url": "https://github.com/bastoica/wasabi/tree/sosp24-ae", "evaluator": "sosp24_wasabi/wasabi/_agent_eval/main.py", "expected_score": 4, "docer_env": "bastoica/ae-agent-ubuntu24.04:latest"} {"artifact_id": "osdi24_anvil", "artifact_dir": "osdi24_anvil", "artifact_readme": "osdi24_anvil/anvil/README.md", "artifact_url": "https://github.com/anvil-verifier/anvil", "evaluator": "osdi24_anvil/_agent_eval/main.py", "expected_score": 4, "docer_env": "bastoica/ae-agent-ubuntu24.04:latest"} {"artifact_id": "sosp23_acto", "artifact_dir": "sosp23_acto", "artifact_readme": "sosp23_acto/acto/README.md", "artifact_url": "https://github.com/xlab-uiuc/acto", "evaluator": "sosp23_acto/_agent_eval/main.py", "expected_score": 4, "docer_env": "bastoica/ae-agent-ubuntu24.04:latest"} -{"artifact_id": "eurosys25_egwalker", "artifact_dir": "eurosys25_egwalker", "artifact_readme": "eurosys25_egwalker/egwalker/README.md", "artifact_url": "https://github.com/josephg/egwalker-paper", "evaluator": "eurosys25_egwalker/_agent_eval/main.py", "expected_score": 4, "docer_env": "bastoica/ae-agent-ubuntu24.04:latest"} \ No newline at end of file +{"artifact_id": "eurosys25_egwalker", "artifact_dir": "eurosys25_egwalker", "artifact_readme": "eurosys25_egwalker/egwalker/README.md", "artifact_url": "https://github.com/josephg/egwalker-paper", "evaluator": "eurosys25_egwalker/_agent_eval/main.py", "expected_score": 4, "docer_env": "bastoica/ae-agent-ubuntu24.04:latest"} +{"artifact_id": "eurosys25_depsurf", "artifact_dir": "eurosys25_depsurf", "artifact_readme": "eurosys25_depsurf/depsurf/README.md", "artifact_url": "https://github.com/ShawnZhong/DepSurf", "evaluator": "eurosys25_depsurf/_agent_eval/main.py", "expected_score": 4, "docer_env": "bastoica/ae-agent-ubuntu24.04:latest"} \ No newline at end of file