Merge remote-tracking branch 'origin/master' into 1.8

This commit is contained in:
Wojtek Figat
2023-11-20 11:16:07 +01:00
41 changed files with 779 additions and 540 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

View File

@@ -132,6 +132,7 @@ public:
static void* LoadLibrary(const Char* filename);
static void FreeLibrary(void* handle);
static void* GetProcAddress(void* handle, const char* symbol);
static Array<StackFrame, HeapAllocation> GetStackFrames(int32 skipCount = 0, int32 maxDepth = 60, void* context = nullptr);
};
#endif

View File

@@ -43,6 +43,7 @@
#include <dlfcn.h>
#if CRASH_LOG_ENABLE
#include <execinfo.h>
#include <cxxabi.h>
#endif
CPUInfo Cpu;
@@ -502,20 +503,42 @@ Array<ApplePlatform::StackFrame> ApplePlatform::GetStackFrames(int32 skipCount,
{
char** names = backtrace_symbols(callstack + skipCount, useCount);
result.Resize(useCount);
Array<StringAnsi> parts;
int32 len;
#define COPY_STR(str, dst) \
len = Math::Min<int32>(str.Length(), ARRAY_COUNT(frame.dst) - 1); \
Platform::MemoryCopy(frame.dst, str.Get(), len); \
frame.dst[len] = 0
for (int32 i = 0; i < useCount; i++)
{
char* name = names[i];
const StringAnsi name(names[i]);
StackFrame& frame = result[i];
frame.ProgramCounter = callstack[skipCount + i];
frame.ModuleName[0] = 0;
frame.FileName[0] = 0;
frame.LineNumber = 0;
int32 nameLen = Math::Min<int32>(StringUtils::Length(name), ARRAY_COUNT(frame.FunctionName) - 1);
Platform::MemoryCopy(frame.FunctionName, name, nameLen);
frame.FunctionName[nameLen] = 0;
// Decode name
parts.Clear();
name.Split(' ', parts);
if (parts.Count() == 6)
{
COPY_STR(parts[1], ModuleName);
const StringAnsiView toDemangle(parts[3]);
int status = 0;
char* demangled = __cxxabiv1::__cxa_demangle(*toDemangle, 0, 0, &status);
const StringAnsiView toCopy = demangled && status == 0 ? StringAnsiView(demangled) : StringAnsiView(toDemangle);
COPY_STR(toCopy, FunctionName);
if (demangled)
free(demangled);
}
else
{
COPY_STR(name, FunctionName);
}
}
free(names);
#undef COPY_STR
}
#endif
return result;

View File

@@ -633,14 +633,21 @@ String PlatformBase::GetStackTrace(int32 skipCount, int32 maxDepth, void* contex
for (const auto& frame : stackFrames)
{
StringAsUTF16<ARRAY_COUNT(StackFrame::FunctionName)> functionName(frame.FunctionName);
const StringView functionNameStr(functionName.Get());
if (StringUtils::Length(frame.FileName) != 0)
{
StringAsUTF16<ARRAY_COUNT(StackFrame::FileName)> fileName(frame.FileName);
result.AppendFormat(TEXT(" at {0}() in {1}:line {2}\n"), functionName.Get(), fileName.Get(), frame.LineNumber);
result.Append(TEXT(" at ")).Append(functionNameStr);
if (!functionNameStr.EndsWith(')'))
result.Append(TEXT("()"));
result.AppendFormat(TEXT("in {0}:line {1}\n"),fileName.Get(), frame.LineNumber);
}
else if (StringUtils::Length(frame.FunctionName) != 0)
{
result.AppendFormat(TEXT(" at {0}()\n"), functionName.Get());
result.Append(TEXT(" at ")).Append(functionNameStr);
if (!functionNameStr.EndsWith(')'))
result.Append(TEXT("()"));
result.Append('\n');
}
else
{

View File

@@ -50,6 +50,10 @@
#include <pwd.h>
#include <inttypes.h>
#include <dlfcn.h>
#if CRASH_LOG_ENABLE
#include <signal.h>
#include <execinfo.h>
#endif
CPUInfo UnixCpu;
int ClockSource;
@@ -1868,6 +1872,46 @@ void LinuxPlatform::GetUTCTime(int32& year, int32& month, int32& dayOfWeek, int3
millisecond = time.tv_usec / 1000;
}
#if !BUILD_RELEASE
bool LinuxPlatform::IsDebuggerPresent()
{
static int32 CachedState = -1;
if (CachedState == -1)
{
CachedState = 0;
// Reference: https://stackoverflow.com/questions/3596781/how-to-detect-if-the-current-process-is-being-run-by-gdb
char buf[4096];
const int status_fd = open("/proc/self/status", O_RDONLY);
if (status_fd == -1)
return false;
const ssize_t num_read = read(status_fd, buf, sizeof(buf) - 1);
close(status_fd);
if (num_read <= 0)
return false;
buf[num_read] = '\0';
constexpr char tracerPidString[] = "TracerPid:";
const auto tracer_pid_ptr = strstr(buf, tracerPidString);
if (!tracer_pid_ptr)
return false;
for (const char* characterPtr = tracer_pid_ptr + sizeof(tracerPidString) - 1; characterPtr <= buf + num_read; ++characterPtr)
{
if (StringUtils::IsWhitespace(*characterPtr))
continue;
else
{
if (StringUtils::IsDigit(*characterPtr) && *characterPtr != '0')
CachedState = 1;
return CachedState == 1;
}
}
}
return CachedState == 1;
}
#endif
bool LinuxPlatform::Init()
{
if (PlatformBase::Init())
@@ -2992,4 +3036,36 @@ void* LinuxPlatform::GetProcAddress(void* handle, const char* symbol)
return dlsym(handle, symbol);
}
Array<LinuxPlatform::StackFrame> LinuxPlatform::GetStackFrames(int32 skipCount, int32 maxDepth, void* context)
{
Array<StackFrame> result;
#if CRASH_LOG_ENABLE
void* callstack[120];
skipCount = Math::Min<int32>(skipCount, ARRAY_COUNT(callstack));
int32 maxCount = Math::Min<int32>(ARRAY_COUNT(callstack), skipCount + maxDepth);
int32 count = backtrace(callstack, maxCount);
int32 useCount = count - skipCount;
if (useCount > 0)
{
char** names = backtrace_symbols(callstack + skipCount, useCount);
result.Resize(useCount);
for (int32 i = 0; i < useCount; i++)
{
char* name = names[i];
StackFrame& frame = result[i];
frame.ProgramCounter = callstack[skipCount + i];
frame.ModuleName[0] = 0;
frame.FileName[0] = 0;
frame.LineNumber = 0;
int32 nameLen = Math::Min<int32>(StringUtils::Length(name), ARRAY_COUNT(frame.FunctionName) - 1);
Platform::MemoryCopy(frame.FunctionName, name, nameLen);
frame.FunctionName[nameLen] = 0;
}
free(names);
}
#endif
return result;
}
#endif

View File

@@ -114,6 +114,9 @@ public:
}
static void GetSystemTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& minute, int32& second, int32& millisecond);
static void GetUTCTime(int32& year, int32& month, int32& dayOfWeek, int32& day, int32& hour, int32& minute, int32& second, int32& millisecond);
#if !BUILD_RELEASE
static bool IsDebuggerPresent();
#endif
static bool Init();
static void BeforeRun();
static void Tick();
@@ -143,6 +146,7 @@ public:
static void* LoadLibrary(const Char* filename);
static void FreeLibrary(void* handle);
static void* GetProcAddress(void* handle, const char* symbol);
static Array<StackFrame, HeapAllocation> GetStackFrames(int32 skipCount = 0, int32 maxDepth = 60, void* context = nullptr);
};
#endif