symbolize_win32.inc 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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. strncpy(out, symbol->Name, out_size);
  58. if (out[out_size - 1] != '\0') {
  59. // strncpy() does not '\0' terminate when it truncates.
  60. static constexpr char kEllipsis[] = "...";
  61. int ellipsis_size =
  62. std::min<int>(sizeof(kEllipsis) - 1, out_size - 1);
  63. memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
  64. out[out_size - 1] = '\0';
  65. }
  66. return true;
  67. }
  68. ABSL_NAMESPACE_END
  69. } // namespace absl