17c804472Sopenharmony_ci/*
27c804472Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
37c804472Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
47c804472Sopenharmony_ci * you may not use this file except in compliance with the License.
57c804472Sopenharmony_ci * You may obtain a copy of the License at
67c804472Sopenharmony_ci *
77c804472Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
87c804472Sopenharmony_ci *
97c804472Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
107c804472Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
117c804472Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127c804472Sopenharmony_ci * See the License for the specific language governing permissions and
137c804472Sopenharmony_ci * limitations under the License.
147c804472Sopenharmony_ci */
157c804472Sopenharmony_ci
167c804472Sopenharmony_ci#include "CrashHandler.h"
177c804472Sopenharmony_ci
187c804472Sopenharmony_ci#include <cstdlib>
197c804472Sopenharmony_ci#include <dbghelp.h>
207c804472Sopenharmony_ci#include <iostream>
217c804472Sopenharmony_ci#include <sstream>
227c804472Sopenharmony_ci#include <unistd.h>
237c804472Sopenharmony_ci#include <windows.h>
247c804472Sopenharmony_ci
257c804472Sopenharmony_ci#include "PreviewerEngineLog.h"
267c804472Sopenharmony_ci#include "PublicMethods.h"
277c804472Sopenharmony_ci
287c804472Sopenharmony_cistatic const int MAX_ADDRESS_LENGTH = 32;
297c804472Sopenharmony_ci
307c804472Sopenharmony_cistruct CrashInfo {
317c804472Sopenharmony_ci    CHAR ErrorCode[MAX_ADDRESS_LENGTH];
327c804472Sopenharmony_ci    CHAR Address[MAX_ADDRESS_LENGTH];
337c804472Sopenharmony_ci    CHAR Flags[MAX_ADDRESS_LENGTH];
347c804472Sopenharmony_ci};
357c804472Sopenharmony_ci
367c804472Sopenharmony_civoid CrashHandler::RecordCallStack(const CONTEXT *context)
377c804472Sopenharmony_ci{
387c804472Sopenharmony_ci    HANDLE hProcess = GetCurrentProcess();
397c804472Sopenharmony_ci    SymInitialize(hProcess, NULL, TRUE);
407c804472Sopenharmony_ci
417c804472Sopenharmony_ci    CONTEXT crashContext = *context;
427c804472Sopenharmony_ci
437c804472Sopenharmony_ci    STACKFRAME64 sf = {};
447c804472Sopenharmony_ci    DWORD imageType = IMAGE_FILE_MACHINE_I386;
457c804472Sopenharmony_ci
467c804472Sopenharmony_ci#ifdef _M_X64
477c804472Sopenharmony_ci    imageType = IMAGE_FILE_MACHINE_AMD64;
487c804472Sopenharmony_ci    sf.AddrPC.Offset = crashContext.Rip;
497c804472Sopenharmony_ci    sf.AddrPC.Mode = AddrModeFlat;
507c804472Sopenharmony_ci    sf.AddrFrame.Offset = crashContext.Rsp;
517c804472Sopenharmony_ci    sf.AddrFrame.Mode = AddrModeFlat;
527c804472Sopenharmony_ci    sf.AddrStack.Offset = crashContext.Rsp;
537c804472Sopenharmony_ci    sf.AddrStack.Mode = AddrModeFlat;
547c804472Sopenharmony_ci#endif
557c804472Sopenharmony_ci
567c804472Sopenharmony_ci    HANDLE hThread = GetCurrentThread();
577c804472Sopenharmony_ci
587c804472Sopenharmony_ci    while (true) {
597c804472Sopenharmony_ci        if (!StackWalk64(imageType, hProcess, hThread, &sf, &crashContext, NULL,
607c804472Sopenharmony_ci                         SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
617c804472Sopenharmony_ci            break;
627c804472Sopenharmony_ci        }
637c804472Sopenharmony_ci        if (sf.AddrFrame.Offset == 0) {
647c804472Sopenharmony_ci            break;
657c804472Sopenharmony_ci        }
667c804472Sopenharmony_ci
677c804472Sopenharmony_ci        int8_t stackIntLog[PublicMethods::MAX_ITOA_BIT] = {0};
687c804472Sopenharmony_ci        unsigned int itoaLength = PublicMethods::Ulltoa(sf.AddrPC.Offset, stackIntLog);
697c804472Sopenharmony_ci        int8_t offsetLog[] = "\n[JsEngine Crash]sf.AddrPC.Offset : 0x";
707c804472Sopenharmony_ci        write(STDERR_FILENO, offsetLog, sizeof(offsetLog));
717c804472Sopenharmony_ci        write(STDERR_FILENO, stackIntLog, itoaLength);
727c804472Sopenharmony_ci    }
737c804472Sopenharmony_ci    SymCleanup(hProcess);
747c804472Sopenharmony_ci}
757c804472Sopenharmony_ci
767c804472Sopenharmony_ciLONG CrashHandler::ApplicationCrashHandler(EXCEPTION_POINTERS *exception)
777c804472Sopenharmony_ci{
787c804472Sopenharmony_ci    int8_t crashBeginLog[] = "[JsEngine Crash]Engine Crash Info Begin.\n";
797c804472Sopenharmony_ci    write(STDERR_FILENO, crashBeginLog, sizeof(crashBeginLog) - 1);
807c804472Sopenharmony_ci
817c804472Sopenharmony_ci    int8_t stackIntLog[PublicMethods::MAX_ITOA_BIT] = {0};
827c804472Sopenharmony_ci    // 16 means hexadecimal
837c804472Sopenharmony_ci    unsigned int itoaLength = PublicMethods::Ulltoa(reinterpret_cast<uintptr_t>
847c804472Sopenharmony_ci                                                    (exception->ExceptionRecord->ExceptionAddress), stackIntLog);
857c804472Sopenharmony_ci    int8_t ELOG[] = "[JsEngine Crash]Address: 0x";
867c804472Sopenharmony_ci    write(STDERR_FILENO, ELOG, sizeof(ELOG) - 1);
877c804472Sopenharmony_ci    write(STDERR_FILENO, stackIntLog, itoaLength);
887c804472Sopenharmony_ci    // 16 means hexadecimal
897c804472Sopenharmony_ci    itoaLength = PublicMethods::Ulltoa(exception->ExceptionRecord->ExceptionCode, stackIntLog);
907c804472Sopenharmony_ci    int8_t addressLog[] = "\n[JsEngine Crash]ErrorCode: 0x";
917c804472Sopenharmony_ci    write(STDERR_FILENO, addressLog, sizeof(addressLog) - 1);
927c804472Sopenharmony_ci    write(STDERR_FILENO, stackIntLog, itoaLength);
937c804472Sopenharmony_ci    // 16 means hexadecimal
947c804472Sopenharmony_ci    RecordCallStack(exception->ContextRecord);
957c804472Sopenharmony_ci
967c804472Sopenharmony_ci    int8_t crashEndLog[] = "\n[JsEngine Crash]Engine Crash Info End.\n";
977c804472Sopenharmony_ci    write(STDERR_FILENO, crashEndLog, sizeof(crashEndLog) - 1);
987c804472Sopenharmony_ci    return 0;
997c804472Sopenharmony_ci}
1007c804472Sopenharmony_ci
1017c804472Sopenharmony_civoid CrashHandler::InitExceptionHandler()
1027c804472Sopenharmony_ci{
1037c804472Sopenharmony_ci    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
1047c804472Sopenharmony_ci}
105