mirror of
https://github.com/mauiaaron/apple2.git
synced 2025-03-14 05:31:43 +00:00
Integrate Breakpad crash dumper and tools into Android build
- Includes Linux x86_64 binaries dump_syms and minidump_stackwalk - Includes adb_sanitize.c tool (gcc -std=gnu11 -o adb_sanitize adb_sanitize.c) for easily pulling local minidumps
This commit is contained in:
parent
a2d62a77b6
commit
b8921b8441
@ -1,2 +1,3 @@
|
||||
APP_ABI := armeabi armeabi-v7a ## TODO : x86
|
||||
APP_PLATFORM := android-23
|
||||
APP_STL := gnustl_static
|
||||
|
@ -7,13 +7,25 @@ PACKAGE_NAME := "apple2ix"
|
||||
COMMON_SOURCES_MK := $(LOCAL_PATH)/sources.mk
|
||||
include $(COMMON_SOURCES_MK)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Breakpad crash reporter ...
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := breakpad_client
|
||||
|
||||
# hmmm, Breakpad's README.ANDROID seems to suggest you shouldn't need to do this kludgery ...
|
||||
BREAKPAD_SRC_PATH := $(APPLE2_SRC_PATH)/../externals/breakpad/src
|
||||
BREAKPAD_CFLAGS := -I$(BREAKPAD_SRC_PATH) -I$(APPLE2_SRC_PATH)/common/android/include
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Android build config
|
||||
|
||||
LOCAL_CPP_EXTENSION := .C
|
||||
LOCAL_CPPFLAGS := -std=gnu++11
|
||||
|
||||
LOCAL_MODULE := libapple2ix
|
||||
LOCAL_SRC_FILES :=
|
||||
LOCAL_SRC_FILES := $(APPLE2_SRC_PATH)/breakpad.C
|
||||
#LOCAL_ARM_MODE := arm
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS)
|
||||
LOCAL_CFLAGS := $(APPLE2_BASE_CFLAGS) $(BREAKPAD_CFLAGS)
|
||||
LOCAL_LDLIBS := $(APPLE2_BASE_LDLIBS)
|
||||
|
||||
# Add assembly files first ... mostly for the benefit of the ARM assembler ...
|
||||
@ -31,4 +43,5 @@ include $(BUILD_SHARED_LIBRARY)
|
||||
# --OR-- Build an executable so native can drive this show
|
||||
#include $(BUILD_EXECUTABLE)
|
||||
|
||||
$(call import-module, breakpad/android/google_breakpad)
|
||||
$(call import-module, android/cpufeatures)
|
||||
|
1
Android/jni/breakpad
Symbolic link
1
Android/jni/breakpad
Symbolic link
@ -0,0 +1 @@
|
||||
../../externals/breakpad
|
1
Android/jni/breakpad.mk
Symbolic link
1
Android/jni/breakpad.mk
Symbolic link
@ -0,0 +1 @@
|
||||
breakpad/android/google_breakpad/Android.mk
|
@ -106,9 +106,9 @@ fi
|
||||
|
||||
# build native sources
|
||||
if test "x$do_release" = "x1" ; then
|
||||
ndk-build V=1 # NDK_TOOLCHAIN_VERSION=clang
|
||||
ndk-build V=1 NDK_MODULE_PATH=. # NDK_TOOLCHAIN_VERSION=clang
|
||||
else
|
||||
ndk-build V=1 NDK_DEBUG=1 # NDK_TOOLCHAIN_VERSION=clang
|
||||
ndk-build V=1 NDK_MODULE_PATH=. NDK_DEBUG=1 # NDK_TOOLCHAIN_VERSION=clang
|
||||
fi
|
||||
ret=$?
|
||||
if test "x$ret" != "x0" ; then
|
||||
|
@ -94,6 +94,14 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobje
|
||||
return;
|
||||
}
|
||||
|
||||
data_dir = strdup(dataDir);
|
||||
if (initializeCrashHandler) {
|
||||
initializeCrashHandler(data_dir);
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, j_dataDir, dataDir);
|
||||
LOG("data_dir : %s", data_dir);
|
||||
|
||||
AndroidCpuFamily family = android_getCpuFamily();
|
||||
uint64_t features = android_getCpuFeatures();
|
||||
if (family == ANDROID_CPU_FAMILY_X86) {
|
||||
@ -123,10 +131,6 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobje
|
||||
}
|
||||
}
|
||||
|
||||
data_dir = strdup(dataDir);
|
||||
(*env)->ReleaseStringUTFChars(env, j_dataDir, dataDir);
|
||||
LOG("data_dir : %s", data_dir);
|
||||
|
||||
android_deviceSampleRateHz = (unsigned long)sampleRate;
|
||||
android_monoBufferSubmitSizeSamples = (unsigned long)monoBufferSize;
|
||||
android_stereoBufferSubmitSizeSamples = (unsigned long)stereoBufferSize;
|
||||
@ -142,7 +146,7 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobje
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeGraphicsChanged(JNIEnv *env, jobject obj, jint width, jint height) {
|
||||
LOG("%s", "");
|
||||
LOG("...");
|
||||
video_backend->reshape(width, height);
|
||||
}
|
||||
|
||||
@ -158,7 +162,7 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnResume(JNIEnv *env, jobje
|
||||
if (!cpu_isPaused()) {
|
||||
return;
|
||||
}
|
||||
LOG("%s", "");
|
||||
LOG("...");
|
||||
if (!isSystemResume) {
|
||||
#if TESTING
|
||||
// test driver thread is managing CPU
|
||||
@ -175,7 +179,7 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnPause(JNIEnv *env, jobjec
|
||||
if (cpu_isPaused()) {
|
||||
return;
|
||||
}
|
||||
LOG("%s", "");
|
||||
LOG("...");
|
||||
|
||||
#if TESTING
|
||||
// test driver thread is managing CPU
|
||||
@ -210,7 +214,7 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeRender(JNIEnv *env, jobject
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeReboot(JNIEnv *env, jobject obj) {
|
||||
LOG("%s", "");
|
||||
LOG("...");
|
||||
cpu65_reboot();
|
||||
}
|
||||
|
||||
@ -220,7 +224,7 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnQuit(JNIEnv *env, jobject
|
||||
#else
|
||||
shuttingDown = true;
|
||||
|
||||
LOG("%s", "");
|
||||
LOG("...");
|
||||
|
||||
c_eject_6(0);
|
||||
c_eject_6(1);
|
||||
@ -327,7 +331,7 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeChooseDisk(JNIEnv *env, job
|
||||
}
|
||||
|
||||
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeEjectDisk(JNIEnv *env, jobject obj, jboolean driveA) {
|
||||
LOG("%s", "");
|
||||
LOG("...");
|
||||
c_eject_6(!driveA);
|
||||
}
|
||||
|
||||
|
0
Android/symbols/armeabi-v7a/.blank
Normal file
0
Android/symbols/armeabi-v7a/.blank
Normal file
0
Android/symbols/armeabi/.blank
Normal file
0
Android/symbols/armeabi/.blank
Normal file
0
Android/symbols/libapple2ix.so/.blank
Normal file
0
Android/symbols/libapple2ix.so/.blank
Normal file
107
Android/toolchain_edits/adb_sanitize.c
Normal file
107
Android/toolchain_edits/adb_sanitize.c
Normal file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// Sigh ... adb shell changes LF to CRLF in binary streams ...
|
||||
//
|
||||
// http://stackoverflow.com/questions/13578416/read-binary-stdout-data-from-adb-shell
|
||||
//
|
||||
// Problem:
|
||||
// ( adb shell run-as com.example.someapp dd if=/data/data/com.example.someapp/some_binfile.bin 2\>/dev/null ) > local_binfile.bin
|
||||
//
|
||||
// * Without piping through adb_sanitize you would get a corrupted binary
|
||||
//
|
||||
// Fix:
|
||||
// ( adb shell run-as com.example.someapp dd if=/data/data/com.example.someapp/some_binfile.bin 2\>/dev/null ) | adb_sanitize > local_binfile.bin
|
||||
//
|
||||
// Addenda:
|
||||
// * The only other way to pull stuff from /data/data/... appears to be to use the heavyweight 'adb backup', yuck
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
// cribbed from AOSP and modified with usleep() and to also ignore EAGAIN
|
||||
#undef TEMP_FAILURE_RETRY
|
||||
#define TEMP_FAILURE_RETRY(exp) ({ \
|
||||
typeof (exp) _rc; \
|
||||
do { \
|
||||
_rc = (exp); \
|
||||
if (_rc == -1 && (errno == EINTR || errno == EAGAIN) ) { \
|
||||
usleep(10); \
|
||||
} else { \
|
||||
break; \
|
||||
} \
|
||||
} while (1); \
|
||||
_rc; })
|
||||
|
||||
static int _convert_crlf_to_lf(void) {
|
||||
|
||||
const char CR = 0x0d;
|
||||
const char LF = 0x0a;
|
||||
|
||||
ssize_t inlen = 0;
|
||||
char inbuf[BUFSIZ];
|
||||
char outbuf[BUFSIZ];
|
||||
bool sawCR = false;
|
||||
char *errRd = NULL;
|
||||
char *errWrt = NULL;
|
||||
|
||||
while ( (inlen = TEMP_FAILURE_RETRY(read(STDIN_FILENO, inbuf, BUFSIZ))) ) {
|
||||
if (inlen == -1) {
|
||||
errRd = "error reading from stdin";
|
||||
break;
|
||||
}
|
||||
|
||||
// convert CRLF -> LF
|
||||
|
||||
ssize_t outlen=0;
|
||||
for (ssize_t i=0; i<inlen; i++) {
|
||||
char c = inbuf[i];
|
||||
|
||||
if (sawCR && (c != LF)) {
|
||||
outbuf[outlen++] = CR;
|
||||
}
|
||||
|
||||
sawCR = false;
|
||||
if (c == CR) {
|
||||
sawCR = true;
|
||||
} else {
|
||||
outbuf[outlen++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY(write(STDOUT_FILENO, outbuf, outlen)) == -1) {
|
||||
errWrt = "error writing to stdout";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sawCR) {
|
||||
if (TEMP_FAILURE_RETRY(write(STDOUT_FILENO, &CR, 1)) == -1) {
|
||||
errWrt = "err writing to stdout";
|
||||
}
|
||||
}
|
||||
|
||||
if (errRd) {
|
||||
fprintf(stderr, "%s : %s", errRd, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (errWrt) {
|
||||
fprintf(stderr, "%s : %s", errWrt, strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
|
||||
TEMP_FAILURE_RETRY(fsync(STDOUT_FILENO));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
#if UNIT_TEST
|
||||
#error TODO FIXME ... should test edge cases CRLF split between buffered reads, and file/stream terminating 0D ([...0D][0A...] , [...0D])
|
||||
_run_unit_tests();
|
||||
#else
|
||||
return _convert_crlf_to_lf();
|
||||
#endif
|
||||
}
|
BIN
externals/bin/dump_syms
vendored
Executable file
BIN
externals/bin/dump_syms
vendored
Executable file
Binary file not shown.
BIN
externals/bin/minidump_stackwalk
vendored
Executable file
BIN
externals/bin/minidump_stackwalk
vendored
Executable file
Binary file not shown.
42
src/breakpad.C
Normal file
42
src/breakpad.C
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// Breakpad crash handling
|
||||
|
||||
#if !defined(__cplusplus)
|
||||
#error Breakpad requires C++
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
|
||||
static google_breakpad::ExceptionHandler *eh = nullptr;
|
||||
|
||||
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) {
|
||||
// WARNING : should only do minimal work from within a crashing context ...
|
||||
//LOG("Dump path: %s\n", descriptor.path());
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static void initializeBreakpadHandler(const char *dumpDir) {
|
||||
LOG("Initializing Breakpad with dump dir : %s", dumpDir);
|
||||
google_breakpad::MinidumpDescriptor descriptor(dumpDir);
|
||||
eh = new google_breakpad::ExceptionHandler(descriptor, NULL, dumpCallback, NULL, true, -1);
|
||||
}
|
||||
|
||||
__attribute__((constructor(CTOR_PRIORITY_EARLY)))
|
||||
static void _breakpad_registration(void) {
|
||||
LOG("Registering Breakpad as handler");
|
||||
initializeCrashHandler = &initializeBreakpadHandler;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ color_mode_t color_mode = COLOR;
|
||||
const char *data_dir = NULL;
|
||||
char **argv = NULL;
|
||||
int argc = 0;
|
||||
void (*initializeCrashHandler)(const char *dumpDir) = NULL;
|
||||
|
||||
__attribute__((constructor(CTOR_PRIORITY_FIRST)))
|
||||
static void _init_common() {
|
||||
|
@ -30,4 +30,7 @@ void emulator_start(void);
|
||||
// shutdown emulator in preparation for app exit
|
||||
void emulator_shutdown(void);
|
||||
|
||||
// crash handler initialization (if available)
|
||||
extern void (*initializeCrashHandler)(const char *dumpDir);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user