1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
import os import sys import argparse
WHITELIST_PATH = 'scripts/abicheck/whitelist.pgx' BASELINE_PATH = 'scripts/abicheck/baseline.abi.pgx' DEFAULT_SYMVERS = 'Module.symvers'
def parse_symvers(symvers_file): syms = {} with open(symvers_file, 'r') as f: for line in f: parts = line.strip().split() if len(parts) < 2: continue crc = int(parts[0], 16) sym = parts[1] syms[sym] = crc return syms
def load_whitelist(path): whitelist = set() if not os.path.exists(path): return whitelist with open(path, 'r') as f: for line in f: line = line.strip() if not line or line.startswith('#') or line.startswith('['): continue parts = line.split() if parts: whitelist.add(parts[0]) return whitelist
def load_baseline(path): baseline = {} if not os.path.exists(path): return baseline with open(path, 'r') as f: for line in f: line = line.strip() if not line or line.startswith('#'): continue parts = line.split() if len(parts) != 2: continue sym, crc_str = parts crc = int(crc_str, 16) baseline[sym] = crc return baseline
def compare_kabi(current, baseline, whitelist): added, removed, changed = [], [], []
for sym in whitelist: if sym in current: if sym not in baseline: added.append(sym) elif current[sym] != baseline[sym]: changed.append(sym)
for sym in whitelist: if sym in baseline and sym not in current: removed.append(sym)
return added, removed, changed
def main(): parser = argparse.ArgumentParser(description='Check kernel ABI stability') parser.add_argument('--symvers', default=DEFAULT_SYMVERS, help='Path to Module.symvers file (default: ./Module.symvers)') parser.add_argument('--baseline', default=BASELINE_PATH, help='Baseline ABI file to compare with') parser.add_argument('--whitelist', default=WHITELIST_PATH, help='Symbol whitelist file') args = parser.parse_args()
if not os.path.exists(args.symvers): print(f"Error: Cannot find Module.symvers at {args.symvers}", file=sys.stderr) return 1
current_abi = parse_symvers(args.symvers) whitelist = load_whitelist(args.whitelist) baseline_abi = load_baseline(args.baseline)
added, removed, changed = compare_kabi(current_abi, baseline_abi, whitelist)
print('\n=== ABI Changes (Only in Whitelist) =======') if added: print(f'Added symbols ({len(added)}):') for sym in added: print(f' + {sym}') if removed: print(f'Removed symbols ({len(removed)}):') for sym in removed: print(f' - {sym}') if changed: print(f'Changed symbols ({len(changed)}):') for sym in changed: old_crc = baseline_abi[sym] new_crc = current_abi[sym] print(f' {sym}: {hex(old_crc)} -> {hex(new_crc)}')
if not (added or removed or changed): print('No ABI change detected in whitelist symbols') print('===========================================')
return 1 if (added or removed or changed) else 0
if __name__ == '__main__': sys.exit(main())
|