debug: seperate platform specifics into units

This commit is contained in:
Danny Robson 2016-02-15 17:21:01 +11:00
parent 18c3a1eaaf
commit df05596524
5 changed files with 186 additions and 114 deletions

View File

@ -327,6 +327,7 @@ UTIL_FILES = \
if PLATFORM_LINUX if PLATFORM_LINUX
UTIL_FILES += \ UTIL_FILES += \
backtrace_execinfo.cpp \ backtrace_execinfo.cpp \
debug_posix.cpp \
io_posix.cpp \ io_posix.cpp \
io_posix.hpp \ io_posix.hpp \
library_posix.hpp \ library_posix.hpp \
@ -340,6 +341,7 @@ endif
if PLATFORM_WIN32 if PLATFORM_WIN32
UTIL_FILES += \ UTIL_FILES += \
backtrace_null.cpp \ backtrace_null.cpp \
debug_win32.cpp \
io_win32.cpp \ io_win32.cpp \
library_win32.hpp \ library_win32.hpp \
library_win32.cpp \ library_win32.cpp \

118
debug.cpp
View File

@ -11,7 +11,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* Copyright 2010 Danny Robson <danny@nerdcruft.net> * Copyright 2010-2016 Danny Robson <danny@nerdcruft.net>
*/ */
#include "backtrace.hpp" #include "backtrace.hpp"
@ -36,27 +36,6 @@ detail::panic (const char *msg)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#if defined(PLATFORM_WIN32)
#include <windows.h>
void
breakpoint (void)
{
DebugBreak ();
}
#else
void
breakpoint (void)
{
#if defined (__x86_64) || defined (__i386)
__asm__ ("int $3;");
#else
raise (SIGINT);
#endif
}
#endif
//-----------------------------------------------------------------------------
void void
detail::not_implemented (const char *msg) detail::not_implemented (const char *msg)
{ {
@ -96,102 +75,13 @@ warn (const char *msg)
} }
////////////////////////////////////////////////////////////////////////////////
#if defined(PLATFORM_LINUX)
#include <fenv.h>
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 <io.h>
#include <fcntl.h>
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<intptr_t> (out_handle), _O_TEXT);
auto err_fd = _open_osfhandle (reinterpret_cast<intptr_t> (err_handle), _O_TEXT);
auto in_fd = _open_osfhandle (reinterpret_cast<intptr_t> (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 void
util::debug::init (void) util::debug::init (void)
{ {
#if defined(PLATFORM_WIN32)
force_console (); force_console ();
prepare_debugger ();
if (nullptr == LoadLibrary("exchndl.dll")) { if (getenv ("DEBUG_WAIT"))
std::cerr << GetLastError () << "\n"; await_debugger ();
LOG_WARNING("Emergency debugger not loaded");
}
#endif
} }

View File

@ -301,6 +301,10 @@ void warn (const char *);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void breakpoint (void); void breakpoint (void);
void await_debugger (void);
void prepare_debugger (void);
void force_console (void);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void enable_fpe (void); void enable_fpe (void);

63
debug_posix.cpp Normal file
View File

@ -0,0 +1,63 @@
#include "./debug.hpp"
#include "./log.hpp"
#include <unistd.h>
#include <sys/ptrace.h>
#include <signal.h>
///////////////////////////////////////////////////////////////////////////////
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 <fenv.h>
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");
}
}

113
debug_win32.cpp Normal file
View File

@ -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 <danny@nerdcruft.net>
*/
#include "./debug.hpp"
#include "./except.hpp"
#include <windows.h>
///////////////////////////////////////////////////////////////////////////////
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 <io.h>
#include <fcntl.h>
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<intptr_t> (out_handle), _O_TEXT);
auto err_fd = _open_osfhandle (reinterpret_cast<intptr_t> (err_handle), _O_TEXT);
auto in_fd = _open_osfhandle (reinterpret_cast<intptr_t> (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";
}