bool FLinuxPlatformStackWalk::ProgramCounterToHumanReadableString( int32 CurrentCallDepth, uint64 ProgramCounter, ANSICHAR* HumanReadableString, SIZE_T HumanReadableStringSize, FGenericCrashContext* Context ) { if (HumanReadableString && HumanReadableStringSize > 0) { ANSICHAR TempArray[MAX_SPRINTF]; if (CurrentCallDepth < 0) { if (PLATFORM_64BITS) { FCStringAnsi::Sprintf(TempArray, "[Callstack] 0x%016llx ", ProgramCounter); } else { FCStringAnsi::Sprintf(TempArray, "[Callstack] 0x%08x ", (uint32) ProgramCounter); } LinuxStackWalkHelpers::AppendToString(HumanReadableString, HumanReadableStringSize, Context, TempArray); // won't be able to display names here } else { if (PLATFORM_64BITS) { FCStringAnsi::Sprintf(TempArray, "[Callstack] %02d 0x%016llx ", CurrentCallDepth, ProgramCounter); } else { FCStringAnsi::Sprintf(TempArray, "[Callstack] %02d 0x%08x ", CurrentCallDepth, (uint32) ProgramCounter); } LinuxStackWalkHelpers::AppendToString(HumanReadableString, HumanReadableStringSize, Context, TempArray); // Get filename. { const char * FunctionName = LinuxStackWalkHelpers::GetFunctionName(Context, CurrentCallDepth); if (FunctionName) { LinuxStackWalkHelpers::AppendToString(HumanReadableString, HumanReadableStringSize, Context, FunctionName); } // try to add source file and line number, too FLinuxCrashContext* LinuxContext = static_cast< FLinuxCrashContext* >( Context ); if (LinuxContext) { const char * SourceFilename = NULL; int LineNumber; if (LinuxContext->GetInfoForAddress(reinterpret_cast< void* >( ProgramCounter ), NULL, &SourceFilename, &LineNumber) && FunctionName != NULL) { FCStringAnsi::Sprintf(TempArray, " [%s, line %d]", SourceFilename, LineNumber); LinuxStackWalkHelpers::AppendToString(HumanReadableString, HumanReadableStringSize, Context, TempArray); FCStringAnsi::Sprintf(TempArray, " [%s:%d]", SourceFilename, LineNumber); // if we were able to find info for this line, it means it's in our code // append program name (strong assumption of monolithic build here!) FCStringAnsi::Strcat(LinuxContext->MinidumpCallstackInfo, ARRAY_COUNT( LinuxContext->MinidumpCallstackInfo ) - 1, TCHAR_TO_ANSI(*FApp::GetName())); FCStringAnsi::Strcat(LinuxContext->MinidumpCallstackInfo, ARRAY_COUNT( LinuxContext->MinidumpCallstackInfo ) - 1, "!"); LinuxStackWalkHelpers::AppendFunctionNameIfAny(*LinuxContext, FunctionName, ProgramCounter); FCStringAnsi::Strcat(LinuxContext->MinidumpCallstackInfo, ARRAY_COUNT( LinuxContext->MinidumpCallstackInfo ) - 1, TempArray); } else { // if we were NOT able to find info for this line, it means it's something else FCStringAnsi::Strcat(LinuxContext->MinidumpCallstackInfo, ARRAY_COUNT( LinuxContext->MinidumpCallstackInfo ) - 1, "Unknown!"); LinuxStackWalkHelpers::AppendFunctionNameIfAny(*LinuxContext, FunctionName, ProgramCounter); } FCStringAnsi::Strcat(LinuxContext->MinidumpCallstackInfo, ARRAY_COUNT( LinuxContext->MinidumpCallstackInfo ) - 1, "\r\n"); // this one always uses Windows line terminators } } } return true; } return true; }