1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "CrashHandler.h" 17 18#include <cstdlib> 19#include <dbghelp.h> 20#include <iostream> 21#include <sstream> 22#include <unistd.h> 23#include <windows.h> 24 25#include "PreviewerEngineLog.h" 26#include "PublicMethods.h" 27 28static const int MAX_ADDRESS_LENGTH = 32; 29 30struct CrashInfo { 31 CHAR ErrorCode[MAX_ADDRESS_LENGTH]; 32 CHAR Address[MAX_ADDRESS_LENGTH]; 33 CHAR Flags[MAX_ADDRESS_LENGTH]; 34}; 35 36void CrashHandler::RecordCallStack(const CONTEXT *context) 37{ 38 HANDLE hProcess = GetCurrentProcess(); 39 SymInitialize(hProcess, NULL, TRUE); 40 41 CONTEXT crashContext = *context; 42 43 STACKFRAME64 sf = {}; 44 DWORD imageType = IMAGE_FILE_MACHINE_I386; 45 46#ifdef _M_X64 47 imageType = IMAGE_FILE_MACHINE_AMD64; 48 sf.AddrPC.Offset = crashContext.Rip; 49 sf.AddrPC.Mode = AddrModeFlat; 50 sf.AddrFrame.Offset = crashContext.Rsp; 51 sf.AddrFrame.Mode = AddrModeFlat; 52 sf.AddrStack.Offset = crashContext.Rsp; 53 sf.AddrStack.Mode = AddrModeFlat; 54#endif 55 56 HANDLE hThread = GetCurrentThread(); 57 58 while (true) { 59 if (!StackWalk64(imageType, hProcess, hThread, &sf, &crashContext, NULL, 60 SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { 61 break; 62 } 63 if (sf.AddrFrame.Offset == 0) { 64 break; 65 } 66 67 int8_t stackIntLog[PublicMethods::MAX_ITOA_BIT] = {0}; 68 unsigned int itoaLength = PublicMethods::Ulltoa(sf.AddrPC.Offset, stackIntLog); 69 int8_t offsetLog[] = "\n[JsEngine Crash]sf.AddrPC.Offset : 0x"; 70 write(STDERR_FILENO, offsetLog, sizeof(offsetLog)); 71 write(STDERR_FILENO, stackIntLog, itoaLength); 72 } 73 SymCleanup(hProcess); 74} 75 76LONG CrashHandler::ApplicationCrashHandler(EXCEPTION_POINTERS *exception) 77{ 78 int8_t crashBeginLog[] = "[JsEngine Crash]Engine Crash Info Begin.\n"; 79 write(STDERR_FILENO, crashBeginLog, sizeof(crashBeginLog) - 1); 80 81 int8_t stackIntLog[PublicMethods::MAX_ITOA_BIT] = {0}; 82 // 16 means hexadecimal 83 unsigned int itoaLength = PublicMethods::Ulltoa(reinterpret_cast<uintptr_t> 84 (exception->ExceptionRecord->ExceptionAddress), stackIntLog); 85 int8_t ELOG[] = "[JsEngine Crash]Address: 0x"; 86 write(STDERR_FILENO, ELOG, sizeof(ELOG) - 1); 87 write(STDERR_FILENO, stackIntLog, itoaLength); 88 // 16 means hexadecimal 89 itoaLength = PublicMethods::Ulltoa(exception->ExceptionRecord->ExceptionCode, stackIntLog); 90 int8_t addressLog[] = "\n[JsEngine Crash]ErrorCode: 0x"; 91 write(STDERR_FILENO, addressLog, sizeof(addressLog) - 1); 92 write(STDERR_FILENO, stackIntLog, itoaLength); 93 // 16 means hexadecimal 94 RecordCallStack(exception->ContextRecord); 95 96 int8_t crashEndLog[] = "\n[JsEngine Crash]Engine Crash Info End.\n"; 97 write(STDERR_FILENO, crashEndLog, sizeof(crashEndLog) - 1); 98 return 0; 99} 100 101void CrashHandler::InitExceptionHandler() 102{ 103 SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler); 104} 105