Add GetStackFrames on Android

This commit is contained in:
Wojtek Figat
2023-11-19 11:07:40 +01:00
parent 31aafeb0d1
commit 389bf89e2a
2 changed files with 69 additions and 0 deletions

View File

@@ -51,6 +51,33 @@
#include <android/window.h>
#include <android/versioning.h>
#if CRASH_LOG_ENABLE
#include <unwind.h>
#include <cxxabi.h>
struct AndroidBacktraceState
{
void** Current;
void** End;
};
_Unwind_Reason_Code AndroidUnwindCallback(struct _Unwind_Context* context, void* arg)
{
AndroidBacktraceState* state = (AndroidBacktraceState*)arg;
uintptr_t pc = _Unwind_GetIP(context);
if (pc)
{
if (state->Current == state->End)
return _URC_END_OF_STACK;
else
*state->Current++ = reinterpret_cast<void*>(pc);
}
return _URC_NO_REASON;
}
#endif
struct AndroidKeyEventType
{
uint32_t KeyCode;
@@ -1066,4 +1093,45 @@ void* AndroidPlatform::GetProcAddress(void* handle, const char* symbol)
return dlsym(handle, symbol);
}
Array<AndroidPlatform::StackFrame> AndroidPlatform::GetStackFrames(int32 skipCount, int32 maxDepth, void* context)
{
Array<StackFrame> result;
#if CRASH_LOG_ENABLE
// Reference: https://stackoverflow.com/questions/8115192/android-ndk-getting-the-backtrace
void* callstack[120];
skipCount = Math::Min<int32>(skipCount, ARRAY_COUNT(callstack));
int32 maxCount = Math::Min<int32>(ARRAY_COUNT(callstack), skipCount + maxDepth);
AndroidBacktraceState state;
state.Current = callstack;
state.End = callstack + maxCount;
_Unwind_Backtrace(AndroidUnwindCallback, &state);
int32 count = (int32)(state.Current - callstack);
int32 useCount = count - skipCount;
if (useCount > 0)
{
result.Resize(useCount);
for (int32 i = 0; i < useCount; i++)
{
StackFrame& frame = result[i];
frame.ProgramCounter = callstack[skipCount + i];
frame.ModuleName[0] = 0;
frame.FileName[0] = 0;
frame.LineNumber = 0;
Dl_info info;
const char* symbol = "";
if (dladdr(frame.ProgramCounter, &info) && info.dli_sname)
symbol = info.dli_sname;
int status = 0;
char* demangled = __cxxabiv1::__cxa_demangle(symbol, 0, 0, &status);
int32 nameLen = Math::Min<int32>(StringUtils::Length(demangled), ARRAY_COUNT(frame.FunctionName) - 1);
Platform::MemoryCopy(frame.FunctionName, demangled, nameLen);
frame.FunctionName[nameLen] = 0;
if (demangled)
free(demangled);
}
}
#endif
return result;
}
#endif