iOSBuildServer/backend/automation/obfuscation/obfuscation_runtime/canonical.py

145 lines
5.1 KiB
Python

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