/thirdparty/breakpad/client/windows/unittests/minidump_test.cc

http://github.com/tomahawk-player/tomahawk · C++ · 332 lines · 231 code · 49 blank · 52 comment · 17 complexity · c343c061ed82137e38bbcbe77f2e098e MD5 · raw file

  1. // Copyright (c) 2010, Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above
  11. // copyright notice, this list of conditions and the following disclaimer
  12. // in the documentation and/or other materials provided with the
  13. // distribution.
  14. // * Neither the name of Google Inc. nor the names of its
  15. // contributors may be used to endorse or promote products derived from
  16. // this software without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. #include <windows.h>
  30. #include <objbase.h>
  31. #include <dbghelp.h>
  32. #include "../crash_generation/minidump_generator.h"
  33. #include "dump_analysis.h" // NOLINT
  34. #include "gtest/gtest.h"
  35. namespace {
  36. // Minidump with stacks, PEB, TEB, and unloaded module list.
  37. const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
  38. MiniDumpWithProcessThreadData | // Get PEB and TEB.
  39. MiniDumpWithUnloadedModules); // Get unloaded modules when available.
  40. // Minidump with all of the above, plus memory referenced from stack.
  41. const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
  42. MiniDumpWithProcessThreadData | // Get PEB and TEB.
  43. MiniDumpWithUnloadedModules | // Get unloaded modules when available.
  44. MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack.
  45. // Large dump with all process memory.
  46. const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
  47. MiniDumpWithFullMemory | // Full memory from process.
  48. MiniDumpWithProcessThreadData | // Get PEB and TEB.
  49. MiniDumpWithHandleData | // Get all handle information.
  50. MiniDumpWithUnloadedModules); // Get unloaded modules when available.
  51. class MinidumpTest: public testing::Test {
  52. public:
  53. MinidumpTest() {
  54. wchar_t temp_dir_path[ MAX_PATH ] = {0};
  55. ::GetTempPath(MAX_PATH, temp_dir_path);
  56. dump_path_ = temp_dir_path;
  57. }
  58. virtual void SetUp() {
  59. // Make sure URLMon isn't loaded into our process.
  60. ASSERT_EQ(NULL, ::GetModuleHandle(L"urlmon.dll"));
  61. // Then load and unload it to ensure we have something to
  62. // stock the unloaded module list with.
  63. HMODULE urlmon = ::LoadLibrary(L"urlmon.dll");
  64. ASSERT_TRUE(urlmon != NULL);
  65. ASSERT_TRUE(::FreeLibrary(urlmon));
  66. }
  67. virtual void TearDown() {
  68. if (!dump_file_.empty()) {
  69. ::DeleteFile(dump_file_.c_str());
  70. dump_file_ = L"";
  71. }
  72. if (!full_dump_file_.empty()) {
  73. ::DeleteFile(full_dump_file_.c_str());
  74. full_dump_file_ = L"";
  75. }
  76. }
  77. bool WriteDump(ULONG flags) {
  78. using google_breakpad::MinidumpGenerator;
  79. // Fake exception is access violation on write to this.
  80. EXCEPTION_RECORD ex_record = {
  81. STATUS_ACCESS_VIOLATION, // ExceptionCode
  82. 0, // ExceptionFlags
  83. NULL, // ExceptionRecord;
  84. reinterpret_cast<void*>(0xCAFEBABE), // ExceptionAddress;
  85. 2, // NumberParameters;
  86. { EXCEPTION_WRITE_FAULT, reinterpret_cast<ULONG_PTR>(this) }
  87. };
  88. CONTEXT ctx_record = {};
  89. EXCEPTION_POINTERS ex_ptrs = {
  90. &ex_record,
  91. &ctx_record,
  92. };
  93. MinidumpGenerator generator(dump_path_);
  94. // And write a dump
  95. bool result = generator.WriteMinidump(::GetCurrentProcess(),
  96. ::GetCurrentProcessId(),
  97. ::GetCurrentThreadId(),
  98. ::GetCurrentThreadId(),
  99. &ex_ptrs,
  100. NULL,
  101. static_cast<MINIDUMP_TYPE>(flags),
  102. TRUE,
  103. &dump_file_,
  104. &full_dump_file_);
  105. return result == TRUE;
  106. }
  107. protected:
  108. std::wstring dump_file_;
  109. std::wstring full_dump_file_;
  110. std::wstring dump_path_;
  111. };
  112. // We need to be able to get file information from Windows
  113. bool HasFileInfo(const std::wstring& file_path) {
  114. DWORD dummy;
  115. const wchar_t* path = file_path.c_str();
  116. DWORD length = ::GetFileVersionInfoSize(path, &dummy);
  117. if (length == 0)
  118. return NULL;
  119. void* data = calloc(length, 1);
  120. if (!data)
  121. return false;
  122. if (!::GetFileVersionInfo(path, dummy, length, data)) {
  123. free(data);
  124. return false;
  125. }
  126. void* translate = NULL;
  127. UINT page_count;
  128. BOOL query_result = VerQueryValue(
  129. data,
  130. L"\\VarFileInfo\\Translation",
  131. static_cast<void**>(&translate),
  132. &page_count);
  133. free(data);
  134. if (query_result && translate) {
  135. return true;
  136. } else {
  137. return false;
  138. }
  139. }
  140. TEST_F(MinidumpTest, Version) {
  141. API_VERSION* version = ::ImagehlpApiVersion();
  142. HMODULE dbg_help = ::GetModuleHandle(L"dbghelp.dll");
  143. ASSERT_TRUE(dbg_help != NULL);
  144. wchar_t dbg_help_file[1024] = {};
  145. ASSERT_TRUE(::GetModuleFileName(dbg_help,
  146. dbg_help_file,
  147. sizeof(dbg_help_file) /
  148. sizeof(*dbg_help_file)));
  149. ASSERT_TRUE(HasFileInfo(std::wstring(dbg_help_file)) != NULL);
  150. // LOG(INFO) << "DbgHelp.dll version: " << file_info->file_version();
  151. }
  152. TEST_F(MinidumpTest, Normal) {
  153. EXPECT_TRUE(WriteDump(MiniDumpNormal));
  154. DumpAnalysis mini(dump_file_);
  155. // We expect threads, modules and some memory.
  156. EXPECT_TRUE(mini.HasStream(ThreadListStream));
  157. EXPECT_TRUE(mini.HasStream(ModuleListStream));
  158. EXPECT_TRUE(mini.HasStream(MemoryListStream));
  159. EXPECT_TRUE(mini.HasStream(ExceptionStream));
  160. EXPECT_TRUE(mini.HasStream(SystemInfoStream));
  161. EXPECT_TRUE(mini.HasStream(MiscInfoStream));
  162. EXPECT_FALSE(mini.HasStream(ThreadExListStream));
  163. EXPECT_FALSE(mini.HasStream(Memory64ListStream));
  164. EXPECT_FALSE(mini.HasStream(CommentStreamA));
  165. EXPECT_FALSE(mini.HasStream(CommentStreamW));
  166. EXPECT_FALSE(mini.HasStream(HandleDataStream));
  167. EXPECT_FALSE(mini.HasStream(FunctionTableStream));
  168. EXPECT_FALSE(mini.HasStream(UnloadedModuleListStream));
  169. EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
  170. EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
  171. EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
  172. EXPECT_FALSE(mini.HasStream(TokenStream));
  173. // We expect no PEB nor TEBs in this dump.
  174. EXPECT_FALSE(mini.HasTebs());
  175. EXPECT_FALSE(mini.HasPeb());
  176. // We expect no off-stack memory in this dump.
  177. EXPECT_FALSE(mini.HasMemory(this));
  178. }
  179. TEST_F(MinidumpTest, SmallDump) {
  180. ASSERT_TRUE(WriteDump(kSmallDumpType));
  181. DumpAnalysis mini(dump_file_);
  182. EXPECT_TRUE(mini.HasStream(ThreadListStream));
  183. EXPECT_TRUE(mini.HasStream(ModuleListStream));
  184. EXPECT_TRUE(mini.HasStream(MemoryListStream));
  185. EXPECT_TRUE(mini.HasStream(ExceptionStream));
  186. EXPECT_TRUE(mini.HasStream(SystemInfoStream));
  187. EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
  188. EXPECT_TRUE(mini.HasStream(MiscInfoStream));
  189. // We expect PEB and TEBs in this dump.
  190. EXPECT_TRUE(mini.HasTebs());
  191. EXPECT_TRUE(mini.HasPeb());
  192. EXPECT_FALSE(mini.HasStream(ThreadExListStream));
  193. EXPECT_FALSE(mini.HasStream(Memory64ListStream));
  194. EXPECT_FALSE(mini.HasStream(CommentStreamA));
  195. EXPECT_FALSE(mini.HasStream(CommentStreamW));
  196. EXPECT_FALSE(mini.HasStream(HandleDataStream));
  197. EXPECT_FALSE(mini.HasStream(FunctionTableStream));
  198. EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
  199. EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
  200. EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
  201. EXPECT_FALSE(mini.HasStream(TokenStream));
  202. // We expect no off-stack memory in this dump.
  203. EXPECT_FALSE(mini.HasMemory(this));
  204. }
  205. TEST_F(MinidumpTest, LargerDump) {
  206. ASSERT_TRUE(WriteDump(kLargerDumpType));
  207. DumpAnalysis mini(dump_file_);
  208. // The dump should have all of these streams.
  209. EXPECT_TRUE(mini.HasStream(ThreadListStream));
  210. EXPECT_TRUE(mini.HasStream(ModuleListStream));
  211. EXPECT_TRUE(mini.HasStream(MemoryListStream));
  212. EXPECT_TRUE(mini.HasStream(ExceptionStream));
  213. EXPECT_TRUE(mini.HasStream(SystemInfoStream));
  214. EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
  215. EXPECT_TRUE(mini.HasStream(MiscInfoStream));
  216. // We expect memory referenced by stack in this dump.
  217. EXPECT_TRUE(mini.HasMemory(this));
  218. // We expect PEB and TEBs in this dump.
  219. EXPECT_TRUE(mini.HasTebs());
  220. EXPECT_TRUE(mini.HasPeb());
  221. EXPECT_FALSE(mini.HasStream(ThreadExListStream));
  222. EXPECT_FALSE(mini.HasStream(Memory64ListStream));
  223. EXPECT_FALSE(mini.HasStream(CommentStreamA));
  224. EXPECT_FALSE(mini.HasStream(CommentStreamW));
  225. EXPECT_FALSE(mini.HasStream(HandleDataStream));
  226. EXPECT_FALSE(mini.HasStream(FunctionTableStream));
  227. EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
  228. EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
  229. EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
  230. EXPECT_FALSE(mini.HasStream(TokenStream));
  231. }
  232. TEST_F(MinidumpTest, FullDump) {
  233. ASSERT_TRUE(WriteDump(kFullDumpType));
  234. ASSERT_TRUE(dump_file_ != L"");
  235. ASSERT_TRUE(full_dump_file_ != L"");
  236. DumpAnalysis mini(dump_file_);
  237. DumpAnalysis full(full_dump_file_);
  238. // Either dumps can contain part of the information.
  239. // The dump should have all of these streams.
  240. EXPECT_TRUE(mini.HasStream(ThreadListStream));
  241. EXPECT_TRUE(full.HasStream(ThreadListStream));
  242. EXPECT_TRUE(mini.HasStream(ModuleListStream));
  243. EXPECT_TRUE(full.HasStream(ModuleListStream));
  244. EXPECT_TRUE(mini.HasStream(ExceptionStream));
  245. EXPECT_TRUE(full.HasStream(ExceptionStream));
  246. EXPECT_TRUE(mini.HasStream(SystemInfoStream));
  247. EXPECT_TRUE(full.HasStream(SystemInfoStream));
  248. EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
  249. EXPECT_TRUE(full.HasStream(UnloadedModuleListStream));
  250. EXPECT_TRUE(mini.HasStream(MiscInfoStream));
  251. EXPECT_TRUE(full.HasStream(MiscInfoStream));
  252. EXPECT_TRUE(mini.HasStream(HandleDataStream));
  253. EXPECT_TRUE(full.HasStream(HandleDataStream));
  254. // We expect memory referenced by stack in this dump.
  255. EXPECT_FALSE(mini.HasMemory(this));
  256. EXPECT_TRUE(full.HasMemory(this));
  257. // We expect PEB and TEBs in this dump.
  258. EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
  259. EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
  260. EXPECT_TRUE(mini.HasStream(MemoryListStream));
  261. EXPECT_TRUE(full.HasStream(Memory64ListStream));
  262. EXPECT_FALSE(mini.HasStream(Memory64ListStream));
  263. EXPECT_FALSE(full.HasStream(MemoryListStream));
  264. // This is the only place we don't use OR because we want both not
  265. // to have the streams.
  266. EXPECT_FALSE(mini.HasStream(ThreadExListStream));
  267. EXPECT_FALSE(full.HasStream(ThreadExListStream));
  268. EXPECT_FALSE(mini.HasStream(CommentStreamA));
  269. EXPECT_FALSE(full.HasStream(CommentStreamA));
  270. EXPECT_FALSE(mini.HasStream(CommentStreamW));
  271. EXPECT_FALSE(full.HasStream(CommentStreamW));
  272. EXPECT_FALSE(mini.HasStream(FunctionTableStream));
  273. EXPECT_FALSE(full.HasStream(FunctionTableStream));
  274. EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
  275. EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
  276. EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
  277. EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
  278. EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
  279. EXPECT_FALSE(full.HasStream(HandleOperationListStream));
  280. EXPECT_FALSE(mini.HasStream(TokenStream));
  281. EXPECT_FALSE(full.HasStream(TokenStream));
  282. }
  283. } // namespace