PageRenderTime 44ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcommon/llstacktrace.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 136 lines | 88 code | 16 blank | 32 comment | 6 complexity | 7b50239aa507912636d797b0fc1e5ffa MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llstacktrace.cpp
  3. * @brief stack tracing functionality
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "llstacktrace.h"
  28. #ifdef LL_WINDOWS
  29. #include <iostream>
  30. #include <sstream>
  31. #include "windows.h"
  32. #include "Dbghelp.h"
  33. typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
  34. IN ULONG frames_to_skip,
  35. IN ULONG frames_to_capture,
  36. OUT PVOID *backtrace,
  37. OUT PULONG backtrace_hash);
  38. static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
  39. (RtlCaptureStackBackTrace_Function*)
  40. GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
  41. bool ll_get_stack_trace(std::vector<std::string>& lines)
  42. {
  43. const S32 MAX_STACK_DEPTH = 32;
  44. const S32 STRING_NAME_LENGTH = 200;
  45. const S32 FRAME_SKIP = 2;
  46. static BOOL symbolsLoaded = false;
  47. static BOOL firstCall = true;
  48. HANDLE hProc = GetCurrentProcess();
  49. // load the symbols if they're not loaded
  50. if(!symbolsLoaded && firstCall)
  51. {
  52. symbolsLoaded = SymInitialize(hProc, NULL, true);
  53. firstCall = false;
  54. }
  55. // if loaded, get the call stack
  56. if(symbolsLoaded)
  57. {
  58. // create the frames to hold the addresses
  59. void* frames[MAX_STACK_DEPTH];
  60. memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
  61. S32 depth = 0;
  62. // get the addresses
  63. depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
  64. IMAGEHLP_LINE64 line;
  65. memset(&line, 0, sizeof(IMAGEHLP_LINE64));
  66. line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
  67. // create something to hold address info
  68. PIMAGEHLP_SYMBOL64 pSym;
  69. pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
  70. memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
  71. pSym->MaxNameLength = STRING_NAME_LENGTH;
  72. pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
  73. // get address info for each address frame
  74. // and store
  75. for(S32 i=0; i < depth; i++)
  76. {
  77. std::stringstream stack_line;
  78. BOOL ret;
  79. DWORD64 addr = (DWORD64)frames[i];
  80. ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
  81. if(ret)
  82. {
  83. stack_line << pSym->Name << " ";
  84. }
  85. DWORD dummy;
  86. ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
  87. if(ret)
  88. {
  89. std::string file_name = line.FileName;
  90. std::string::size_type index = file_name.rfind("\\");
  91. stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber;
  92. }
  93. lines.push_back(stack_line.str());
  94. }
  95. free(pSym);
  96. // TODO: figure out a way to cleanup symbol loading
  97. // Not hugely necessary, however.
  98. //SymCleanup(hProc);
  99. return true;
  100. }
  101. else
  102. {
  103. lines.push_back("Stack Trace Failed. PDB symbol info not loaded");
  104. }
  105. return false;
  106. }
  107. #else
  108. bool ll_get_stack_trace(std::vector<std::string>& lines)
  109. {
  110. return false;
  111. }
  112. #endif