mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-09-28 16:54:51 +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 nativeEjectDisk(boolean driveA);
|
||||||
|
|
||||||
|
public native void nativePerformCrash(int crashType);
|
||||||
|
|
||||||
|
|
||||||
private void _setCustomExceptionHandler() {
|
private void _setCustomExceptionHandler() {
|
||||||
if (mSetUncaughtExceptionHandler) {
|
if (mSetUncaughtExceptionHandler) {
|
||||||
|
@ -15,11 +15,13 @@ import android.app.AlertDialog;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.deadc0de.apple2ix.basic.BuildConfig;
|
||||||
import org.deadc0de.apple2ix.basic.R;
|
import org.deadc0de.apple2ix.basic.R;
|
||||||
|
|
||||||
public class Apple2SettingsMenu extends Apple2AbstractMenu {
|
public class Apple2SettingsMenu extends Apple2AbstractMenu {
|
||||||
@ -290,6 +292,67 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu {
|
|||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
activity.registerAndShowDialog(dialog);
|
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;
|
public static final int size = SETTINGS.values().length;
|
||||||
|
@ -18,6 +18,16 @@
|
|||||||
<string name="color_bw">Black/white</string>
|
<string name="color_bw">Black/white</string>
|
||||||
<string name="color_color">Color</string>
|
<string name="color_color">Color</string>
|
||||||
<string name="color_interpolated">Interpolated 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="diskA">Drive 1</string>
|
||||||
<string name="diskB">Drive 2</string>
|
<string name="diskB">Drive 2</string>
|
||||||
<string name="disk_eject">Eject</string>
|
<string name="disk_eject">Eject</string>
|
||||||
|
@ -23,7 +23,7 @@ LOCAL_CPP_EXTENSION := .C
|
|||||||
LOCAL_CPPFLAGS := -std=gnu++11
|
LOCAL_CPPFLAGS := -std=gnu++11
|
||||||
|
|
||||||
LOCAL_MODULE := libapple2ix
|
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_ARM_MODE := arm
|
||||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) $(BREAKPAD_CFLAGS)
|
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) $(BREAKPAD_CFLAGS)
|
||||||
LOCAL_LDLIBS := $(APPLE2_BASE_LDLIBS)
|
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…
Reference in New Issue
Block a user