mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-03 12:32:53 +08:00
[fix] include OpenSSL resource symbols in iOS archives
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate matching symbols for Xcode's embedded, codeless OpenSSL framework."""
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def uuids(path):
|
||||
output = subprocess.check_output(["xcrun", "dwarfdump", "--uuid", str(path)], text=True)
|
||||
result = dict((arch, uuid.upper()) for uuid, arch in
|
||||
re.findall(r"UUID: ([0-9A-Fa-f-]{36}) \(([^)]+)\)", output))
|
||||
if not result:
|
||||
raise ValueError(f"No Mach-O UUIDs found: {path}")
|
||||
return result
|
||||
|
||||
|
||||
def verify_symbols(binary, dsym):
|
||||
dwarf = dsym / "Contents/Resources/DWARF" / binary.name
|
||||
if not dwarf.is_file():
|
||||
raise ValueError(f"Missing dSYM DWARF file: {dwarf}")
|
||||
if uuids(binary) != uuids(dwarf):
|
||||
raise ValueError(f"dSYM UUIDs do not match {binary}: {dwarf}")
|
||||
|
||||
|
||||
def generate(binary, output):
|
||||
# This is only for Xcode's resource placeholder. Real OpenSSL code remains
|
||||
# statically linked into the app and must not receive an empty dSYM here.
|
||||
commands = subprocess.check_output(["xcrun", "otool", "-l", str(binary)], text=True)
|
||||
text_sizes = re.findall(
|
||||
r"sectname __text\s+segname __TEXT\s+addr \S+\s+size (0x[0-9a-fA-F]+)", commands)
|
||||
if not text_sizes or any(int(size, 16) for size in text_sizes):
|
||||
raise ValueError(f"Expected a codeless OpenSSL resource stub: {binary}")
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
# No function-level debug info exists in this empty stub. dsymutil still
|
||||
# emits a valid UUID-matched DWARF companion; quiet suppresses that expected
|
||||
# warning only after verifying that there is no executable code to lose.
|
||||
subprocess.run(["xcrun", "dsymutil", "--quiet", str(binary), "-o", str(output)], check=True)
|
||||
verify_symbols(binary, output)
|
||||
subprocess.run(["xcrun", "dwarfdump", "--verify", str(output)], check=True)
|
||||
print(f"Generated UUID-matched OpenSSL resource symbols: {output}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--binary", required=True, type=Path)
|
||||
parser.add_argument("--output", required=True, type=Path)
|
||||
args = parser.parse_args()
|
||||
generate(args.binary, args.output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except (OSError, ValueError, subprocess.CalledProcessError) as error:
|
||||
print(f"OpenSSL symbols: {error}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
@@ -10,8 +10,10 @@ import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from generate_openssl_symbols import verify_symbols
|
||||
|
||||
def verify(app, require_release=False):
|
||||
|
||||
def verify(app, require_release=False, dsym_dir=None):
|
||||
info = plistlib.loads((app / "Info.plist").read_bytes())
|
||||
binary = app / info["CFBundleExecutable"]
|
||||
subprocess.run(["xcrun", "lipo", str(binary), "-verify_arch", "arm64"], check=True)
|
||||
@@ -63,6 +65,14 @@ def verify(app, require_release=False):
|
||||
sdk_symbols = subprocess.check_output(["xcrun", "nm", "-gU", str(embedded_binary)], text=True)
|
||||
if re.search(r"\b_(?:SSL_new|OPENSSL_init_crypto)\b", sdk_symbols):
|
||||
raise ValueError("Unexpected dynamic OpenSSL implementation in resource framework")
|
||||
# Archive validation includes the exact files that Organizer uploads.
|
||||
if dsym_dir is None and app.parents[2].suffix == ".xcarchive":
|
||||
dsym_dir = app.parents[2] / "dSYMs"
|
||||
if dsym_dir is not None:
|
||||
verify_symbols(binary, dsym_dir / f"{app.name}.dSYM")
|
||||
if embedded_binary.exists():
|
||||
verify_symbols(embedded_binary, dsym_dir / "OpenSSL.framework.dSYM")
|
||||
print("Verified app and embedded OpenSSL dSYM UUIDs")
|
||||
linked = subprocess.check_output(["xcrun", "otool", "-L", str(binary)], text=True)
|
||||
if "OpenSSL.framework" in linked:
|
||||
raise ValueError("OpenSSL must be statically linked into the application")
|
||||
@@ -79,8 +89,9 @@ def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("app", type=Path)
|
||||
parser.add_argument("--require-release", action="store_true")
|
||||
parser.add_argument("--dsym-dir", type=Path)
|
||||
args = parser.parse_args()
|
||||
verify(args.app, args.require_release)
|
||||
verify(args.app.resolve(), args.require_release, args.dsym_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user