addr_base_msvc.hpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright Antony Polukhin, 2016-2025.
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_STACKTRACE_DETAIL_ADDR_BASE_MSVC_HPP
  7. #define BOOST_STACKTRACE_DETAIL_ADDR_BASE_MSVC_HPP
  8. #include <boost/config.hpp>
  9. #ifdef BOOST_HAS_PRAGMA_ONCE
  10. # pragma once
  11. #endif
  12. #include <cstdio>
  13. #include <cstdint>
  14. #include <memory>
  15. #ifdef WIN32_LEAN_AND_MEAN
  16. #include <windows.h>
  17. #include <psapi.h>
  18. #else
  19. // Prevent inclusion of extra Windows SDK headers which can cause conflict
  20. // with other code using Windows SDK
  21. #define WIN32_LEAN_AND_MEAN
  22. #include <windows.h>
  23. #include <psapi.h>
  24. #undef WIN32_LEAN_AND_MEAN
  25. #endif
  26. namespace boost { namespace stacktrace { namespace detail {
  27. inline std::uintptr_t get_own_proc_addr_base(const void* addr) {
  28. // Try to avoid allocating memory for the modules array if possible.
  29. // The stack buffer should be large enough for most processes.
  30. HMODULE modules_stack[1024];
  31. std::unique_ptr<HMODULE[]> modules_allocated;
  32. HMODULE* modules = modules_stack;
  33. DWORD needed_bytes = 0;
  34. std::uintptr_t addr_base = 0;
  35. HANDLE process_handle = GetCurrentProcess();
  36. auto enum_process_is_ok = EnumProcessModules(process_handle, modules, sizeof(modules), &needed_bytes);
  37. // Check if the error is because the buffer is too small.
  38. if (!enum_process_is_ok && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  39. modules_allocated.reset(new HMODULE[needed_bytes / sizeof(HMODULE)]);
  40. modules = modules_allocated.get();
  41. enum_process_is_ok = EnumProcessModules(process_handle, modules, needed_bytes, &needed_bytes);
  42. }
  43. if (enum_process_is_ok) {
  44. for (std::size_t i = 0; i < (needed_bytes / sizeof(HMODULE)); ++i) {
  45. MODULEINFO module_info;
  46. // Get the module name
  47. if (GetModuleInformation(process_handle, modules[i], &module_info, sizeof(module_info))
  48. && module_info.lpBaseOfDll <= addr && addr < LPBYTE(module_info.lpBaseOfDll) + module_info.SizeOfImage) {
  49. // Module contains the address
  50. addr_base = reinterpret_cast<std::uintptr_t>(module_info.lpBaseOfDll);
  51. break;
  52. }
  53. }
  54. }
  55. CloseHandle(process_handle);
  56. return addr_base;
  57. }
  58. }}} // namespace boost::stacktrace::detail
  59. #endif // BOOST_STACKTRACE_DETAIL_ADDR_BASE_MSVC_HPP