symbolize_win32.inc 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Copyright 2018 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // See "Retrieving Symbol Information by Address":
  15. // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx
  16. #include <windows.h>
  17. // MSVC header dbghelp.h has a warning for an ignored typedef.
  18. #pragma warning(push)
  19. #pragma warning(disable:4091)
  20. #include <dbghelp.h>
  21. #pragma warning(pop)
  22. #pragma comment(lib, "dbghelp.lib")
  23. #include <algorithm>
  24. #include <cstring>
  25. #include "absl/base/internal/raw_logging.h"
  26. namespace absl {
  27. ABSL_NAMESPACE_BEGIN
  28. static HANDLE process = NULL;
  29. void InitializeSymbolizer(const char*) {
  30. if (process != nullptr) {
  31. return;
  32. }
  33. process = GetCurrentProcess();
  34. // Symbols are not loaded until a reference is made requiring the
  35. // symbols be loaded. This is the fastest, most efficient way to use
  36. // the symbol handler.
  37. SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME);
  38. if (!SymInitialize(process, nullptr, true)) {
  39. // GetLastError() returns a Win32 DWORD, but we assign to
  40. // unsigned long long to simplify the ABSL_RAW_LOG case below. The uniform
  41. // initialization guarantees this is not a narrowing conversion.
  42. const unsigned long long error{GetLastError()}; // NOLINT(runtime/int)
  43. ABSL_RAW_LOG(FATAL, "SymInitialize() failed: %llu", error);
  44. }
  45. }
  46. bool Symbolize(const void* pc, char* out, int out_size) {
  47. if (out_size <= 0) {
  48. return false;
  49. }
  50. alignas(SYMBOL_INFO) char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
  51. SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(buf);
  52. symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  53. symbol->MaxNameLen = MAX_SYM_NAME;
  54. if (!SymFromAddr(process, reinterpret_cast<DWORD64>(pc), nullptr, symbol)) {
  55. return false;
  56. }
  57. const size_t out_size_t = static_cast<size_t>(out_size);
  58. strncpy(out, symbol->Name, out_size_t);
  59. if (out[out_size_t - 1] != '\0') {
  60. // strncpy() does not '\0' terminate when it truncates.
  61. static constexpr char kEllipsis[] = "...";
  62. size_t ellipsis_size =
  63. std::min(sizeof(kEllipsis) - 1, out_size_t - 1);
  64. memcpy(out + out_size_t - ellipsis_size - 1, kEllipsis, ellipsis_size);
  65. out[out_size_t - 1] = '\0';
  66. }
  67. return true;
  68. }
  69. ABSL_NAMESPACE_END
  70. } // namespace absl