web-dev-qa-db-fra.com

Débogage de la bibliothèque C ++ avec Android Studio

Je travaille sur un projet Android qui utilise une classe Java qui est un wrapper sur un C++ bibliothèque. La bibliothèque C++ est une bibliothèque interne à l'entreprise et nous avons accès à son code source, mais dans le projet Android, elle n'est liée que dynamiquement, elle n'est donc utilisée que sous la forme d'en-têtes (.h) et les objets partagés (. so). Ayant accès au code source de la bibliothèque, est-il possible de spécifier à Android Studio le chemin d'accès au code source pour que je puisse entrer dans la bibliothèque à l'aide du débogueur?

Le débogueur fonctionne, je peux entrer dans le Java_clory_engine_sdk_CloryNative_nativeInit, mais je voudrais également déboguer davantage la bibliothèque correspondant à Clory::Engine classe qui, comme je l'ai mentionné, est une bibliothèque interne à laquelle nous avons accès en code source.

c_clory

Par exemple, Clory::Engine::instance fait partie de la bibliothèque et je voudrais spécifier à Android Studio l'emplacement du CloryEngine.cpp fichier pour que je puisse entrer Clory::Engine::instance avec le débogueur, déboguant ainsi cette fonction membre statique.

J'utilise Android Studio 3.1.4.

Est-ce possible?

MODIFIER:

Le clory-sdk.gradle le fichier spécifie le CMakeLists.txt fichier qui configure la couche C++.

externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}

J'utilise donc une application interne qui utilise le Clory SDK. À l'intérieur de app.gradle fichier que j'utilise:

dependencies {
...
    compile project(':clory-sdk-core')
    compile project(':clory-sdk')
...
}

donc je ne pense pas que nous utilisons les aars pour les app.gradle projet. Les aar sont expédiés au client, mais nous utilisons app.gradle projet de tester nos petites fonctionnalités du SDK avant de le faire. La couche JNI est à l'intérieur clory-sdk-core projet.

EDIT 2:

Voici la CMakeLists.txt qui gère la couche JNI:

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_BUILD_TYPE Debug)

add_library(
    clory-lib
    SHARED
    # JNI layer and other helper classes for transferring data from Java to Qt/C++
    src/main/cpp/clory-lib.cpp
    src/main/cpp/JObjectHandler.cpp
    src/main/cpp/JObjectResolver.cpp
    src/main/cpp/JObjectCreator.cpp
    src/main/cpp/DataConverter.cpp
    src/main/cpp/JObjectHelper.cpp
    src/main/cpp/JEnvironmentManager.cpp
)

find_library(
    log-lib
    log
)

target_compile_options(clory-lib
    PUBLIC
        -std=c++11
)

# Hardcoded for now...will fix later...
set(_QT_ROOT_PATH /Users/jacob/Qt/5.8)

if(${Android_ABI} MATCHES ^armeabi-v7.*$)
    set(_QT_Arch Android_armv7)
elseif(${Android_ABI} MATCHES ^x86$)
    set(_QT_Arch Android_x86)
else()
    message(FATAL_ERROR "Unsupported Android architecture!!!")
endif()

set(CMAKE_FIND_ROOT_PATH ${_QT_ROOT_PATH}/${_QT_Arch})

find_package(Qt5 REQUIRED COMPONENTS
    Core
    CONFIG
)

target_include_directories(clory-lib
    PUBLIC
        ${CMAKE_CURRENT_LIST_DIR}/src/main/cpp
)

set(_CLORYSDK_LIB_PATH ${CMAKE_CURRENT_LIST_DIR}/src/main/jniLibs/${Android_ABI})

target_link_libraries(clory-lib
    ${log-lib}
    -L${_CLORYSDK_LIB_PATH}
    clorysdk
    Qt5::Core
)

La bibliothèque clorysdk est en fait notre bibliothèque interne dont je parlais, qui contient par exemple Clory::Engine::instance Je voudrais intervenir avec le débogueur. Il a été construit avec qmake et est construit en mode débogage (CONFIG+=debug a été ajouté dans l'appel qmake effectif).

EDIT 3:

Dans la session LLDB qui s'est ouverte après avoir atteint le Java_clory_engine_sdk_CloryNative_nativeInit point d'arrêt, j'ai obtenu ce qui suit:

(lldb) image lookup -vrn Clory::Engine::instance
2 matches found in /Users/jacob/.lldb/module_cache/remote-Android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so:
        Address: libclorysdk.so[0x0001bb32] (libclorysdk.so..text + 8250)
        Summary: libclorysdk.so`Clory::Engine::instance(Clory::Engine::Purpose)
         Module: file = "/Users/jacob/.lldb/module_cache/remote-Android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so", Arch = "arm"
         Symbol: id = {0x0000005e}, range = [0xcb41eb32-0xcb41ebc0), name="Clory::Engine::instance(Clory::Engine::Purpose)", mangled="_ZN4Clory2Engine8instanceENS0_7PurposeE"
        Address: libclorysdk.so[0x0001b82c] (libclorysdk.so..text + 7476)
        Summary: libclorysdk.so`Clory::Engine::instance(Clory::RuntimeConfiguration const&, Clory::Engine::Purpose)
         Module: file = "/Users/jacob/.lldb/module_cache/remote-Android/.cache/6EDE4F0A-0000-0000-0000-000000000000/libclorysdk.so", Arch = "arm"
         Symbol: id = {0x000000bd}, range = [0xcb41e82c-0xcb41e970), name="Clory::Engine::instance(Clory::RuntimeConfiguration const&, Clory::Engine::Purpose)", mangled="_ZN4Clory2Engine8instanceERKNS_20RuntimeConfigurationENS0_7PurposeE"

(lldb) settings show target.source-map
target.source-map (path-map) =

Tout d'abord, il n'y avait pas de section CompileUnit dans le résultat de la commande image lookup -vrn Clory::Engine::instance. Comment est-il possible de n'avoir aucune source-map définie (seconde lldb commande) si la commande libclorysdk.so a été construit en mode Débogage? Est-il possible de le définir explicitement pour que le débogueur y recherche les fichiers source de la bibliothèque?

EDIT 4:

Après avoir cherché plus, j'ai découvert que le processus de création de l'APK supprime en fait le *.so bibliothèques à partir de leurs symboles de débogage. libclorysdk.so construit en mode débogage a environ 10 Mo tandis que le libclorysdk.so fichier que j'ai extrait après désarchivage du *.apk le fichier ne fait que 350 Ko. Comme indiqué ici , exécutant greadelf --debug-dump=decodedline libclorysdk.so sur la version de débogage renvoie des références aux fichiers source, mais si la commande est exécutée sur le *.apk bibliothèque extraite, elle ne produit rien.

Existe-t-il un moyen d'empêcher Android Studio de supprimer le *.sos? J'ai essayé Comment éviter de supprimer les symboles de code natif pour Android mais je n'ai eu aucun effet, *.apk le fichier a la même taille qu'auparavant et le débogage des bibliothèques natives ne fonctionne toujours pas.

J'utilise Gradle 3.1.4.

EDIT 5:

La solution de décapage fonctionne, mais dans mon cas, il fallait un Clean & Build avant d'atteindre les points d'arrêt dans la bibliothèque. Déploiement de *.sos qui ne sont pas supprimés vous permet d'avoir des sessions de débogage et de pénétrer dans les bibliothèques natives.

Remarque:

Si les bibliothèques sont construites en utilisant le Qt for Android chaîne d'outils, le *.sos déployés sur $SHADOW_BUILD/Android-build sont également supprimés (où $SHADOW_BUILD est le répertoire de construction commençant généralement par build-*). Donc, pour déboguer ceux-ci, vous devez les copier de l'extérieur du Android-build répertoire où chaque *.so est généré.

23
Jacob Krieg

Les informations de débogage enregistrent l'emplacement des fichiers source lors de leur génération.

(lldb) image lookup -vrn Clory::Engine::instance

La ligne CompileUnit affiche le fichier source. Supposons qu'il indique:

"/BuildDirectory/Sources/Clory/CloryEngine.cpp"

Supposons que vous ayez la source sur votre machine ici:

"Users/me/Sources/Clory"

Vous pouvez donc dire à lldb: recherchez plutôt le fichier source enraciné dans/BuildDirectory/Sources/Clory dans Users/me/Sources/Clory.

(lldb) settings set target.source-map /BuildDirectory/Sources/Clory Users/me/Sources/Clory

Vous pouvez utiliser ces commandes dans la console lldb de Android Studio ou les placer dans un fichier .lldbinit pour une utilisation générale.

15
Peter

si aucun symbole de débogage n'est disponible, vous devrez peut-être créer la bibliothèque référencée en mode débogage.

soit avec -DCMAKE_BUILD_TYPE=DEBUG:

defaultConfig {
    externalNativeBuild {
        cmake {
            arguments "-DANDROID_TOOLCHAIN=gcc", "-DCMAKE_BUILD_TYPE=DEBUG"
            cppFlags "-std=c++14 -fexceptions -frtti"
        }
    }
}

externalNativeBuild {
    cmake {
        path file('src/main/cpp/CMakeLists.txt')
    }
}

ou ajoutez ceci au CMakeLists.txt de la bibliothèque:

set(CMAKE_BUILD_TYPE Debug)

voir la documentation CMake et Symbolicating with LLDB .

ailleurs ça explique (lldb) settings set target.source-map /buildbot/path /my/path:

Remappez les noms de chemin du fichier source pour la session de débogage. Si vos fichiers source ne se trouvent plus au même endroit que lorsque le programme a été construit --- peut-être que le programme a été construit sur un autre ordinateur - - vous devez indiquer au débogueur comment trouver les sources sur leur chemin de fichier local au lieu du chemin de fichier du système de génération.

il y a aussi (lldb) settings show target.source-map, pour voir ce qui est mappé. (lldb) set append target.source-map /buildbot/path /my/path semble plutôt approprié, afin de ne pas écraser les mappages existants.

9
Martin Zeitler