Files
python-bpf/pythonbpf/license_pass.py
2025-10-08 17:20:45 +00:00

71 lines
2.4 KiB
Python

"""
LICENSE global variable processing for BPF programs.
This module handles the processing of the LICENSE function which is required
for BPF programs to declare their license (typically "GPL").
"""
from llvmlite import ir
import ast
from logging import Logger
import logging
logger: Logger = logging.getLogger(__name__)
def emit_license(module: ir.Module, license_str: str):
"""
Emit a LICENSE global variable into the LLVM IR module.
Args:
module: The LLVM IR module to add the LICENSE variable to
license_str: The license string (e.g., 'GPL')
Returns:
The created global variable
"""
license_bytes = license_str.encode("utf8") + b"\x00"
elems = [ir.Constant(ir.IntType(8), b) for b in license_bytes]
ty = ir.ArrayType(ir.IntType(8), len(elems))
gvar = ir.GlobalVariable(module, ty, name="LICENSE")
gvar.initializer = ir.Constant(ty, elems) # type: ignore
gvar.align = 1 # type: ignore
gvar.linkage = "dso_local" # type: ignore
gvar.global_constant = False
gvar.section = "license" # type: ignore
return gvar
def license_processing(tree, module):
"""Process the LICENSE function decorated with @bpf and @bpfglobal and return the section name"""
count = 0
for node in tree.body:
if isinstance(node, ast.FunctionDef) and node.name == "LICENSE":
# check decorators
decorators = [
dec.id for dec in node.decorator_list if isinstance(dec, ast.Name)
]
if "bpf" in decorators and "bpfglobal" in decorators:
if count == 0:
count += 1
# check function body has a return string
if (
len(node.body) == 1
and isinstance(node.body[0], ast.Return)
and isinstance(node.body[0].value, ast.Constant)
and isinstance(node.body[0].value.value, str)
):
emit_license(module, node.body[0].value.value)
return "LICENSE"
else:
logger.info("ERROR: LICENSE() must return a string literal")
return None
else:
logger.info("ERROR: LICENSE already defined")
return None
return None