From 700ae2eff3134792f09cea2b051666688b1d5b97 Mon Sep 17 00:00:00 2001 From: GPUCode <47210458+GPUCode@users.noreply.github.com> Date: Sat, 24 Jun 2023 18:24:15 +0300 Subject: [PATCH] boost: Add stack traces (#31) --- boost/stacktrace.hpp | 19 + boost/stacktrace/detail/addr2line_impls.hpp | 226 +++++++ boost/stacktrace/detail/collect_msvc.ipp | 33 + boost/stacktrace/detail/collect_noop.ipp | 25 + boost/stacktrace/detail/collect_unwind.ipp | 106 ++++ boost/stacktrace/detail/frame_decl.hpp | 159 +++++ boost/stacktrace/detail/frame_msvc.ipp | 377 +++++++++++ boost/stacktrace/detail/frame_noop.ipp | 44 ++ boost/stacktrace/detail/frame_unwind.ipp | 114 ++++ .../stacktrace/detail/libbacktrace_impls.hpp | 248 ++++++++ .../detail/location_from_symbol.hpp | 105 +++ boost/stacktrace/detail/pop_options.h | 12 + boost/stacktrace/detail/push_options.h | 31 + boost/stacktrace/detail/safe_dump_noop.ipp | 37 ++ boost/stacktrace/detail/safe_dump_posix.ipp | 59 ++ boost/stacktrace/detail/safe_dump_win.ipp | 66 ++ boost/stacktrace/detail/to_dec_array.hpp | 46 ++ boost/stacktrace/detail/to_hex_array.hpp | 54 ++ boost/stacktrace/detail/try_dec_convert.hpp | 29 + boost/stacktrace/detail/unwind_base_impls.hpp | 50 ++ boost/stacktrace/detail/void_ptr_cast.hpp | 46 ++ boost/stacktrace/frame.hpp | 67 ++ boost/stacktrace/safe_dump_to.hpp | 222 +++++++ boost/stacktrace/stacktrace.hpp | 423 +++++++++++++ boost/stacktrace/stacktrace_fwd.hpp | 28 + boost/winapi/access_rights.hpp | 84 +++ boost/winapi/dll.hpp | 199 ++++++ boost/winapi/file_management.hpp | 597 ++++++++++++++++++ boost/winapi/get_proc_address.hpp | 81 +++ boost/winapi/handles.hpp | 75 +++ boost/winapi/limits.hpp | 52 ++ boost/winapi/overlapped.hpp | 45 ++ boost/winapi/stack_backtrace.hpp | 55 ++ build.cmd | 1 + 34 files changed, 3815 insertions(+) create mode 100644 boost/stacktrace.hpp create mode 100644 boost/stacktrace/detail/addr2line_impls.hpp create mode 100644 boost/stacktrace/detail/collect_msvc.ipp create mode 100644 boost/stacktrace/detail/collect_noop.ipp create mode 100644 boost/stacktrace/detail/collect_unwind.ipp create mode 100644 boost/stacktrace/detail/frame_decl.hpp create mode 100644 boost/stacktrace/detail/frame_msvc.ipp create mode 100644 boost/stacktrace/detail/frame_noop.ipp create mode 100644 boost/stacktrace/detail/frame_unwind.ipp create mode 100644 boost/stacktrace/detail/libbacktrace_impls.hpp create mode 100644 boost/stacktrace/detail/location_from_symbol.hpp create mode 100644 boost/stacktrace/detail/pop_options.h create mode 100644 boost/stacktrace/detail/push_options.h create mode 100644 boost/stacktrace/detail/safe_dump_noop.ipp create mode 100644 boost/stacktrace/detail/safe_dump_posix.ipp create mode 100644 boost/stacktrace/detail/safe_dump_win.ipp create mode 100644 boost/stacktrace/detail/to_dec_array.hpp create mode 100644 boost/stacktrace/detail/to_hex_array.hpp create mode 100644 boost/stacktrace/detail/try_dec_convert.hpp create mode 100644 boost/stacktrace/detail/unwind_base_impls.hpp create mode 100644 boost/stacktrace/detail/void_ptr_cast.hpp create mode 100644 boost/stacktrace/frame.hpp create mode 100644 boost/stacktrace/safe_dump_to.hpp create mode 100644 boost/stacktrace/stacktrace.hpp create mode 100644 boost/stacktrace/stacktrace_fwd.hpp create mode 100644 boost/winapi/access_rights.hpp create mode 100644 boost/winapi/dll.hpp create mode 100644 boost/winapi/file_management.hpp create mode 100644 boost/winapi/get_proc_address.hpp create mode 100644 boost/winapi/handles.hpp create mode 100644 boost/winapi/limits.hpp create mode 100644 boost/winapi/overlapped.hpp create mode 100644 boost/winapi/stack_backtrace.hpp diff --git a/boost/stacktrace.hpp b/boost/stacktrace.hpp new file mode 100644 index 0000000..ad8dffe --- /dev/null +++ b/boost/stacktrace.hpp @@ -0,0 +1,19 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_HPP +#define BOOST_STACKTRACE_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include // Actually already includes all the headers +#include + +#endif // BOOST_STACKTRACE_HPP diff --git a/boost/stacktrace/detail/addr2line_impls.hpp b/boost/stacktrace/detail/addr2line_impls.hpp new file mode 100644 index 0000000..e00590b --- /dev/null +++ b/boost/stacktrace/detail/addr2line_impls.hpp @@ -0,0 +1,226 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_ADDR2LINE_IMPLS_HPP +#define BOOST_STACKTRACE_DETAIL_ADDR2LINE_IMPLS_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include + + +namespace boost { namespace stacktrace { namespace detail { + + +#if defined(BOOST_STACKTRACE_ADDR2LINE_LOCATION) && !defined(BOOST_NO_CXX11_CONSTEXPR) + +constexpr bool is_abs_path(const char* path) BOOST_NOEXCEPT { + return *path != '\0' && ( + *path == ':' || *path == '/' || is_abs_path(path + 1) + ); +} + +#endif + +class addr2line_pipe { + ::FILE* p; + ::pid_t pid; + +public: + explicit addr2line_pipe(const char *flag, const char* exec_path, const char* addr) BOOST_NOEXCEPT + : p(0) + , pid(0) + { + int pdes[2]; + #ifdef BOOST_STACKTRACE_ADDR2LINE_LOCATION + char prog_name[] = BOOST_STRINGIZE( BOOST_STACKTRACE_ADDR2LINE_LOCATION ); + #if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_STATIC_ASSERT) + static_assert( + boost::stacktrace::detail::is_abs_path( BOOST_STRINGIZE( BOOST_STACKTRACE_ADDR2LINE_LOCATION ) ), + "BOOST_STACKTRACE_ADDR2LINE_LOCATION must be an absolute path" + ); + #endif + + #else + char prog_name[] = "/usr/bin/addr2line"; + #endif + + char* argp[] = { + prog_name, + const_cast(flag), + const_cast(exec_path), + const_cast(addr), + 0 + }; + + if (::pipe(pdes) < 0) { + return; + } + + pid = ::fork(); + switch (pid) { + case -1: + // Failed... + ::close(pdes[0]); + ::close(pdes[1]); + return; + + case 0: + // We are the child. + ::close(STDERR_FILENO); + ::close(pdes[0]); + if (pdes[1] != STDOUT_FILENO) { + ::dup2(pdes[1], STDOUT_FILENO); + } + + // Do not use `execlp()`, `execvp()`, and `execvpe()` here! + // `exec*p*` functions are vulnerable to PATH variable evaluation attacks. + ::execv(prog_name, argp); + ::_exit(127); + } + + p = ::fdopen(pdes[0], "r"); + ::close(pdes[1]); + } + + operator ::FILE*() const BOOST_NOEXCEPT { + return p; + } + + ~addr2line_pipe() BOOST_NOEXCEPT { + if (p) { + ::fclose(p); + int pstat = 0; + ::kill(pid, SIGKILL); + ::waitpid(pid, &pstat, 0); + } + } +}; + +inline std::string addr2line(const char* flag, const void* addr) { + std::string res; + + boost::stacktrace::detail::location_from_symbol loc(addr); + if (!loc.empty()) { + res = loc.name(); + } else { + res.resize(16); + int rlin_size = ::readlink("/proc/self/exe", &res[0], res.size() - 1); + while (rlin_size == static_cast(res.size() - 1)) { + res.resize(res.size() * 4); + rlin_size = ::readlink("/proc/self/exe", &res[0], res.size() - 1); + } + if (rlin_size == -1) { + res.clear(); + return res; + } + res.resize(rlin_size); + } + + addr2line_pipe p(flag, res.c_str(), to_hex_array(addr).data()); + res.clear(); + + if (!p) { + return res; + } + + char data[32]; + while (!::feof(p)) { + if (::fgets(data, sizeof(data), p)) { + res += data; + } else { + break; + } + } + + // Trimming + while (!res.empty() && (res[res.size() - 1] == '\n' || res[res.size() - 1] == '\r')) { + res.erase(res.size() - 1); + } + + return res; +} + + +struct to_string_using_addr2line { + std::string res; + void prepare_function_name(const void* addr) { + res = boost::stacktrace::frame(addr).name(); + } + + bool prepare_source_location(const void* addr) { + //return addr2line("-Cfipe", addr); // Does not seem to work in all cases + std::string source_line = boost::stacktrace::detail::addr2line("-Cpe", addr); + if (!source_line.empty() && source_line[0] != '?') { + res += " at "; + res += source_line; + return true; + } + + return false; + } +}; + +template class to_string_impl_base; +typedef to_string_impl_base to_string_impl; + +inline std::string name_impl(const void* addr) { + std::string res = boost::stacktrace::detail::addr2line("-fe", addr); + res = res.substr(0, res.find_last_of('\n')); + res = boost::core::demangle(res.c_str()); + + if (res == "??") { + res.clear(); + } + + return res; +} + +} // namespace detail + +std::string frame::source_file() const { + std::string res; + res = boost::stacktrace::detail::addr2line("-e", addr_); + res = res.substr(0, res.find_last_of(':')); + if (res == "??") { + res.clear(); + } + + return res; +} + + +std::size_t frame::source_line() const { + std::size_t line_num = 0; + std::string res = boost::stacktrace::detail::addr2line("-e", addr_); + const std::size_t last = res.find_last_of(':'); + if (last == std::string::npos) { + return 0; + } + res = res.substr(last + 1); + + if (!boost::stacktrace::detail::try_dec_convert(res.c_str(), line_num)) { + return 0; + } + + return line_num; +} + + +}} // namespace boost::stacktrace + +#endif // BOOST_STACKTRACE_DETAIL_ADDR2LINE_IMPLS_HPP diff --git a/boost/stacktrace/detail/collect_msvc.ipp b/boost/stacktrace/detail/collect_msvc.ipp new file mode 100644 index 0000000..d620298 --- /dev/null +++ b/boost/stacktrace/detail/collect_msvc.ipp @@ -0,0 +1,33 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_COLLECT_MSVC_IPP +#define BOOST_STACKTRACE_DETAIL_COLLECT_MSVC_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +#include + +namespace boost { namespace stacktrace { namespace detail { + +std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT { + return boost::winapi::RtlCaptureStackBackTrace( + static_cast(skip), + static_cast(max_frames_count), + const_cast(out_frames), + 0 + ); +} + + +}}} // namespace boost::stacktrace + +#endif // BOOST_STACKTRACE_DETAIL_COLLECT_MSVC_IPP diff --git a/boost/stacktrace/detail/collect_noop.ipp b/boost/stacktrace/detail/collect_noop.ipp new file mode 100644 index 0000000..e7a3340 --- /dev/null +++ b/boost/stacktrace/detail/collect_noop.ipp @@ -0,0 +1,25 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_COLLECT_NOOP_IPP +#define BOOST_STACKTRACE_DETAIL_COLLECT_NOOP_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +namespace boost { namespace stacktrace { namespace detail { + +std::size_t this_thread_frames::collect(native_frame_ptr_t* /*out_frames*/, std::size_t /*max_frames_count*/, std::size_t /*skip*/) BOOST_NOEXCEPT { + return 0; +} + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_COLLECT_NOOP_IPP diff --git a/boost/stacktrace/detail/collect_unwind.ipp b/boost/stacktrace/detail/collect_unwind.ipp new file mode 100644 index 0000000..58a6c87 --- /dev/null +++ b/boost/stacktrace/detail/collect_unwind.ipp @@ -0,0 +1,106 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP +#define BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +// On iOS 32-bit ARM architecture _Unwind_Backtrace function doesn't exist, symbol is undefined. +// Forcing libc backtrace() function usage. +#include +#if defined(BOOST_OS_IOS_AVAILABLE) && defined(BOOST_ARCH_ARM_AVAILABLE) && BOOST_VERSION_NUMBER_MAJOR(BOOST_ARCH_ARM) < 8 +#define BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION +#endif + +#if defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) +#include +#include +#else +#include +#endif +#include + +#if !defined(_GNU_SOURCE) && !defined(BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED) && !defined(BOOST_WINDOWS) +#error "Boost.Stacktrace requires `_Unwind_Backtrace` function. Define `_GNU_SOURCE` macro or `BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED` if _Unwind_Backtrace is available without `_GNU_SOURCE`." +#endif + +namespace boost { namespace stacktrace { namespace detail { + +#if !defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) +struct unwind_state { + std::size_t frames_to_skip; + native_frame_ptr_t* current; + native_frame_ptr_t* end; +}; + +inline _Unwind_Reason_Code unwind_callback(::_Unwind_Context* context, void* arg) { + // Note: do not write `::_Unwind_GetIP` because it is a macro on some platforms. + // Use `_Unwind_GetIP` instead! + unwind_state* const state = static_cast(arg); + if (state->frames_to_skip) { + --state->frames_to_skip; + return _Unwind_GetIP(context) ? ::_URC_NO_REASON : ::_URC_END_OF_STACK; + } + + *state->current = reinterpret_cast( + _Unwind_GetIP(context) + ); + + ++state->current; + if (!*(state->current - 1) || state->current == state->end) { + return ::_URC_END_OF_STACK; + } + return ::_URC_NO_REASON; +} +#endif //!defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) + +std::size_t this_thread_frames::collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT { + std::size_t frames_count = 0; + if (!max_frames_count) { + return frames_count; + } + skip += 1; + +#if defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) + // According to https://opensource.apple.com/source/Libc/Libc-1272.200.26/gen/backtrace.c.auto.html + // it looks like the `::backtrace` is async signal safe. + frames_count = static_cast(::backtrace(const_cast(out_frames), static_cast(max_frames_count))); + + // NOTE: There is no way to pass "skip" count to backtrace function so we need to perform left shift operation. + // If number of elements in result backtrace is >= max_frames_count then "skip" elements are wasted. + if (frames_count && skip) { + if (skip >= frames_count) { + frames_count = 0; + } else { + std::copy(out_frames + skip, out_frames + frames_count, out_frames); + frames_count -= skip; + } + } +#else + boost::stacktrace::detail::unwind_state state = { skip, out_frames, out_frames + max_frames_count }; + ::_Unwind_Backtrace(&boost::stacktrace::detail::unwind_callback, &state); + frames_count = state.current - out_frames; +#endif //defined(BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION) + + if (frames_count && out_frames[frames_count - 1] == 0) { + -- frames_count; + } + + return frames_count; +} + + +}}} // namespace boost::stacktrace::detail + +#undef BOOST_STACKTRACE_USE_LIBC_BACKTRACE_FUNCTION + +#endif // BOOST_STACKTRACE_DETAIL_COLLECT_UNWIND_IPP diff --git a/boost/stacktrace/detail/frame_decl.hpp b/boost/stacktrace/detail/frame_decl.hpp new file mode 100644 index 0000000..938a4db --- /dev/null +++ b/boost/stacktrace/detail/frame_decl.hpp @@ -0,0 +1,159 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_FRAME_DECL_HPP +#define BOOST_STACKTRACE_DETAIL_FRAME_DECL_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include + +#include + +#include // boost::stacktrace::detail::native_frame_ptr_t +#include + +#include + +/// @file boost/stacktrace/detail/frame_decl.hpp +/// Use header instead of this one! + +namespace boost { namespace stacktrace { + +/// @class boost::stacktrace::frame boost/stacktrace/detail/frame_decl.hpp +/// @brief Class that stores frame/function address and can get information about it at runtime. +class frame { +public: + typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t; + +private: + /// @cond + native_frame_ptr_t addr_; + /// @endcond + +public: + /// @brief Constructs frame that references NULL address. + /// Calls to source_file() and source_line() will return empty string. + /// Calls to source_line() will return 0. + /// + /// @b Complexity: O(1). + /// + /// @b Async-Handler-Safety: Safe. + /// @throws Nothing. + BOOST_CONSTEXPR frame() BOOST_NOEXCEPT + : addr_(0) + {} + +#ifdef BOOST_STACKTRACE_DOXYGEN_INVOKED + /// @brief Copy constructs frame. + /// + /// @b Complexity: O(1). + /// + /// @b Async-Handler-Safety: Safe. + /// @throws Nothing. + constexpr frame(const frame&) = default; + + /// @brief Copy assigns frame. + /// + /// @b Complexity: O(1). + /// + /// @b Async-Handler-Safety: Safe. + /// @throws Nothing. + constexpr frame& operator=(const frame&) = default; +#endif + + /// @brief Constructs frame that references addr and could later generate information about that address using platform specific features. + /// + /// @b Complexity: O(1). + /// + /// @b Async-Handler-Safety: Safe. + /// @throws Nothing. + BOOST_CONSTEXPR explicit frame(native_frame_ptr_t addr) BOOST_NOEXCEPT + : addr_(addr) + {} + + /// @brief Constructs frame that references function_addr and could later generate information about that function using platform specific features. + /// + /// @b Complexity: O(1). + /// + /// @b Async-Handler-Safety: Safe. + /// @throws Nothing. + template + explicit frame(T* function_addr) BOOST_NOEXCEPT + : addr_(boost::stacktrace::detail::void_ptr_cast(function_addr)) + {} + + /// @returns Name of the frame (function name in a human readable form). + /// + /// @b Complexity: unknown (lots of platform specific work). + /// + /// @b Async-Handler-Safety: Unsafe. + /// @throws std::bad_alloc if not enough memory to construct resulting string. + BOOST_STACKTRACE_FUNCTION std::string name() const; + + /// @returns Address of the frame function. + /// + /// @b Complexity: O(1). + /// + /// @b Async-Handler-Safety: Safe. + /// @throws Nothing. + BOOST_CONSTEXPR native_frame_ptr_t address() const BOOST_NOEXCEPT { + return addr_; + } + + /// @returns Path to the source file, were the function of the frame is defined. Returns empty string + /// if this->source_line() == 0. + /// @throws std::bad_alloc if not enough memory to construct resulting string. + /// + /// @b Complexity: unknown (lots of platform specific work). + /// + /// @b Async-Handler-Safety: Unsafe. + BOOST_STACKTRACE_FUNCTION std::string source_file() const; + + /// @returns Code line in the source file, were the function of the frame is defined. + /// @throws std::bad_alloc if not enough memory to construct string for internal needs. + /// + /// @b Complexity: unknown (lots of platform specific work). + /// + /// @b Async-Handler-Safety: Unsafe. + BOOST_STACKTRACE_FUNCTION std::size_t source_line() const; + + /// @brief Checks that frame is not references NULL address. + /// @returns `true` if `this->address() != 0` + /// + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + BOOST_EXPLICIT_OPERATOR_BOOL() + + /// @brief Checks that frame references NULL address. + /// @returns `true` if `this->address() == 0` + /// + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return !address(); } + + /// @cond + BOOST_CONSTEXPR bool operator!() const BOOST_NOEXCEPT { return !address(); } + /// @endcond +}; + + +namespace detail { + BOOST_STACKTRACE_FUNCTION std::string to_string(const frame* frames, std::size_t size); +} // namespace detail + +}} // namespace boost::stacktrace + + +#include + +#endif // BOOST_STACKTRACE_DETAIL_FRAME_DECL_HPP diff --git a/boost/stacktrace/detail/frame_msvc.ipp b/boost/stacktrace/detail/frame_msvc.ipp new file mode 100644 index 0000000..4e43c0b --- /dev/null +++ b/boost/stacktrace/detail/frame_msvc.ipp @@ -0,0 +1,377 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_FRAME_MSVC_IPP +#define BOOST_STACKTRACE_DETAIL_FRAME_MSVC_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include "dbgeng.h" + +#ifdef BOOST_MSVC +# pragma comment(lib, "ole32.lib") +# pragma comment(lib, "Dbgeng.lib") +#endif + + +#ifdef __CRT_UUID_DECL // for __MINGW32__ + __CRT_UUID_DECL(IDebugClient,0x27fe5639,0x8407,0x4f47,0x83,0x64,0xee,0x11,0x8f,0xb0,0x8a,0xc8) + __CRT_UUID_DECL(IDebugControl,0x5182e668,0x105e,0x416e,0xad,0x92,0x24,0xef,0x80,0x04,0x24,0xba) + __CRT_UUID_DECL(IDebugSymbols,0x8c31e98c,0x983a,0x48a5,0x90,0x16,0x6f,0xe5,0xd6,0x67,0xa9,0x50) +#elif defined(DEFINE_GUID) && !defined(BOOST_MSVC) + DEFINE_GUID(IID_IDebugClient,0x27fe5639,0x8407,0x4f47,0x83,0x64,0xee,0x11,0x8f,0xb0,0x8a,0xc8); + DEFINE_GUID(IID_IDebugControl,0x5182e668,0x105e,0x416e,0xad,0x92,0x24,0xef,0x80,0x04,0x24,0xba); + DEFINE_GUID(IID_IDebugSymbols,0x8c31e98c,0x983a,0x48a5,0x90,0x16,0x6f,0xe5,0xd6,0x67,0xa9,0x50); +#endif + + + +// Testing. Remove later +//# define __uuidof(x) ::IID_ ## x + +namespace boost { namespace stacktrace { namespace detail { + +template +class com_holder: boost::noncopyable { + T* holder_; + +public: + com_holder() BOOST_NOEXCEPT + : holder_(0) + {} + + T* operator->() const BOOST_NOEXCEPT { + return holder_; + } + + void** to_void_ptr_ptr() BOOST_NOEXCEPT { + return reinterpret_cast(&holder_); + } + + bool is_inited() const BOOST_NOEXCEPT { + return !!holder_; + } + + ~com_holder() BOOST_NOEXCEPT { + if (holder_) { + holder_->Release(); + } + } +}; + + +inline std::string mingw_demangling_workaround(const std::string& s) { +#ifdef BOOST_GCC + if (s.empty()) { + return s; + } + + if (s[0] != '_') { + return boost::core::demangle(('_' + s).c_str()); + } + + return boost::core::demangle(s.c_str()); +#else + return s; +#endif +} + +inline void trim_right_zeroes(std::string& s) { + // MSVC-9 does not have back() and pop_back() functions in std::string + while (!s.empty()) { + const std::size_t last = static_cast(s.size() - 1); + if (s[last] != '\0') { + break; + } + s.resize(last); + } +} + +class debugging_symbols: boost::noncopyable { + static void try_init_com(com_holder< ::IDebugSymbols>& idebug) BOOST_NOEXCEPT { + com_holder< ::IDebugClient> iclient; + if (S_OK != ::DebugCreate(__uuidof(IDebugClient), iclient.to_void_ptr_ptr())) { + return; + } + + com_holder< ::IDebugControl> icontrol; + const bool res0 = (S_OK == iclient->QueryInterface( + __uuidof(IDebugControl), + icontrol.to_void_ptr_ptr() + )); + if (!res0) { + return; + } + + const bool res1 = (S_OK == iclient->AttachProcess( + 0, + ::GetCurrentProcessId(), + DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND + )); + if (!res1) { + return; + } + + if (S_OK != icontrol->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE)) { + return; + } + + // No checking: QueryInterface sets the output parameter to NULL in case of error. + iclient->QueryInterface(__uuidof(IDebugSymbols), idebug.to_void_ptr_ptr()); + } + +#ifndef BOOST_STACKTRACE_USE_WINDBG_CACHED + + com_holder< ::IDebugSymbols> idebug_; +public: + debugging_symbols() BOOST_NOEXCEPT + { + try_init_com(idebug_); + } + +#else + +#ifdef BOOST_NO_CXX11_THREAD_LOCAL +# error Your compiler does not support C++11 thread_local storage. It`s impossible to build with BOOST_STACKTRACE_USE_WINDBG_CACHED. +#endif + + static com_holder< ::IDebugSymbols>& get_thread_local_debug_inst() BOOST_NOEXCEPT { + // [class.mfct]: A static local variable or local type in a member function always refers to the same entity, whether + // or not the member function is inline. + static thread_local com_holder< ::IDebugSymbols> idebug; + + if (!idebug.is_inited()) { + try_init_com(idebug); + } + + return idebug; + } + + com_holder< ::IDebugSymbols>& idebug_; +public: + debugging_symbols() BOOST_NOEXCEPT + : idebug_( get_thread_local_debug_inst() ) + {} + +#endif // #ifndef BOOST_STACKTRACE_USE_WINDBG_CACHED + + bool is_inited() const BOOST_NOEXCEPT { + return idebug_.is_inited(); + } + + std::string get_name_impl(const void* addr, std::string* module_name = 0) const { + std::string result; + if (!is_inited()) { + return result; + } + const ULONG64 offset = reinterpret_cast(addr); + + char name[256]; + name[0] = '\0'; + ULONG size = 0; + bool res = (S_OK == idebug_->GetNameByOffset( + offset, + name, + sizeof(name), + &size, + 0 + )); + + if (!res && size != 0) { + result.resize(size); + res = (S_OK == idebug_->GetNameByOffset( + offset, + &result[0], + static_cast(result.size()), + &size, + 0 + )); + + // According to https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/dbgeng/nf-dbgeng-idebugsymbols-getnamebyoffset + // "This size includes the space for the '\0' terminating character." + result.resize(size - 1); + } else if (res) { + result.assign(name, size - 1); + } + + if (!res) { + result.clear(); + return result; + } + + const std::size_t delimiter = result.find_first_of('!'); + if (module_name) { + *module_name = result.substr(0, delimiter); + } + + if (delimiter == std::string::npos) { + // If 'delimiter' is equal to 'std::string::npos' then we have only module name. + result.clear(); + return result; + } + + result = mingw_demangling_workaround( + result.substr(delimiter + 1) + ); + + return result; + } + + std::size_t get_line_impl(const void* addr) const BOOST_NOEXCEPT { + ULONG result = 0; + if (!is_inited()) { + return result; + } + + const bool is_ok = (S_OK == idebug_->GetLineByOffset( + reinterpret_cast(addr), + &result, + 0, + 0, + 0, + 0 + )); + + return (is_ok ? result : 0); + } + + std::pair get_source_file_line_impl(const void* addr) const { + std::pair result; + if (!is_inited()) { + return result; + } + const ULONG64 offset = reinterpret_cast(addr); + + char name[256]; + name[0] = 0; + ULONG size = 0; + ULONG line_num = 0; + bool res = (S_OK == idebug_->GetLineByOffset( + offset, + &line_num, + name, + sizeof(name), + &size, + 0 + )); + + if (res) { + result.first = name; + result.second = line_num; + return result; + } + + if (!res && size == 0) { + return result; + } + + result.first.resize(size); + res = (S_OK == idebug_->GetLineByOffset( + offset, + &line_num, + &result.first[0], + static_cast(result.first.size()), + &size, + 0 + )); + trim_right_zeroes(result.first); + result.second = line_num; + + if (!res) { + result.first.clear(); + result.second = 0; + } + + return result; + } + + void to_string_impl(const void* addr, std::string& res) const { + if (!is_inited()) { + return; + } + + std::string module_name; + std::string name = this->get_name_impl(addr, &module_name); + if (!name.empty()) { + res += name; + } else { + res += to_hex_array(addr).data(); + } + + std::pair source_line = this->get_source_file_line_impl(addr); + if (!source_line.first.empty() && source_line.second) { + res += " at "; + res += source_line.first; + res += ':'; + res += boost::stacktrace::detail::to_dec_array(source_line.second).data(); + } else if (!module_name.empty()) { + res += " in "; + res += module_name; + } + } +}; + +std::string to_string(const frame* frames, std::size_t size) { + boost::stacktrace::detail::debugging_symbols idebug; + if (!idebug.is_inited()) { + return std::string(); + } + + std::string res; + res.reserve(64 * size); + for (std::size_t i = 0; i < size; ++i) { + if (i < 10) { + res += ' '; + } + res += boost::stacktrace::detail::to_dec_array(i).data(); + res += '#'; + res += ' '; + idebug.to_string_impl(frames[i].address(), res); + res += '\n'; + } + + return res; +} + +} // namespace detail + +std::string frame::name() const { + boost::stacktrace::detail::debugging_symbols idebug; + return idebug.get_name_impl(addr_); +} + + +std::string frame::source_file() const { + boost::stacktrace::detail::debugging_symbols idebug; + return idebug.get_source_file_line_impl(addr_).first; +} + +std::size_t frame::source_line() const { + boost::stacktrace::detail::debugging_symbols idebug; + return idebug.get_line_impl(addr_); +} + +std::string to_string(const frame& f) { + std::string res; + + boost::stacktrace::detail::debugging_symbols idebug; + idebug.to_string_impl(f.address(), res); + return res; +} + +}} // namespace boost::stacktrace + +#endif // BOOST_STACKTRACE_DETAIL_FRAME_MSVC_IPP diff --git a/boost/stacktrace/detail/frame_noop.ipp b/boost/stacktrace/detail/frame_noop.ipp new file mode 100644 index 0000000..3561ad4 --- /dev/null +++ b/boost/stacktrace/detail/frame_noop.ipp @@ -0,0 +1,44 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_FRAME_NOOP_IPP +#define BOOST_STACKTRACE_DETAIL_FRAME_NOOP_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +namespace boost { namespace stacktrace { namespace detail { + +std::string to_string(const frame* /*frames*/, std::size_t /*count*/) { + return std::string(); +} + +} // namespace detail + +std::string frame::name() const { + return std::string(); +} + +std::string frame::source_file() const { + return std::string(); +} + +std::size_t frame::source_line() const { + return 0; +} + +std::string to_string(const frame& /*f*/) { + return std::string(); +} + + +}} // namespace boost::stacktrace + +#endif // BOOST_STACKTRACE_DETAIL_FRAME_NOOP_IPP diff --git a/boost/stacktrace/detail/frame_unwind.ipp b/boost/stacktrace/detail/frame_unwind.ipp new file mode 100644 index 0000000..48d843e --- /dev/null +++ b/boost/stacktrace/detail/frame_unwind.ipp @@ -0,0 +1,114 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP +#define BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +#include +#include +#include +#include + +#include + +#ifdef BOOST_STACKTRACE_USE_BACKTRACE +# include +#elif defined(BOOST_STACKTRACE_USE_ADDR2LINE) +# include +#else +# include +#endif + +namespace boost { namespace stacktrace { namespace detail { + +template +class to_string_impl_base: private Base { +public: + std::string operator()(boost::stacktrace::detail::native_frame_ptr_t addr) { + Base::res.clear(); + Base::prepare_function_name(addr); + if (!Base::res.empty()) { + Base::res = boost::core::demangle(Base::res.c_str()); + } else { + Base::res = to_hex_array(addr).data(); + } + + if (Base::prepare_source_location(addr)) { + return Base::res; + } + + boost::stacktrace::detail::location_from_symbol loc(addr); + if (!loc.empty()) { + Base::res += " in "; + Base::res += loc.name(); + } + + return Base::res; + } +}; + +std::string to_string(const frame* frames, std::size_t size) { + std::string res; + if (size == 0) { + return res; + } + res.reserve(64 * size); + + to_string_impl impl; + + for (std::size_t i = 0; i < size; ++i) { + if (i < 10) { + res += ' '; + } + res += boost::stacktrace::detail::to_dec_array(i).data(); + res += '#'; + res += ' '; + res += impl(frames[i].address()); + res += '\n'; + } + + return res; +} + + +} // namespace detail + + +std::string frame::name() const { + if (!addr_) { + return std::string(); + } + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + ::Dl_info dli; + const bool dl_ok = !!::dladdr(const_cast(addr_), &dli); // `dladdr` on Solaris accepts nonconst addresses + if (dl_ok && dli.dli_sname) { + return boost::core::demangle(dli.dli_sname); + } +#endif + return boost::stacktrace::detail::name_impl(addr_); +} + +std::string to_string(const frame& f) { + if (!f) { + return std::string(); + } + + boost::stacktrace::detail::to_string_impl impl; + return impl(f.address()); +} + + +}} // namespace boost::stacktrace + +#endif // BOOST_STACKTRACE_DETAIL_FRAME_UNWIND_IPP diff --git a/boost/stacktrace/detail/libbacktrace_impls.hpp b/boost/stacktrace/detail/libbacktrace_impls.hpp new file mode 100644 index 0000000..35fe01a --- /dev/null +++ b/boost/stacktrace/detail/libbacktrace_impls.hpp @@ -0,0 +1,248 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP +#define BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include +#include +#include + +#ifdef BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE +# include BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE +#else +# include +#endif + +namespace boost { namespace stacktrace { namespace detail { + + +struct pc_data { + std::string* function; + std::string* filename; + std::size_t line; +}; + +inline void libbacktrace_syminfo_callback(void *data, uintptr_t /*pc*/, const char *symname, uintptr_t /*symval*/, uintptr_t /*symsize*/) { + pc_data& d = *static_cast(data); + if (d.function && symname) { + *d.function = symname; + } +} + +// Old versions of libbacktrace have different signature for the callback +inline void libbacktrace_syminfo_callback(void *data, uintptr_t pc, const char *symname, uintptr_t symval) { + boost::stacktrace::detail::libbacktrace_syminfo_callback(data, pc, symname, symval, 0); +} + +inline int libbacktrace_full_callback(void *data, uintptr_t /*pc*/, const char *filename, int lineno, const char *function) { + pc_data& d = *static_cast(data); + if (d.filename && filename) { + *d.filename = filename; + } + if (d.function && function) { + *d.function = function; + } + d.line = lineno; + return 0; +} + +inline void libbacktrace_error_callback(void* /*data*/, const char* /*msg*/, int /*errnum*/) BOOST_NOEXCEPT { + // Do nothing, just return. +} + +// Not async-signal-safe, so this method is not called from async-safe functions. +// +// This function is not async signal safe because: +// * Dynamic initialization of a block-scope variable with static storage duration could lock a mutex +// * No guarantees on `backtrace_create_state` function. +// +// Currently `backtrace_create_state` can not detect file name on Windows https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82543 +// That's why we provide a `prog_location` here. +BOOST_SYMBOL_VISIBLE inline ::backtrace_state* construct_state(const program_location& prog_location) BOOST_NOEXCEPT { + // [dcl.inline]: A static local variable in an inline function with external linkage always refers to the same object. + + // TODO: The most obvious solution: + // + //static ::backtrace_state* state = ::backtrace_create_state( + // prog_location.name(), + // 1, // allow safe concurrent usage of the same state + // boost::stacktrace::detail::libbacktrace_error_callback, + // 0 // pointer to data that will be passed to callback + //); + // + // + // Unfortunately, that solution segfaults when `construct_state()` function is in .so file + // and multiple threads concurrently work with state. I failed to localize the root cause: + // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=87653 + +#define BOOST_STACKTRACE_DETAIL_IS_MT 1 + +#if !defined(BOOST_HAS_THREADS) +# define BOOST_STACKTRACE_DETAIL_STORAGE static +# undef BOOST_STACKTRACE_DETAIL_IS_MT +# define BOOST_STACKTRACE_DETAIL_IS_MT 0 +#elif defined(BOOST_STACKTRACE_BACKTRACE_FORCE_STATIC) +# define BOOST_STACKTRACE_DETAIL_STORAGE static +#elif !defined(BOOST_NO_CXX11_THREAD_LOCAL) +# define BOOST_STACKTRACE_DETAIL_STORAGE thread_local +#elif defined(__GNUC__) && !defined(__clang__) +# define BOOST_STACKTRACE_DETAIL_STORAGE static __thread +#else +# define BOOST_STACKTRACE_DETAIL_STORAGE /* just a local variable */ +#endif + + BOOST_STACKTRACE_DETAIL_STORAGE ::backtrace_state* state = ::backtrace_create_state( + prog_location.name(), + BOOST_STACKTRACE_DETAIL_IS_MT, + boost::stacktrace::detail::libbacktrace_error_callback, + 0 + ); + +#undef BOOST_STACKTRACE_DETAIL_IS_MT +#undef BOOST_STACKTRACE_DETAIL_STORAGE + + return state; +} + +struct to_string_using_backtrace { + std::string res; + boost::stacktrace::detail::program_location prog_location; + ::backtrace_state* state; + std::string filename; + std::size_t line; + + void prepare_function_name(const void* addr) { + boost::stacktrace::detail::pc_data data = {&res, &filename, 0}; + if (state) { + ::backtrace_pcinfo( + state, + reinterpret_cast(addr), + boost::stacktrace::detail::libbacktrace_full_callback, + boost::stacktrace::detail::libbacktrace_error_callback, + &data + ) + || + ::backtrace_syminfo( + state, + reinterpret_cast(addr), + boost::stacktrace::detail::libbacktrace_syminfo_callback, + boost::stacktrace::detail::libbacktrace_error_callback, + &data + ); + } + line = data.line; + } + + bool prepare_source_location(const void* /*addr*/) { + if (filename.empty() || !line) { + return false; + } + + res += " at "; + res += filename; + res += ':'; + res += boost::stacktrace::detail::to_dec_array(line).data(); + return true; + } + + to_string_using_backtrace() BOOST_NOEXCEPT { + state = boost::stacktrace::detail::construct_state(prog_location); + } +}; + +template class to_string_impl_base; +typedef to_string_impl_base to_string_impl; + +inline std::string name_impl(const void* addr) { + std::string res; + + boost::stacktrace::detail::program_location prog_location; + ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location); + + boost::stacktrace::detail::pc_data data = {&res, 0, 0}; + if (state) { + ::backtrace_pcinfo( + state, + reinterpret_cast(addr), + boost::stacktrace::detail::libbacktrace_full_callback, + boost::stacktrace::detail::libbacktrace_error_callback, + &data + ) + || + ::backtrace_syminfo( + state, + reinterpret_cast(addr), + boost::stacktrace::detail::libbacktrace_syminfo_callback, + boost::stacktrace::detail::libbacktrace_error_callback, + &data + ); + } + if (!res.empty()) { + res = boost::core::demangle(res.c_str()); + } + + return res; +} + +} // namespace detail + +std::string frame::source_file() const { + std::string res; + + if (!addr_) { + return res; + } + + boost::stacktrace::detail::program_location prog_location; + ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location); + + boost::stacktrace::detail::pc_data data = {0, &res, 0}; + if (state) { + ::backtrace_pcinfo( + state, + reinterpret_cast(addr_), + boost::stacktrace::detail::libbacktrace_full_callback, + boost::stacktrace::detail::libbacktrace_error_callback, + &data + ); + } + + return res; +} + +std::size_t frame::source_line() const { + if (!addr_) { + return 0; + } + + boost::stacktrace::detail::program_location prog_location; + ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location); + + boost::stacktrace::detail::pc_data data = {0, 0, 0}; + if (state) { + ::backtrace_pcinfo( + state, + reinterpret_cast(addr_), + boost::stacktrace::detail::libbacktrace_full_callback, + boost::stacktrace::detail::libbacktrace_error_callback, + &data + ); + } + + return data.line; +} + + +}} // namespace boost::stacktrace + +#endif // BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP diff --git a/boost/stacktrace/detail/location_from_symbol.hpp b/boost/stacktrace/detail/location_from_symbol.hpp new file mode 100644 index 0000000..6677b50 --- /dev/null +++ b/boost/stacktrace/detail/location_from_symbol.hpp @@ -0,0 +1,105 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP +#define BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# include +#else +# include +#endif + +namespace boost { namespace stacktrace { namespace detail { + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +class location_from_symbol { + ::Dl_info dli_; + +public: + explicit location_from_symbol(const void* addr) BOOST_NOEXCEPT + : dli_() + { + if (!::dladdr(const_cast(addr), &dli_)) { // `dladdr` on Solaris accepts nonconst addresses + dli_.dli_fname = 0; + } + } + + bool empty() const BOOST_NOEXCEPT { + return !dli_.dli_fname; + } + + const char* name() const BOOST_NOEXCEPT { + return dli_.dli_fname; + } +}; + +class program_location { +public: + const char* name() const BOOST_NOEXCEPT { + return 0; + } +}; + +#else + +class location_from_symbol { + BOOST_STATIC_CONSTEXPR boost::winapi::DWORD_ DEFAULT_PATH_SIZE_ = 260; + char file_name_[DEFAULT_PATH_SIZE_]; + +public: + explicit location_from_symbol(const void* addr) BOOST_NOEXCEPT { + file_name_[0] = '\0'; + + boost::winapi::MEMORY_BASIC_INFORMATION_ mbi; + if (!boost::winapi::VirtualQuery(addr, &mbi, sizeof(mbi))) { + return; + } + + boost::winapi::HMODULE_ handle = reinterpret_cast(mbi.AllocationBase); + if (!boost::winapi::GetModuleFileNameA(handle, file_name_, DEFAULT_PATH_SIZE_)) { + file_name_[0] = '\0'; + return; + } + } + + bool empty() const BOOST_NOEXCEPT { + return file_name_[0] == '\0'; + } + + const char* name() const BOOST_NOEXCEPT { + return file_name_; + } +}; + +class program_location { + BOOST_STATIC_CONSTEXPR boost::winapi::DWORD_ DEFAULT_PATH_SIZE_ = 260; + char file_name_[DEFAULT_PATH_SIZE_]; + +public: + program_location() BOOST_NOEXCEPT { + file_name_[0] = '\0'; + + const boost::winapi::HMODULE_ handle = 0; + if (!boost::winapi::GetModuleFileNameA(handle, file_name_, DEFAULT_PATH_SIZE_)) { + file_name_[0] = '\0'; + } + } + + const char* name() const BOOST_NOEXCEPT { + return file_name_[0] ? file_name_ : 0; + } +}; +#endif + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_LOCATION_FROM_SYMBOL_HPP diff --git a/boost/stacktrace/detail/pop_options.h b/boost/stacktrace/detail/pop_options.h new file mode 100644 index 0000000..0822b68 --- /dev/null +++ b/boost/stacktrace/detail/pop_options.h @@ -0,0 +1,12 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// No include guards! Intentionally. + +#ifdef BOOST_STACKTRACE_FUNCTION +# undef BOOST_STACKTRACE_FUNCTION +#endif + diff --git a/boost/stacktrace/detail/push_options.h b/boost/stacktrace/detail/push_options.h new file mode 100644 index 0000000..8162d29 --- /dev/null +++ b/boost/stacktrace/detail/push_options.h @@ -0,0 +1,31 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// No include guards! Intentionally. + +// Link or header only +#if !defined(BOOST_STACKTRACE_LINK) && defined(BOOST_STACKTRACE_DYN_LINK) +# define BOOST_STACKTRACE_LINK +#endif + +#if defined(BOOST_STACKTRACE_LINK) && !defined(BOOST_STACKTRACE_DYN_LINK) && defined(BOOST_ALL_DYN_LINK) +# define BOOST_STACKTRACE_DYN_LINK +#endif + +#ifdef BOOST_STACKTRACE_LINK +# if defined(BOOST_STACKTRACE_DYN_LINK) +# ifdef BOOST_STACKTRACE_INTERNAL_BUILD_LIBS +# define BOOST_STACKTRACE_FUNCTION BOOST_SYMBOL_EXPORT +# else +# define BOOST_STACKTRACE_FUNCTION BOOST_SYMBOL_IMPORT +# endif +# else +# define BOOST_STACKTRACE_FUNCTION +# endif +#elif !defined(BOOST_STACKTRACE_DOXYGEN_INVOKED) +# define BOOST_STACKTRACE_FUNCTION inline +#endif + diff --git a/boost/stacktrace/detail/safe_dump_noop.ipp b/boost/stacktrace/detail/safe_dump_noop.ipp new file mode 100644 index 0000000..9d84d5e --- /dev/null +++ b/boost/stacktrace/detail/safe_dump_noop.ipp @@ -0,0 +1,37 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_SAFE_DUMP_NOOP_IPP +#define BOOST_STACKTRACE_DETAIL_SAFE_DUMP_NOOP_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +namespace boost { namespace stacktrace { namespace detail { + + +#if defined(BOOST_WINDOWS) +std::size_t dump(void* /*fd*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT { + return 0; +} +#else +std::size_t dump(int /*fd*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT { + return 0; +} +#endif + + +std::size_t dump(const char* /*file*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT { + return 0; +} + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_SAFE_DUMP_NOOP_IPP diff --git a/boost/stacktrace/detail/safe_dump_posix.ipp b/boost/stacktrace/detail/safe_dump_posix.ipp new file mode 100644 index 0000000..feb0f4c --- /dev/null +++ b/boost/stacktrace/detail/safe_dump_posix.ipp @@ -0,0 +1,59 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_SAFE_DUMP_POSIX_IPP +#define BOOST_STACKTRACE_DETAIL_SAFE_DUMP_POSIX_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +#include // ::write +#include // ::open +#include // S_IWUSR and friends + + +namespace boost { namespace stacktrace { namespace detail { + +std::size_t dump(int fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT { + // We do not retry, because this function must be typically called from signal handler so it's: + // * to scary to continue in case of EINTR + // * EAGAIN or EWOULDBLOCK may occur only in case of O_NONBLOCK is set for fd, + // so it seems that user does not want to block + if (::write(fd, frames, sizeof(native_frame_ptr_t) * frames_count) == -1) { + return 0; + } + + return frames_count; +} + +std::size_t dump(const char* file, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT { + const int fd = ::open( + file, + O_CREAT | O_WRONLY | O_TRUNC, +#if defined(S_IWUSR) && defined(S_IRUSR) // Workarounds for some Android OSes + S_IWUSR | S_IRUSR +#elif defined(S_IWRITE) && defined(S_IREAD) + S_IWRITE | S_IREAD +#else + 0 +#endif + ); + if (fd == -1) { + return 0; + } + + const std::size_t size = boost::stacktrace::detail::dump(fd, frames, frames_count); + ::close(fd); + return size; +} + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_SAFE_DUMP_POSIX_IPP diff --git a/boost/stacktrace/detail/safe_dump_win.ipp b/boost/stacktrace/detail/safe_dump_win.ipp new file mode 100644 index 0000000..0294183 --- /dev/null +++ b/boost/stacktrace/detail/safe_dump_win.ipp @@ -0,0 +1,66 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_SAFE_DUMP_WIN_IPP +#define BOOST_STACKTRACE_DETAIL_SAFE_DUMP_WIN_IPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +#include + +#include +#include +#include +#include + +namespace boost { namespace stacktrace { namespace detail { + +std::size_t dump(void* /*fd*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT { +#if 0 // This code potentially could cause deadlocks (according to the MSDN). Disabled + boost::winapi::DWORD_ written; + const boost::winapi::DWORD_ bytes_to_write = static_cast( + sizeof(native_frame_ptr_t) * frames_count + ); + if (!boost::winapi::WriteFile(fd, frames, bytes_to_write, &written, 0)) { + return 0; + } + + return frames_count; +#endif + return 0; +} + +std::size_t dump(const char* /*file*/, const native_frame_ptr_t* /*frames*/, std::size_t /*frames_count*/) BOOST_NOEXCEPT { +#if 0 // This code causing deadlocks on some platforms. Disabled + void* const fd = boost::winapi::CreateFileA( + file, + boost::winapi::GENERIC_WRITE_, + 0, + 0, + boost::winapi::CREATE_ALWAYS_, + boost::winapi::FILE_ATTRIBUTE_NORMAL_, + 0 + ); + + if (fd == boost::winapi::invalid_handle_value) { + return 0; + } + + const std::size_t size = boost::stacktrace::detail::dump(fd, frames, frames_count); + boost::winapi::CloseHandle(fd); + return size; +#endif + return 0; +} + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_SAFE_DUMP_WIN_IPP diff --git a/boost/stacktrace/detail/to_dec_array.hpp b/boost/stacktrace/detail/to_dec_array.hpp new file mode 100644 index 0000000..38ba999 --- /dev/null +++ b/boost/stacktrace/detail/to_dec_array.hpp @@ -0,0 +1,46 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_TO_DEC_ARRAY_HPP +#define BOOST_STACKTRACE_DETAIL_TO_DEC_ARRAY_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +namespace boost { namespace stacktrace { namespace detail { + +// We do not use boost::lexical_cast in this function to reduce module dependencies +inline boost::array to_dec_array(std::size_t value) BOOST_NOEXCEPT { + boost::array ret; + if (!value) { + ret[0] = '0'; + ret[1] = '\0'; + return ret; + } + + std::size_t digits = 0; + for (std::size_t value_copy = value; value_copy; value_copy /= 10) { + ++ digits; + } + + for (std::size_t i = 1; i <= digits; ++i) { + ret[digits - i] = static_cast('0' + (value % 10)); + value /= 10; + } + + ret[digits] = '\0'; + + return ret; +} + + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_TO_DEC_ARRAY_HPP diff --git a/boost/stacktrace/detail/to_hex_array.hpp b/boost/stacktrace/detail/to_hex_array.hpp new file mode 100644 index 0000000..0a60ea1 --- /dev/null +++ b/boost/stacktrace/detail/to_hex_array.hpp @@ -0,0 +1,54 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_TO_HEX_ARRAY_HPP +#define BOOST_STACKTRACE_DETAIL_TO_HEX_ARRAY_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include +#include +#include + +namespace boost { namespace stacktrace { namespace detail { + +BOOST_STATIC_CONSTEXPR char to_hex_array_bytes[] = "0123456789ABCDEF"; + +template +inline boost::array to_hex_array(T addr) BOOST_NOEXCEPT { + boost::array ret = {"0x"}; + ret.back() = '\0'; + BOOST_STATIC_ASSERT_MSG(!boost::is_pointer::value, ""); + + const std::size_t s = sizeof(T); + + char* out = ret.data() + s * 2 + 1; + + for (std::size_t i = 0; i < s; ++i) { + const unsigned char tmp_addr = (addr & 0xFFu); + *out = to_hex_array_bytes[tmp_addr & 0xF]; + -- out; + *out = to_hex_array_bytes[tmp_addr >> 4]; + -- out; + addr >>= 8; + } + + return ret; +} + +inline boost::array to_hex_array(const void* addr) BOOST_NOEXCEPT { + return to_hex_array( + reinterpret_cast< boost::make_unsigned::type >(addr) + ); +} + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_TO_HEX_ARRAY_HPP diff --git a/boost/stacktrace/detail/try_dec_convert.hpp b/boost/stacktrace/detail/try_dec_convert.hpp new file mode 100644 index 0000000..f24aafc --- /dev/null +++ b/boost/stacktrace/detail/try_dec_convert.hpp @@ -0,0 +1,29 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_TRY_DEC_CONVERT_HPP +#define BOOST_STACKTRACE_DETAIL_TRY_DEC_CONVERT_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +namespace boost { namespace stacktrace { namespace detail { + +// We do not use boost::lexical_cast in this function to reduce module dependencies +inline bool try_dec_convert(const char* s, std::size_t& res) BOOST_NOEXCEPT { + char* end_ptr = 0; + res = std::strtoul(s, &end_ptr, 10); + return *end_ptr == '\0'; +} + + +}}} // namespace boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_TRY_DEC_CONVERT_HPP diff --git a/boost/stacktrace/detail/unwind_base_impls.hpp b/boost/stacktrace/detail/unwind_base_impls.hpp new file mode 100644 index 0000000..a91d536 --- /dev/null +++ b/boost/stacktrace/detail/unwind_base_impls.hpp @@ -0,0 +1,50 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_UNWIND_BASE_IMPLS_HPP +#define BOOST_STACKTRACE_DETAIL_UNWIND_BASE_IMPLS_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include + +namespace boost { namespace stacktrace { namespace detail { + +struct to_string_using_nothing { + std::string res; + + void prepare_function_name(const void* addr) { + res = boost::stacktrace::frame(addr).name(); + } + + bool prepare_source_location(const void* /*addr*/) const BOOST_NOEXCEPT { + return false; + } +}; + +template class to_string_impl_base; +typedef to_string_impl_base to_string_impl; + +inline std::string name_impl(const void* /*addr*/) { + return std::string(); +} + +} // namespace detail + +std::string frame::source_file() const { + return std::string(); +} + +std::size_t frame::source_line() const { + return 0; +} + +}} // namespace boost::stacktrace + +#endif // BOOST_STACKTRACE_DETAIL_UNWIND_BASE_IMPLS_HPP diff --git a/boost/stacktrace/detail/void_ptr_cast.hpp b/boost/stacktrace/detail/void_ptr_cast.hpp new file mode 100644 index 0000000..29114a8 --- /dev/null +++ b/boost/stacktrace/detail/void_ptr_cast.hpp @@ -0,0 +1,46 @@ +// Copyright 2014 Renato Tegon Forti, Antony Polukhin. +// Copyright Antony Polukhin, 2015-2023. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_DETAIL_VOID_PTR_CAST_HPP +#define BOOST_STACKTRACE_DETAIL_VOID_PTR_CAST_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ * 100 + __GNUC_MINOR__ > 301) +# pragma GCC system_header +#endif + +namespace boost { namespace stacktrace { namespace detail { + +// GCC warns when reinterpret_cast between function pointer and object pointer occur. +// This functionsuppress the warnings and ensures that such casts are safe. +template +To void_ptr_cast(From* v) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT_MSG( + boost::is_pointer::value, + "`void_ptr_cast` function must be used only for casting to or from void pointers." + ); + + BOOST_STATIC_ASSERT_MSG( + sizeof(From*) == sizeof(To), + "Pointer to function and pointer to object differ in size on your platform." + ); + + return reinterpret_cast(v); +} + + +}}} // boost::stacktrace::detail + +#endif // BOOST_STACKTRACE_DETAIL_VOID_PTR_CAST_HPP + diff --git a/boost/stacktrace/frame.hpp b/boost/stacktrace/frame.hpp new file mode 100644 index 0000000..d3c0fd1 --- /dev/null +++ b/boost/stacktrace/frame.hpp @@ -0,0 +1,67 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_FRAME_HPP +#define BOOST_STACKTRACE_FRAME_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include + +#include + +#include // boost::stacktrace::detail::native_frame_ptr_t + +#include +#include + +namespace boost { namespace stacktrace { + +/// Comparison operators that provide platform dependant ordering and have O(1) complexity; are Async-Handler-Safe. +BOOST_CONSTEXPR inline bool operator< (const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return lhs.address() < rhs.address(); } +BOOST_CONSTEXPR inline bool operator> (const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return rhs < lhs; } +BOOST_CONSTEXPR inline bool operator<=(const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return !(lhs > rhs); } +BOOST_CONSTEXPR inline bool operator>=(const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return !(lhs < rhs); } +BOOST_CONSTEXPR inline bool operator==(const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return lhs.address() == rhs.address(); } +BOOST_CONSTEXPR inline bool operator!=(const frame& lhs, const frame& rhs) BOOST_NOEXCEPT { return !(lhs == rhs); } + +/// Fast hashing support, O(1) complexity; Async-Handler-Safe. +inline std::size_t hash_value(const frame& f) BOOST_NOEXCEPT { + return reinterpret_cast(f.address()); +} + +/// Outputs stacktrace::frame in a human readable format to string; unsafe to use in async handlers. +BOOST_STACKTRACE_FUNCTION std::string to_string(const frame& f); + +/// Outputs stacktrace::frame in a human readable format to output stream; unsafe to use in async handlers. +template +std::basic_ostream& operator<<(std::basic_ostream& os, const frame& f) { + return os << boost::stacktrace::to_string(f); +} + +}} // namespace boost::stacktrace + +/// @cond + +#include + +#ifndef BOOST_STACKTRACE_LINK +# if defined(BOOST_STACKTRACE_USE_NOOP) +# include +# elif defined(BOOST_MSVC) || defined(BOOST_STACKTRACE_USE_WINDBG) || defined(BOOST_STACKTRACE_USE_WINDBG_CACHED) +# include +# else +# include +# endif +#endif +/// @endcond + + +#endif // BOOST_STACKTRACE_FRAME_HPP diff --git a/boost/stacktrace/safe_dump_to.hpp b/boost/stacktrace/safe_dump_to.hpp new file mode 100644 index 0000000..e233878 --- /dev/null +++ b/boost/stacktrace/safe_dump_to.hpp @@ -0,0 +1,222 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_SAFE_DUMP_TO_HPP +#define BOOST_STACKTRACE_SAFE_DUMP_TO_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#if defined(BOOST_WINDOWS) +#include +#endif + +#include + +#ifdef BOOST_INTEL +# pragma warning(push) +# pragma warning(disable:2196) // warning #2196: routine is both "inline" and "noinline" +#endif + +/// @file safe_dump_to.hpp This header contains low-level async-signal-safe functions for dumping call stacks. Dumps are binary serialized arrays of `void*`, +/// so you could read them by using 'od -tx8 -An stacktrace_dump_failename' Linux command or using boost::stacktrace::stacktrace::from_dump functions. + +namespace boost { namespace stacktrace { + +/// @cond +namespace detail { + + typedef const void* native_frame_ptr_t; // TODO: change to `typedef void(*native_frame_ptr_t)();` + enum helper{ max_frames_dump = 128 }; + + BOOST_STACKTRACE_FUNCTION std::size_t from_dump(const char* filename, native_frame_ptr_t* out_frames); + BOOST_STACKTRACE_FUNCTION std::size_t dump(const char* file, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT; +#if defined(BOOST_WINDOWS) + BOOST_STACKTRACE_FUNCTION std::size_t dump(void* fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT; +#else + // POSIX + BOOST_STACKTRACE_FUNCTION std::size_t dump(int fd, const native_frame_ptr_t* frames, std::size_t frames_count) BOOST_NOEXCEPT; +#endif + + +struct this_thread_frames { // struct is required to avoid warning about usage of inline+BOOST_NOINLINE + BOOST_NOINLINE BOOST_STACKTRACE_FUNCTION static std::size_t collect(native_frame_ptr_t* out_frames, std::size_t max_frames_count, std::size_t skip) BOOST_NOEXCEPT; + + BOOST_NOINLINE static std::size_t safe_dump_to_impl(void* memory, std::size_t size, std::size_t skip) BOOST_NOEXCEPT { + typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t; + + if (size < sizeof(native_frame_ptr_t)) { + return 0; + } + + native_frame_ptr_t* mem = static_cast(memory); + const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(mem, size / sizeof(native_frame_ptr_t) - 1, skip + 1); + mem[frames_count] = 0; + return frames_count + 1; + } + + template + BOOST_NOINLINE static std::size_t safe_dump_to_impl(T file, std::size_t skip, std::size_t max_depth) BOOST_NOEXCEPT { + typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t; + + native_frame_ptr_t buffer[boost::stacktrace::detail::max_frames_dump + 1]; + if (max_depth > boost::stacktrace::detail::max_frames_dump) { + max_depth = boost::stacktrace::detail::max_frames_dump; + } + + const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(buffer, max_depth, skip + 1); + buffer[frames_count] = 0; + return boost::stacktrace::detail::dump(file, buffer, frames_count + 1); + } +}; + +} // namespace detail +/// @endcond + +/// @brief Stores current function call sequence into the memory. +/// +/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. +/// +/// @b Async-Handler-Safety: Safe. +/// +/// @returns Stored call sequence depth including terminating zero frame. To get the actually consumed bytes multiply this value by the sizeof(boost::stacktrace::frame::native_frame_ptr_t) +/// +/// @param memory Preallocated buffer to store current function call sequence into. +/// +/// @param size Size of the preallocated buffer. +BOOST_FORCEINLINE std::size_t safe_dump_to(void* memory, std::size_t size) BOOST_NOEXCEPT { + return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(memory, size, 0); +} + +/// @brief Stores current function call sequence into the memory. +/// +/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. +/// +/// @b Async-Handler-Safety: Safe. +/// +/// @returns Stored call sequence depth including terminating zero frame. To get the actually consumed bytes multiply this value by the sizeof(boost::stacktrace::frame::native_frame_ptr_t) +/// +/// @param skip How many top calls to skip and do not store. +/// +/// @param memory Preallocated buffer to store current function call sequence into. +/// +/// @param size Size of the preallocated buffer. +BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, void* memory, std::size_t size) BOOST_NOEXCEPT { + return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(memory, size, skip); +} + + +/// @brief Opens a file and rewrites its content with current function call sequence if such operations are async signal safe. +/// +/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. +/// +/// @b Async-Handler-Safety: Safe. +/// +/// @returns Stored call sequence depth including terminating zero frame. +/// +/// @param file File to store current function call sequence. +BOOST_FORCEINLINE std::size_t safe_dump_to(const char* file) BOOST_NOEXCEPT { + return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(file, 0, boost::stacktrace::detail::max_frames_dump); +} + +/// @brief Opens a file and rewrites its content with current function call sequence if such operations are async signal safe. +/// +/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. +/// +/// @b Async-Handler-Safety: Safe. +/// +/// @returns Stored call sequence depth including terminating zero frame. +/// +/// @param skip How many top calls to skip and do not store. +/// +/// @param max_depth Max call sequence depth to collect. +/// +/// @param file File to store current function call sequence. +BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, std::size_t max_depth, const char* file) BOOST_NOEXCEPT { + return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(file, skip, max_depth); +} + +#ifdef BOOST_STACKTRACE_DOXYGEN_INVOKED + +/// @brief Writes into the provided file descriptor the current function call sequence if such operation is async signal safe. +/// +/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. +/// +/// @b Async-Handler-Safety: Safe. +/// +/// @returns Stored call sequence depth including terminating zero frame. +/// +/// @param file File to store current function call sequence. +BOOST_FORCEINLINE std::size_t safe_dump_to(platform_specific_descriptor fd) BOOST_NOEXCEPT; + +/// @brief Writes into the provided file descriptor the current function call sequence if such operation is async signal safe. +/// +/// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. +/// +/// @b Async-Handler-Safety: Safe. +/// +/// @returns Stored call sequence depth including terminating zero frame. +/// +/// @param skip How many top calls to skip and do not store. +/// +/// @param max_depth Max call sequence depth to collect. +/// +/// @param file File to store current function call sequence. +BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, std::size_t max_depth, platform_specific_descriptor fd) BOOST_NOEXCEPT; + +#elif defined(BOOST_WINDOWS) + +BOOST_FORCEINLINE std::size_t safe_dump_to(void* fd) BOOST_NOEXCEPT { + return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(fd, 0, boost::stacktrace::detail::max_frames_dump); +} + +BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, std::size_t max_depth, void* fd) BOOST_NOEXCEPT { + return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(fd, skip, max_depth); +} + +#else + +// POSIX +BOOST_FORCEINLINE std::size_t safe_dump_to(int fd) BOOST_NOEXCEPT { + return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(fd, 0, boost::stacktrace::detail::max_frames_dump); +} + +BOOST_FORCEINLINE std::size_t safe_dump_to(std::size_t skip, std::size_t max_depth, int fd) BOOST_NOEXCEPT { + return boost::stacktrace::detail::this_thread_frames::safe_dump_to_impl(fd, skip, max_depth); +} + +#endif + + +}} // namespace boost::stacktrace + +#ifdef BOOST_INTEL +# pragma warning(pop) +#endif + +#include + +#if !defined(BOOST_STACKTRACE_LINK) || defined(BOOST_STACKTRACE_INTERNAL_BUILD_LIBS) +# if defined(BOOST_STACKTRACE_USE_NOOP) +# include +# include +# else +# if defined(BOOST_WINDOWS) +# include +# else +# include +# endif +# if defined(BOOST_WINDOWS) && !defined(BOOST_WINAPI_IS_MINGW) // MinGW does not provide RtlCaptureStackBackTrace. MinGW-w64 does. +# include +# else +# include +# endif +# endif +#endif + +#endif // BOOST_STACKTRACE_SAFE_DUMP_TO_HPP diff --git a/boost/stacktrace/stacktrace.hpp b/boost/stacktrace/stacktrace.hpp new file mode 100644 index 0000000..eb456c7 --- /dev/null +++ b/boost/stacktrace/stacktrace.hpp @@ -0,0 +1,423 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_STACKTRACE_HPP +#define BOOST_STACKTRACE_STACKTRACE_HPP + +#include +#ifdef BOOST_HAS_PRAGMA_ONCE +# pragma once +#endif + +#include +#include +#include + +#include +#include +#include + +#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS +# include +#endif + +#include +#include +#include +#include + +#ifdef BOOST_INTEL +# pragma warning(push) +# pragma warning(disable:2196) // warning #2196: routine is both "inline" and "noinline" +#endif + +namespace boost { namespace stacktrace { + +/// Class that on construction copies minimal information about call stack into its internals and provides access to that information. +/// @tparam Allocator Allocator to use during stack capture. +template +class basic_stacktrace { + std::vector impl_; + typedef boost::stacktrace::detail::native_frame_ptr_t native_frame_ptr_t; + + /// @cond + void fill(native_frame_ptr_t* begin, std::size_t size) { + if (!size) { + return; + } + + impl_.reserve(static_cast(size)); + for (std::size_t i = 0; i < size; ++i) { + if (!begin[i]) { + return; + } + impl_.push_back( + frame(begin[i]) + ); + } + } + + static std::size_t frames_count_from_buffer_size(std::size_t buffer_size) BOOST_NOEXCEPT { + const std::size_t ret = (buffer_size > sizeof(native_frame_ptr_t) ? buffer_size / sizeof(native_frame_ptr_t) : 0); + return (ret > 1024 ? 1024 : ret); // Dealing with suspiciously big sizes + } + + BOOST_NOINLINE void init(std::size_t frames_to_skip, std::size_t max_depth) { + BOOST_CONSTEXPR_OR_CONST std::size_t buffer_size = 128; + if (!max_depth) { + return; + } + + BOOST_TRY { + { // Fast path without additional allocations + native_frame_ptr_t buffer[buffer_size]; + const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(buffer, buffer_size < max_depth ? buffer_size : max_depth, frames_to_skip + 1); + if (buffer_size > frames_count || frames_count == max_depth) { + fill(buffer, frames_count); + return; + } + } + + // Failed to fit in `buffer_size`. Allocating memory: +#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename Allocator::template rebind::other allocator_void_t; +#else + typedef typename std::allocator_traits::template rebind_alloc allocator_void_t; +#endif + std::vector buf(buffer_size * 2, 0, impl_.get_allocator()); + do { + const std::size_t frames_count = boost::stacktrace::detail::this_thread_frames::collect(&buf[0], buf.size() < max_depth ? buf.size() : max_depth, frames_to_skip + 1); + if (buf.size() > frames_count || frames_count == max_depth) { + fill(&buf[0], frames_count); + return; + } + + buf.resize(buf.size() * 2); + } while (buf.size() < buf.max_size()); // close to `true`, but suppresses `C4127: conditional expression is constant`. + } BOOST_CATCH (...) { + // ignore exception + } + BOOST_CATCH_END + } + /// @endcond + +public: + typedef typename std::vector::value_type value_type; + typedef typename std::vector::allocator_type allocator_type; + typedef typename std::vector::const_pointer pointer; + typedef typename std::vector::const_pointer const_pointer; + typedef typename std::vector::const_reference reference; + typedef typename std::vector::const_reference const_reference; + typedef typename std::vector::size_type size_type; + typedef typename std::vector::difference_type difference_type; + typedef typename std::vector::const_iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + typedef typename std::vector::const_reverse_iterator reverse_iterator; + typedef typename std::vector::const_reverse_iterator const_reverse_iterator; + + /// @brief Stores the current function call sequence inside *this without any decoding or any other heavy platform specific operations. + /// + /// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. + /// + /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe. + BOOST_FORCEINLINE basic_stacktrace() BOOST_NOEXCEPT + : impl_() + { + init(0 , static_cast(-1)); + } + + /// @brief Stores the current function call sequence inside *this without any decoding or any other heavy platform specific operations. + /// + /// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. + /// + /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe. + /// + /// @param a Allocator that would be passed to underlying storage. + BOOST_FORCEINLINE explicit basic_stacktrace(const allocator_type& a) BOOST_NOEXCEPT + : impl_(a) + { + init(0 , static_cast(-1)); + } + + /// @brief Stores [skip, skip + max_depth) of the current function call sequence inside *this without any decoding or any other heavy platform specific operations. + /// + /// @b Complexity: O(N) where N is call sequence length, O(1) if BOOST_STACKTRACE_USE_NOOP is defined. + /// + /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe. + /// + /// @param skip How many top calls to skip and do not store in *this. + /// + /// @param max_depth Max call sequence depth to collect. + /// + /// @param a Allocator that would be passed to underlying storage. + /// + /// @throws Nothing. Note that default construction of allocator may throw, however it is + /// performed outside the constructor and exception in `allocator_type()` would not result in calling `std::terminate`. + BOOST_FORCEINLINE basic_stacktrace(std::size_t skip, std::size_t max_depth, const allocator_type& a = allocator_type()) BOOST_NOEXCEPT + : impl_(a) + { + init(skip , max_depth); + } + + /// @b Complexity: O(st.size()) + /// + /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe. + basic_stacktrace(const basic_stacktrace& st) + : impl_(st.impl_) + {} + + /// @b Complexity: O(st.size()) + /// + /// @b Async-Handler-Safety: Safe if Allocator construction, copying, Allocator::allocate and Allocator::deallocate are async signal safe. + basic_stacktrace& operator=(const basic_stacktrace& st) { + impl_ = st.impl_; + return *this; + } + +#ifdef BOOST_STACKTRACE_DOXYGEN_INVOKED + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe if Allocator::deallocate is async signal safe. + ~basic_stacktrace() BOOST_NOEXCEPT = default; +#endif + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe if Allocator construction and copying are async signal safe. + basic_stacktrace(basic_stacktrace&& st) BOOST_NOEXCEPT + : impl_(std::move(st.impl_)) + {} + + /// @b Complexity: O(st.size()) + /// + /// @b Async-Handler-Safety: Safe if Allocator construction and copying are async signal safe. + basic_stacktrace& operator=(basic_stacktrace&& st) +#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS + BOOST_NOEXCEPT_IF(( std::is_nothrow_move_assignable< std::vector >::value )) +#else + BOOST_NOEXCEPT +#endif + { + impl_ = std::move(st.impl_); + return *this; + } +#endif + + /// @returns Number of function names stored inside the class. + /// + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + size_type size() const BOOST_NOEXCEPT { + return impl_.size(); + } + + /// @param frame_no Zero based index of frame to return. 0 + /// is the function index where stacktrace was constructed and + /// index close to this->size() contains function `main()`. + /// @returns frame that references the actual frame info, stored inside *this. + /// + /// @b Complexity: O(1). + /// + /// @b Async-Handler-Safety: Safe. + const_reference operator[](std::size_t frame_no) const BOOST_NOEXCEPT { + return impl_[frame_no]; + } + + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + const_iterator begin() const BOOST_NOEXCEPT { return impl_.begin(); } + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + const_iterator cbegin() const BOOST_NOEXCEPT { return impl_.begin(); } + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + const_iterator end() const BOOST_NOEXCEPT { return impl_.end(); } + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + const_iterator cend() const BOOST_NOEXCEPT { return impl_.end(); } + + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return impl_.rbegin(); } + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return impl_.rbegin(); } + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + const_reverse_iterator rend() const BOOST_NOEXCEPT { return impl_.rend(); } + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + const_reverse_iterator crend() const BOOST_NOEXCEPT { return impl_.rend(); } + + + /// @brief Allows to check that stack trace capturing was successful. + /// @returns `true` if `this->size() != 0` + /// + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /// @brief Allows to check that stack trace failed. + /// @returns `true` if `this->size() == 0` + /// + /// @b Complexity: O(1) + /// + /// @b Async-Handler-Safety: Safe. + bool empty() const BOOST_NOEXCEPT { return !size(); } + + /// @cond + bool operator!() const BOOST_NOEXCEPT { return !size(); } + /// @endcond + + const std::vector& as_vector() const BOOST_NOEXCEPT { + return impl_; + } + + /// Constructs stacktrace from basic_istreamable that references the dumped stacktrace. Terminating zero frame is discarded. + /// + /// @b Complexity: O(N) + template + static basic_stacktrace from_dump(std::basic_istream& in, const allocator_type& a = allocator_type()) { + typedef typename std::basic_istream::pos_type pos_type; + basic_stacktrace ret(0, 0, a); + + // reserving space + const pos_type pos = in.tellg(); + in.seekg(0, in.end); + const std::size_t frames_count = frames_count_from_buffer_size(static_cast(in.tellg())); + in.seekg(pos); + + if (!frames_count) { + return ret; + } + + native_frame_ptr_t ptr = 0; + ret.impl_.reserve(frames_count); + while (in.read(reinterpret_cast(&ptr), sizeof(ptr))) { + if (!ptr) { + break; + } + + ret.impl_.push_back(frame(ptr)); + } + + return ret; + } + + /// Constructs stacktrace from raw memory dump. Terminating zero frame is discarded. + /// + /// @param begin Beginning of the memory where the stacktrace was saved using the boost::stacktrace::safe_dump_to + /// + /// @param buffer_size_in_bytes Size of the memory. Usually the same value that was passed to the boost::stacktrace::safe_dump_to + /// + /// @b Complexity: O(size) in worst case + static basic_stacktrace from_dump(const void* begin, std::size_t buffer_size_in_bytes, const allocator_type& a = allocator_type()) { + basic_stacktrace ret(0, 0, a); + const native_frame_ptr_t* first = static_cast(begin); + const std::size_t frames_count = frames_count_from_buffer_size(buffer_size_in_bytes); + if (!frames_count) { + return ret; + } + + const native_frame_ptr_t* const last = first + frames_count; + ret.impl_.reserve(frames_count); + for (; first != last; ++first) { + if (!*first) { + break; + } + + ret.impl_.push_back(frame(*first)); + } + + return ret; + } +}; + +/// @brief Compares stacktraces for less, order is platform dependent. +/// +/// @b Complexity: Amortized O(1); worst case O(size()) +/// +/// @b Async-Handler-Safety: Safe. +template +bool operator< (const basic_stacktrace& lhs, const basic_stacktrace& rhs) BOOST_NOEXCEPT { + return lhs.size() < rhs.size() || (lhs.size() == rhs.size() && lhs.as_vector() < rhs.as_vector()); +} + +/// @brief Compares stacktraces for equality. +/// +/// @b Complexity: Amortized O(1); worst case O(size()) +/// +/// @b Async-Handler-Safety: Safe. +template +bool operator==(const basic_stacktrace& lhs, const basic_stacktrace& rhs) BOOST_NOEXCEPT { + return lhs.as_vector() == rhs.as_vector(); +} + + +/// Comparison operators that provide platform dependant ordering and have amortized O(1) complexity; O(size()) worst case complexity; are Async-Handler-Safe. +template +bool operator> (const basic_stacktrace& lhs, const basic_stacktrace& rhs) BOOST_NOEXCEPT { + return rhs < lhs; +} + +template +bool operator<=(const basic_stacktrace& lhs, const basic_stacktrace& rhs) BOOST_NOEXCEPT { + return !(lhs > rhs); +} + +template +bool operator>=(const basic_stacktrace& lhs, const basic_stacktrace& rhs) BOOST_NOEXCEPT { + return !(lhs < rhs); +} + +template +bool operator!=(const basic_stacktrace& lhs, const basic_stacktrace& rhs) BOOST_NOEXCEPT { + return !(lhs == rhs); +} + +/// Fast hashing support, O(st.size()) complexity; Async-Handler-Safe. +template +std::size_t hash_value(const basic_stacktrace& st) BOOST_NOEXCEPT { + return boost::hash_range(st.as_vector().begin(), st.as_vector().end()); +} + +/// Returns std::string with the stacktrace in a human readable format; unsafe to use in async handlers. +template +std::string to_string(const basic_stacktrace& bt) { + if (!bt) { + return std::string(); + } + + return boost::stacktrace::detail::to_string(&bt.as_vector()[0], bt.size()); +} + +/// Outputs stacktrace in a human readable format to the output stream `os`; unsafe to use in async handlers. +template +std::basic_ostream& operator<<(std::basic_ostream& os, const basic_stacktrace& bt) { + return os << boost::stacktrace::to_string(bt); +} + +/// This is the typedef to use unless you'd like to provide a specific allocator to boost::stacktrace::basic_stacktrace. +typedef basic_stacktrace<> stacktrace; + +}} // namespace boost::stacktrace + +#ifdef BOOST_INTEL +# pragma warning(pop) +#endif + +#endif // BOOST_STACKTRACE_STACKTRACE_HPP diff --git a/boost/stacktrace/stacktrace_fwd.hpp b/boost/stacktrace/stacktrace_fwd.hpp new file mode 100644 index 0000000..a48a6b5 --- /dev/null +++ b/boost/stacktrace/stacktrace_fwd.hpp @@ -0,0 +1,28 @@ +// Copyright Antony Polukhin, 2016-2023. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STACKTRACE_STACKTRACE_FWD_HPP +#define BOOST_STACKTRACE_STACKTRACE_FWD_HPP + +#include +#include + +/// @file stacktrace_fwd.hpp This header contains only forward declarations of +/// boost::stacktrace::frame, boost::stacktrace::basic_stacktrace, boost::stacktrace::stacktrace +/// and does not include any other Boost headers. + +/// @cond +namespace boost { namespace stacktrace { + +class frame; +template > class basic_stacktrace; +typedef basic_stacktrace<> stacktrace; + +}} // namespace boost::stacktrace +/// @endcond + + +#endif // BOOST_STACKTRACE_STACKTRACE_FWD_HPP diff --git a/boost/winapi/access_rights.hpp b/boost/winapi/access_rights.hpp new file mode 100644 index 0000000..a95c01d --- /dev/null +++ b/boost/winapi/access_rights.hpp @@ -0,0 +1,84 @@ +/* + * Copyright 2016 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_ACCESS_RIGHTS_HPP_INCLUDED_ +#define BOOST_WINAPI_ACCESS_RIGHTS_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace winapi { + +#if defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ DELETE_ = DELETE; +BOOST_CONSTEXPR_OR_CONST DWORD_ READ_CONTROL_ = READ_CONTROL; +BOOST_CONSTEXPR_OR_CONST DWORD_ WRITE_DAC_ = WRITE_DAC; +BOOST_CONSTEXPR_OR_CONST DWORD_ WRITE_OWNER_ = WRITE_OWNER; +BOOST_CONSTEXPR_OR_CONST DWORD_ SYNCHRONIZE_ = SYNCHRONIZE; + +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_ALL_ = STANDARD_RIGHTS_ALL; +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_EXECUTE_ = STANDARD_RIGHTS_EXECUTE; +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_READ_ = STANDARD_RIGHTS_READ; +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_REQUIRED_ = STANDARD_RIGHTS_REQUIRED; +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_WRITE_ = STANDARD_RIGHTS_WRITE; + +BOOST_CONSTEXPR_OR_CONST DWORD_ SPECIFIC_RIGHTS_ALL_ = SPECIFIC_RIGHTS_ALL; + +BOOST_CONSTEXPR_OR_CONST DWORD_ ACCESS_SYSTEM_SECURITY_ = ACCESS_SYSTEM_SECURITY; + +BOOST_CONSTEXPR_OR_CONST DWORD_ MAXIMUM_ALLOWED_ = MAXIMUM_ALLOWED; + +BOOST_CONSTEXPR_OR_CONST DWORD_ GENERIC_ALL_ = GENERIC_ALL; +BOOST_CONSTEXPR_OR_CONST DWORD_ GENERIC_EXECUTE_ = GENERIC_EXECUTE; +BOOST_CONSTEXPR_OR_CONST DWORD_ GENERIC_WRITE_ = GENERIC_WRITE; +BOOST_CONSTEXPR_OR_CONST DWORD_ GENERIC_READ_ = GENERIC_READ; + +typedef ::ACCESS_MASK ACCESS_MASK_; +typedef ::PACCESS_MASK PACCESS_MASK_; + +#else // defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ DELETE_ = 0x00010000; +BOOST_CONSTEXPR_OR_CONST DWORD_ READ_CONTROL_ = 0x00020000; +BOOST_CONSTEXPR_OR_CONST DWORD_ WRITE_DAC_ = 0x00040000; +BOOST_CONSTEXPR_OR_CONST DWORD_ WRITE_OWNER_ = 0x00080000; +BOOST_CONSTEXPR_OR_CONST DWORD_ SYNCHRONIZE_ = 0x00100000; + +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_ALL_ = 0x001F0000; +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_EXECUTE_ = READ_CONTROL_; +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_READ_ = READ_CONTROL_; +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_REQUIRED_ = 0x000F0000; +BOOST_CONSTEXPR_OR_CONST DWORD_ STANDARD_RIGHTS_WRITE_ = READ_CONTROL_; + +BOOST_CONSTEXPR_OR_CONST DWORD_ SPECIFIC_RIGHTS_ALL_ = 0x0000FFFF; + +BOOST_CONSTEXPR_OR_CONST DWORD_ ACCESS_SYSTEM_SECURITY_ = 0x01000000; + +BOOST_CONSTEXPR_OR_CONST DWORD_ MAXIMUM_ALLOWED_ = 0x02000000; + +BOOST_CONSTEXPR_OR_CONST DWORD_ GENERIC_ALL_ = 0x10000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ GENERIC_EXECUTE_ = 0x20000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ GENERIC_WRITE_ = 0x40000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ GENERIC_READ_ = 0x80000000; + +typedef DWORD_ ACCESS_MASK_; +typedef ACCESS_MASK_* PACCESS_MASK_; + +#endif // defined( BOOST_USE_WINDOWS_H ) + +} +} + +#include + +#endif // BOOST_WINAPI_ACCESS_RIGHTS_HPP_INCLUDED_ diff --git a/boost/winapi/dll.hpp b/boost/winapi/dll.hpp new file mode 100644 index 0000000..a4bb8d0 --- /dev/null +++ b/boost/winapi/dll.hpp @@ -0,0 +1,199 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2014 Renato Tegon Forti, Antony Polukhin + * Copyright 2015, 2020 Andrey Semashev + * Copyright 2015 Antony Polukhin + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_DLL_HPP_INCLUDED_ +#define BOOST_WINAPI_DLL_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::HMODULE_ BOOST_WINAPI_WINAPI_CC +LoadLibraryA(boost::winapi::LPCSTR_ lpFileName); + +BOOST_WINAPI_IMPORT boost::winapi::HMODULE_ BOOST_WINAPI_WINAPI_CC +LoadLibraryExA( + boost::winapi::LPCSTR_ lpFileName, + boost::winapi::HANDLE_ hFile, + boost::winapi::DWORD_ dwFlags +); + +BOOST_WINAPI_IMPORT boost::winapi::HMODULE_ BOOST_WINAPI_WINAPI_CC +GetModuleHandleA(boost::winapi::LPCSTR_ lpFileName); + +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +GetModuleFileNameA( + boost::winapi::HMODULE_ hModule, + boost::winapi::LPSTR_ lpFilename, + boost::winapi::DWORD_ nSize +); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HMODULE_ BOOST_WINAPI_WINAPI_CC +LoadLibraryW(boost::winapi::LPCWSTR_ lpFileName); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HMODULE_ BOOST_WINAPI_WINAPI_CC +LoadLibraryExW( + boost::winapi::LPCWSTR_ lpFileName, + boost::winapi::HANDLE_ hFile, + boost::winapi::DWORD_ dwFlags +); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HMODULE_ BOOST_WINAPI_WINAPI_CC +GetModuleHandleW(boost::winapi::LPCWSTR_ lpFileName); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +GetModuleFileNameW( + boost::winapi::HMODULE_ hModule, + boost::winapi::LPWSTR_ lpFilename, + boost::winapi::DWORD_ nSize +); + +struct _MEMORY_BASIC_INFORMATION; + +#if !defined( BOOST_WINAPI_IS_MINGW ) +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::SIZE_T_ BOOST_WINAPI_WINAPI_CC +VirtualQuery( + boost::winapi::LPCVOID_ lpAddress, + ::_MEMORY_BASIC_INFORMATION* lpBuffer, + boost::winapi::SIZE_T_ dwLength +); +#else // !defined( BOOST_WINAPI_IS_MINGW ) +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +VirtualQuery( + boost::winapi::LPCVOID_ lpAddress, + ::_MEMORY_BASIC_INFORMATION* lpBuffer, + boost::winapi::DWORD_ dwLength +); +#endif // !defined( BOOST_WINAPI_IS_MINGW ) +} // extern "C" +#endif // #if !defined( BOOST_USE_WINDOWS_H ) + +namespace boost { +namespace winapi { + +typedef struct BOOST_MAY_ALIAS MEMORY_BASIC_INFORMATION_ { + PVOID_ BaseAddress; + PVOID_ AllocationBase; + DWORD_ AllocationProtect; + SIZE_T_ RegionSize; + DWORD_ State; + DWORD_ Protect; + DWORD_ Type; +} *PMEMORY_BASIC_INFORMATION_; + +#if defined( BOOST_USE_WINDOWS_H ) +BOOST_CONSTEXPR_OR_CONST DWORD_ DONT_RESOLVE_DLL_REFERENCES_ = DONT_RESOLVE_DLL_REFERENCES; +BOOST_CONSTEXPR_OR_CONST DWORD_ LOAD_WITH_ALTERED_SEARCH_PATH_ = LOAD_WITH_ALTERED_SEARCH_PATH; +#else // defined( BOOST_USE_WINDOWS_H ) +BOOST_CONSTEXPR_OR_CONST DWORD_ DONT_RESOLVE_DLL_REFERENCES_ = 0x00000001; +BOOST_CONSTEXPR_OR_CONST DWORD_ LOAD_WITH_ALTERED_SEARCH_PATH_ = 0x00000008; +#endif // defined( BOOST_USE_WINDOWS_H ) + +// This one is not defined by MinGW +BOOST_CONSTEXPR_OR_CONST DWORD_ LOAD_IGNORE_CODE_AUTHZ_LEVEL_ = 0x00000010; + +#if !defined( BOOST_NO_ANSI_APIS ) +using ::LoadLibraryA; +using ::LoadLibraryExA; +using ::GetModuleHandleA; +using ::GetModuleFileNameA; +#endif // !defined( BOOST_NO_ANSI_APIS ) +using ::LoadLibraryW; +using ::LoadLibraryExW; +using ::GetModuleHandleW; +using ::GetModuleFileNameW; + +BOOST_FORCEINLINE SIZE_T_ VirtualQuery(LPCVOID_ lpAddress, MEMORY_BASIC_INFORMATION_* lpBuffer, SIZE_T_ dwLength) +{ + return ::VirtualQuery(lpAddress, reinterpret_cast< ::_MEMORY_BASIC_INFORMATION* >(lpBuffer), dwLength); +} + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_FORCEINLINE HMODULE_ load_library(LPCSTR_ lpFileName) +{ + return ::LoadLibraryA(lpFileName); +} + +BOOST_FORCEINLINE HMODULE_ load_library_ex(LPCSTR_ lpFileName, HANDLE_ hFile, DWORD_ dwFlags) +{ + return ::LoadLibraryExA(lpFileName, hFile, dwFlags); +} + +BOOST_FORCEINLINE HMODULE_ get_module_handle(LPCSTR_ lpFileName) +{ + return ::GetModuleHandleA(lpFileName); +} + +BOOST_FORCEINLINE DWORD_ get_module_file_name(HMODULE_ hModule, LPSTR_ lpFilename, DWORD_ nSize) +{ + return ::GetModuleFileNameA(hModule, lpFilename, nSize); +} +#endif // #if !defined( BOOST_NO_ANSI_APIS ) + +BOOST_FORCEINLINE HMODULE_ load_library(LPCWSTR_ lpFileName) +{ + return ::LoadLibraryW(lpFileName); +} + +BOOST_FORCEINLINE HMODULE_ load_library_ex(LPCWSTR_ lpFileName, HANDLE_ hFile, DWORD_ dwFlags) +{ + return ::LoadLibraryExW(lpFileName, hFile, dwFlags); +} + +BOOST_FORCEINLINE HMODULE_ get_module_handle(LPCWSTR_ lpFileName) +{ + return ::GetModuleHandleW(lpFileName); +} + +BOOST_FORCEINLINE DWORD_ get_module_file_name(HMODULE_ hModule, LPWSTR_ lpFilename, DWORD_ nSize) +{ + return ::GetModuleFileNameW(hModule, lpFilename, nSize); +} + +} // namespace winapi +} // namespace boost + +#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM + +// +// FreeLibrary is in a different partition set (slightly) +// + +#if BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM + +#if !defined(BOOST_USE_WINDOWS_H) +extern "C" { +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +FreeLibrary(boost::winapi::HMODULE_ hModule); +} +#endif + +namespace boost { +namespace winapi { +using ::FreeLibrary; +} +} + +#endif // BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM + +#include + +#endif // BOOST_WINAPI_DLL_HPP_INCLUDED_ diff --git a/boost/winapi/file_management.hpp b/boost/winapi/file_management.hpp new file mode 100644 index 0000000..b4da8f8 --- /dev/null +++ b/boost/winapi/file_management.hpp @@ -0,0 +1,597 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * Copyright 2016 Jorge Lodos + * Copyright 2017 James E. King, III + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_FILE_MANAGEMENT_HPP_INCLUDED_ +#define BOOST_WINAPI_FILE_MANAGEMENT_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +/* + * UWP: + * API SDK 8 SDK 10 _WIN32_WINNT + * AreFileApisANSI DESKTOP - DESKTOP | SYSTEM + * CreateFile DESKTOP - DESKTOP | SYSTEM + * DeleteFile APP - APP | SYSTEM + * FindClose APP - APP | SYSTEM + * FindFirstFile DESKTOP > APP | SYSTEM + * FindNextFile DESKTOP > APP | SYSTEM + * GetFileAttributes DESKTOP > APP | SYSTEM + * GetFileInformationByHandle DESKTOP - DESKTOP | SYSTEM + * GetFileSizeEx DESKTOP > APP | SYSTEM + * LockFile DESKTOP - DESKTOP | SYSTEM + * MoveFileEx APP - APP | SYSTEM + * ReadFile APP - APP | SYSTEM + * SetEndOfFile APP - APP | SYSTEM + * SetFilePointer DESKTOP > APP | SYSTEM + * SetFileValidData DESKTOP - DESKTOP | SYSTEM >= 0x0501 + * UnlockFile DESKTOP - DESKTOP | SYSTEM + * WriteFile APP - APP | SYSTEM + */ + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { + +#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +AreFileApisANSI(BOOST_WINAPI_DETAIL_VOID); + +BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +CreateFileA( + boost::winapi::LPCSTR_ lpFileName, + boost::winapi::DWORD_ dwDesiredAccess, + boost::winapi::DWORD_ dwShareMode, + ::_SECURITY_ATTRIBUTES* lpSecurityAttributes, + boost::winapi::DWORD_ dwCreationDisposition, + boost::winapi::DWORD_ dwFlagsAndAttributes, + boost::winapi::HANDLE_ hTemplateFile); + +struct _WIN32_FIND_DATAA; +BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +FindFirstFileA(boost::winapi::LPCSTR_ lpFileName, ::_WIN32_FIND_DATAA* lpFindFileData); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +FindNextFileA(boost::winapi::HANDLE_ hFindFile, ::_WIN32_FIND_DATAA* lpFindFileData); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +CreateFileW( + boost::winapi::LPCWSTR_ lpFileName, + boost::winapi::DWORD_ dwDesiredAccess, + boost::winapi::DWORD_ dwShareMode, + ::_SECURITY_ATTRIBUTES* lpSecurityAttributes, + boost::winapi::DWORD_ dwCreationDisposition, + boost::winapi::DWORD_ dwFlagsAndAttributes, + boost::winapi::HANDLE_ hTemplateFile); + +struct _WIN32_FIND_DATAW; +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +FindFirstFileW(boost::winapi::LPCWSTR_ lpFileName, ::_WIN32_FIND_DATAW* lpFindFileData); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +FindNextFileW(boost::winapi::HANDLE_ hFindFile, ::_WIN32_FIND_DATAW* lpFindFileData); + +struct _BY_HANDLE_FILE_INFORMATION; +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +GetFileInformationByHandle( + boost::winapi::HANDLE_ hFile, + ::_BY_HANDLE_FILE_INFORMATION* lpFileInformation); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +LockFile( + boost::winapi::HANDLE_ hFile, + boost::winapi::DWORD_ dwFileOffsetLow, + boost::winapi::DWORD_ dwFileOffsetHigh, + boost::winapi::DWORD_ nNumberOfBytesToLockLow, + boost::winapi::DWORD_ nNumberOfBytesToLockHigh); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +LockFileEx( + boost::winapi::HANDLE_ hFile, + boost::winapi::DWORD_ dwFlags, + boost::winapi::DWORD_ dwReserved, + boost::winapi::DWORD_ nNumberOfBytesToLockLow, + boost::winapi::DWORD_ nNumberOfBytesToLockHigh, + ::_OVERLAPPED* lpOverlapped); + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WINXP +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +SetFileValidData( + boost::winapi::HANDLE_ hFile, + boost::winapi::LONGLONG_ ValidDataLength); +#endif + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +UnlockFile( + boost::winapi::HANDLE_ hFile, + boost::winapi::DWORD_ dwFileOffsetLow, + boost::winapi::DWORD_ dwFileOffsetHigh, + boost::winapi::DWORD_ nNumberOfBytesToUnlockLow, + boost::winapi::DWORD_ nNumberOfBytesToUnlockHigh); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +UnlockFileEx( + boost::winapi::HANDLE_ hFile, + boost::winapi::DWORD_ dwReserved, + boost::winapi::DWORD_ nNumberOfBytesToUnlockLow, + boost::winapi::DWORD_ nNumberOfBytesToUnlockHigh, + ::_OVERLAPPED* lpOverlapped); +#endif + +#if BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +DeleteFileA(boost::winapi::LPCSTR_ lpFileName); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +MoveFileExA( + boost::winapi::LPCSTR_ lpExistingFileName, + boost::winapi::LPCSTR_ lpNewFileName, + boost::winapi::DWORD_ dwFlags); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +DeleteFileW(boost::winapi::LPCWSTR_ lpFileName); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +FindClose(boost::winapi::HANDLE_ hFindFile); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +MoveFileExW( + boost::winapi::LPCWSTR_ lpExistingFileName, + boost::winapi::LPCWSTR_ lpNewFileName, + boost::winapi::DWORD_ dwFlags); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +ReadFile( + boost::winapi::HANDLE_ hFile, + boost::winapi::LPVOID_ lpBuffer, + boost::winapi::DWORD_ nNumberOfBytesToRead, + boost::winapi::LPDWORD_ lpNumberOfBytesRead, + ::_OVERLAPPED* lpOverlapped); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +SetEndOfFile(boost::winapi::HANDLE_ hFile); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +WriteFile( + boost::winapi::HANDLE_ hFile, + boost::winapi::LPCVOID_ lpBuffer, + boost::winapi::DWORD_ nNumberOfBytesToWrite, + boost::winapi::LPDWORD_ lpNumberOfBytesWritten, + ::_OVERLAPPED* lpOverlapped); +#endif // BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +GetFileAttributesA(boost::winapi::LPCSTR_ lpFileName); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +GetFileAttributesW(boost::winapi::LPCWSTR_ lpFileName); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +GetFileSizeEx(boost::winapi::HANDLE_ hFile, ::_LARGE_INTEGER* lpFileSize); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +SetFilePointer( + boost::winapi::HANDLE_ hFile, + boost::winapi::LONG_ lpDistanceToMove, + boost::winapi::PLONG_ lpDistanceToMoveHigh, + boost::winapi::DWORD_ dwMoveMethod); +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +} // extern "C" +#endif // !defined(BOOST_USE_WINDOWS_H) + +namespace boost { +namespace winapi { + +#if defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ INVALID_FILE_SIZE_ = INVALID_FILE_SIZE; +BOOST_CONSTEXPR_OR_CONST DWORD_ INVALID_SET_FILE_POINTER_ = INVALID_SET_FILE_POINTER; +BOOST_CONSTEXPR_OR_CONST DWORD_ INVALID_FILE_ATTRIBUTES_ = INVALID_FILE_ATTRIBUTES; + +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_READONLY_ = FILE_ATTRIBUTE_READONLY; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_HIDDEN_ = FILE_ATTRIBUTE_HIDDEN; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_SYSTEM_ = FILE_ATTRIBUTE_SYSTEM; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_DIRECTORY_ = FILE_ATTRIBUTE_DIRECTORY; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_ARCHIVE_ = FILE_ATTRIBUTE_ARCHIVE; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_DEVICE_ = FILE_ATTRIBUTE_DEVICE; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_NORMAL_ = FILE_ATTRIBUTE_NORMAL; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_TEMPORARY_ = FILE_ATTRIBUTE_TEMPORARY; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_SPARSE_FILE_ = FILE_ATTRIBUTE_SPARSE_FILE; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_REPARSE_POINT_ = FILE_ATTRIBUTE_REPARSE_POINT; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_COMPRESSED_ = FILE_ATTRIBUTE_COMPRESSED; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_OFFLINE_ = FILE_ATTRIBUTE_OFFLINE; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED_ = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_ENCRYPTED_ = FILE_ATTRIBUTE_ENCRYPTED; + +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_NEW_ = CREATE_NEW; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_ALWAYS_ = CREATE_ALWAYS; +BOOST_CONSTEXPR_OR_CONST DWORD_ OPEN_EXISTING_ = OPEN_EXISTING; +BOOST_CONSTEXPR_OR_CONST DWORD_ OPEN_ALWAYS_ = OPEN_ALWAYS; +BOOST_CONSTEXPR_OR_CONST DWORD_ TRUNCATE_EXISTING_ = TRUNCATE_EXISTING; + +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_SHARE_READ_ = FILE_SHARE_READ; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_SHARE_WRITE_ = FILE_SHARE_WRITE; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_SHARE_DELETE_ = FILE_SHARE_DELETE; + +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_BEGIN_ = FILE_BEGIN; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_CURRENT_ = FILE_CURRENT; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_END_ = FILE_END; + +#else // defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ INVALID_FILE_SIZE_ = ((DWORD_)0xFFFFFFFF); +BOOST_CONSTEXPR_OR_CONST DWORD_ INVALID_SET_FILE_POINTER_ = ((DWORD_)-1); +BOOST_CONSTEXPR_OR_CONST DWORD_ INVALID_FILE_ATTRIBUTES_ = ((DWORD_)-1); + +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_READONLY_ = 0x00000001; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_HIDDEN_ = 0x00000002; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_SYSTEM_ = 0x00000004; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_DIRECTORY_ = 0x00000010; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_ARCHIVE_ = 0x00000020; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_DEVICE_ = 0x00000040; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_NORMAL_ = 0x00000080; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_TEMPORARY_ = 0x00000100; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_SPARSE_FILE_ = 0x00000200; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_REPARSE_POINT_ = 0x00000400; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_COMPRESSED_ = 0x00000800; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_OFFLINE_ = 0x00001000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED_ = 0x00002000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_ENCRYPTED_ = 0x00004000; + +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_NEW_ = 1; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_ALWAYS_ = 2; +BOOST_CONSTEXPR_OR_CONST DWORD_ OPEN_EXISTING_ = 3; +BOOST_CONSTEXPR_OR_CONST DWORD_ OPEN_ALWAYS_ = 4; +BOOST_CONSTEXPR_OR_CONST DWORD_ TRUNCATE_EXISTING_ = 5; + +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_SHARE_READ_ = 0x00000001; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_SHARE_WRITE_ = 0x00000002; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_SHARE_DELETE_ = 0x00000004; + +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_BEGIN_ = 0; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_CURRENT_ = 1; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_END_ = 2; + +#endif // defined( BOOST_USE_WINDOWS_H ) + +// Some of these constants are not defined by Windows SDK in MinGW or older MSVC +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_WRITE_THROUGH_ = 0x80000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_OVERLAPPED_ = 0x40000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_NO_BUFFERING_ = 0x20000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_RANDOM_ACCESS_ = 0x10000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_SEQUENTIAL_SCAN_ = 0x08000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_DELETE_ON_CLOSE_ = 0x04000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_BACKUP_SEMANTICS_ = 0x02000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_POSIX_SEMANTICS_ = 0x01000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_SESSION_AWARE_ = 0x00800000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_OPEN_REPARSE_POINT_ = 0x00200000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_OPEN_NO_RECALL_ = 0x00100000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_FIRST_PIPE_INSTANCE_ = 0x00080000; + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN8 +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_FLAG_OPEN_REQUIRING_OPLOCK_ = 0x00040000; +#endif + +// This constant is not defined in Windows SDK up until 6.0A +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_VIRTUAL_ = 0x00010000; + +// These constants are not defined in Windows SDK up until 8.0 and MinGW/MinGW-w64 (as of 2016-02-14). +// They are documented to be supported only since Windows 8/Windows Server 2012 +// but defined unconditionally. +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_INTEGRITY_STREAM_ = 0x00008000; +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_NO_SCRUB_DATA_ = 0x00020000; +// Undocumented +BOOST_CONSTEXPR_OR_CONST DWORD_ FILE_ATTRIBUTE_EA_ = 0x00040000; + +#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM +#if !defined( BOOST_NO_ANSI_APIS ) +using ::AreFileApisANSI; + +BOOST_FORCEINLINE HANDLE_ CreateFileA( + LPCSTR_ lpFileName, + DWORD_ dwDesiredAccess, + DWORD_ dwShareMode, + SECURITY_ATTRIBUTES_* lpSecurityAttributes, + DWORD_ dwCreationDisposition, + DWORD_ dwFlagsAndAttributes, + HANDLE_ hTemplateFile) +{ + return ::CreateFileA( + lpFileName, + dwDesiredAccess, + dwShareMode, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes), + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); +} + +BOOST_FORCEINLINE HANDLE_ create_file( + LPCSTR_ lpFileName, + DWORD_ dwDesiredAccess, + DWORD_ dwShareMode, + SECURITY_ATTRIBUTES_* lpSecurityAttributes, + DWORD_ dwCreationDisposition, + DWORD_ dwFlagsAndAttributes, + HANDLE_ hTemplateFile) +{ + return ::CreateFileA( + lpFileName, + dwDesiredAccess, + dwShareMode, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes), + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); +} + +typedef struct BOOST_MAY_ALIAS _WIN32_FIND_DATAA { + DWORD_ dwFileAttributes; + FILETIME_ ftCreationTime; + FILETIME_ ftLastAccessTime; + FILETIME_ ftLastWriteTime; + DWORD_ nFileSizeHigh; + DWORD_ nFileSizeLow; + DWORD_ dwReserved0; + DWORD_ dwReserved1; + CHAR_ cFileName[MAX_PATH_]; + CHAR_ cAlternateFileName[14]; +#ifdef _MAC + DWORD_ dwFileType; + DWORD_ dwCreatorType; + WORD_ wFinderFlags; +#endif +} WIN32_FIND_DATAA_, *PWIN32_FIND_DATAA_, *LPWIN32_FIND_DATAA_; + +BOOST_FORCEINLINE HANDLE_ FindFirstFileA(LPCSTR_ lpFileName, WIN32_FIND_DATAA_* lpFindFileData) +{ + return ::FindFirstFileA(lpFileName, reinterpret_cast< ::_WIN32_FIND_DATAA* >(lpFindFileData)); +} + +BOOST_FORCEINLINE HANDLE_ find_first_file(LPCSTR_ lpFileName, WIN32_FIND_DATAA_* lpFindFileData) +{ + return ::FindFirstFileA(lpFileName, reinterpret_cast< ::_WIN32_FIND_DATAA* >(lpFindFileData)); +} + +BOOST_FORCEINLINE BOOL_ FindNextFileA(HANDLE_ hFindFile, WIN32_FIND_DATAA_* lpFindFileData) +{ + return ::FindNextFileA(hFindFile, reinterpret_cast< ::_WIN32_FIND_DATAA* >(lpFindFileData)); +} + +BOOST_FORCEINLINE BOOL_ find_next_file(HANDLE_ hFindFile, WIN32_FIND_DATAA_* lpFindFileData) +{ + return ::FindNextFileA(hFindFile, reinterpret_cast< ::_WIN32_FIND_DATAA* >(lpFindFileData)); +} + +#endif // !defined( BOOST_NO_ANSI_APIS ) + +BOOST_FORCEINLINE HANDLE_ CreateFileW( + LPCWSTR_ lpFileName, + DWORD_ dwDesiredAccess, + DWORD_ dwShareMode, + SECURITY_ATTRIBUTES_* lpSecurityAttributes, + DWORD_ dwCreationDisposition, + DWORD_ dwFlagsAndAttributes, + HANDLE_ hTemplateFile) +{ + return ::CreateFileW( + lpFileName, + dwDesiredAccess, + dwShareMode, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes), + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); +} + +BOOST_FORCEINLINE HANDLE_ create_file( + LPCWSTR_ lpFileName, + DWORD_ dwDesiredAccess, + DWORD_ dwShareMode, + SECURITY_ATTRIBUTES_* lpSecurityAttributes, + DWORD_ dwCreationDisposition, + DWORD_ dwFlagsAndAttributes, + HANDLE_ hTemplateFile) +{ + return ::CreateFileW( + lpFileName, + dwDesiredAccess, + dwShareMode, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes), + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); +} + +typedef struct BOOST_MAY_ALIAS _WIN32_FIND_DATAW { + DWORD_ dwFileAttributes; + FILETIME_ ftCreationTime; + FILETIME_ ftLastAccessTime; + FILETIME_ ftLastWriteTime; + DWORD_ nFileSizeHigh; + DWORD_ nFileSizeLow; + DWORD_ dwReserved0; + DWORD_ dwReserved1; + WCHAR_ cFileName[MAX_PATH_]; + WCHAR_ cAlternateFileName[14]; +#ifdef _MAC + DWORD_ dwFileType; + DWORD_ dwCreatorType; + WORD_ wFinderFlags; +#endif +} WIN32_FIND_DATAW_, *PWIN32_FIND_DATAW_, *LPWIN32_FIND_DATAW_; + +typedef struct BOOST_MAY_ALIAS _BY_HANDLE_FILE_INFORMATION { + DWORD_ dwFileAttributes; + FILETIME_ ftCreationTime; + FILETIME_ ftLastAccessTime; + FILETIME_ ftLastWriteTime; + DWORD_ dwVolumeSerialNumber; + DWORD_ nFileSizeHigh; + DWORD_ nFileSizeLow; + DWORD_ nNumberOfLinks; + DWORD_ nFileIndexHigh; + DWORD_ nFileIndexLow; +} BY_HANDLE_FILE_INFORMATION_, *PBY_HANDLE_FILE_INFORMATION_, *LPBY_HANDLE_FILE_INFORMATION_; + +BOOST_FORCEINLINE HANDLE_ FindFirstFileW(LPCWSTR_ lpFileName, WIN32_FIND_DATAW_* lpFindFileData) +{ + return ::FindFirstFileW(lpFileName, reinterpret_cast< ::_WIN32_FIND_DATAW* >(lpFindFileData)); +} + +BOOST_FORCEINLINE HANDLE_ find_first_file(LPCWSTR_ lpFileName, WIN32_FIND_DATAW_* lpFindFileData) +{ + return ::FindFirstFileW(lpFileName, reinterpret_cast< ::_WIN32_FIND_DATAW* >(lpFindFileData)); +} + +BOOST_FORCEINLINE BOOL_ FindNextFileW(HANDLE_ hFindFile, WIN32_FIND_DATAW_* lpFindFileData) +{ + return ::FindNextFileW(hFindFile, reinterpret_cast< ::_WIN32_FIND_DATAW* >(lpFindFileData)); +} + +BOOST_FORCEINLINE BOOL_ find_next_file(HANDLE_ hFindFile, WIN32_FIND_DATAW_* lpFindFileData) +{ + return ::FindNextFileW(hFindFile, reinterpret_cast< ::_WIN32_FIND_DATAW* >(lpFindFileData)); +} + +BOOST_FORCEINLINE BOOL_ GetFileInformationByHandle(HANDLE_ h, BY_HANDLE_FILE_INFORMATION_* info) +{ + return ::GetFileInformationByHandle(h, reinterpret_cast< ::_BY_HANDLE_FILE_INFORMATION* >(info)); +} + +using ::LockFile; + +BOOST_FORCEINLINE BOOL_ LockFileEx( + HANDLE_ hFile, + DWORD_ dwFlags, + DWORD_ dwReserved, + DWORD_ nNumberOfBytesToLockLow, + DWORD_ nNumberOfBytesToLockHigh, + OVERLAPPED_* lpOverlapped) +{ + return ::LockFileEx(hFile, dwFlags, dwReserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped)); +} + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WINXP +using ::SetFileValidData; +#endif + +using ::UnlockFile; + +BOOST_FORCEINLINE BOOL_ UnlockFileEx( + HANDLE_ hFile, + DWORD_ dwReserved, + DWORD_ nNumberOfBytesToUnlockLow, + DWORD_ nNumberOfBytesToUnlockHigh, + OVERLAPPED_* lpOverlapped) +{ + return ::UnlockFileEx(hFile, dwReserved, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped)); +} +#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM + +#if BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM +#if !defined( BOOST_NO_ANSI_APIS ) +using ::DeleteFileA; + +BOOST_FORCEINLINE BOOL_ delete_file(LPCSTR_ lpFileName) +{ + return ::DeleteFileA(lpFileName); +} + +using ::MoveFileExA; + +BOOST_FORCEINLINE BOOL_ move_file(LPCSTR_ lpExistingFileName, LPCSTR_ lpNewFileName, DWORD_ dwFlags) +{ + return ::MoveFileExA(lpExistingFileName, lpNewFileName, dwFlags); +} + +#endif +using ::DeleteFileW; + +BOOST_FORCEINLINE BOOL_ delete_file(LPCWSTR_ lpFileName) +{ + return ::DeleteFileW(lpFileName); +} + +using ::FindClose; +using ::MoveFileExW; + +BOOST_FORCEINLINE BOOL_ move_file(LPCWSTR_ lpExistingFileName, LPCWSTR_ lpNewFileName, DWORD_ dwFlags) +{ + return ::MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags); +} + +BOOST_FORCEINLINE BOOL_ ReadFile( + HANDLE_ hFile, + LPVOID_ lpBuffer, + DWORD_ nNumberOfBytesToWrite, + LPDWORD_ lpNumberOfBytesWritten, + OVERLAPPED_* lpOverlapped) +{ + return ::ReadFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped)); +} + +using ::SetEndOfFile; + +BOOST_FORCEINLINE BOOL_ WriteFile( + HANDLE_ hFile, + LPCVOID_ lpBuffer, + DWORD_ nNumberOfBytesToWrite, + LPDWORD_ lpNumberOfBytesWritten, + OVERLAPPED_* lpOverlapped) +{ + return ::WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped)); +} +#endif // BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +#if !defined( BOOST_NO_ANSI_APIS ) +using ::GetFileAttributesA; + +BOOST_FORCEINLINE DWORD_ get_file_attributes(LPCSTR_ lpFileName) +{ + return ::GetFileAttributesA(lpFileName); +} +#endif +using ::GetFileAttributesW; + +BOOST_FORCEINLINE DWORD_ get_file_attributes(LPCWSTR_ lpFileName) +{ + return ::GetFileAttributesW(lpFileName); +} + +BOOST_FORCEINLINE BOOL_ GetFileSizeEx(HANDLE_ hFile, LARGE_INTEGER_* lpFileSize) +{ + return ::GetFileSizeEx(hFile, reinterpret_cast< ::_LARGE_INTEGER* >(lpFileSize)); +} + +using ::SetFilePointer; +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +} +} + +#include + +#endif // BOOST_WINAPI_FILE_MANAGEMENT_HPP_INCLUDED_ diff --git a/boost/winapi/get_proc_address.hpp b/boost/winapi/get_proc_address.hpp new file mode 100644 index 0000000..2240930 --- /dev/null +++ b/boost/winapi/get_proc_address.hpp @@ -0,0 +1,81 @@ +/* + * Copyright 2020 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_GET_PROC_ADDRESS_HPP_INCLUDED_ +#define BOOST_WINAPI_GET_PROC_ADDRESS_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM + +#include + +#if !defined(BOOST_USE_WINDOWS_H) +namespace boost { namespace winapi { +#ifdef _WIN64 +typedef INT_PTR_ (BOOST_WINAPI_WINAPI_CC *FARPROC_)(); +typedef INT_PTR_ (BOOST_WINAPI_WINAPI_CC *NEARPROC_)(); +typedef INT_PTR_ (BOOST_WINAPI_WINAPI_CC *PROC_)(); +#else +typedef int (BOOST_WINAPI_WINAPI_CC *FARPROC_)(); +typedef int (BOOST_WINAPI_WINAPI_CC *NEARPROC_)(); +typedef int (BOOST_WINAPI_WINAPI_CC *PROC_)(); +#endif // _WIN64 +}} // namespace boost::winapi + +extern "C" { +#if !defined(UNDER_CE) +BOOST_WINAPI_IMPORT boost::winapi::FARPROC_ BOOST_WINAPI_WINAPI_CC +GetProcAddress(boost::winapi::HMODULE_ hModule, boost::winapi::LPCSTR_ lpProcName); +#else +// On Windows CE there are two functions: GetProcAddressA (since Windows CE 3.0) and GetProcAddressW. +// GetProcAddress is a macro that is _always_ defined to GetProcAddressW. +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::FARPROC_ BOOST_WINAPI_WINAPI_CC +GetProcAddressA(boost::winapi::HMODULE_ hModule, boost::winapi::LPCSTR_ lpProcName); +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::FARPROC_ BOOST_WINAPI_WINAPI_CC +GetProcAddressW(boost::winapi::HMODULE_ hModule, boost::winapi::LPCWSTR_ lpProcName); +#endif +} // extern "C" +#endif // !defined(BOOST_USE_WINDOWS_H) + +namespace boost { +namespace winapi { + +#if defined(BOOST_USE_WINDOWS_H) +typedef ::FARPROC FARPROC_; +typedef ::NEARPROC NEARPROC_; +typedef ::PROC PROC_; +#endif // defined(BOOST_USE_WINDOWS_H) + +#if !defined(UNDER_CE) +// For backward compatibility, don't use directly. Use get_proc_address instead. +using ::GetProcAddress; +#else +using ::GetProcAddressA; +using ::GetProcAddressW; +#endif + +BOOST_FORCEINLINE FARPROC_ get_proc_address(HMODULE_ hModule, LPCSTR_ lpProcName) +{ +#if !defined(UNDER_CE) + return ::GetProcAddress(hModule, lpProcName); +#else + return ::GetProcAddressA(hModule, lpProcName); +#endif +} + +} // namespace winapi +} // namespace boost + +#include + +#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM +#endif // BOOST_WINAPI_GET_PROC_ADDRESS_HPP_INCLUDED_ diff --git a/boost/winapi/handles.hpp b/boost/winapi/handles.hpp new file mode 100644 index 0000000..d3db4f7 --- /dev/null +++ b/boost/winapi/handles.hpp @@ -0,0 +1,75 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_HANDLES_HPP_INCLUDED_ +#define BOOST_WINAPI_HANDLES_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CloseHandle(boost::winapi::HANDLE_ handle); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +DuplicateHandle( + boost::winapi::HANDLE_ hSourceProcessHandle, + boost::winapi::HANDLE_ hSourceHandle, + boost::winapi::HANDLE_ hTargetProcessHandle, + boost::winapi::HANDLE_* lpTargetHandle, + boost::winapi::DWORD_ dwDesiredAccess, + boost::winapi::BOOL_ bInheritHandle, + boost::winapi::DWORD_ dwOptions); + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN10 +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CompareObjectHandles( + boost::winapi::HANDLE_ hFirstObjectHandle, + boost::winapi::HANDLE_ hSecondObjectHandle); +#endif +} // extern "C" +#endif + +namespace boost { +namespace winapi { + +using ::CloseHandle; +using ::DuplicateHandle; + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN10 +using ::CompareObjectHandles; +#endif + +// Note: MSVC-14.1 does not interpret INVALID_HANDLE_VALUE_ initializer as a constant expression +#if defined( BOOST_USE_WINDOWS_H ) +BOOST_CONSTEXPR_OR_CONST DWORD_ DUPLICATE_CLOSE_SOURCE_ = DUPLICATE_CLOSE_SOURCE; +BOOST_CONSTEXPR_OR_CONST DWORD_ DUPLICATE_SAME_ACCESS_ = DUPLICATE_SAME_ACCESS; +const HANDLE_ INVALID_HANDLE_VALUE_ = INVALID_HANDLE_VALUE; +#else +BOOST_CONSTEXPR_OR_CONST DWORD_ DUPLICATE_CLOSE_SOURCE_ = 1; +BOOST_CONSTEXPR_OR_CONST DWORD_ DUPLICATE_SAME_ACCESS_ = 2; +const HANDLE_ INVALID_HANDLE_VALUE_ = (HANDLE_)(-1); +#endif + +BOOST_CONSTEXPR_OR_CONST DWORD_ duplicate_close_source = DUPLICATE_CLOSE_SOURCE_; +BOOST_CONSTEXPR_OR_CONST DWORD_ duplicate_same_access = DUPLICATE_SAME_ACCESS_; +// Note: The "unused" attribute here should not be necessary because the variable is a constant. +// However, MinGW gcc 5.3 spams warnings about this particular constant. +const HANDLE_ invalid_handle_value BOOST_ATTRIBUTE_UNUSED = INVALID_HANDLE_VALUE_; + +} +} + +#include + +#endif // BOOST_WINAPI_HANDLES_HPP_INCLUDED_ diff --git a/boost/winapi/limits.hpp b/boost/winapi/limits.hpp new file mode 100644 index 0000000..0a628d7 --- /dev/null +++ b/boost/winapi/limits.hpp @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_LIMITS_HPP_INCLUDED_ +#define BOOST_WINAPI_LIMITS_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace winapi { + +#if defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ MAX_PATH_ = MAX_PATH; + +#else + +BOOST_CONSTEXPR_OR_CONST DWORD_ MAX_PATH_ = 260; + +#endif + +#if defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ UNICODE_STRING_MAX_BYTES_ = UNICODE_STRING_MAX_BYTES; +BOOST_CONSTEXPR_OR_CONST DWORD_ UNICODE_STRING_MAX_CHARS_ = UNICODE_STRING_MAX_CHARS; + +#else + +BOOST_CONSTEXPR_OR_CONST DWORD_ UNICODE_STRING_MAX_BYTES_ = 65534; +BOOST_CONSTEXPR_OR_CONST DWORD_ UNICODE_STRING_MAX_CHARS_ = 32767; + +#endif + +BOOST_CONSTEXPR_OR_CONST DWORD_ max_path = MAX_PATH_; +BOOST_CONSTEXPR_OR_CONST DWORD_ unicode_string_max_bytes = UNICODE_STRING_MAX_BYTES_; +BOOST_CONSTEXPR_OR_CONST DWORD_ unicode_string_max_chars = UNICODE_STRING_MAX_CHARS_; + +} +} + +#include + +#endif // BOOST_WINAPI_LIMITS_HPP_INCLUDED_ diff --git a/boost/winapi/overlapped.hpp b/boost/winapi/overlapped.hpp new file mode 100644 index 0000000..8027b35 --- /dev/null +++ b/boost/winapi/overlapped.hpp @@ -0,0 +1,45 @@ +/* + * Copyright 2016 Klemens D. Morgenstern + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_OVERLAPPED_HPP_INCLUDED_ +#define BOOST_WINAPI_OVERLAPPED_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { +struct _OVERLAPPED; +} +#endif + +namespace boost { +namespace winapi { + +typedef struct BOOST_MAY_ALIAS _OVERLAPPED { + ULONG_PTR_ Internal; + ULONG_PTR_ InternalHigh; + union { + BOOST_WINAPI_DETAIL_EXTENSION struct { + DWORD_ Offset; + DWORD_ OffsetHigh; + }; + PVOID_ Pointer; + }; + HANDLE_ hEvent; +} OVERLAPPED_, *LPOVERLAPPED_; + +} // namespace winapi +} // namespace boost + +#include + +#endif // BOOST_WINAPI_OVERLAPPED_HPP_INCLUDED_ diff --git a/boost/winapi/stack_backtrace.hpp b/boost/winapi/stack_backtrace.hpp new file mode 100644 index 0000000..e5e295a --- /dev/null +++ b/boost/winapi/stack_backtrace.hpp @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_STACK_BACKTRACE_HPP_INCLUDED_ +#define BOOST_WINAPI_STACK_BACKTRACE_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// MinGW does not provide RtlCaptureStackBackTrace +#if !defined( BOOST_WINAPI_IS_MINGW ) + +// Note: RtlCaptureStackBackTrace is available in WinXP SP1 and later +#if (BOOST_USE_NTDDI_VERSION > BOOST_WINAPI_NTDDI_WINXP) + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +#include + +// Windows SDK shipped with MSVC 7.1 and 8 does not declare RtlCaptureStackBackTrace in headers but allows to link with it +#if !defined( BOOST_USE_WINDOWS_H ) || (defined(_MSC_VER) && (_MSC_VER+0) < 1500) +extern "C" { + +BOOST_WINAPI_IMPORT boost::winapi::WORD_ +BOOST_WINAPI_NTAPI_CC RtlCaptureStackBackTrace( + boost::winapi::DWORD_ FramesToSkip, + boost::winapi::DWORD_ FramesToCapture, + boost::winapi::PVOID_* BackTrace, + boost::winapi::PDWORD_ BackTraceHash); + +} // extern "C" +#endif + +namespace boost { +namespace winapi { + +using ::RtlCaptureStackBackTrace; + +} +} + +#include + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM +#endif // (BOOST_USE_NTDDI_VERSION > BOOST_WINAPI_NTDDI_WINXP) +#endif // !defined( BOOST_WINAPI_IS_MINGW ) +#endif // BOOST_WINAPI_STACK_BACKTRACE_HPP_INCLUDED_ diff --git a/build.cmd b/build.cmd index b1dc8d3..3974d6b 100644 --- a/build.cmd +++ b/build.cmd @@ -14,6 +14,7 @@ bcp ^ boost/smart_ptr/intrusive_ptr.hpp ^ boost/system/error_code.hpp ^ boost/system/system_error.hpp ^ + boost/stacktrace.hpp ^ boost/variant/ ^ boost/archive/binary_iarchive.hpp ^ boost/archive/binary_oarchive.hpp ^