static SymbolInfo lookup(string var) { SymbolTable *s = symtable; while (s) { SymbolInfo res = lookup_single(var, s); if (res.s == SymbolInfo::OK) return res; s = s->next; } return SymbolInfo(); }
static SymbolInfo lookup_single(string var, SymbolTable *s) { if (s->table.find(var) != s->table.end()) return s->table[var]; return SymbolInfo(); }
// for unbound vars static void store(string name, string full_name, Expression::Type t) { if (symtable->table.find(name) != symtable->table.end()) throw string("Error: symbol '" + name + "' already in table!"); symtable->table[name] = SymbolInfo(full_name, t, symtable->num_args++); }
// for bound variables static void store(string name, string full_name, Expression *expr) { symtable->table[name] = SymbolInfo(full_name, expr); }
int FWindowsPlatformStackWalkExt::GetCallstacks() { const int32 MAX_NAME_LENGHT = FProgramCounterSymbolInfo::MAX_NAME_LENGHT; int32 NumValidFunctionNames = 0; FCrashExceptionInfo& Exception = CrashInfo.Exception; FMemMark Mark(FMemStack::Get()); //const float int int32 FString const int32 ContextSize = 4096; byte* Context = new(FMemStack::Get()) byte[ContextSize]; ULONG DebugEvent = 0; ULONG ProcessID = 0; ULONG ThreadID = 0; ULONG ContextUsed = 0; // Get the context of the crashed thread HRESULT hr = Control->GetStoredEventInformation(&DebugEvent, &ProcessID, &ThreadID, Context, ContextSize, &ContextUsed, NULL, 0, 0); if( FAILED(hr) ) { return NumValidFunctionNames; } // Some magic number checks if( ContextUsed == 716 ) { UE_LOG( LogCrashDebugHelper, Log, TEXT( "Context size matches x86 sizeof( CONTEXT )" ) ); } else if( ContextUsed == 1232 ) { UE_LOG( LogCrashDebugHelper, Log, TEXT( "Context size matches x64 sizeof( CONTEXT )" ) ); } // Get the entire stack trace const uint32 MaxFrames = 8192; const uint32 MaxFramesSize = MaxFrames * ContextUsed; DEBUG_STACK_FRAME* StackFrames = new(FMemStack::Get()) DEBUG_STACK_FRAME[MaxFrames]; ULONG Count = 0; bool bFoundSourceFile = false; void* ContextData = FMemStack::Get().PushBytes( MaxFramesSize, 0 ); FMemory::Memzero( ContextData, MaxFramesSize ); HRESULT HR = Control->GetContextStackTrace( Context, ContextUsed, StackFrames, MaxFrames, ContextData, MaxFramesSize, ContextUsed, &Count ); int32 AssertOrEnsureIndex = -1; for( uint32 StackIndex = 0; StackIndex < Count; StackIndex++ ) { const uint64 Offset = StackFrames[StackIndex].InstructionOffset; if( IsOffsetWithinModules( Offset ) ) { // Get the module, function, and offset uint64 Displacement = 0; TCHAR NameByOffset[MAX_PATH] = {0}; Symbol->GetNameByOffsetWide( Offset, NameByOffset, ARRAYSIZE( NameByOffset ) - 1, NULL, &Displacement ); FString ModuleAndFunction = NameByOffset; // Don't care about any more entries higher than this if (ModuleAndFunction.Contains( TEXT( "tmainCRTStartup" ) ) || ModuleAndFunction.Contains( TEXT( "FRunnableThreadWin::GuardedRun" ) )) { break; } // Look for source file name and line number TCHAR SourceName[MAX_PATH] = { 0 }; ULONG LineNumber = 0; Symbol->GetLineByOffsetWide( Offset, &LineNumber, SourceName, ARRAYSIZE( SourceName ) - 1, NULL, NULL ); // Remember the top of the stack to locate in the source file if( !bFoundSourceFile && FCString::Strlen( SourceName ) > 0 && LineNumber > 0 ) { CrashInfo.SourceFile = ExtractRelativePath( TEXT( "source" ), SourceName ); CrashInfo.SourceLineNumber = LineNumber; bFoundSourceFile = true; } FString ModuleName; FString FunctionName; // According to MSDN, the symbol name will include an ! if the function name could be discovered, delimiting it from the module name // https://msdn.microsoft.com/en-us/library/windows/hardware/ff547186(v=vs.85).aspx if( ModuleAndFunction.Contains( TEXT( "!" ) ) ) { NumValidFunctionNames++; ModuleAndFunction.Split( TEXT( "!" ), &ModuleName, &FunctionName ); FunctionName += TEXT( "()" ); } else { ModuleName = ModuleAndFunction; } // #YRX_Crash: 2015-07-24 Add for other platforms // If we find an assert, the actual source file we're interested in is the next one up, so reset the source file found flag if( FunctionName.Len() > 0 ) { if( FunctionName.Contains( TEXT( "FDebug::" ), ESearchCase::CaseSensitive ) || FunctionName.Contains( TEXT( "NewReportEnsure" ), ESearchCase::CaseSensitive ) ) { bFoundSourceFile = false; AssertOrEnsureIndex = FMath::Max( AssertOrEnsureIndex, (int32)StackIndex ); } } // FString InModuleName, FString InFunctionName, FString InFilename, uint32 InLineNumber, uint64 InSymbolDisplacement, uint64 InOffsetInModule, uint64 InProgramCounter FProgramCounterSymbolInfoEx SymbolInfo( ModuleName, FunctionName, SourceName, LineNumber, Displacement, Offset, 0 ); FString GenericFormattedCallstackLine; FGenericPlatformStackWalk::SymbolInfoToHumanReadableStringEx( SymbolInfo, GenericFormattedCallstackLine ); Exception.CallStackString.Add( GenericFormattedCallstackLine ); UE_LOG( LogCrashDebugHelper, Log, TEXT( "%3u: %s" ), StackIndex, *GenericFormattedCallstackLine ); } } // Remove callstack entries below FDebug, we don't need them. if (AssertOrEnsureIndex > 0) { Exception.CallStackString.RemoveAt( 0, AssertOrEnsureIndex ); UE_LOG( LogCrashDebugHelper, Warning, TEXT( "Callstack trimmed to %i entries" ), Exception.CallStackString.Num() ); } UE_LOG( LogCrashDebugHelper, Warning, TEXT( "Callstack generated with %i valid function names" ), NumValidFunctionNames ); return NumValidFunctionNames; }
JString* signature = NULL; if (vers > 63) { JBoolean hasSignature; input >> hasSignature; if (hasSignature) { signature = new JString; assert( signature != NULL ); input >> *signature; } } itsSymbolList->AppendElement( SymbolInfo(name, signature, (CBLanguage) lang, (Type) type, fullyQualifiedFileScope, fileID, lineIndex)); } itsSymbolList->SetBlockSize(kBlockSize); if (vers < 51) { itsSymbolList->SetCompareFunction(CompareSymbolsAndTypes); itsSymbolList->Sort(); itsSymbolList->SetCompareFunction(CompareSymbols); } Broadcast(Changed()); } /******************************************************************************