Android 및 iOS에서 LLDB로 Rust 프로그램 디버깅

여기에 이미지 설명 삽입

Rust에서 출력된 로그 정보는 println!()Xcode에서는 표시될 수 있지만 Android Studio에서는 표시되지 않습니다. 따라서 Android는 android_logger를 사용하여 로그 출력을 달성할 수 있습니다. 그러나 개발 단계에서만 로그를 인쇄하여 디버그하는 것만으로는 충분하지 않으며 디버그 모드도 필요합니다. 그래서 이 글의 내용과 함께.

LLDB(Low Level Debugger)는 차세대 경량 고성능 디버거이며 Xcode내부 및 내부의 Android Studio기본 디버거 입니다. Android 개발 학생에 비해 iOS 학생이 더 익숙합니다. Rust는 LLDB 기반 디버깅 툴체인을 제공하므로 이를 사용하여 Rust 프로그램을 디버깅할 수 있습니다.

준비

먼저 Rust 라이브러리 크로스 컴파일을 읽고 Android 및 iOS에서 사용하여 Rust 프로그램을 Android 또는 iOS에 통합하는 방법을 배우는 것이 좋습니다. 이 문서의 예제에서도 이 문서의 데모를 사용합니다.

Android든 iOS든 이 기사의 내용은 CodeLLDB디버깅을 위해 플러그인을 사용하므로 VS Code와 이 플러그인이 설치되어 있어야 합니다.

여기에 이미지 설명 삽입

기계적 인조 인간

구체적인 조작

Android 프로젝트에서 우리는 debug so 파일이 압축 및 최적화되지 않도록 구성해야 하며 debug에 의해 생성된 so 파일에 주의를 기울여야 합니다.

android {
    
    
	...

	packagingOptions{
    
    
    	doNotStrip "**/libxxx.so"
	}
}

1. lldb-server를 전화기에 푸시합니다.

adb push lldb-server /data/local/tmp/

장치가 이전에 JNI 코드를 디버깅한 적이 있으면 이 파일이 /data/local/tmp/디렉터리에 있으므로 이 단계를 무시해도 됩니다. 마찬가지로 이 파일이 없으면 새 Native C++ 프로젝트를 만들고 조정할 수 있습니다. 또는 ndk로 이동하여 파일을
사진 설명을 추가해주세요
찾으십시오 .lldb-server

find . -name lldb-server

사진 설명을 추가해주세요
예를 들어 내 휴대폰은 64비트이므로 aarch64다음을 선택합니다. 그런 다음 lldb-server전화로 푸시합니다.

2. 앱을 시작하고 pid를 얻습니다.

# 启动App
adb shell am start -a android.intent.action.MAIN -n <package-name>/.<activity-name>
# 获取pid
adb shell pidof <package-name>

3. lldb 서버 시작

adb shell /data/local/tmp/lldb-server p --server --listen "*:9876"

4. Rust 프로젝트 디버그 구성

launch.json구성은 다음과 같으며 기능은 대상 프로세스에 연결하는 것입니다.

{
    
    
    "version": "0.2.0",
    "configurations": [
        {
    
    
            "type": "lldb",
            "request": "attach",
            "name": "Android",
            "pid": "xxx",
            "initCommands": [
                "platform select remote-android",
                "platform connect connect://localhost:9876",
                "file target/aarch64-linux-android/debug/libxxx.so",
            ]
        }
    ]
}
  • pid이전 단계에서 얻은 대로 입력합니다.
  • target/aarch64-linux-android/debug/librust_demo.so디버그 바이너리 위치의 경우 Android 프로젝트와 동일한 파일을 유지합니다.

다른 부분은 수정할 수 없습니다. 그런 다음 디버그를 실행할 때 디버그할 디버그 지점을 중단할 수 있습니다.
사진 설명을 추가해주세요

질문

위의 내용은 실제로 루팅된 장치에만 적합합니다. 그렇지 않으면 attach xxx실행 시 권한이 없다는 메시지가 표시됩니다. 그래서 처음에는 에뮬레이터를 사용하고 루트 권한을 얻어 디버깅을 했습니다.

나중에 Android 기본 개발 사례인 Native Crash의 gdb 디버깅 부분을 분석하는 방법을 보고 해결책을 찾았습니다.

네이티브 디버깅을 위해 Android Studio의 lldb 디버거를 사용하면 다음과 같은 결과가 나타납니다.

사진 설명을 추가해주세요

위에서 볼 수 있듯이 Android Studio는 cat 출력 lldb-server과 run-as를 사용하여 수신할 애플리케이션의 권한으로 cat을 실행한 다음 lldb-server앱의 개인 데이터 디렉토리에 쓴 다음 chmod 700실행 권한을 높입니다. 그런 다음 동일한 방법을 사용하여 start_lldb_server.sh셸 스크립트를 앱 데이터 디렉터리로 보냅니다. 마지막으로 앱 권한으로 스크립트를 실행하여 lldb를 시작합니다.

사실 이 질문에 대해 신중하게 생각해 보십시오. 왜 루트 없이 디버깅할 수 있지만 우리는 그렇게 할 수 없습니까? 따라서 다음과 같은 숙제를 복사하는 것입니다.

adb shell "cat /data/local/tmp/lldb-server 
| run-as <package-name> sh -c 'cat > /data/data/<package-name>/lldb/bin/lldb-server 
&& chmod 700 /data/data/<package-name>/lldb/bin/lldb-server'"

# 启动lldb-server
adb shell run-as <package-name> ./lldb/bin/lldb-server p --server --listen "*:9876"

시작되면 Operation not permitted오류가 보고됩니다. 이 방법에서 구현되는 unix-abstract방법을 사용할 수 있습니다 .start_lldb_server.sh

adb shell run-as <package-name> ./lldb/bin/lldb-server p --server --listen unix-abstract:///<package-name>/debug.sock

해당 launch.jsonin은 platform connect connect://localhost:9876로 대체됩니다
platform connect unix-abstract-connect:///<package-name>/debug.sock.

물론 <package-name>/debug.sock원하는 대로 이름을 정의할 수 있습니다. 여기서는 충돌을 피하기 위해 제안된 형식일 뿐입니다.

최적화

네 번째 단계에서는 매번 pid를 수동으로 교체해야 하는데 이는 상당히 번거로운 작업입니다. 이것을 최적화하고 pid를 동적으로 얻을 수 있습니다.

tasks.json다음 내용으로 파일을 만듭니다 .

{
    
    
    "version": "2.0.0",
    "tasks": [
        {
    
    
            "label": "get pid",
            "type": "shell",
            "command": "adb shell pidof <package-name> | tr -d '\n' > ${workspaceRoot}/pid.txt"
        }
    ]
}

기능은 pid를 가져온 다음 pid.txt 파일에 쓰는 것입니다.

launch.json다음과 같이 수정합니다.

{
    
    
    "version": "0.2.0",
    "configurations": [
        {
    
    
            "type": "lldb",
            "request": "attach",
            "name": "Attach",
            "pid": "${input:pid}",
            "preLaunchTask": "get pid",
            "initCommands": [
                "platform select remote-android",
                "platform connect connect://localhost:9876",
                "file target/aarch64-linux-android/debug/libxxx.so",
            ]
        }
    ],
    "inputs": [
        {
    
    
            "id": "pid",
            "type": "command",
            "command": "extension.commandvariable.file.content",
            "args": {
    
    
                "fileName": "${workspaceFolder}/pid.txt"
            }
        }
    ]
}

런타임 시 pid.txt파일 내용을 pid로 읽습니다.

  • 여기에서 사용하려면 플러그인을 extension.commandvariable.file.content설치하려면 코드가 필요합니다 .Command Variable
  • 이 방법의 문제점은 파일의 pid를 먼저 읽고 먼저 실행한다는 것입니다 get pid. 따라서 올바른 pid를 얻으려면 두 번째로 실행해야 합니다. 하지만 앱이 종료되지 않는 한 pid는 변하지 않기 때문에 큰 문제는 아닙니다.

Android는 위의 방법을 통해 Rust 코드를 디버깅할 수 있지만 결국 as에서 직접 지원하는 편리함은 없습니다. 지금은 대화가 없는 것보다 낫습니다.

아이폰 OS

iOS는 전체적으로 Android보다 훨씬 간단하고 편리합니다.먼저 Android와 마찬가지로 디버그 정적 라이브러리 패키지(명령어)를 사용해야 합니다 cargo lipo. 그런 다음 에서 Frameworks,Libraries,and Embedded Content구성 Library Search Paths합니다 libxxx.a.
사진 설명을 추가해주세요
에뮬레이터를 사용하므로 x86_64-apple-ios여기에서 폴더를 선택합니다.

launch.json구성은 다음과 같습니다.

{
    
    
    "version": "0.2.0",
    "configurations": [
        {
    
    
            "type": "lldb",
            "request": "attach",
            "name": "iOS",
            "program": "RustDemo",
        },
    ]
}

RustDemo여기서는 이 데모의 이름인 앱 이름에 따라 연결됩니다 .

앱을 시작한 다음 잘 디버깅합니다.
사진 설명을 추가해주세요
매우 간단하지 않습니까?

참고

추천

출처blog.csdn.net/qq_17766199/article/details/129402080