From nobody Thu Apr 2 17:16:42 2026 Received: from mailgw01.zimbra-vnc.de (mailgw01.zimbra-vnc.de [148.251.101.236]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3544D337BA4; Tue, 10 Feb 2026 20:55:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.101.236 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770756917; cv=none; b=G3TZR/UuTqK7KCB2YwfhEvPUYYK0ZYvs6JmcoYgUrBkREUIm7FYhg791cDerZAVMiUOps1H0gnoAyUeZpPmNhk+bfTJVwzfXwm9P00gegHrRbHTq+8+ewVxEBSlEuys38ZbsyCl1VwXHg7xxU6xz4645uov+HnSSLsrVY6UTdOY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770756917; c=relaxed/simple; bh=6sBEOTE+l0vVo7PIBudUNhudZ5Lxk36nUT9fmcEOEWI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Cf70M2ps5MpXAKwXBT2W59RQ4XcDqSDot7C07DYACka0LkDHGbxDSQmuEwMgM9OPagDKkFV9DC8NyOrygrWrp2Ie9+TKcGJtcQKULdSx37tD0eafWlA8RqDV5DfuxD6D/qc6kcZyiXoB2VtWSy17Zj7hNF0PfYx9WsqtfqaczlU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=tngtech.com; spf=pass smtp.mailfrom=tngtech.com; dkim=pass (2048-bit key) header.d=tngtech.com header.i=@tngtech.com header.b=OhqBUq3q; arc=none smtp.client-ip=148.251.101.236 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=tngtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=tngtech.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=tngtech.com header.i=@tngtech.com header.b="OhqBUq3q" Received: from zmproxy.tng.vnc.biz (zimbra-vnc.tngtech.com [35.234.71.156]) by mailgw01.zimbra-vnc.de (Postfix) with ESMTPS id 5148A3FAF2; Tue, 10 Feb 2026 21:55:13 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by zmproxy.tng.vnc.biz (Postfix) with ESMTP id 3634D1FA99B; Tue, 10 Feb 2026 21:55:13 +0100 (CET) Received: from zmproxy.tng.vnc.biz ([127.0.0.1]) by localhost (zmproxy.tng.vnc.biz [127.0.0.1]) (amavis, port 10032) with ESMTP id JQ0gZ__GOZKS; Tue, 10 Feb 2026 21:55:12 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by zmproxy.tng.vnc.biz (Postfix) with ESMTP id 802011FA999; Tue, 10 Feb 2026 21:55:12 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.10.3 zmproxy.tng.vnc.biz 802011FA999 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tngtech.com; s=B14491C6-869D-11EB-BB6C-8DD33D883B31; t=1770756912; bh=KJcoRnov97uDkXuQQOD7VnxuA4vLvXSr70B2GE3QuKg=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=OhqBUq3qIa9XzkAmpRA5YrW9VVPmxoSzkCR79qEbrDDANQ8F6jhcL3QpJvdCmmeLx WVTm8tOLv2P+sHyBG6sw8ankYUmZJsB/1Emb5weANpkBwIDp7AiVjr0U4sGt+3VAzK xzE0UIbtPXEyYrrStvxnZh+cyuTN7EvccIUXXTMQi0hPFcKN0ltIUu+n8aKlIq3AAW mQOBERol09Drs5H07swqVLeV1j/f0DnTmoCwJ0vdsahklFtvexYvpx66vJYPG+HXtD 00gunJ0KqhE/qtwwB3QziGW1dWrNQRBNqhCyp4zGjpA5KB1vmmvTwtVfHXM03Q9+DC eJFIt6uyOARqw== X-Virus-Scanned: amavis at zmproxy.tng.vnc.biz Received: from zmproxy.tng.vnc.biz ([127.0.0.1]) by localhost (zmproxy.tng.vnc.biz [127.0.0.1]) (amavis, port 10026) with ESMTP id d4lYDrvun2Js; Tue, 10 Feb 2026 21:55:12 +0100 (CET) Received: from DESKTOP-0O0JV6I.localdomain (ipservice-092-208-231-176.092.208.pools.vodafone-ip.de [92.208.231.176]) by zmproxy.tng.vnc.biz (Postfix) with ESMTPSA id 15CF11FA9B1; Tue, 10 Feb 2026 21:55:12 +0100 (CET) From: Luis Augenstein To: nathan@kernel.org, nsc@kernel.org Cc: linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, akpm@linux-foundation.org, gregkh@linuxfoundation.org, kstewart@linuxfoundation.org, maximilian.huber@tngtech.com, Luis Augenstein Subject: [PATCH 06/15] scripts/sbom: add additional dependency sources for cmd graph Date: Tue, 10 Feb 2026 21:54:15 +0100 Message-Id: <20260210205424.11195-7-luis.augenstein@tngtech.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260210205424.11195-1-luis.augenstein@tngtech.com> References: <20260210205424.11195-1-luis.augenstein@tngtech.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add hardcoded dependencies and .incbin directive parsing to discover dependencies not tracked by .cmd files. Assisted-by: Claude Sonnet 4.5 Assisted-by: GLM-4.7 Co-developed-by: Maximilian Huber Signed-off-by: Maximilian Huber Signed-off-by: Luis Augenstein --- .../sbom/cmd_graph/hardcoded_dependencies.py | 83 +++++++++++++++++++ scripts/sbom/sbom/cmd_graph/incbin_parser.py | 42 ++++++++++ scripts/sbom/sbom/environment.py | 14 ++++ 3 files changed, 139 insertions(+) create mode 100644 scripts/sbom/sbom/cmd_graph/hardcoded_dependencies.py create mode 100644 scripts/sbom/sbom/cmd_graph/incbin_parser.py create mode 100644 scripts/sbom/sbom/environment.py diff --git a/scripts/sbom/sbom/cmd_graph/hardcoded_dependencies.py b/script= s/sbom/sbom/cmd_graph/hardcoded_dependencies.py new file mode 100644 index 000000000000..a5977f14ae49 --- /dev/null +++ b/scripts/sbom/sbom/cmd_graph/hardcoded_dependencies.py @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0-only OR MIT +# Copyright (C) 2025 TNG Technology Consulting GmbH + +import os +from typing import Callable +import sbom.sbom_logging as sbom_logging +from sbom.path_utils import PathStr, is_relative_to +from sbom.environment import Environment + +HARDCODED_DEPENDENCIES: dict[str, list[str]] =3D { + # defined in linux/Kbuild + "include/generated/rq-offsets.h": ["kernel/sched/rq-offsets.s"], + "kernel/sched/rq-offsets.s": ["include/generated/asm-offsets.h"], + "include/generated/bounds.h": ["kernel/bounds.s"], + "include/generated/asm-offsets.h": ["arch/{arch}/kernel/asm-offsets.s"= ], +} + + +def get_hardcoded_dependencies(path: PathStr, obj_tree: PathStr, src_tree:= PathStr) -> list[PathStr]: + """ + Some files in the kernel build process are not tracked by the .cmd dep= endency mechanism. + Parsing these dependencies programmatically is too complex for the sco= pe of this project. + Therefore, this function provides manually defined dependencies to be = added to the build graph. + + Args: + path: absolute path to a file within the src tree or object tree. + obj_tree: absolute Path to the base directory of the object tree. + src_tree: absolute Path to the `linux` source directory. + + Returns: + list[PathStr]: A list of dependency file paths (relative to the ob= ject tree) required to build the file at the given path. + """ + if is_relative_to(path, obj_tree): + path =3D os.path.relpath(path, obj_tree) + elif is_relative_to(path, src_tree): + path =3D os.path.relpath(path, src_tree) + + if path not in HARDCODED_DEPENDENCIES: + return [] + + template_variables: dict[str, Callable[[], str | None]] =3D { + "arch": lambda: _get_arch(path), + } + + dependencies: list[PathStr] =3D [] + for dependency_template in HARDCODED_DEPENDENCIES[path]: + dependency =3D _evaluate_template(dependency_template, template_va= riables) + if dependency is None: + continue + if os.path.exists(os.path.join(obj_tree, dependency)): + dependencies.append(dependency) + elif os.path.exists(os.path.join(src_tree, dependency)): + dependencies.append(os.path.relpath(dependency, obj_tree)) + else: + sbom_logging.error( + "Skip hardcoded dependency '{dependency}' for '{path}' bec= ause the dependency lies neither in the src tree nor the object tree.", + dependency=3Ddependency, + path=3Dpath, + ) + + return dependencies + + +def _evaluate_template(template: str, variables: dict[str, Callable[[], st= r | None]]) -> str | None: + for key, value_function in variables.items(): + template_key =3D "{" + key + "}" + if template_key in template: + value =3D value_function() + if value is None: + return None + template =3D template.replace(template_key, value) + return template + + +def _get_arch(path: PathStr): + srcarch =3D Environment.SRCARCH() + if srcarch is None: + sbom_logging.error( + "Skipped architecture specific hardcoded dependency for '{path= }' because the SRCARCH environment variable was not set.", + path=3Dpath, + ) + return None + return srcarch diff --git a/scripts/sbom/sbom/cmd_graph/incbin_parser.py b/scripts/sbom/sb= om/cmd_graph/incbin_parser.py new file mode 100644 index 000000000000..130f9520837d --- /dev/null +++ b/scripts/sbom/sbom/cmd_graph/incbin_parser.py @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-only OR MIT +# Copyright (C) 2025 TNG Technology Consulting GmbH + +from dataclasses import dataclass +import re + +from sbom.path_utils import PathStr + +INCBIN_PATTERN =3D re.compile(r'\s*\.incbin\s+"(?P[^"]+)"') +"""Regex pattern for matching `.incbin ""` statements.""" + + +@dataclass +class IncbinStatement: + """A parsed `.incbin ""` directive.""" + + path: PathStr + """path to the file referenced by the `.incbin` directive.""" + + full_statement: str + """Full `.incbin ""` statement as it originally appeared in the = file.""" + + +def parse_incbin_statements(absolute_path: PathStr) -> list[IncbinStatemen= t]: + """ + Parses `.incbin` directives from an `.S` assembly file. + + Args: + absolute_path: Absolute path to the `.S` assembly file. + + Returns: + list[IncbinStatement]: Parsed `.incbin` statements. + """ + with open(absolute_path, "rt") as f: + content =3D f.read() + return [ + IncbinStatement( + path=3Dmatch.group("path"), + full_statement=3Dmatch.group(0).strip(), + ) + for match in INCBIN_PATTERN.finditer(content) + ] diff --git a/scripts/sbom/sbom/environment.py b/scripts/sbom/sbom/environme= nt.py new file mode 100644 index 000000000000..b3fb2f0ba61d --- /dev/null +++ b/scripts/sbom/sbom/environment.py @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only OR MIT +# Copyright (C) 2025 TNG Technology Consulting GmbH + +import os + + +class Environment: + """ + Read-only accessor for kernel build environment variables. + """ + + @classmethod + def SRCARCH(cls) -> str | None: + return os.getenv("SRCARCH") --=20 2.34.1