mirror of
https://github.com/mauiaaron/apple2.git
synced 2025-01-10 06:31:13 +00:00
Code to test/exercise Android Breakpad crash handler
This commit is contained in:
parent
79613b49fb
commit
a6397b22d2
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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
93
Android/jni/jnicrash.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user