diff --git a/Makefile.am b/Makefile.am index f34b8c00..a2d9b994 100644 --- a/Makefile.am +++ b/Makefile.am @@ -327,6 +327,7 @@ UTIL_FILES = \ if PLATFORM_LINUX UTIL_FILES += \ backtrace_execinfo.cpp \ + debug_posix.cpp \ io_posix.cpp \ io_posix.hpp \ library_posix.hpp \ @@ -340,6 +341,7 @@ endif if PLATFORM_WIN32 UTIL_FILES += \ backtrace_null.cpp \ + debug_win32.cpp \ io_win32.cpp \ library_win32.hpp \ library_win32.cpp \ diff --git a/debug.cpp b/debug.cpp index 1bc93f99..91a01b72 100644 --- a/debug.cpp +++ b/debug.cpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2010 Danny Robson + * Copyright 2010-2016 Danny Robson */ #include "backtrace.hpp" @@ -36,27 +36,6 @@ detail::panic (const char *msg) //////////////////////////////////////////////////////////////////////////////// -#if defined(PLATFORM_WIN32) -#include -void -breakpoint (void) -{ - DebugBreak (); -} -#else -void -breakpoint (void) -{ -#if defined (__x86_64) || defined (__i386) - __asm__ ("int $3;"); -#else - raise (SIGINT); -#endif -} -#endif - - -//----------------------------------------------------------------------------- void detail::not_implemented (const char *msg) { @@ -96,102 +75,13 @@ warn (const char *msg) } -//////////////////////////////////////////////////////////////////////////////// -#if defined(PLATFORM_LINUX) -#include -void -enable_fpe (void) -{ - feenableexcept (FE_DIVBYZERO | FE_INVALID); -} - - -//----------------------------------------------------------------------------- -void -disable_fpe (void) -{ - feenableexcept (0); -} -#else -// contropfp is not defined supposedly due to a regression in GCC include behaviours. - - -//----------------------------------------------------------------------------- -void -enable_fpe (void) -{ - LOG_WARN ("Non-Linux exception code is broken under current GCC."); -// _clearfp(); -// unsigned int ignored; -// _controlfp_s (&ignored, _MCW_EM, _MCW_EM); -} - - -//----------------------------------------------------------------------------- -void -disable_fpe (void) -{ - LOG_WARN ("Non-Linux exception code is broken under current GCC."); -// _clearfp(); -// unsigned int ignored; -// _controlfp_s (&ignored, 0, _MCW_EM); -} -#endif - - -//////////////////////////////////////////////////////////////////////////////// -#if defined(PLATFORM_WIN32) -#include -#include - -void -force_console (void) -{ - if (!AttachConsole (ATTACH_PARENT_PROCESS)) - return; - - auto out_handle = GetStdHandle (STD_OUTPUT_HANDLE); - auto err_handle = GetStdHandle (STD_ERROR_HANDLE); - auto in_handle = GetStdHandle (STD_INPUT_HANDLE); - - auto out_fd = _open_osfhandle (reinterpret_cast (out_handle), _O_TEXT); - auto err_fd = _open_osfhandle (reinterpret_cast (err_handle), _O_TEXT); - auto in_fd = _open_osfhandle (reinterpret_cast (in_handle), _O_TEXT); - - auto out_file = _fdopen (out_fd, "w"); - auto err_file = _fdopen (err_fd, "w"); - auto in_file = _fdopen (in_fd, "r"); - - /// FILE objects are not reassignable, but Windows doesn't leave us much - /// choice here. - *stdout = *out_file; - *stderr = *err_file; - *stdin = *in_file; - - setvbuf (stdout, NULL, _IONBF, 0); - setvbuf (stderr, NULL, _IONBF, 0); - setvbuf (stdin, NULL, _IONBF, 0); - - ios::sync_with_stdio (); - - // Windows doesn't give an immediate newline when an application is run - // from a console, so we provide one here for sanity. - std::cout << "\n"; - std::cerr << "Console installed\n"; -} -#endif - - //////////////////////////////////////////////////////////////////////////////// void util::debug::init (void) { -#if defined(PLATFORM_WIN32) force_console (); + prepare_debugger (); - if (nullptr == LoadLibrary("exchndl.dll")) { - std::cerr << GetLastError () << "\n"; - LOG_WARNING("Emergency debugger not loaded"); - } -#endif + if (getenv ("DEBUG_WAIT")) + await_debugger (); } diff --git a/debug.hpp b/debug.hpp index 7a0f97e7..35fb06d4 100644 --- a/debug.hpp +++ b/debug.hpp @@ -301,6 +301,10 @@ void warn (const char *); /////////////////////////////////////////////////////////////////////////////// void breakpoint (void); +void await_debugger (void); +void prepare_debugger (void); + +void force_console (void); /////////////////////////////////////////////////////////////////////////////// void enable_fpe (void); diff --git a/debug_posix.cpp b/debug_posix.cpp new file mode 100644 index 00000000..f27be73d --- /dev/null +++ b/debug_posix.cpp @@ -0,0 +1,63 @@ +#include "./debug.hpp" + +#include "./log.hpp" + +#include +#include +#include + + +/////////////////////////////////////////////////////////////////////////////// +void +breakpoint (void) +{ +#if defined (__x86_64) || defined (__i386) + __asm__ ("int $3;"); +#else + raise (SIGINT); +#endif +} + + +/////////////////////////////////////////////////////////////////////////////// +void +prepare_debugger (void) +{ + ; +} + + +//----------------------------------------------------------------------------- +void +await_debugger (void) +{ + if (ptrace (PTRACE_TRACEME)) + LOG_CRITICAL ("unable to wait for debugger"); +} + + +/////////////////////////////////////////////////////////////////////////////// +#include +void +enable_fpe (void) +{ + feenableexcept (FE_DIVBYZERO | FE_INVALID); +} + + +//----------------------------------------------------------------------------- +void +disable_fpe (void) +{ + feenableexcept (0); +} + + +/////////////////////////////////////////////////////////////////////////////// +void +force_console (void) +{ + if (!isatty (fileno (stdout))) { + LOG_ERROR ("expected debugging under a console"); + } +} diff --git a/debug_win32.cpp b/debug_win32.cpp new file mode 100644 index 00000000..63a8ff58 --- /dev/null +++ b/debug_win32.cpp @@ -0,0 +1,113 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2016 Danny Robson + */ + +#include "./debug.hpp" + +#include "./except.hpp" + +#include + + +/////////////////////////////////////////////////////////////////////////////// +void +breakpoint (void) +{ + DebugBreak (); +} + + +/////////////////////////////////////////////////////////////////////////////// +void +await_debugger (void) +{ + // HACK: This is terribly inefficient, but it's not a performance + // priority for the time being. + while (!IsDebuggerPresent ()) + Sleep (100); +} + + +//----------------------------------------------------------------------------- +void +prepare_debugger (void) +{ + if (nullptr == LoadLibrary("exchndl.dll")) { + LOG_WARNING("Emergency debugger not loaded: %s", util::win32_error ()); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +void +enable_fpe (void) +{ + LOG_WARN ("Non-Linux exception code is broken under current GCC."); +// _clearfp(); +// unsigned int ignored; +// _controlfp_s (&ignored, _MCW_EM, _MCW_EM); +} + + +//----------------------------------------------------------------------------- +void +disable_fpe (void) +{ + LOG_WARN ("Non-Linux exception code is broken under current GCC."); +// _clearfp(); +// unsigned int ignored; +// _controlfp_s (&ignored, 0, _MCW_EM); +} + + +/////////////////////////////////////////////////////////////////////////////// +#include +#include + +void +force_console (void) +{ + if (!AttachConsole (ATTACH_PARENT_PROCESS)) + return; + + auto out_handle = GetStdHandle (STD_OUTPUT_HANDLE); + auto err_handle = GetStdHandle (STD_ERROR_HANDLE); + auto in_handle = GetStdHandle (STD_INPUT_HANDLE); + + auto out_fd = _open_osfhandle (reinterpret_cast (out_handle), _O_TEXT); + auto err_fd = _open_osfhandle (reinterpret_cast (err_handle), _O_TEXT); + auto in_fd = _open_osfhandle (reinterpret_cast (in_handle), _O_TEXT); + + auto out_file = _fdopen (out_fd, "w"); + auto err_file = _fdopen (err_fd, "w"); + auto in_file = _fdopen (in_fd, "r"); + + /// FILE objects are not reassignable, but Windows doesn't leave us much + /// choice here. + *stdout = *out_file; + *stderr = *err_file; + *stdin = *in_file; + + setvbuf (stdout, NULL, _IONBF, 0); + setvbuf (stderr, NULL, _IONBF, 0); + setvbuf (stdin, NULL, _IONBF, 0); + + ios::sync_with_stdio (); + + // Windows doesn't give an immediate newline when an application is run + // from a console, so we provide one here for sanity. + std::cout << "\n"; + std::cerr << "Console installed\n"; +}