diff --git a/benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl b/benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl index d3ad1586..1f46440a 100644 --- a/benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl +++ b/benchmarks/arteval_bench/data/benchmark/arteval_tasks.jsonl @@ -1,4 +1,6 @@ {"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"} +{"artifact_id": "osdi24_eet", "artifact_dir": "osdi24_eet", "artifact_readme": "osdi24_eet/eet/README.md", "artifact_url": "https://github.com/JZuming/EET", "evaluator": "osdi24_eet/_agent_eval/main.py", "expected_score": 4, "docer_env": "bastoica/ae-agent-ubuntu24.04:latest"} \ No newline at end of file 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..5cbb5374 --- /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 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/_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) 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 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, + ), + ) 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) 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/B6qhRo8zKlSvj3k7Lcaxatcrs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fzt27BgdXXSUFq3RyuKkuac9evSwf998883RecOu2NMNN9xg03Q1RzfVYlKF6fp/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+84McdrCncvyus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", + "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": "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+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 00000000..e79c127e Binary files /dev/null and b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/fonts/Inconsolata_ExtraCondensed-Medium.ttf differ diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/paths.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/paths.py new file mode 100644 index 00000000..515d423b --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/paths.py @@ -0,0 +1,16 @@ +from pathlib import Path + +UTILS_PATH = Path(__file__).parent +PROJ_PATH = UTILS_PATH.parent + +DATA_PATH = PROJ_PATH / "data" +OUTPUT_PATH = DATA_PATH / "output" + +PAPER_PATH = PROJ_PATH / "paper" +TAB_PATH = PAPER_PATH / "tabs" +FIG_PATH = PAPER_PATH / "figs" + +SOFTWARE_PATH = DATA_PATH / "software" + +FONTS_PATH = UTILS_PATH / "fonts" +FONT_MONO = FONTS_PATH / "Inconsolata_ExtraCondensed-Medium.ttf" diff --git a/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_latex.py b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_latex.py new file mode 100644 index 00000000..f73944ed --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/eurosys25_depsurf/depsurf/utils/utils_latex.py @@ -0,0 +1,118 @@ +import logging +import re +from pathlib import Path +from typing import Optional + +from .paths import TAB_PATH + +GRAY_DASH = r"\color{lightgray}{-}" + + +def texttt(text: str): + return f"\\texttt{{{text}}}" + + +def makebox(text: str, width: str, align: str = "r") -> 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) diff --git a/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/main.py b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/main.py new file mode 100644 index 00000000..285c27ba --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/main.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +"""Runs environment setup, build, benchmark prep, and experiment runs checks for EET (OSDI'24).""" + +from __future__ import annotations + +import os +import sys +from pathlib import Path +from typing import Dict + +from evaluator.utils import ( + EntryConfig, + LoggerConfig, + get_logger, + record_result, +) + +from oracle_artifact_build import OracleArtifactBuild +from oracle_benchmark_prep import OracleBenchmarkPrep +from oracle_env_setup import OracleEnvSetup +from oracle_experiment_runs import OracleExperimentRuns + + +def _resolve_workspace_paths() -> tuple[Path, Path, Path]: + """Resolve and validate _agent_eval/ and eet/ locations. + + Expects either: + (1) _agent_eval/ and eet/ are located in the same workspace root; or + (2) _AGENT_EVAL_DIR is set to the directory containing this main.py and + _WORKSPACE_ROOT (preferred) or _EET_HOME is set to the workspace root. + """ + try: + env_agent_eval = os.environ.get("_AGENT_EVAL_DIR") + env_workspace_root = os.environ.get("_WORKSPACE_ROOT") or os.environ.get( + "_EET_HOME") + + if env_agent_eval: + agent_eval_dir = Path(env_agent_eval).expanduser().resolve() + else: + agent_eval_dir = Path(__file__).resolve().parent + + if env_workspace_root: + workspace_root = Path(env_workspace_root).expanduser().resolve() + else: + workspace_root = 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"Set _AGENT_EVAL_DIR to the directory containing main.py if needed.") + + eet_repo_root = workspace_root / "eet" + if not eet_repo_root.exists() or not eet_repo_root.is_dir(): + raise RuntimeError( + f"Invalid workspace root: {workspace_root}\n" + f"Expected to find an 'eet/' directory at: {eet_repo_root}\n" + f"This runner expects _agent_eval/ and eet/ to be located in the same workspace root.\n" + f"Set _WORKSPACE_ROOT (or legacy _EET_HOME) to the workspace root if needed." + ) + + eet_home = workspace_root + return agent_eval_dir, eet_home, workspace_root + + except OSError as exc: + raise RuntimeError(f"Failed to resolve workspace paths: {exc}") from exc + + +def _build_configs(*, agent_eval_dir: Path, + workspace_root: Path) -> EntryConfig: + """Construct EntryConfig for the EET evaluation bundle from resolved paths.""" + canonical_benchmarks = ["mysql", "postgres", "sqlite", "clickhouse", "tidb"] + + eet_repo = (workspace_root / "eet").resolve() + + results_paths = { + "bugs_observed_json": + (agent_eval_dir / "outputs" / "bugs_observed.json").resolve(), + } + for bench in canonical_benchmarks: + results_paths[f"{bench}_test_dir"] = (workspace_root / + f"{bench}_test").resolve() + + return EntryConfig( + name="osdi24-eet", + home_dir=workspace_root, + repository_paths={"osdi24-eet": eet_repo}, + results_paths=results_paths, + ground_truth_paths={ + "bugs_expected_json": + (agent_eval_dir / "refs" / "bugs_expected.json").resolve(), + }, + similarity_ratio=0.75, + metadata={ + "eet_benchmark_prep": { + "scripts_dir": "scripts", + "required_files": ["Dockerfile", "test_setup.sh", "run_test.sh"], + "versions": { + "mysql": "8.0.34", + "postgres": "3f1aaaa", + "sqlite": "20e09ba", + "clickhouse": "30464b9", + "tidb": "f5ca27e", + }, + }, + "benchmarks": canonical_benchmarks, + }, + ) + + +def main(argv: list[str]) -> int: + verbose = "--verbose" in argv + + results: Dict[str, int] = {} + score = 0 + + logger_name = os.environ.get("EVAL_LOGGER_NAME", "EET-AGENT-EVALUATOR") + logger = get_logger(LoggerConfig(root_name=logger_name)) + + try: + agent_eval_dir, _eet_home, workspace_root = _resolve_workspace_paths() + eet_config = _build_configs(agent_eval_dir=agent_eval_dir, + workspace_root=workspace_root) + except RuntimeError as exc: + raise SystemExit(str(exc)) from exc + + env_checker = OracleEnvSetup(config=eet_config, logger=logger) + env_ok = env_checker.run(verbose=verbose) + score += record_result(results, type(env_checker).__name__, env_ok) + + build_checker = OracleArtifactBuild(config=eet_config, logger=logger) + build_ok = build_checker.run(verbose=verbose) + score += record_result(results, type(build_checker).__name__, build_ok) + + prep_checker = OracleBenchmarkPrep(config=eet_config, logger=logger) + prep_ok = prep_checker.run(verbose=verbose) + score += record_result(results, type(prep_checker).__name__, prep_ok) + + runs_checker = OracleExperimentRuns(config=eet_config, logger=logger) + runs_ok = runs_checker.run(verbose=verbose) + score += record_result(results, type(runs_checker).__name__, runs_ok) + + 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/osdi24_eet/_agent_eval/oracle_artifact_build.py b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_artifact_build.py new file mode 100644 index 00000000..7b0b23e0 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_artifact_build.py @@ -0,0 +1,86 @@ +"""Artifact build oracle for EET (OSDI'24). + +Validates: + - Repository working directory exists. + - Native 'make' build command executes successfully. +""" + +from collections.abc import Mapping, Sequence +from dataclasses import dataclass, field +import logging +import os +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. + + Attributes: + name: Label for logs and debug printing. + cmd: Command to execute as an argv sequence. + rel_workdir: Directory to run cmd in (optional, default: cwd). + optional: Whether this check is optional or the oracle should exit when failed. + timeout_seconds: Maximum time allowed for the command to complete. + env_vars: Environment variables to add / override. + """ + + name: str + cmd: Sequence[str] + rel_workdir: Path | None = None + optional: bool = False + timeout_seconds: float = 60.0 + env_vars: 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.rel_workdir is not None and not isinstance(self.rel_workdir, Path): + object.__setattr__(self, "rel_workdir", Path(self.rel_workdir)) + + +class OracleArtifactBuild(OracleArtifactBuildBase): + """Artifact build oracle for EET.""" + + def __init__( + self, + *, + config: EntryConfig, + logger: logging.Logger, + ) -> None: + super().__init__(logger=logger) + self._config = config + + 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, + ),) + + cpu_count = os.cpu_count() or 1 + make_jobs = max(1, cpu_count // 2) + + return (BuildCommandRequirement( + name=f"EET: make -j{make_jobs}", + optional=False, + cwd=repo_root, + cmd=("make", f"-j{make_jobs}"), + timeout_seconds=600.0, + ),) diff --git a/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_benchmark_prep.py b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_benchmark_prep.py new file mode 100644 index 00000000..36c7314b --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_benchmark_prep.py @@ -0,0 +1,174 @@ +"""Benchmark preparation oracle for EET (OSDI'24). + +Validates: + - Scripts directory layout and main scripts are present. + - Each ./scripts//run_test.sh script contains the expected version/commit version. +""" + +import logging +from pathlib import Path +from typing import Any, Mapping, Sequence + +from evaluator import utils +from evaluator.utils import EntryConfig +from evaluator.oracle_benchmark_prep_primitives import ( + BenchmarkRequirement, + FailRequirement, + OracleBenchmarkPrepBase, +) + + +def _read_meta_dict(config: EntryConfig, key: str) -> Mapping[str, Any] | None: + """Returns a EntryConfig entry, or None if missing/invalid.""" + obj: Any = config.metadata.get(key) + if isinstance(obj, dict): + return obj + return None + + +def _require_path( + reqs: list[utils.BaseRequirement], + *, + name: str, + path: Path, + req_type: str, +) -> None: + """Append requirements for path existence and expected type (file/dir).""" + reqs.append(BenchmarkRequirement(name=f"{name}_exists", filepath=path)) + + if not path.exists(): + return + + if req_type is "dir" and not path.is_dir(): + reqs.append( + FailRequirement( + name=f"{name}_is_directory", + message=f"expected directory, found non-directory path: {path}", + )) + elif req_type is "file" and not path.is_file(): + reqs.append( + FailRequirement( + name=f"{name}_is_file", + message=f"expected file, found non-file path: {path}", + )) + else: + raise ValueError(f"Unknown type: {req_type}") + + +class OracleBenchmarkPrep(OracleBenchmarkPrepBase): + """Validates dataset prerequisites for _agent_eval 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 = Path(self._config.repository_paths.get(self._config.name)) + if repo_root is None: + return [ + FailRequirement( + name="config:repo_root", + message= + (f"Missing repository_paths[{self._config.name!r}] in EntryConfig" + ), + ) + ] + + benchmarks = _read_meta_dict(self._config, "benchmarks") + metadata = _read_meta_dict(self._config, "eet_benchmark_prep") + if metadata is None: + return [ + FailRequirement( + name="config:eet_benchmark_prep", + message= + "Missing/invalid metadata['eet_benchmark_prep'] (expected dict)", + ) + ] + + scripts_dir_name = metadata.get("scripts_dir") + required_files = metadata.get("required_files") + versions = metadata.get("versions") + + if not isinstance(scripts_dir_name, str) or not scripts_dir_name.strip(): + return [ + FailRequirement( + name="config:scripts_dir", + message= + "metadata['eet_benchmark_prep']['scripts_dir'] must be a non-empty string", + ) + ] + if not isinstance(benchmarks, list) or not all( + isinstance(x, str) and x.strip() for x in benchmarks): + return [ + FailRequirement( + name="config:benchmarks", + message= + "metadata['eet_benchmark_prep']['benchmarks'] must be a list of non-empty strings", + ) + ] + if not isinstance(required_files, list) or not all( + isinstance(x, str) and x.strip() for x in required_files): + return [ + FailRequirement( + name="config:required_files", + message= + "metadata['eet_benchmark_prep']['required_files'] must be a list of non-empty strings", + ) + ] + if not isinstance(versions, dict) or not all( + isinstance(k, str) and k.strip() and isinstance(v, str) and v.strip() + for k, v in versions.items()): + return [ + FailRequirement( + name="config:versions", + message= + "metadata['eet_benchmark_prep']['versions'] must be a dict[str,str] with non-empty values", + ) + ] + + scripts_dir = Path(repo_root / scripts_dir_name) + + # Check repository layout and script directory exist + _require_path(reqs, name="repo_root", path=repo_root, req_type="dir") + _require_path(reqs, name="scripts_dir", path=scripts_dir, req_type="dir") + + # Validate ./scripts/ layout + for bench in benchmarks: + bench_dir = Path(scripts_dir / bench) + + _require_path(reqs, + name=f"scripts_subdir:{bench}", + path=bench_dir, + req_type="dir") + + for fname in required_files: + fpath = Path(bench_dir / fname) + _require_path(reqs, + name=f"scripts_file:{bench}:{fname}", + path=fpath, + req_type="file") + + version = versions.get(bench) + if not isinstance(version, str) or not version.strip(): + reqs.append( + FailRequirement( + name=f"config:version_missing:{bench}", + message=( + "metadata['eet_benchmark_prep']['versions'] missing/invalid " + f"for bench {bench!r}"), + )) + continue + + run_test = Path(bench_dir / "run_test.sh") + reqs.append( + BenchmarkRequirement( + name=f"run_test_contains_version:{bench}", + filepath=run_test, + cmd=("cat", "run_test.sh"), + signature=version, + timeout_seconds=10.0, + )) + + return reqs diff --git a/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_env_setup.py b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_env_setup.py new file mode 100644 index 00000000..b54bfcd8 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_env_setup.py @@ -0,0 +1,85 @@ +"""Environment setup oracle for EET (OSDI'24). + +Validates: + - Required host tools for the recommended Docker-based evaluation workflow. + - Optional native-build tools for compiling EET on Debian (as documented). + - Repository directory exists and contains expected helper scripts. + - Any configured ground-truth reference files exist. +""" + +import logging +from pathlib import Path +from typing import Mapping, Sequence + +from evaluator import utils +from evaluator.utils import EntryConfig +from evaluator.oracle_env_setup_primitives import ( + DependencyVersionRequirement, + FilesystemPathRequirement, + OracleEnvSetupBase, + PathType, + VersionCompare, +) + + +def _required_path(paths: Mapping[str, Path], key: str, *, label: str) -> Path: + """Returns a required path from a EntryConfig dictionary.""" + try: + return paths[key] + except KeyError as e: + raise ValueError(f"Missing {label}[{key!r}] in EntryConfig") from e + + +class OracleEnvSetup(OracleEnvSetupBase): + """Checks environment prerequisites for EET.""" + + def __init__(self, *, config: EntryConfig, logger: logging.Logger) -> None: + super().__init__(logger) + self._config = config + + def requirements(self) -> Sequence[utils.BaseRequirement]: + repo_root = _required_path(self._config.repository_paths, + self._config.name, + label="repository_paths") + + reqs: list[utils.BaseRequirement] = [ + DependencyVersionRequirement( + name="docker", + cmd=("docker", "--version"), + required_version=(24, 0, 0), + compare=VersionCompare.GEQ, + ), + DependencyVersionRequirement( + name="g++", + cmd=("g++", "--version"), + required_version=(13, 2, 0), + compare=VersionCompare.GEQ, + optional=True, + ), + DependencyVersionRequirement( + name="make", + cmd=("make", "--version"), + required_version=(4, 3, 0), + compare=VersionCompare.GEQ, + optional=True, + ), + DependencyVersionRequirement( + name="autoconf", + cmd=("autoconf", "--version"), + required_version=(2, 71, 0), + compare=VersionCompare.GEQ, + optional=True, + ), + FilesystemPathRequirement( + name="repo_root_exists", + path=repo_root, + path_type=PathType.DIRECTORY, + ), + FilesystemPathRequirement( + name="scripts_dir_exists", + path=repo_root / "scripts", + path_type=PathType.DIRECTORY, + ), + ] + + return reqs diff --git a/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_experiment_runs.py b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_experiment_runs.py new file mode 100644 index 00000000..b45274dd --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/oracle_experiment_runs.py @@ -0,0 +1,157 @@ +"""Experiment runs oracle for EET (OSDI'24). + +Validates: + - Bug totals are computed per DBMS from the produced `bugs/` directories. + - Observed per-DBMS totals match the expected reference JSON in refs/. +""" + +from __future__ import annotations + +import json +import logging +from pathlib import Path +from typing import Any, Dict, Mapping, Sequence + +from evaluator import utils +from evaluator.oracle_experiment_runs_primitives import ( + ElementwiseSimilarityThresholdRequirement, + OracleExperimentRunsBase, +) +from evaluator.utils import EntryConfig + + +def _required_path(paths: Mapping[str, Path], key: str, *, label: str) -> Path: + try: + return paths[key] + except KeyError as exc: + raise KeyError(f"Missing {label} path in EntryConfig: {key!r}") from exc + + +def _load_json_object(path: Path) -> Any: + try: + with path.open("r", encoding="utf-8") as f: + return json.load(f) + except FileNotFoundError as exc: + raise RuntimeError(f"JSON file not found: {path}") from exc + except json.JSONDecodeError as exc: + raise RuntimeError(f"Invalid JSON in {path}: {exc}") from exc + except OSError as exc: + raise RuntimeError(f"Failed to read JSON file {path}: {exc}") from exc + + +def _validate_expected_mapping(obj: Any, *, path: Path) -> Dict[str, int]: + if not isinstance(obj, dict): + raise RuntimeError(f"Expected JSON must be an object in {path}, got: {type(obj)}") + out: Dict[str, int] = {} + for k, v in obj.items(): + if not isinstance(k, str): + raise RuntimeError(f"Expected JSON keys must be strings in {path}, got key: {k!r}") + if not isinstance(v, int): + raise RuntimeError(f"Expected JSON values must be integers in {path}, got {k!r}: {v!r}") + out[k] = v + return out + + +def _read_meta_benchmarks(config: EntryConfig) -> list[str]: + meta = config.metadata or {} + obj: Any = meta.get("benchmarks") + if isinstance(obj, (list, tuple)): + return [str(x) for x in obj] + return [] + + +def _resolve_benchmark_bugs_dir(config: EntryConfig, benchmark: str) -> Path: + direct_key = f"{benchmark}_bugs_dir" + testdir_key = f"{benchmark}_test_dir" + + if direct_key in config.results_paths: + return config.results_paths[direct_key] + if testdir_key in config.results_paths: + return config.results_paths[testdir_key] / "bugs" + + return config.home_dir / "_missing_results" / benchmark / "bugs" + + +def _count_bug_dirs(bugs_dir: Path) -> int: + """Each triggered bug corresponds to one subdirectory under bugs/.""" + if not bugs_dir.exists() or not bugs_dir.is_dir(): + return 0 + try: + return sum(1 for p in bugs_dir.iterdir() if p.is_dir()) + except OSError: + return 0 + + +def _ensure_parent_dir(path: Path) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + + +def _write_json(path: Path, obj: Any) -> None: + _ensure_parent_dir(path) + with path.open("w", encoding="utf-8") as f: + json.dump(obj, f, indent=2, sort_keys=True) + f.write("\n") + + +class OracleExperimentRuns(OracleExperimentRunsBase): + """Experiment runs oracle for EET.""" + + def __init__(self, *, config: EntryConfig, logger: logging.Logger) -> None: + super().__init__(logger=logger) + self._config = config + + def requirements(self) -> Sequence[utils.BaseRequirement]: + expected_path = _required_path( + self._config.ground_truth_paths, + "bugs_expected_json", + label="expected bug totals JSON", + ) + observed_json_path = _required_path( + self._config.results_paths, + "bugs_observed_json", + label="observed bug totals JSON output", + ) + + expected_obj = _load_json_object(expected_path) + expected = _validate_expected_mapping(expected_obj, path=expected_path) + + declared = [b.lower() for b in _read_meta_benchmarks(self._config)] + if declared: + order = [b for b in declared if b in {k.lower() for k in expected.keys()}] + extra = sorted(k.lower() for k in expected.keys() if k.lower() not in set(declared)) + order.extend(extra) + else: + order = sorted(k.lower() for k in expected.keys()) + + observed_map: Dict[str, int] = {} + observed_vec: list[float] = [] + reference_vec: list[float] = [] + + expected_lc = {k.lower(): v for k, v in expected.items()} + + for bench in order: + bugs_dir = _resolve_benchmark_bugs_dir(self._config, bench) + obs = _count_bug_dirs(bugs_dir) + ref = expected_lc.get(bench) + + if ref is None: + raise RuntimeError(f"Expected JSON missing benchmark key {bench!r} (after normalization)") + + observed_map[bench] = obs + observed_vec.append(float(obs)) + reference_vec.append(float(ref)) + + self._logger.info("Bug count for %s: observed=%d expected=%d (from %s)", bench, obs, ref, bugs_dir) + + # Save observed number of bugs (debugging) + _write_json(observed_json_path, observed_map) + + threshold = float(getattr(self._config, "similarity_ratio", 1.0)) + return [ + ElementwiseSimilarityThresholdRequirement( + name="bugs_totals_elementwise_similarity", + observed=observed_vec, + reference=reference_vec, + threshold=threshold, + ) + ] \ No newline at end of file diff --git a/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/refs/bugs_expected.json b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/refs/bugs_expected.json new file mode 100644 index 00000000..93bdc41f --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/_agent_eval/refs/bugs_expected.json @@ -0,0 +1,7 @@ +{ + "mysql": 16, + "postgres": 9, + "sqlite": 10, + "clickhouse": 21, + "tidb": 10 +} \ No newline at end of file diff --git a/benchmarks/arteval_bench/data/benchmark/osdi24_eet/eet/COPYING b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/eet/COPYING new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/eet/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/benchmarks/arteval_bench/data/benchmark/osdi24_eet/eet/Doxyfile.in b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/eet/Doxyfile.in new file mode 100644 index 00000000..731a78f2 --- /dev/null +++ b/benchmarks/arteval_bench/data/benchmark/osdi24_eet/eet/Doxyfile.in @@ -0,0 +1,2427 @@ +# Doxyfile 1.8.11 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "@PACKAGE_NAME@" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = "@CONFIG_GIT_REVISION@" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "A random SQL query generator" + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = "logo.png" + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ./ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, +# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /