Wie kann verhindert werden, dass die C-Funktion in der iOS-App beim Hochladen auf TestFlight entfernt wird?IOS

Programmierung für iOS
Anonymous
 Wie kann verhindert werden, dass die C-Funktion in der iOS-App beim Hochladen auf TestFlight entfernt wird?

Post by Anonymous »

  • Ich habe eine iOS-Bibliothek, die eine C-Funktion verfügbar macht. Diese Funktion ist mit Standardsichtbarkeit gekennzeichnet und wird über Attribut-Tags verwendet, um zu verhindern, dass der Compiler/Linker sie entfernt

    Code: Select all

    #ifdef __cplusplus
    #define DYLIB_EXPORT
    extern "C" __attribute__((visibility("default"))) __attribute__((used))
    #else
    #define DYLIB_EXPORT
    __attribute__((visibility("default"))) __attribute__((used))
    #endif
    
    DYLIB_EXPORT bool say_hello_world();
    

    Code: Select all

    #import "helper_functions.h"
    #import 
    
    bool say_hello_world() {
    NSLog(@"Hello WORLD 🟢!");
    return true;
    }
    
  • Aus einer dynamischen Bibliothek namens sdk möchte ich diese Funktion aufrufen. In diesem Beispiel handelt es sich um eine Rust-Bibliothek

    Code: Select all

    unsafe extern "C" {
    fn say_hello_world() -> bool;
    }
    
    #[unsafe(no_mangle)]
    extern "C" fn sdk_init() -> i32 {
    unsafe {
    say_hello_world();
    }
    return 0;
    }
    
  • Wenn die App von Xcode kompiliert und gestartet wird (entweder bei Debug-- oder Release--Schemata), dann funktioniert das, das folgende Snippet funktioniert und gibt die „Hallo Welt“-Nachricht aus:

    Code: Select all

     #import "Wrapper.h"
    #import "helper_functions.h"
    #import "sdk.h"
    
    @implementation Wrapper
    // This function is called on the main view controller mount
    + (int)initialize {
    NSBundle *frameworkBundle =
    [NSBundle bundleWithIdentifier:@"sdk"];
    if (![frameworkBundle isLoaded]) {
    BOOL success = [frameworkBundle load];
    if (!success) {
    return -1;
    }
    
    int status = sdk_init();
    return status;
    }
    
    return 0;
    }
    
    @end
    
  • Beim Archivieren und Hochladen auf TestFlight erfolgt jedoch ein zusätzlicher Stripping-Schritt, der die Funktion say_hello_world entfernt. Die dynamische Bibliothek stürzt dann mit einer Nullzeiger-Ausnahme ab:

    Code: Select all

    Thread 3 name:
    Thread 3 Crashed:
    0   ???                              0x0000000000000000 0x0 + 0
    1   sdk                              0x0000000105931ec0 0x105820000 + 1121984
    
Mindest reproduzierbares Beispiel
Abgesehen von den Snippets besteht die einzige Möglichkeit, das Beispiel zu reproduzieren, darin, mit einer vollständig kompilierbaren iOS-App eine gestrippte Binärdatei zu generieren, die auf dem Gerät ausgeführt wird. Daher habe ich den Code so weit wie möglich reduziert, um das Problem in diesem Repo zu reproduzieren:
https://github.com/ospfranco/dylib_crash
Archivieren Sie dann die App und exportieren Sie sie dann mit der Debugging-Option. Ziehen Sie es per Drag-and-Drop in ein verbundenes iPhone-Finder-Fenster, um es direkt auf dem Gerät zu installieren.
Zusätzliche Hinweise
  • In den Apple-Entwicklerforen gab es einige Diskussionen
  • Die Rust-Bibliothek wurde mit zusätzlichen Flags kompiliert, um zu verhindern, dass der Linker ausfällt, wenn die Funktion während der Kompilierung nicht vorhanden ist:

    Code: Select all

    println!("cargo:rustc-link-arg=-Wl,-U,_say_hello_world");
    
  • Ich weiß mit Sicherheit, dass dies ein Problem mit dem Entfernen von totem Code ist, denn wenn ich das Entfernen von totem Code in den Projekteinstellungen deaktiviere, wird überhaupt kein Code entfernt, was die Binärdatei aufbläht, aber der Absturz tritt nicht mehr auf. Dies geschieht jedoch nur beim Erstellen einer verteilbaren .ipa und nicht bei der direkten Ausführung von Xcode

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post