diff --git a/build.gradle b/build.gradle index 5ccc4621d..0bc03316c 100644 --- a/build.gradle +++ b/build.gradle @@ -393,6 +393,7 @@ subprojects { p -> // Sqlite Database // librariesLocation isn't used because it's too long for replacing paths in native libraries + // Allowing strings larger than the original string would require shifting the entire binary's contents transform(NativeTransformer) { before { relocate "org.sqlite", "dh_sqlite", { diff --git a/buildSrc/src/main/java/NativeRelocator.java b/buildSrc/src/main/java/NativeRelocator.java index 7823db358..eaa32152b 100644 --- a/buildSrc/src/main/java/NativeRelocator.java +++ b/buildSrc/src/main/java/NativeRelocator.java @@ -9,7 +9,12 @@ class NativeRelocator private static final Path rootDirectory = Path.of(System.getProperty("user.dir"), "relocate_natives"); private static final Path cacheRoot = rootDirectory.resolve("cache"); - + /** + * Initializes the NativeRelocator by preparing the environment if necessary. + * Executes the appropriate preparation script based on the OS. + * + * @throws Exception if the preparation script fails or an unsupported OS is detected. + */ NativeRelocator() throws Exception { if (rootDirectory.resolve(".venv").toFile().exists()) @@ -46,7 +51,12 @@ class NativeRelocator } } - + /** + * Reads and prints the output and error streams of a process asynchronously. + * + * @param process The process whose streams should be read. + * @return A CompletableFuture that completes once all output has been processed. + */ private static CompletableFuture readOutputStreams(Process process) { return CompletableFuture.runAsync(() -> { @@ -79,6 +89,14 @@ class NativeRelocator }); } + /** + * Replaces occurrences of a target string in a byte array, ensuring null termination. + * + * @param byteArray The byte array where replacements should occur. + * @param target The string to replace. + * @param replacement The replacement string (must not be longer than the target). + * @throws IllegalArgumentException if the replacement is longer than the target. + */ private void replaceInNullTerminatedStrings(byte[] byteArray, String target, String replacement) { if (target.length() < replacement.length()) @@ -117,6 +135,14 @@ class NativeRelocator } } + /** + * Runs an external script to fix a modified binary and returns the processed content. + * + * @param outputFilePath Path to store the processed binary. + * @param content The original binary content. + * @return The modified binary content. + * @throws Exception if the process execution fails. + */ public byte[] fixModifiedBinary(Path outputFilePath, byte[] content) throws Exception { ProcessBuilder processBuilder = new ProcessBuilder(); @@ -147,6 +173,15 @@ class NativeRelocator return Files.readAllBytes(outputFilePath); } + /** + * Processes a binary file, applying string replacements and fixing modifications. + * + * @param outputPath The output file path relative to the cache directory. + * @param content The binary content to process. + * @param replacements A map of string replacements to apply. + * @return The modified binary content. + * @throws Exception if processing fails. + */ public byte[] processBinary(String outputPath, byte[] content, Map replacements) throws Exception { Path outputFilePath = cacheRoot.resolve(outputPath); diff --git a/relocate_natives/fix_modified_binary.py b/relocate_natives/fix_modified_binary.py index 573581feb..daa2a9c31 100644 --- a/relocate_natives/fix_modified_binary.py +++ b/relocate_natives/fix_modified_binary.py @@ -4,23 +4,28 @@ import subprocess import download_codesign from pathlib import Path +# Parse the input binary & xit if binary is invalid output_path = sys.argv[1] binary = lief.parse(sys.stdin.buffer.read()) - if binary is None: exit(1) +# Remove signature from Mac binaries if isinstance(binary, lief.MachO.Binary): binary.remove_signature() +# Write the modified binary to the output path binary.write(output_path) +# Sign Mac binaries (required to make them usable because apple) if isinstance(binary, lief.MachO.Binary): print(f"Signing {output_path}...") + # Check if the Apple code-signing files are available, if not, download them if not Path("./apple-codesign/COPYING").exists(): download_codesign.download_and_unpack() + # Run the code-signing process sign_process = subprocess.Popen(["./apple-codesign/rcodesign", "sign", output_path], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) sign_process.wait()