Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Relative Virtual Addresses to allow their decoding without knowing the base address #200

Merged
merged 7 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions include/boost/stacktrace/detail/addr_base_msvc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright Antony Polukhin, 2016-2024.
//
// 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_ADDR_BASE_MSVC_HPP
#define BOOST_STACKTRACE_DETAIL_ADDR_BASE_MSVC_HPP

#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif

apolukhin marked this conversation as resolved.
Show resolved Hide resolved
#ifdef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <psapi.h>
#else
// Prevent inclusion of extra Windows SDK headers which can cause conflict
// with other code using Windows SDK
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <psapi.h>
#undef WIN32_LEAN_AND_MEAN
#endif

namespace boost { namespace stacktrace { namespace detail {
inline uintptr_t get_own_proc_addr_base(const void* addr) {
apolukhin marked this conversation as resolved.
Show resolved Hide resolved
// Try to avoid allocating memory for the modules array if possible.
// The stack buffer should be large enough for most processes.
HMODULE modules_stack[1024];
HMODULE* modules_allocated = nullptr;
apolukhin marked this conversation as resolved.
Show resolved Hide resolved
HMODULE* modules = modules_stack;

DWORD needed_bytes = 0;
uintptr_t addr_base = 0;

HANDLE process_handle = GetCurrentProcess();
bool enum_process_result = EnumProcessModules(process_handle, modules, sizeof(modules), &needed_bytes);

// Check if the error is because the buffer is too small.
if (!enum_process_result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
modules_allocated = new HMODULE[needed_bytes / sizeof(HMODULE)];
enum_process_result = EnumProcessModules(process_handle, modules, sizeof(modules), &needed_bytes);
apolukhin marked this conversation as resolved.
Show resolved Hide resolved
modules = modules_allocated;
}

if (enum_process_result) {
for (int i = 0; i < (needed_bytes / sizeof(HMODULE)); ++i) {
apolukhin marked this conversation as resolved.
Show resolved Hide resolved
MODULEINFO module_info;
TCHAR module_name[MAX_PATH];

// Get the module name
if (GetModuleBaseName(process_handle, modules[i], module_name, sizeof(module_name) / sizeof(TCHAR))
apolukhin marked this conversation as resolved.
Show resolved Hide resolved
&& GetModuleInformation(process_handle, modules[i], &module_info, sizeof(module_info))
&& module_info.lpBaseOfDll <= addr && addr < LPBYTE(module_info.lpBaseOfDll) + module_info.SizeOfImage) {
// Module contains the address
addr_base = reinterpret_cast<uintptr_t>(module_info.lpBaseOfDll);
apolukhin marked this conversation as resolved.
Show resolved Hide resolved
break;
}
}
}

CloseHandle(process_handle);
if (modules_allocated) {
delete[] modules_allocated;
}

return addr_base;
}

}}} // namespace boost::stacktrace::detail

#endif // BOOST_STACKTRACE_DETAIL_ADDR_BASE_MSVC_HPP
10 changes: 10 additions & 0 deletions include/boost/stacktrace/detail/frame_msvc.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#include <boost/stacktrace/detail/to_dec_array.hpp>
#include <boost/stacktrace/detail/to_hex_array.hpp>

#ifndef BOOST_STACKTRACE_DISABLE_OFFSET_ADDR_BASE
#include <boost/stacktrace/detail/addr_base_msvc.hpp>
#endif

#ifdef WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
Expand Down Expand Up @@ -391,7 +395,13 @@ public:
if (!name.empty()) {
res += name;
} else {
#ifdef BOOST_STACKTRACE_DISABLE_OFFSET_ADDR_BASE
res += to_hex_array(addr).data();
#else
// Get own base address
const uintptr_t base_addr = get_own_proc_addr_base(addr);
res += to_hex_array(reinterpret_cast<uintptr_t>(addr) - base_addr).data();
#endif
}

std::pair<std::string, std::size_t> source_line = this->get_source_file_line_impl(addr);
Expand Down
6 changes: 6 additions & 0 deletions include/boost/stacktrace/detail/frame_unwind.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#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/stacktrace/detail/addr_base.hpp>
#include <boost/core/demangle.hpp>

#include <cstdio>
Expand All @@ -40,7 +41,12 @@ public:
if (!Base::res.empty()) {
Base::res = boost::core::demangle(Base::res.c_str());
} else {
#ifdef BOOST_STACKTRACE_DISABLE_OFFSET_ADDR_BASE
Base::res = to_hex_array(addr).data();
#else
const auto addr_base = boost::stacktrace::detail::get_own_proc_addr_base(addr);
Base::res = to_hex_array(reinterpret_cast<uintptr_t>(addr) - addr_base).data();
#endif
}

if (Base::prepare_source_location(addr)) {
Expand Down
Loading