import hashlib import json def build_canonical_symbol_tables( swift_files: list, objc_files: list, method_files: list, *, enable_objc_symbols: bool, prefilter_files, type_pattern: str, method_pattern: str, extract_swift_symbols, extract_objc_symbols, extract_methods, objc_symbol_prefixes: tuple, already_obfuscated_re, symbol_whitelist, symbol_prefix_whitelist: tuple, is_system_method, split_swift_signature_key, ) -> dict: swift_symbol_files = prefilter_files(swift_files, type_pattern) objc_symbol_files = prefilter_files(objc_files, type_pattern) if enable_objc_symbols else [] method_symbol_files = prefilter_files(method_files, method_pattern) swift_symbols = set() objc_symbols = set() direct_methods = set() objc_selectors = set() swift_signatures = {} for file_path in swift_symbol_files: swift_symbols.update(extract_swift_symbols(file_path)) for file_path in objc_symbol_files: objc_symbols.update(extract_objc_symbols(file_path)) for file_path in method_symbol_files: method_data = extract_methods(file_path) direct_methods.update(method_data["direct_names"]) objc_selectors.update(method_data["objc_selectors"]) swift_signatures.update(method_data["swift_signatures"]) canonical = { "swift_symbols": sorted(swift_symbols), "objc_symbols": [ name for name in sorted(objc_symbols) if any(name.startswith(prefix) for prefix in objc_symbol_prefixes) and not already_obfuscated_re.match(name) and name not in symbol_whitelist and not name.startswith(symbol_prefix_whitelist) ], "direct_methods": [ name for name in sorted(direct_methods) if name and not already_obfuscated_re.match(name) and name not in symbol_whitelist and not is_system_method(name) ], "objc_selectors": [ name for name in sorted(objc_selectors) if name and not already_obfuscated_re.match(name) and name not in symbol_whitelist and not is_system_method(name) ], "swift_signatures": {}, } for signature_key in sorted(swift_signatures.keys()): base_name, _ = split_swift_signature_key(signature_key) if not base_name: continue if already_obfuscated_re.match(base_name) or base_name in symbol_whitelist or is_system_method(base_name): continue canonical["swift_signatures"][signature_key] = swift_signatures[signature_key] digest_payload = { key: canonical[key] for key in ("swift_symbols", "objc_symbols", "direct_methods", "objc_selectors", "swift_signatures") } canonical["digest"] = hashlib.sha256( json.dumps(digest_payload, ensure_ascii=False, sort_keys=True).encode("utf-8") ).hexdigest() return canonical def build_type_mappings_from_canonical_table(canonical_tables: dict, salt: str, *, enable_objc_symbols: bool, build_unique_mapping, type_prefix: str) -> tuple: ordered_names = [] seen = set() for bucket_name in ("objc_symbols", "swift_symbols"): for name in canonical_tables.get(bucket_name, []): if name in seen: continue seen.add(name) ordered_names.append(name) combined_mapping = build_unique_mapping(ordered_names, salt, prefix=type_prefix) mapping_swift = { name: combined_mapping[name] for name in canonical_tables.get("swift_symbols", []) if name in combined_mapping } mapping_objc = {} if enable_objc_symbols: mapping_objc = { name: combined_mapping[name] for name in canonical_tables.get("objc_symbols", []) if name in combined_mapping } return mapping_swift, mapping_objc def build_method_mapping_from_canonical_table(canonical_tables: dict, salt: str, *, build_unique_mapping, method_prefix: str) -> dict: swift_signature_mapping = canonical_tables.get("swift_signatures", {}) ordered_names = [] seen = set() for bucket in ( canonical_tables.get("direct_methods", []), canonical_tables.get("objc_selectors", []), sorted(swift_signature_mapping.keys()), ): for name in bucket: if name in seen: continue seen.add(name) ordered_names.append(name) combined_tokens = build_unique_mapping(ordered_names, salt, prefix=method_prefix) method_mapping = { name: combined_tokens[name] for name in canonical_tables.get("direct_methods", []) if name in combined_tokens } method_mapping.update({ name: combined_tokens[name] for name in canonical_tables.get("objc_selectors", []) if name in combined_tokens }) for signature_key in sorted(swift_signature_mapping.keys()): if signature_key not in combined_tokens: continue entry = dict(swift_signature_mapping[signature_key]) entry["obfuscated"] = combined_tokens[signature_key] method_mapping[signature_key] = entry return method_mapping