Skip to content

Commit

Permalink
Implement SIGSEGV, SIGABRT handler for easier debugging on android
Browse files Browse the repository at this point in the history
Signed-off-by: Seonghyun Kim <[email protected]>
  • Loading branch information
ksh8281 authored and clover2123 committed May 19, 2023
1 parent 9581488 commit eb1380e
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 7 deletions.
11 changes: 7 additions & 4 deletions build/android/escargot/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ SET (ESCARGOT_ARCH ${ANDROID_SYSROOT_ABI})
# STRING(TOLOWER ${CMAKE_BUILD_TYPE} ESCARGOT_MODE)
SET (ESCARGOT_MODE "release")
SET (ESCARGOT_THREADING ON)
SET (ESCARGOT_BUILD_64BIT_FORCE_LARGE ON)

if (ENABLE_SHELL)
ADD_DEFINITIONS(-DESCARGOT_ENABLE_TEST)
ADD_DEFINITIONS(-DESCARGOT_ENABLE_TEMPORAL)
SET (ESCARGOT_EXPORT_ALL ON)
endif ()
ADD_SUBDIRECTORY (${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../ escargot)

Expand All @@ -38,14 +39,16 @@ endif ()
TARGET_LINK_LIBRARIES (escargot-jni PRIVATE escargot ${LOG_LIBRARY})

if (ENABLE_SHELL)
SET(CMAKE_EXE_LINKER_FLAGS -Wl,-export-dynamic) # export symbol of Shell.cpp
ADD_COMPILE_OPTIONS(-DNDEBUG -g3)
ADD_LINK_OPTIONS(-static-libstdc++)
ADD_EXECUTABLE(escargot-shell ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/shell/Shell.cpp)
TARGET_INCLUDE_DIRECTORIES(escargot-shell PRIVATE ADD_SUBDIRECTORY
(${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../third_party/GCutil/)
(${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../third_party/GCutil/bdwgc/include)
(${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src))
TARGET_LINK_LIBRARIES (escargot-shell PRIVATE escargot ${LOG_LIBRARY})
ADD_DEFINITIONS(-DNDEBUG)

ADD_EXECUTABLE(test262-runner ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../tools/test/test262/test-data-runner.cpp)
TARGET_COMPILE_OPTIONS(test262-runner PRIVATE -std=c++11)
ADD_EXECUTABLE(test-data-runner ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../tools/test/test-data-runner/test-data-runner.cpp)
TARGET_COMPILE_OPTIONS(test-data-runner PRIVATE -std=c++11)
endif ()
4 changes: 4 additions & 0 deletions build/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ IF (ESCARGOT_THREADING)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_THREADING -DGC_THREAD_ISOLATE)
ENDIF()

IF (ESCARGOT_EXPORT_ALL)
SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -fvisibility=default)
ENDIF()

IF (ESCARGOT_TCO)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_TCO)
ENDIF()
Expand Down
112 changes: 109 additions & 3 deletions src/shell/Shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,98 @@
#if defined(ESCARGOT_ENABLE_TEST)
// these header & function below are used for Escargot internal development
// general client doesn't need this

#if defined(ANDROID)
#include <unwind.h>
#include <dlfcn.h>
#endif

#if !defined(__APPLE__)
#include <signal.h>
#include <execinfo.h>

void btSighandler(int sig, struct sigcontext ctx)
{
if (sig == SIGSEGV) {
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) \
|| defined(i386) || defined(__i386) || defined(__i386__) || defined(__IA32__) || defined(_M_IX86) || defined(__X86__) \
|| defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || defined(__386)
printf("Got signal %d, pid %d, faulty address is %p\n",
sig, (int)getpid(), (void*)ctx.cr2);
#elif defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) || defined(_M_ARMT) || defined(__arm) || defined(__arm) || defined(__aarch64__)
printf("Got signal %d, pid %d, faulty address is %p\n",
sig, (int)getpid(), (void*)ctx.fault_address);
#else
printf("Got signal %d, pid %d\n", sig, (int)getpid());
#endif
} else {
printf("Got signal %d, pid %d\n", sig, (int)getpid());
}

printf("[bt] Execution path:\n");
#if defined(ANDROID)
struct BacktraceContext {
int ignoreCount; // ignore signal handler
int currentDepth;
int maxDepth;
} backtraceContext = { 1, 0, 128 };

_Unwind_Backtrace([](struct _Unwind_Context* ctx, void* data) -> _Unwind_Reason_Code {
BacktraceContext* backtraceContext = (BacktraceContext*)data;
if (backtraceContext->ignoreCount < backtraceContext->currentDepth) {
void* pc = (void*)_Unwind_GetIP(ctx);

Dl_info dlInfo;
dladdr(pc, &dlInfo);

void* computedPc = (void*)((size_t)pc - (size_t)dlInfo.dli_fbase);

printf("[bt] #%d pc: %p - %s(%s)", backtraceContext->currentDepth, computedPc, dlInfo.dli_sname, dlInfo.dli_fname);
printf("\n");
}
if (backtraceContext->currentDepth++ < backtraceContext->maxDepth) {
return _URC_NO_REASON;
}
return _URC_END_OF_STACK;
},
&backtraceContext);
#else
void* trace[128];
char** messages = (char**)NULL;
int i, traceSize = 0;
traceSize = backtrace(trace, 128);

messages = backtrace_symbols(trace, traceSize);
/* skip first stack frame (points here) */
for (i = 1; i < traceSize; ++i) {
printf("[bt] #%d %s ", i, messages[i]);

char syscom[256];
std::string temp = messages[i];
auto moduleEnd = temp.find("(");
auto addrStart = temp.find("+");
auto addrEnd = temp.find(")");
if (moduleEnd != std::string::npos && addrStart != std::string::npos && addrEnd != std::string::npos) {
std::string modulePath = temp.substr(0, moduleEnd);
std::string addr = temp.substr(addrStart, addrEnd - addrStart);
sprintf(syscom, "addr2line %s -e %s", addr.c_str(),
modulePath.c_str());
system(syscom);
} else {
printf("\n");
}
}
#endif

fflush(stdout);
fflush(stderr);

// this is the trick: it will trigger the core dump
signal(sig, SIG_DFL);
kill(getpid(), sig);
}
#endif

#include <GCUtil.h>
void doFullGCWithoutSeeingStack()
{
Expand All @@ -59,7 +151,11 @@ void printEveryReachableGCObjects()
[](void* obj, size_t bytes, void* cd) {
size_t size;
int kind = GC_get_kind_and_size(obj, &size);
#if defined(NDEBUG)
void* ptr = obj;
#else
void* ptr = GC_USR_PTR_FROM_BASE(obj);
#endif
size_t* totalSize = (size_t*)cd;
*totalSize += size;
printf("@@@ kind %d pointer %p size %d\n", (int)kind, ptr, (int)size);
Expand Down Expand Up @@ -961,14 +1057,24 @@ int main(int argc, char* argv[])
setbuf(stderr, NULL);
#endif

#if defined(ESCARGOT_ENABLE_TEST) && !defined(__APPLE__)
struct sigaction sa;
sa.sa_handler = (void (*)(int))btSighandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;

sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGABRT, &sa, NULL);
#endif

#ifdef M_MMAP_THRESHOLD
mallopt(M_MMAP_THRESHOLD, 2048);
#endif
#ifdef M_MMAP_MAX
mallopt(M_MMAP_MAX, 1024 * 1024);
#endif

bool wait_before_exit = false;
bool waitBeforeExit = false;

ShellPlatform* platform = new ShellPlatform();
Globals::initialize(platform);
Expand Down Expand Up @@ -1024,7 +1130,7 @@ int main(int argc, char* argv[])
continue;
}
if (strcmp(argv[i], "--wait-before-exit") == 0) {
wait_before_exit = true;
waitBeforeExit = true;
continue;
}
} else { // `-option` case
Expand Down Expand Up @@ -1076,7 +1182,7 @@ int main(int argc, char* argv[])
printf("escargot version:%s, %s%s\n", Globals::version(), Globals::buildDate(), Globals::supportsThreading() ? "(supports threading)" : "");
}

if (wait_before_exit || context->isWaitBeforeExit()) {
if (waitBeforeExit || context->isWaitBeforeExit()) {
auto evalResult = Evaluator::execute(context, [](ExecutionStateRef* state, ScriptRef* script) -> ValueRef* {
return script->execute(state);
},
Expand Down

0 comments on commit eb1380e

Please sign in to comment.