mirror of
https://github.com/shadps4-emu/ext-boost.git
synced 2024-11-26 21:00:21 +00:00
boost: Add stack traces (#31)
This commit is contained in:
parent
32f5cd8ebb
commit
700ae2eff3
19
boost/stacktrace.hpp
Normal file
19
boost/stacktrace.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/frame.hpp>
|
||||
#include <boost/stacktrace/stacktrace.hpp> // Actually already includes all the headers
|
||||
#include <boost/stacktrace/safe_dump_to.hpp>
|
||||
|
||||
#endif // BOOST_STACKTRACE_HPP
|
226
boost/stacktrace/detail/addr2line_impls.hpp
Normal file
226
boost/stacktrace/detail/addr2line_impls.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <boost/stacktrace/detail/to_dec_array.hpp>
|
||||
#include <boost/stacktrace/detail/try_dec_convert.hpp>
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
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<char*>(flag),
|
||||
const_cast<char*>(exec_path),
|
||||
const_cast<char*>(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<int>(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 Base> class to_string_impl_base;
|
||||
typedef to_string_impl_base<to_string_using_addr2line> 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
|
33
boost/stacktrace/detail/collect_msvc.ipp
Normal file
33
boost/stacktrace/detail/collect_msvc.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/safe_dump_to.hpp>
|
||||
|
||||
#include <boost/winapi/stack_backtrace.hpp>
|
||||
|
||||
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<boost::winapi::ULONG_>(skip),
|
||||
static_cast<boost::winapi::ULONG_>(max_frames_count),
|
||||
const_cast<boost::winapi::PVOID_*>(out_frames),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}}} // namespace boost::stacktrace
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_COLLECT_MSVC_IPP
|
25
boost/stacktrace/detail/collect_noop.ipp
Normal file
25
boost/stacktrace/detail/collect_noop.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/safe_dump_to.hpp>
|
||||
|
||||
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
|
106
boost/stacktrace/detail/collect_unwind.ipp
Normal file
106
boost/stacktrace/detail/collect_unwind.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/safe_dump_to.hpp>
|
||||
|
||||
// On iOS 32-bit ARM architecture _Unwind_Backtrace function doesn't exist, symbol is undefined.
|
||||
// Forcing libc backtrace() function usage.
|
||||
#include <boost/predef.h>
|
||||
#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 <execinfo.h>
|
||||
#include <algorithm>
|
||||
#else
|
||||
#include <unwind.h>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
|
||||
#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<unwind_state*>(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<native_frame_ptr_t>(
|
||||
_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<size_t>(::backtrace(const_cast<void **>(out_frames), static_cast<int>(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
|
159
boost/stacktrace/detail/frame_decl.hpp
Normal file
159
boost/stacktrace/detail/frame_decl.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <boost/core/explicit_operator_bool.hpp>
|
||||
|
||||
#include <boost/stacktrace/safe_dump_to.hpp> // boost::stacktrace::detail::native_frame_ptr_t
|
||||
#include <boost/stacktrace/detail/void_ptr_cast.hpp>
|
||||
|
||||
#include <boost/stacktrace/detail/push_options.h>
|
||||
|
||||
/// @file boost/stacktrace/detail/frame_decl.hpp
|
||||
/// Use <boost/stacktrace/frame.hpp> header instead of this one!
|
||||
|
||||
namespace boost { namespace stacktrace {
|
||||
|
||||
/// @class boost::stacktrace::frame boost/stacktrace/detail/frame_decl.hpp <boost/stacktrace/frame.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 <class T>
|
||||
explicit frame(T* function_addr) BOOST_NOEXCEPT
|
||||
: addr_(boost::stacktrace::detail::void_ptr_cast<native_frame_ptr_t>(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 <boost/stacktrace/detail/pop_options.h>
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_FRAME_DECL_HPP
|
377
boost/stacktrace/detail/frame_msvc.ipp
Normal file
377
boost/stacktrace/detail/frame_msvc.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/frame.hpp>
|
||||
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <boost/stacktrace/detail/to_dec_array.hpp>
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <windows.h>
|
||||
#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 T>
|
||||
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<void**>(&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<std::size_t>(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<ULONG64>(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<ULONG>(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<ULONG64>(addr),
|
||||
&result,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
));
|
||||
|
||||
return (is_ok ? result : 0);
|
||||
}
|
||||
|
||||
std::pair<std::string, std::size_t> get_source_file_line_impl(const void* addr) const {
|
||||
std::pair<std::string, std::size_t> result;
|
||||
if (!is_inited()) {
|
||||
return result;
|
||||
}
|
||||
const ULONG64 offset = reinterpret_cast<ULONG64>(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<ULONG>(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<std::string, std::size_t> 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
|
44
boost/stacktrace/detail/frame_noop.ipp
Normal file
44
boost/stacktrace/detail/frame_noop.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/frame.hpp>
|
||||
|
||||
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
|
114
boost/stacktrace/detail/frame_unwind.ipp
Normal file
114
boost/stacktrace/detail/frame_unwind.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/frame.hpp>
|
||||
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <boost/stacktrace/detail/location_from_symbol.hpp>
|
||||
#include <boost/stacktrace/detail/to_dec_array.hpp>
|
||||
#include <boost/core/demangle.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef BOOST_STACKTRACE_USE_BACKTRACE
|
||||
# include <boost/stacktrace/detail/libbacktrace_impls.hpp>
|
||||
#elif defined(BOOST_STACKTRACE_USE_ADDR2LINE)
|
||||
# include <boost/stacktrace/detail/addr2line_impls.hpp>
|
||||
#else
|
||||
# include <boost/stacktrace/detail/unwind_base_impls.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
template <class Base>
|
||||
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<void*>(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
|
248
boost/stacktrace/detail/libbacktrace_impls.hpp
Normal file
248
boost/stacktrace/detail/libbacktrace_impls.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/detail/to_hex_array.hpp>
|
||||
#include <boost/stacktrace/detail/to_dec_array.hpp>
|
||||
#include <boost/stacktrace/detail/location_from_symbol.hpp>
|
||||
#include <boost/core/demangle.hpp>
|
||||
|
||||
#ifdef BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE
|
||||
# include BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE
|
||||
#else
|
||||
# include <backtrace.h>
|
||||
#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<pc_data*>(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<pc_data*>(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<uintptr_t>(addr),
|
||||
boost::stacktrace::detail::libbacktrace_full_callback,
|
||||
boost::stacktrace::detail::libbacktrace_error_callback,
|
||||
&data
|
||||
)
|
||||
||
|
||||
::backtrace_syminfo(
|
||||
state,
|
||||
reinterpret_cast<uintptr_t>(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 Base> class to_string_impl_base;
|
||||
typedef to_string_impl_base<to_string_using_backtrace> 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<uintptr_t>(addr),
|
||||
boost::stacktrace::detail::libbacktrace_full_callback,
|
||||
boost::stacktrace::detail::libbacktrace_error_callback,
|
||||
&data
|
||||
)
|
||||
||
|
||||
::backtrace_syminfo(
|
||||
state,
|
||||
reinterpret_cast<uintptr_t>(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<uintptr_t>(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<uintptr_t>(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
|
105
boost/stacktrace/detail/location_from_symbol.hpp
Normal file
105
boost/stacktrace/detail/location_from_symbol.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
# include <dlfcn.h>
|
||||
#else
|
||||
# include <boost/winapi/dll.hpp>
|
||||
#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<void*>(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<boost::winapi::HMODULE_>(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
|
12
boost/stacktrace/detail/pop_options.h
Normal file
12
boost/stacktrace/detail/pop_options.h
Normal file
@ -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
|
||||
|
31
boost/stacktrace/detail/push_options.h
Normal file
31
boost/stacktrace/detail/push_options.h
Normal file
@ -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
|
||||
|
37
boost/stacktrace/detail/safe_dump_noop.ipp
Normal file
37
boost/stacktrace/detail/safe_dump_noop.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/safe_dump_to.hpp>
|
||||
|
||||
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
|
59
boost/stacktrace/detail/safe_dump_posix.ipp
Normal file
59
boost/stacktrace/detail/safe_dump_posix.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/safe_dump_to.hpp>
|
||||
|
||||
#include <unistd.h> // ::write
|
||||
#include <fcntl.h> // ::open
|
||||
#include <sys/stat.h> // 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
|
66
boost/stacktrace/detail/safe_dump_win.ipp
Normal file
66
boost/stacktrace/detail/safe_dump_win.ipp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/safe_dump_to.hpp>
|
||||
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
|
||||
#include <boost/winapi/get_current_process.hpp>
|
||||
#include <boost/winapi/file_management.hpp>
|
||||
#include <boost/winapi/handles.hpp>
|
||||
#include <boost/winapi/access_rights.hpp>
|
||||
|
||||
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<boost::winapi::DWORD_>(
|
||||
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
|
46
boost/stacktrace/detail/to_dec_array.hpp
Normal file
46
boost/stacktrace/detail/to_dec_array.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/array.hpp>
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
// We do not use boost::lexical_cast in this function to reduce module dependencies
|
||||
inline boost::array<char, 40> to_dec_array(std::size_t value) BOOST_NOEXCEPT {
|
||||
boost::array<char, 40> 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<char>('0' + (value % 10));
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
ret[digits] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_TO_DEC_ARRAY_HPP
|
54
boost/stacktrace/detail/to_hex_array.hpp
Normal file
54
boost/stacktrace/detail/to_hex_array.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
|
||||
namespace boost { namespace stacktrace { namespace detail {
|
||||
|
||||
BOOST_STATIC_CONSTEXPR char to_hex_array_bytes[] = "0123456789ABCDEF";
|
||||
|
||||
template <class T>
|
||||
inline boost::array<char, 2 + sizeof(void*) * 2 + 1> to_hex_array(T addr) BOOST_NOEXCEPT {
|
||||
boost::array<char, 2 + sizeof(void*) * 2 + 1> ret = {"0x"};
|
||||
ret.back() = '\0';
|
||||
BOOST_STATIC_ASSERT_MSG(!boost::is_pointer<T>::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<char, 2 + sizeof(void*) * 2 + 1> to_hex_array(const void* addr) BOOST_NOEXCEPT {
|
||||
return to_hex_array(
|
||||
reinterpret_cast< boost::make_unsigned<std::ptrdiff_t>::type >(addr)
|
||||
);
|
||||
}
|
||||
|
||||
}}} // namespace boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_TO_HEX_ARRAY_HPP
|
29
boost/stacktrace/detail/try_dec_convert.hpp
Normal file
29
boost/stacktrace/detail/try_dec_convert.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
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
|
50
boost/stacktrace/detail/unwind_base_impls.hpp
Normal file
50
boost/stacktrace/detail/unwind_base_impls.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/frame.hpp>
|
||||
|
||||
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 Base> class to_string_impl_base;
|
||||
typedef to_string_impl_base<to_string_using_nothing> 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
|
46
boost/stacktrace/detail/void_ptr_cast.hpp
Normal file
46
boost/stacktrace/detail/void_ptr_cast.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
|
||||
#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 <class To, class From>
|
||||
To void_ptr_cast(From* v) BOOST_NOEXCEPT {
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_pointer<To>::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<To>(v);
|
||||
}
|
||||
|
||||
|
||||
}}} // boost::stacktrace::detail
|
||||
|
||||
#endif // BOOST_STACKTRACE_DETAIL_VOID_PTR_CAST_HPP
|
||||
|
67
boost/stacktrace/frame.hpp
Normal file
67
boost/stacktrace/frame.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <boost/core/explicit_operator_bool.hpp>
|
||||
|
||||
#include <boost/stacktrace/safe_dump_to.hpp> // boost::stacktrace::detail::native_frame_ptr_t
|
||||
|
||||
#include <boost/stacktrace/detail/frame_decl.hpp>
|
||||
#include <boost/stacktrace/detail/push_options.h>
|
||||
|
||||
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<std::size_t>(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 <class CharT, class TraitsT>
|
||||
std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const frame& f) {
|
||||
return os << boost::stacktrace::to_string(f);
|
||||
}
|
||||
|
||||
}} // namespace boost::stacktrace
|
||||
|
||||
/// @cond
|
||||
|
||||
#include <boost/stacktrace/detail/pop_options.h>
|
||||
|
||||
#ifndef BOOST_STACKTRACE_LINK
|
||||
# if defined(BOOST_STACKTRACE_USE_NOOP)
|
||||
# include <boost/stacktrace/detail/frame_noop.ipp>
|
||||
# elif defined(BOOST_MSVC) || defined(BOOST_STACKTRACE_USE_WINDBG) || defined(BOOST_STACKTRACE_USE_WINDBG_CACHED)
|
||||
# include <boost/stacktrace/detail/frame_msvc.ipp>
|
||||
# else
|
||||
# include <boost/stacktrace/detail/frame_unwind.ipp>
|
||||
# endif
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
|
||||
#endif // BOOST_STACKTRACE_FRAME_HPP
|
222
boost/stacktrace/safe_dump_to.hpp
Normal file
222
boost/stacktrace/safe_dump_to.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
#include <boost/winapi/config.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/detail/push_options.h>
|
||||
|
||||
#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<native_frame_ptr_t*>(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 <class T>
|
||||
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 <boost/stacktrace/detail/pop_options.h>
|
||||
|
||||
#if !defined(BOOST_STACKTRACE_LINK) || defined(BOOST_STACKTRACE_INTERNAL_BUILD_LIBS)
|
||||
# if defined(BOOST_STACKTRACE_USE_NOOP)
|
||||
# include <boost/stacktrace/detail/safe_dump_noop.ipp>
|
||||
# include <boost/stacktrace/detail/collect_noop.ipp>
|
||||
# else
|
||||
# if defined(BOOST_WINDOWS)
|
||||
# include <boost/stacktrace/detail/safe_dump_win.ipp>
|
||||
# else
|
||||
# include <boost/stacktrace/detail/safe_dump_posix.ipp>
|
||||
# endif
|
||||
# if defined(BOOST_WINDOWS) && !defined(BOOST_WINAPI_IS_MINGW) // MinGW does not provide RtlCaptureStackBackTrace. MinGW-w64 does.
|
||||
# include <boost/stacktrace/detail/collect_msvc.ipp>
|
||||
# else
|
||||
# include <boost/stacktrace/detail/collect_unwind.ipp>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // BOOST_STACKTRACE_SAFE_DUMP_TO_HPP
|
423
boost/stacktrace/stacktrace.hpp
Normal file
423
boost/stacktrace/stacktrace.hpp
Normal file
@ -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 <boost/config.hpp>
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/core/explicit_operator_bool.hpp>
|
||||
#include <boost/core/no_exceptions_support.hpp>
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
|
||||
# include <type_traits>
|
||||
#endif
|
||||
|
||||
#include <boost/stacktrace/stacktrace_fwd.hpp>
|
||||
#include <boost/stacktrace/safe_dump_to.hpp>
|
||||
#include <boost/stacktrace/detail/frame_decl.hpp>
|
||||
#include <boost/stacktrace/frame.hpp>
|
||||
|
||||
#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 Allocator>
|
||||
class basic_stacktrace {
|
||||
std::vector<boost::stacktrace::frame, Allocator> 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<std::size_t>(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<native_frame_ptr_t>::other allocator_void_t;
|
||||
#else
|
||||
typedef typename std::allocator_traits<Allocator>::template rebind_alloc<native_frame_ptr_t> allocator_void_t;
|
||||
#endif
|
||||
std::vector<native_frame_ptr_t, allocator_void_t> 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<boost::stacktrace::frame, Allocator>::value_type value_type;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::allocator_type allocator_type;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_pointer pointer;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_pointer const_pointer;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_reference reference;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_reference const_reference;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::size_type size_type;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::difference_type difference_type;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_iterator iterator;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_iterator const_iterator;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::const_reverse_iterator reverse_iterator;
|
||||
typedef typename std::vector<boost::stacktrace::frame, Allocator>::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<std::size_t>(-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<std::size_t>(-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<boost::stacktrace::frame, Allocator> >::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<boost::stacktrace::frame, Allocator>& 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 <class Char, class Trait>
|
||||
static basic_stacktrace from_dump(std::basic_istream<Char, Trait>& in, const allocator_type& a = allocator_type()) {
|
||||
typedef typename std::basic_istream<Char, Trait>::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<std::size_t>(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<Char*>(&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<const native_frame_ptr_t*>(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 <class Allocator1, class Allocator2>
|
||||
bool operator< (const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& 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 <class Allocator1, class Allocator2>
|
||||
bool operator==(const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& 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 <class Allocator1, class Allocator2>
|
||||
bool operator> (const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template <class Allocator1, class Allocator2>
|
||||
bool operator<=(const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
|
||||
return !(lhs > rhs);
|
||||
}
|
||||
|
||||
template <class Allocator1, class Allocator2>
|
||||
bool operator>=(const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template <class Allocator1, class Allocator2>
|
||||
bool operator!=(const basic_stacktrace<Allocator1>& lhs, const basic_stacktrace<Allocator2>& rhs) BOOST_NOEXCEPT {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// Fast hashing support, O(st.size()) complexity; Async-Handler-Safe.
|
||||
template <class Allocator>
|
||||
std::size_t hash_value(const basic_stacktrace<Allocator>& 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 <class Allocator>
|
||||
std::string to_string(const basic_stacktrace<Allocator>& 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 <class CharT, class TraitsT, class Allocator>
|
||||
std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const basic_stacktrace<Allocator>& 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
|
28
boost/stacktrace/stacktrace_fwd.hpp
Normal file
28
boost/stacktrace/stacktrace_fwd.hpp
Normal file
@ -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 <cstddef>
|
||||
#include <memory>
|
||||
|
||||
/// @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 Allocator = std::allocator<frame> > class basic_stacktrace;
|
||||
typedef basic_stacktrace<> stacktrace;
|
||||
|
||||
}} // namespace boost::stacktrace
|
||||
/// @endcond
|
||||
|
||||
|
||||
#endif // BOOST_STACKTRACE_STACKTRACE_FWD_HPP
|
84
boost/winapi/access_rights.hpp
Normal file
84
boost/winapi/access_rights.hpp
Normal file
@ -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 <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/detail/header.hpp>
|
||||
|
||||
#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 <boost/winapi/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_WINAPI_ACCESS_RIGHTS_HPP_INCLUDED_
|
199
boost/winapi/dll.hpp
Normal file
199
boost/winapi/dll.hpp
Normal file
@ -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 <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/get_proc_address.hpp>
|
||||
#include <boost/winapi/detail/header.hpp>
|
||||
|
||||
#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 <boost/winapi/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_WINAPI_DLL_HPP_INCLUDED_
|
597
boost/winapi/file_management.hpp
Normal file
597
boost/winapi/file_management.hpp
Normal file
@ -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 <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/limits.hpp>
|
||||
#include <boost/winapi/time.hpp>
|
||||
#include <boost/winapi/overlapped.hpp>
|
||||
#include <boost/winapi/detail/header.hpp>
|
||||
|
||||
#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 <boost/winapi/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_WINAPI_FILE_MANAGEMENT_HPP_INCLUDED_
|
81
boost/winapi/get_proc_address.hpp
Normal file
81
boost/winapi/get_proc_address.hpp
Normal file
@ -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 <boost/winapi/basic_types.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
|
||||
|
||||
#include <boost/winapi/detail/header.hpp>
|
||||
|
||||
#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 <boost/winapi/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
|
||||
#endif // BOOST_WINAPI_GET_PROC_ADDRESS_HPP_INCLUDED_
|
75
boost/winapi/handles.hpp
Normal file
75
boost/winapi/handles.hpp
Normal file
@ -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 <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/detail/header.hpp>
|
||||
|
||||
#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 <boost/winapi/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_WINAPI_HANDLES_HPP_INCLUDED_
|
52
boost/winapi/limits.hpp
Normal file
52
boost/winapi/limits.hpp
Normal file
@ -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 <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/detail/header.hpp>
|
||||
|
||||
#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 <boost/winapi/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_WINAPI_LIMITS_HPP_INCLUDED_
|
45
boost/winapi/overlapped.hpp
Normal file
45
boost/winapi/overlapped.hpp
Normal file
@ -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 <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/detail/header.hpp>
|
||||
|
||||
#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 <boost/winapi/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_WINAPI_OVERLAPPED_HPP_INCLUDED_
|
55
boost/winapi/stack_backtrace.hpp
Normal file
55
boost/winapi/stack_backtrace.hpp
Normal file
@ -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 <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/config.hpp>
|
||||
|
||||
#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 <boost/winapi/detail/header.hpp>
|
||||
|
||||
// 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 <boost/winapi/detail/footer.hpp>
|
||||
|
||||
#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_
|
Loading…
Reference in New Issue
Block a user