/// \file BadBehaviorLibrary.cpp /// This file, when compiled into a library, crashes in a manner configured in /// the environment variables. // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include #include #include #include #include "llvm/ADT/StringRef.h" #include "revng/Support/Assert.h" // Ugly way to bypass the check-conventions check that enforces the usage of // revng_abort(). We specifically don't want to use it in this case. #define sneaky_abort abort int *SomeGlobalPointerNobodyWillInitialize; static void printAndFlush(llvm::StringRef String) { std::cout << String.str() << std::endl; std::cout.flush(); } static void doCrash() { const char *CEnv = std::getenv("REVNG_CRASH_SIGNAL"); if (CEnv == nullptr) { // But would this be a bug or a feature? revng_abort("$REVNG_CRASH_SIGNAL not set"); } std::string Env(CEnv); int Signal = std::stoi(Env); switch (Signal) { case SIGILL: printAndFlush("SIGILL via illegal instruction"); asm(".byte 0x0f, 0x0b"); break; case SIGABRT: printAndFlush("SIGABRT via abort"); sneaky_abort(); case SIGSEGV: printAndFlush("SIGSEGV via write to uninitialized pointer"); *SomeGlobalPointerNobodyWillInitialize = 69; break; default: std::cout << "Signal " << Signal << " via raise()" << std::endl; std::cout.flush(); std::raise(Signal); break; } revng_abort("This shouldn't be executed"); } class WillCrash { public: WillCrash() { doCrash(); } }; static WillCrash WillCrashInstance;