Code to test/exercise Android Breakpad crash handler

This commit is contained in:
Aaron Culliney 2015-09-19 13:15:13 -07:00
parent 79613b49fb
commit a6397b22d2
5 changed files with 169 additions and 1 deletions

View File

@ -106,6 +106,8 @@ public class Apple2Activity extends Activity {
public native void nativeEjectDisk(boolean driveA);
public native void nativePerformCrash(int crashType);
private void _setCustomExceptionHandler() {
if (mSetUncaughtExceptionHandler) {

View File

@ -15,11 +15,13 @@ import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import org.deadc0de.apple2ix.basic.BuildConfig;
import org.deadc0de.apple2ix.basic.R;
public class Apple2SettingsMenu extends Apple2AbstractMenu {
@ -290,6 +292,67 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu {
AlertDialog dialog = builder.create();
activity.registerAndShowDialog(dialog);
}
},
CRASH {
@Override
public final String getTitle(Apple2Activity activity) {
if (BuildConfig.DEBUG) {
// in debug mode we actually exercise the crash reporter ...
return activity.getResources().getString(R.string.crasher_title);
} else {
return activity.getResources().getString(R.string.crasher_send_title);
}
}
@Override
public final String getSummary(Apple2Activity activity) {
if (BuildConfig.DEBUG) {
return activity.getResources().getString(R.string.crasher_summary);
} else {
return activity.getResources().getString(R.string.crasher_send_summary);
}
}
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
if (BuildConfig.DEBUG) {
_alertDialogHandleSelection(activity, R.string.crasher, new String[]{
activity.getResources().getString(R.string.crash_java_npe),
activity.getResources().getString(R.string.crash_null),
activity.getResources().getString(R.string.crash_stackcall_overflow),
activity.getResources().getString(R.string.crash_stackbuf_overflow),
}, new IPreferenceLoadSave() {
@Override
public int intValue() {
return -1;
}
@Override
public void saveInt(int value) {
switch (value) {
case 0: {
final String[] str = new String[1];
str[0] = null;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "About to NPE : " + str[0].length());
}
});
}
break;
default:
activity.nativePerformCrash(value);
break;
}
}
});
} else {
// TODO FIXME : run local crash analysis and open Email Intent to send
}
}
};
public static final int size = SETTINGS.values().length;

View File

@ -18,6 +18,16 @@
<string name="color_bw">Black/white</string>
<string name="color_color">Color</string>
<string name="color_interpolated">Interpolated color</string>
<string name="crasher">Crasher</string>
<string name="crasher_title">Crash emulator</string>
<string name="crasher_summary">Test crash generation</string>
<string name="crasher_send">Send crash reports</string>
<string name="crasher_send_title">Send crash reports</string>
<string name="crasher_send_summary">Will email crash reports to developer (if any)</string>
<string name="crash_null">NULL-deref</string>
<string name="crash_java_npe">Java NPE</string>
<string name="crash_stackcall_overflow">stack call overflow</string>
<string name="crash_stackbuf_overflow">stack buffer overflow</string>
<string name="diskA">Drive 1</string>
<string name="diskB">Drive 2</string>
<string name="disk_eject">Eject</string>

View File

@ -23,7 +23,7 @@ LOCAL_CPP_EXTENSION := .C
LOCAL_CPPFLAGS := -std=gnu++11
LOCAL_MODULE := libapple2ix
LOCAL_SRC_FILES := $(APPLE2_SRC_PATH)/breakpad.C
LOCAL_SRC_FILES := $(APPLE2_SRC_PATH)/breakpad.C jnicrash.c
#LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) $(BREAKPAD_CFLAGS)
LOCAL_LDLIBS := $(APPLE2_BASE_LDLIBS)

93
Android/jni/jnicrash.c Normal file
View File

@ -0,0 +1,93 @@
/*
* Apple // emulator for *nix
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include "common.h"
// Keep these in sync with the Java side
enum {
CRASH_JAVA=0,
CRASH_NULL_DEREF,
CRASH_STACKCALL_OVERFLOW,
CRASH_STACKBUF_OVERFLOW,
// MOAR!
};
#include <jni.h>
static volatile int __attribute__((noinline)) _crash_null_deref(void) {
static volatile uintptr_t *ptr = NULL;
while ((ptr+1)) {
*ptr++ = 0xAA;
}
return (int)ptr[0];
}
static volatile int (*funPtr0)(void) = NULL;
static volatile int __attribute__((noinline)) _crash_stackcall_overflow(void) {
if (funPtr0) {
funPtr0();
funPtr0 = NULL;
} else {
funPtr0 = &_crash_stackcall_overflow;
funPtr0();
}
return getpid();
}
static volatile int (*funPtr1)(unsigned int) = NULL;
static volatile int __attribute__((noinline)) _crash_stackbuf_overflow0(unsigned int smashSize) {
volatile char buf[32];
memset((char *)buf, 0x55, smashSize);
return (int)&buf[0];
}
static volatile int __attribute__((noinline)) _crash_stackbuf_overflow(void) {
static volatile unsigned int smashSize = 0;
while (1) {
if (funPtr1) {
funPtr1(smashSize);
funPtr1 = NULL;
} else {
funPtr1 = &_crash_stackbuf_overflow0;
funPtr1(smashSize);
}
smashSize += 32;
if (!smashSize) {
break;
}
}
return getpid();
}
void Java_org_deadc0de_apple2ix_Apple2Activity_nativePerformCrash(JNIEnv *env, jobject obj, jint crashType) {
LOG("... performing crash of type : %d", crashType);
switch (crashType) {
case CRASH_NULL_DEREF:
_crash_null_deref();
break;
case CRASH_STACKCALL_OVERFLOW:
_crash_stackcall_overflow();
break;
case CRASH_STACKBUF_OVERFLOW:
_crash_stackbuf_overflow();
break;
default:
// unknown crasher, just abort ...
abort();
break;
}
}