// Copyright 2006-2008 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/base/logging.h" #include <cctype> #include <cstdarg> #include <cstdio> #include <cstdlib> #include "src/base/debug/stack_trace.h" #include "src/base/platform/platform.h" namespace v8 { namespace base { namespace { void DefaultDcheckHandler(const char* file, int line, const char* message); void (*g_print_stack_trace)() = nullptr; void (*g_dcheck_function)(const char*, int, const char*) = DefaultDcheckHandler; void PrettyPrintChar(std::ostream& os, int ch) { switch (ch) { #define CHAR_PRINT_CASE(ch) \ case ch: \ os << #ch; \ break; CHAR_PRINT_CASE('\0') CHAR_PRINT_CASE('\'') CHAR_PRINT_CASE('\\') CHAR_PRINT_CASE('\a') CHAR_PRINT_CASE('\b') CHAR_PRINT_CASE('\f') CHAR_PRINT_CASE('\n') CHAR_PRINT_CASE('\r') CHAR_PRINT_CASE('\t') CHAR_PRINT_CASE('\v') #undef CHAR_PRINT_CASE default: if (std::isprint(ch)) { os << '\'' << ch << '\''; } else { auto flags = os.flags(std::ios_base::hex); os << "\\x" << static_cast<unsigned int>(ch); os.flags(flags); } } } void DefaultDcheckHandler(const char* file, int line, const char* message) { V8_Fatal(file, line, "Debug check failed: %s.", message); } } // namespace void SetPrintStackTrace(void (*print_stack_trace)()) { g_print_stack_trace = print_stack_trace; } void SetDcheckFunction(void (*dcheck_function)(const char*, int, const char*)) { g_dcheck_function = dcheck_function ? dcheck_function : &DefaultDcheckHandler; } // Define specialization to pretty print characters (escaping non-printable // characters) and to print c strings as pointers instead of strings. #define DEFINE_PRINT_CHECK_OPERAND_CHAR(type) \ template <> \ void PrintCheckOperand<type>(std::ostream & os, type ch) { \ PrettyPrintChar(os, ch); \ } \ template <> \ void PrintCheckOperand<type*>(std::ostream & os, type * cstr) { \ os << static_cast<void*>(cstr); \ } \ template <> \ void PrintCheckOperand<const type*>(std::ostream & os, const type* cstr) { \ os << static_cast<const void*>(cstr); \ } DEFINE_PRINT_CHECK_OPERAND_CHAR(char) DEFINE_PRINT_CHECK_OPERAND_CHAR(signed char) DEFINE_PRINT_CHECK_OPERAND_CHAR(unsigned char) #undef DEFINE_PRINT_CHECK_OPERAND_CHAR // Explicit instantiations for commonly used comparisons. #define DEFINE_MAKE_CHECK_OP_STRING(type) \ template std::string* MakeCheckOpString<type, type>(type, type, \ char const*); \ template void PrintCheckOperand<type>(std::ostream&, type); DEFINE_MAKE_CHECK_OP_STRING(int) DEFINE_MAKE_CHECK_OP_STRING(long) // NOLINT(runtime/int) DEFINE_MAKE_CHECK_OP_STRING(long long) // NOLINT(runtime/int) DEFINE_MAKE_CHECK_OP_STRING(unsigned int) DEFINE_MAKE_CHECK_OP_STRING(unsigned long) // NOLINT(runtime/int) DEFINE_MAKE_CHECK_OP_STRING(unsigned long long) // NOLINT(runtime/int) DEFINE_MAKE_CHECK_OP_STRING(void const*) #undef DEFINE_MAKE_CHECK_OP_STRING // Explicit instantiations for floating point checks. #define DEFINE_CHECK_OP_IMPL(NAME) \ template std::string* Check##NAME##Impl<float, float>(float lhs, float rhs, \ char const* msg); \ template std::string* Check##NAME##Impl<double, double>( \ double lhs, double rhs, char const* msg); DEFINE_CHECK_OP_IMPL(EQ) DEFINE_CHECK_OP_IMPL(NE) DEFINE_CHECK_OP_IMPL(LE) DEFINE_CHECK_OP_IMPL(LT) DEFINE_CHECK_OP_IMPL(GE) DEFINE_CHECK_OP_IMPL(GT) #undef DEFINE_CHECK_OP_IMPL } // namespace base } // namespace v8 // Contains protection against recursive calls (faults while handling faults). void V8_Fatal(const char* file, int line, const char* format, ...) { fflush(stdout); fflush(stderr); v8::base::OS::PrintError("\n\n#\n# Fatal error in %s, line %d\n# ", file, line); va_list arguments; va_start(arguments, format); v8::base::OS::VPrintError(format, arguments); va_end(arguments); v8::base::OS::PrintError("\n#\n"); if (v8::base::g_print_stack_trace) v8::base::g_print_stack_trace(); fflush(stderr); v8::base::OS::Abort(); } void V8_Dcheck(const char* file, int line, const char* message) { v8::base::g_dcheck_function(file, line, message); }