1#!/usr/bin/env python3
2#
3# Copyright (c) 2024 STMicroelectronics
4# SPDX-License-Identifier: Apache-2.0
5
6"""
7This file implements the Symbol Link Identifer (SLID)
8generation code, for use by the LLEXT subsystem.
9SLID-based linking is enabled by the Kconfig
10option 'CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID'.
11
12When executed as a script, this file can be used as
13an interactive prompt to calculate the SLID of arbitrary
14symbols, which can be useful for debugging purposes.
15
16IMPLEMENTATION NOTES:
17  Currently, SLIDs are generated by taking the first
18  [pointer size] bytes of the symbol name's SHA-256
19  hash, taken in big-endian order.
20
21  This ordering provides one advantage: the 32-bit
22  SLID for an export is present in the top 32 bits of
23  the 64-bit SLID for the same export.
24"""
25
26from hashlib import sha256
27
28
29def generate_slid(symbol_name: str, slid_size: int) -> int:
30    """
31    Generates the Symbol Link Identifier (SLID) for a symbol.
32
33        symbol_name: Name of the symbol for which to generate a SLID
34        slid_side: Size of the SLID in bytes (4/8)
35    """
36    if slid_size not in (4, 8):
37        raise AssertionError(f"Invalid SLID size {slid_size}")
38
39    m = sha256()
40    m.update(symbol_name.encode("utf-8"))
41    hash = m.digest()
42    return int.from_bytes(hash[0:slid_size], byteorder='big', signed=False)
43
44
45def format_slid(slid: int, slid_size: int) -> str:
46    if slid_size == 4:
47        fmt = f"0x{slid:08X}"
48    elif slid_size == 8:
49        fmt = f"0x{slid:016X}"
50    return fmt
51
52
53def repl():
54    while True:
55        sym_name = input("Symbol name? ")
56        slid32 = generate_slid(sym_name, 4)
57        slid64 = generate_slid(sym_name, 8)
58        print(f"  32-bit SLID for '{sym_name}': {format_slid(slid32, 4)}")
59        print(f"  64-bit SLID for '{sym_name}': {format_slid(slid64, 8)}")
60        print()
61
62
63if __name__ == "__main__":
64    print("LLEXT SLID calculation REPL")
65    print("Press ^C to exit.")
66    try:
67        repl()
68    except KeyboardInterrupt:
69        print()
70