Android Studio art_sigsegv_fault when debugging native methods that receive a jstring

Viewed 329

When I try debugging NDK code under Android Studio, if I set a breakpoint in a function that receives a jstring, I get an immediate art_sigsegv_fault.

I've made a very simple test app:

MainActivity.java:

package com.example.ndktestapp;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        testFoo(5);
        testBar("/tmp/");
    }

    static native void testFoo(int x);
    static native void testBar(String path);

    static {
        System.loadLibrary("TestLib");
    }
}

NDKTestApp.cpp:

#include <jni.h>
#include <android/log.h>

extern "C"
JNIEXPORT void JNICALL
Java_com_example_ndktestapp_MainActivity_testFoo(JNIEnv *env, jclass cls, jint x)
{
    __android_log_print(ANDROID_LOG_INFO, "NDKTest", "This is foo");
    __android_log_print(ANDROID_LOG_INFO, "NDKTest", "foo x = %d", x);
    __android_log_print(ANDROID_LOG_INFO, "NDKTest", "foo EXIT");
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_ndktestapp_MainActivity_testBar(JNIEnv *env, jclass cls, jstring tmpPath)
{
    __android_log_print(ANDROID_LOG_INFO, "NDKTest", "This is Bar");

    auto nativeChars = env->GetStringUTFChars(tmpPath, 0);

    __android_log_print(ANDROID_LOG_INFO, "NDKTest", "Bar path = %s", nativeChars);

    env->ReleaseStringUTFChars(tmpPath, nativeChars);

    __android_log_print(ANDROID_LOG_INFO, "NDKTest", "Bar EXIT");
}

To be clear: this app works perfectly if I just run it. The problem happens when I try to debug it.

The first function, testFoo(int) receives a jint and I can set a breakpoint and single step through it with no problem.

The second function, testBar(String), receives a jstring and crashes immediately when it hits my breakpoint:

art_sigsegv_fault 0x00000000e3785bf0
art::FaultManager::HandleFault(int, siginfo*, void*) 0x00000000e37861a4
art::art_fault_handler(int, siginfo*, void*) (.llvm.6299116872343706859) 0x00000000e3785ebb
art::SignalChain::Handler(int, siginfo*, void*) 0x000000005cef31ae
__restore_rt 0x00000000e5560bc0
art::Thread::DecodeJObject(_jobject*) const 0x00000000e3bb121a
<unknown> 0x00000000e595e06d
<unknown> 0x000000005cef1170
art_quick_generic_jni_trampoline 0x00000000e364b133
art_quick_invoke_static_stub 0x00000000e3644af3
art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x00000000e36d9393
art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*) 0x00000000e388f702
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000e3883a3f
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000e3656201
ExecuteSwitchImplAsm 0x00000000e364bde3
art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool, bool) (.llvm.16375758241455872412) 0x00000000e3878c82
art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*) 0x00000000e3882c20
bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x00000000e3883a21
void art::interpreter::ExecuteSwitchImplCpp<false, false>(art::interpreter::SwitchImplContext*) 0x00000000e3657e4f
ExecuteSwitchImplAsm 0x00000000e364bde3
...

A little experimenting shows that my testBar() function can call into another function that looks e.g. like this:

static void
notNdk(const char *str)
{
    __android_log_print(ANDROID_LOG_INFO, "NDKTest", "notNdk received %s", str);
}

and I can step through that, but as soon as it returns to testBar(), I get my sigsegv. So I suppose I do have a work-around.

0 Answers
Related