diff --git a/src/hir2mpl/common/src/hir2mpl.cpp b/src/hir2mpl/common/src/hir2mpl.cpp index acf5efe541402d5a8d34df6a9eec2f79a618ea07..b7b2febb18e4afcb4fc061560e5563ae9dd15600 100644 --- a/src/hir2mpl/common/src/hir2mpl.cpp +++ b/src/hir2mpl/common/src/hir2mpl.cpp @@ -12,11 +12,14 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -#include "hir2mpl_compiler.h" #include "fe_utils.h" +#include "hir2mpl_compiler.h" +#include "mpl_sighandler.h" using namespace maple; int main(int argc, char **argv) { + SigHandler::EnableAll(); + MPLTimer timer; timer.Start(); HIR2MPLOptions &options = HIR2MPLOptions::GetInstance(); diff --git a/src/mapleall/maple_be/mdgen/src/mdmain.cpp b/src/mapleall/maple_be/mdgen/src/mdmain.cpp index e94d9acdccf359f4f787b9d9a91dcae5ea1760b1..36e27efbf271bc62dbbdf8a9a8c0eedf38f8d715 100644 --- a/src/mapleall/maple_be/mdgen/src/mdmain.cpp +++ b/src/mapleall/maple_be/mdgen/src/mdmain.cpp @@ -13,8 +13,10 @@ * See the Mulan PSL v2 for more details. */ #include -#include "mdparser.h" + #include "mdgenerator.h" +#include "mdparser.h" +#include "mpl_sighandler.h" using namespace MDGen; namespace { @@ -69,6 +71,8 @@ bool GenSchedFiles(const std::string &fileName, const std::string &fileDir) { } int main(int argc, char **argv) { + SigHandler::EnableAll(); + constexpr int minimumArgNum = 2; if (argc <= minimumArgNum) { return PrintHelpAndExit(); diff --git a/src/mapleall/maple_driver/src/maple.cpp b/src/mapleall/maple_driver/src/maple.cpp index cbc13c00553b8a9beaa8128852e0259495fa3b8a..d969cfca7d52890952e69ad166dfaac1752535fb 100644 --- a/src/mapleall/maple_driver/src/maple.cpp +++ b/src/mapleall/maple_driver/src/maple.cpp @@ -15,10 +15,13 @@ #include "compiler_factory.h" #include "error_code.h" #include "mpl_options.h" +#include "mpl_sighandler.h" using namespace maple; int main(int argc, char **argv) { + SigHandler::EnableAll(); + MplOptions mplOptions; int ret = static_cast(mplOptions.Parse(argc, argv)); if (ret == kErrorNoError) { diff --git a/src/mapleall/maple_ir/src/driver.cpp b/src/mapleall/maple_ir/src/driver.cpp index 7f3cc64ba7c825236358339043c16465ddbca86b..6f0c33f4b3a7e2ae4c8e1e1b2fb18ad186c01331 100644 --- a/src/mapleall/maple_ir/src/driver.cpp +++ b/src/mapleall/maple_ir/src/driver.cpp @@ -13,14 +13,16 @@ * See the Mulan PSL v2 for more details. */ #include -#include #include -#include "mir_parser.h" +#include + #include "bin_mplt.h" -#include "opcode_info.h" -#include "mir_function.h" #include "constantfold.h" +#include "mir_function.h" +#include "mir_parser.h" #include "mir_type.h" +#include "mpl_sighandler.h" +#include "opcode_info.h" using namespace maple; @@ -29,6 +31,8 @@ std::unordered_set dumpFuncSet = {}; #if MIR_FEATURE_FULL int main(int argc, char **argv) { + SigHandler::EnableAll(); + constexpr int judgeNumber = 2; constexpr uint32 k2Argv = 2; constexpr uint32 k10Argv = 10; diff --git a/src/mapleall/maple_ir/src/mpl_dbg.cpp b/src/mapleall/maple_ir/src/mpl_dbg.cpp index abb0ee7abf55bd90d65a0e18496e5564a4d3b855..7676ba3600e6e972173215480a0b43493bcd7654 100644 --- a/src/mapleall/maple_ir/src/mpl_dbg.cpp +++ b/src/mapleall/maple_ir/src/mpl_dbg.cpp @@ -13,21 +13,25 @@ * See the MulanPSL - 2.0 for more details. */ -#include "mir_parser.h" -#include "debug_info.h" -#include "bin_mplt.h" -#include "opcode_info.h" #include +#include +#include + +#include "bin_mplt.h" +#include "debug_info.h" #include "mir_function.h" +#include "mir_parser.h" #include "mir_type.h" -#include -#include +#include "mpl_sighandler.h" +#include "opcode_info.h" using namespace maple; std::unordered_set dumpFuncSet = {}; int main(int argc, char **argv) { + SigHandler::EnableAll(); + if (argc < k2BitSize) { MIR_PRINTF("usage: mpldbg foo.mpl\n"); exit(1); diff --git a/src/mapleall/maple_util/BUILD.gn b/src/mapleall/maple_util/BUILD.gn index dbfadbaa0477514cc308d5260e529df2bfe3366d..2c824f7730c6654cff469e5273f1baa81b785509 100755 --- a/src/mapleall/maple_util/BUILD.gn +++ b/src/mapleall/maple_util/BUILD.gn @@ -29,6 +29,7 @@ src_libmplutil = [ "src/mpl_int_val.cpp", "src/mpl_profdata.cpp", "src/suffix_array.cpp", + "src/mpl_posix_sighandler.cpp" ] src_libcommandline = [ @@ -54,7 +55,7 @@ configs = [ "${MAPLEALL_ROOT}:mapleallcompilecfg" ] static_library("libmplutil") { sources = src_libmplutil include_dirs = include_libmplutil - libs = [ "pthread" ] + libs = [ "pthread", "dl" ] output_dir = "${root_out_dir}/lib/${HOST_ARCH}" } diff --git a/src/mapleall/maple_util/include/mpl_sighandler.h b/src/mapleall/maple_util/include/mpl_sighandler.h new file mode 100644 index 0000000000000000000000000000000000000000..b9f516ca6df2e8b21ad97c9bbec4670b7663c3e3 --- /dev/null +++ b/src/mapleall/maple_util/include/mpl_sighandler.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) [2022] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +#ifndef MAPLE_UTIL_INCLUDE_MPL_SIGHANDLER +#define MAPLE_UTIL_INCLUDE_MPL_SIGHANDLER + +#include +#include + +namespace maple { + +class SigHandler { + public: + SigHandler() = delete; + ~SigHandler(){}; + + /// @brief enable handlig all supported signals + static void EnableAll(); + /// @brief enable handlig signal "sig" + static void EnableSig(int sig); + + /// @brief disable handling all supported signals + static void DisableAll(); + /// @brief disable handling signal with num 'sig' + static void DisableSig(int sig); + + /// @brief this function will be called in case that programm received signal + static void Handler(int sig, siginfo_t *info, void *ucontext) noexcept; + + [[maybe_unused]] static void (*emptyFuncPtr)(int, siginfo_t *, void *) noexcept; + using FuncPtr = decltype(emptyFuncPtr); + + /// @brief set user-defined signal callback + /// 'callback' will be called at the end of handler function + static void SetCallback(int sig, FuncPtr callback); + + /// @brief set alarm timer + static void SetTimer(int seconds); + + /// @return true if signal is supported, otherwise -- false + static bool IsSupportedSig(int sig); + + private: + static void SetSigaction(int sig, FuncPtr callback); + static void SetDefaultSigaction(int sig); + + // map of user-defined callbacks + static std::map sig2callback; +}; +} // namespace maple + +#endif // MAPLE_UTIL_INCLUDE_MPL_SIGHANDLER diff --git a/src/mapleall/maple_util/src/mpl_posix_sighandler.cpp b/src/mapleall/maple_util/src/mpl_posix_sighandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5af39cf097d83f2eb1b8509bf807e9eb078fd74 --- /dev/null +++ b/src/mapleall/maple_util/src/mpl_posix_sighandler.cpp @@ -0,0 +1,366 @@ +/* + * Copyright (c) [2022] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +#include "mpl_sighandler.h" + +#ifdef __unix__ +#include +#include +#include +#endif + +#include +#include + +#include "mpl_logging.h" +#include "mpl_stacktrace.h" + +namespace maple { + +std::map SigHandler::sig2callback = +#ifdef __unix__ + {{SIGINT, nullptr}, {SIGINT, nullptr}, {SIGTERM, nullptr}, {SIGSEGV, nullptr}, + {SIGBUS, nullptr}, {SIGABRT, nullptr}, {SIGILL, nullptr}, {SIGFPE, nullptr}, + {SIGXFSZ, nullptr}, {SIGUSR1, nullptr}, {SIGUSR2, nullptr}, {SIGALRM, nullptr}}; +#else + {}; +#endif + +void SigHandler::EnableAll() { +#ifdef __unix__ + for (auto it = sig2callback.cbegin(); it != sig2callback.cend(); ++it) { + SetSigaction(it->first, Handler); + } +#else + LogInfo::MapleLogger(kLlWarn) << "Sighandler : signal handler isn't implemented for non-unix os" << std::endl; +#endif +} + +void SigHandler::EnableSig(int sig) { +#ifdef __unix__ + if (!IsSupportedSig(sig)) { + LogInfo::MapleLogger(kLlWarn) << "SigHandler::enable(...) : signum " << sig << " isn't supported" << std::endl; + return; + } + + SetSigaction(sig, Handler); +#else + LogInfo::MapleLogger(kLlWarn) << "Sighandler : signal handler isn't implemented for non-unix os" << std::endl; +#endif +} + +void SigHandler::DisableAll() { + for (auto it = sig2callback.cbegin(); it != sig2callback.cend(); ++it) { + SetDefaultSigaction(it->first); + } +} + +void SigHandler::DisableSig(int sig) { + if (!IsSupportedSig(sig)) { + return; + } + + SetDefaultSigaction(sig); +} + +void SigHandler::SetTimer(int seconds) { +#ifdef __unix__ + struct itimerval timeValue { + {seconds, 0}, { + seconds, 0 + } + }; + + if (setitimer(ITIMER_REAL, &timeValue, nullptr)) { + LogInfo::MapleLogger(kLlErr) << "setitimer failed with " << errno << std::endl; + exit(EXIT_FAILURE); + } +#endif +} + +void SigHandler::SetCallback(int sig, SigHandler::FuncPtr callback) { + if (!IsSupportedSig(sig)) { + LogInfo::MapleLogger(kLlWarn) << "SigHandler :" << sig << " isn't supported" << std::endl; + return; + } + + sig2callback[sig] = callback; +} + +bool SigHandler::IsSupportedSig(int sig) { + return sig2callback.count(sig) > 0; +} + +static std::string SEGVcodename(int code) { +#ifdef __unix__ + switch (code) { + case SEGV_MAPERR: + return "Address not mapped"; + case SEGV_ACCERR: + return "Invalid permissions"; + default: + return "unknown SEGV code"; + } +#else + return std::string(); +#endif +} + +static std::string BUScodename(int code) { +#ifdef __unux__ + switch (code) { + case BUS_ADRALN: + return "Invalid address alignment"; + case BUS_ADRERR: + return "Non-existent physical address"; + case BUS_OBJERR: + return "Object-specific hardware error"; + default: + return "unknown BUS code"; + } +#else + return std::string(); +#endif +} + +static std::string ILLcodename(int code) { +#ifdef __unix__ + switch (code) { + case ILL_ILLOPC: + return "Illegal opcode"; + case ILL_ILLOPN: + return "Illegal operand"; + case ILL_ILLADR: + return "Illegal addressing mode"; + case ILL_ILLTRP: + return "Illegal trap"; + case ILL_PRVOPC: + return "Privileged opcode"; + case ILL_PRVREG: + return "Privileged register"; + case ILL_COPROC: + return "Coprocessor error"; + case ILL_BADSTK: + return "Internal stack error"; + default: + return "unknown ILL code"; + } +#else + return std::string(); +#endif +} + +static std::string FPEcodename(int code) noexcept { +#ifdef __unix__ + switch (code) { + case FPE_INTDIV: + return "Integer divide-by-zero"; + case FPE_INTOVF: + return "Integer overflow"; + case FPE_FLTDIV: + return "Floating point divide-by-zero"; + case FPE_FLTOVF: + return "Floating point overflow"; + case FPE_FLTUND: + return "Floating point underflow"; + case FPE_FLTRES: + return "Floating point inexact result"; + case FPE_FLTINV: + return "Invalid floating point operation"; + case FPE_FLTSUB: + return "Subscript out of range"; + default: + return "unknown FPE code"; + } +#else + return std::string(); +#endif +} + +static std::string XFSZcodename(int code) { +#ifdef __unix__ + switch (code) { + case SEGV_MAPERR: + return "Address not mapped"; + case SEGV_ACCERR: + return "Invalid permissions"; + default: + return "unknown XFSZ code"; + } +#else + return std::string(); +#endif +} + +static bool NeedDumpFaultingAddr(int sig) { +#ifdef __unix__ + return (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGFPE || sig == SIGXFSZ); +#else + return false; +#endif +} + +static void DumpErrorMsg(int sig, int code) { +#ifdef __unix__ + LogInfo::MapleLogger(kLlErr) << "Program ends with "; + switch (sig) { + case SIGINT: + LogInfo::MapleLogger(kLlErr) << "interrupt"; + break; + case SIGTERM: + LogInfo::MapleLogger(kLlErr) << "terminate()"; + break; + case SIGSEGV: + LogInfo::MapleLogger(kLlErr) << "SEGV signal: " << SEGVcodename(code); + break; + case SIGBUS: + LogInfo::MapleLogger(kLlErr) << "BUS signal: " << BUScodename(code); + break; + case SIGABRT: + LogInfo::MapleLogger(kLlErr) << "abort()"; + break; + case SIGILL: + LogInfo::MapleLogger(kLlErr) << "ILL signal: " << ILLcodename(code); + break; + case SIGFPE: + LogInfo::MapleLogger(kLlErr) << "FPE signal: " << FPEcodename(code); + break; + case SIGXFSZ: + LogInfo::MapleLogger(kLlErr) << "XFSZ signal: " << XFSZcodename(code); + break; + case SIGUSR1: + case SIGUSR2: + LogInfo::MapleLogger(kLlErr) << "USR signal"; + break; + case SIGALRM: + LogInfo::MapleLogger(kLlErr) << "ALRM signal"; + break; + default: + LogInfo::MapleLogger(kLlErr) << "unknown signal"; + break; + } + + LogInfo::MapleLogger(kLlErr) << std::endl; +#endif +} + +static uintptr_t GetLinkAddr(uintptr_t addr) { +#ifdef __unix__ + Dl_info info; + void *extraInfo = nullptr; + int status = dladdr1(reinterpret_cast(addr), &info, &extraInfo, static_cast(RTLD_DL_LINKMAP)); + link_map *linkMap = static_cast(extraInfo); + + if (status != 1) { + return 0; + } + + return reinterpret_cast(linkMap->l_addr); +#else + return 0; +#endif +} + +static void InitAlternativeStack() { +#ifdef __unix__ + stack_t oldStack; + if (sigaltstack(nullptr, &oldStack) == -1) { + LogInfo::MapleLogger(kLlErr) << "sigaltstack failed with " << errno << std::endl; + exit(EXIT_FAILURE); + } + + if (oldStack.ss_sp) { + return; + } + + stack_t stack; + constexpr size_t stackSizeMultiplier = 4; + constexpr size_t stackSize = stackSizeMultiplier * SIGSTKSZ; + stack.ss_size = stackSize; + stack.ss_sp = std::malloc(stackSize); + if (stack.ss_sp == nullptr) { + LogInfo::MapleLogger(kLlErr) << "malloc failed with " << errno << std::endl; + exit(EXIT_FAILURE); + } + + stack.ss_flags = 0; + + if (sigaltstack(&stack, nullptr) == -1) { + LogInfo::MapleLogger(kLlErr) << "sigaltstack faled with " << errno << std::endl; + exit(EXIT_FAILURE); + } +#else + return; +#endif +} + +void SigHandler::SetSigaction(int sig, SigHandler::FuncPtr callback) { +#ifdef __unix__ + InitAlternativeStack(); + + struct sigaction sigact = {}; + sigact.sa_flags = SA_SIGINFO | SA_ONSTACK; + sigact.sa_sigaction = callback; + + if (sigaction(sig, &sigact, nullptr)) { + LogInfo::MapleLogger(kLlErr) << "sigacton failed with " << errno << std::endl; + exit(EXIT_FAILURE); + } +#else + return; +#endif +} + +void SigHandler::SetDefaultSigaction(int sig) { +#ifdef __unix__ + struct sigaction sigact = {}; + sigact.sa_handler = SIG_DFL; + if (sigaction(sig, &sigact, nullptr)) { + LogInfo::MapleLogger(kLlErr) << "sigacton failed with " << errno << std::endl; + exit(EXIT_FAILURE); + } +#else + return; +#endif +} + +void DumpFaultingAddr(uintptr_t addr) { + uintptr_t linkAddr = GetLinkAddr(addr); + LogInfo::MapleLogger(kLlErr) << "faulting address: "; + if (linkAddr) { + LogInfo::MapleLogger(kLlErr) << "0x" << std::hex << addr - linkAddr << " (0x" << std::hex << addr << ")" + << std::endl; + } else { + LogInfo::MapleLogger(kLlErr) << "0x" << std::hex << addr << std::endl; + } +} + +void SigHandler::Handler(int sig, siginfo_t *info, void *ucontext) noexcept { + DumpErrorMsg(sig, info->si_code); + + if (NeedDumpFaultingAddr(sig)) { + DumpFaultingAddr(reinterpret_cast(info->si_addr)); + } + + LogInfo::MapleLogger(kLlErr) << Stacktrace<>() << std::endl; + + if (FuncPtr callback = sig2callback.at(sig)) { + callback(sig, info, ucontext); + } + + exit(EXIT_FAILURE); +} + +} // namespace maple