Files
AXP-Resurection/scripts/check-module-abi.py
T
sunfish-admin 12d2179c20 AXP Magisk resurrection track: Speckit 009 port AXP/LOS22 to LOS23.
Ship Magisk like GOLDEN; KernelSU optional recycle only; parallel to sunfish-a16-rom standby.
2026-09-16 21:56:22 +00:00

52 lines
1.8 KiB
Python

#!/usr/bin/env python3
"""Check a Linux module's versioned imports against its target Module.symvers.
Requires kmod's modprobe. A pass checks symbol CRCs only, not complete ABI,
vermagic, CFI, signatures, firmware or hardware behaviour.
"""
import argparse
from pathlib import Path
import subprocess
import sys
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("symvers", type=Path)
parser.add_argument("modules", nargs="+", type=Path)
args = parser.parse_args()
exports = {}
for line in args.symvers.read_text().splitlines():
fields = line.split()
if len(fields) >= 2:
exports[fields[1]] = int(fields[0], 16)
if not exports:
parser.error("Module.symvers contains no exports")
failed = False
for module in args.modules:
result = subprocess.run(
["modprobe", "--show-modversions", str(module.resolve())],
text=True, capture_output=True,
)
if result.returncode or not result.stdout.strip():
print(f"UNVERIFIED {module}: {result.stderr.strip() or 'no versioned imports'}")
failed = True
continue
mismatch = 0
imports = result.stdout.splitlines()
for line in imports:
crc, symbol = line.split()
expected = exports.get(symbol)
if expected != int(crc, 16):
mismatch += 1
target = "missing export" if expected is None else f"0x{expected:08x}"
print(f" {symbol}: module={crc}, kernel={target}")
failed |= bool(mismatch)
print(f"{'FAIL' if mismatch else 'PASS'} {module}: "
f"{mismatch}/{len(imports)} incompatible versioned imports")
return int(failed)
if __name__ == "__main__":
sys.exit(main())