/thirdparty/breakpad/processor/minidump_unittest.cc

http://github.com/tomahawk-player/tomahawk · C++ · 907 lines · 748 code · 114 blank · 45 comment · 39 complexity · 5473437013dd1c92ef8ca3f07270c58d 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. // Unit test for Minidump. Uses a pre-generated minidump and
  30. // verifies that certain streams are correct.
  31. #include <iostream>
  32. #include <fstream>
  33. #include <sstream>
  34. #include <stdlib.h>
  35. #include <string>
  36. #include <vector>
  37. #include "breakpad_googletest_includes.h"
  38. #include "google_breakpad/common/minidump_format.h"
  39. #include "google_breakpad/processor/minidump.h"
  40. #include "processor/logging.h"
  41. #include "processor/synth_minidump.h"
  42. namespace {
  43. using google_breakpad::Minidump;
  44. using google_breakpad::MinidumpContext;
  45. using google_breakpad::MinidumpException;
  46. using google_breakpad::MinidumpMemoryInfo;
  47. using google_breakpad::MinidumpMemoryInfoList;
  48. using google_breakpad::MinidumpMemoryList;
  49. using google_breakpad::MinidumpMemoryRegion;
  50. using google_breakpad::MinidumpModule;
  51. using google_breakpad::MinidumpModuleList;
  52. using google_breakpad::MinidumpSystemInfo;
  53. using google_breakpad::MinidumpThread;
  54. using google_breakpad::MinidumpThreadList;
  55. using google_breakpad::SynthMinidump::Context;
  56. using google_breakpad::SynthMinidump::Dump;
  57. using google_breakpad::SynthMinidump::Exception;
  58. using google_breakpad::SynthMinidump::Memory;
  59. using google_breakpad::SynthMinidump::Module;
  60. using google_breakpad::SynthMinidump::Stream;
  61. using google_breakpad::SynthMinidump::String;
  62. using google_breakpad::SynthMinidump::SystemInfo;
  63. using google_breakpad::SynthMinidump::Thread;
  64. using google_breakpad::test_assembler::kBigEndian;
  65. using google_breakpad::test_assembler::kLittleEndian;
  66. using std::ifstream;
  67. using std::istringstream;
  68. using std::string;
  69. using std::vector;
  70. using ::testing::Return;
  71. class MinidumpTest : public ::testing::Test {
  72. public:
  73. void SetUp() {
  74. minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
  75. "/src/processor/testdata/minidump2.dmp";
  76. }
  77. string minidump_file_;
  78. };
  79. TEST_F(MinidumpTest, TestMinidumpFromFile) {
  80. Minidump minidump(minidump_file_);
  81. ASSERT_EQ(minidump.path(), minidump_file_);
  82. ASSERT_TRUE(minidump.Read());
  83. const MDRawHeader* header = minidump.header();
  84. ASSERT_NE(header, (MDRawHeader*)NULL);
  85. ASSERT_EQ(header->signature, u_int32_t(MD_HEADER_SIGNATURE));
  86. //TODO: add more checks here
  87. }
  88. TEST_F(MinidumpTest, TestMinidumpFromStream) {
  89. // read minidump contents into memory, construct a stringstream around them
  90. ifstream file_stream(minidump_file_.c_str(), std::ios::in);
  91. ASSERT_TRUE(file_stream.good());
  92. vector<char> bytes;
  93. file_stream.seekg(0, std::ios_base::end);
  94. ASSERT_TRUE(file_stream.good());
  95. bytes.resize(file_stream.tellg());
  96. file_stream.seekg(0, std::ios_base::beg);
  97. ASSERT_TRUE(file_stream.good());
  98. file_stream.read(&bytes[0], bytes.size());
  99. ASSERT_TRUE(file_stream.good());
  100. string str(&bytes[0], bytes.size());
  101. istringstream stream(str);
  102. ASSERT_TRUE(stream.good());
  103. // now read minidump from stringstream
  104. Minidump minidump(stream);
  105. ASSERT_EQ(minidump.path(), "");
  106. ASSERT_TRUE(minidump.Read());
  107. const MDRawHeader* header = minidump.header();
  108. ASSERT_NE(header, (MDRawHeader*)NULL);
  109. ASSERT_EQ(header->signature, u_int32_t(MD_HEADER_SIGNATURE));
  110. //TODO: add more checks here
  111. }
  112. TEST(Dump, ReadBackEmpty) {
  113. Dump dump(0);
  114. dump.Finish();
  115. string contents;
  116. ASSERT_TRUE(dump.GetContents(&contents));
  117. istringstream stream(contents);
  118. Minidump minidump(stream);
  119. ASSERT_TRUE(minidump.Read());
  120. ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
  121. }
  122. TEST(Dump, ReadBackEmptyBigEndian) {
  123. Dump big_minidump(0, kBigEndian);
  124. big_minidump.Finish();
  125. string contents;
  126. ASSERT_TRUE(big_minidump.GetContents(&contents));
  127. istringstream stream(contents);
  128. Minidump minidump(stream);
  129. ASSERT_TRUE(minidump.Read());
  130. ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
  131. }
  132. TEST(Dump, OneStream) {
  133. Dump dump(0, kBigEndian);
  134. Stream stream(dump, 0xfbb7fa2bU);
  135. stream.Append("stream contents");
  136. dump.Add(&stream);
  137. dump.Finish();
  138. string contents;
  139. ASSERT_TRUE(dump.GetContents(&contents));
  140. istringstream minidump_stream(contents);
  141. Minidump minidump(minidump_stream);
  142. ASSERT_TRUE(minidump.Read());
  143. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  144. const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
  145. ASSERT_TRUE(dir != NULL);
  146. EXPECT_EQ(0xfbb7fa2bU, dir->stream_type);
  147. u_int32_t stream_length;
  148. ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length));
  149. ASSERT_EQ(15U, stream_length);
  150. char stream_contents[15];
  151. ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents)));
  152. EXPECT_EQ(string("stream contents"),
  153. string(stream_contents, sizeof(stream_contents)));
  154. EXPECT_FALSE(minidump.GetThreadList());
  155. EXPECT_FALSE(minidump.GetModuleList());
  156. EXPECT_FALSE(minidump.GetMemoryList());
  157. EXPECT_FALSE(minidump.GetException());
  158. EXPECT_FALSE(minidump.GetAssertion());
  159. EXPECT_FALSE(minidump.GetSystemInfo());
  160. EXPECT_FALSE(minidump.GetMiscInfo());
  161. EXPECT_FALSE(minidump.GetBreakpadInfo());
  162. }
  163. TEST(Dump, OneMemory) {
  164. Dump dump(0, kBigEndian);
  165. Memory memory(dump, 0x309d68010bd21b2cULL);
  166. memory.Append("memory contents");
  167. dump.Add(&memory);
  168. dump.Finish();
  169. string contents;
  170. ASSERT_TRUE(dump.GetContents(&contents));
  171. istringstream minidump_stream(contents);
  172. Minidump minidump(minidump_stream);
  173. ASSERT_TRUE(minidump.Read());
  174. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  175. const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
  176. ASSERT_TRUE(dir != NULL);
  177. EXPECT_EQ((u_int32_t) MD_MEMORY_LIST_STREAM, dir->stream_type);
  178. MinidumpMemoryList *memory_list = minidump.GetMemoryList();
  179. ASSERT_TRUE(memory_list != NULL);
  180. ASSERT_EQ(1U, memory_list->region_count());
  181. MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0);
  182. ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase());
  183. ASSERT_EQ(15U, region1->GetSize());
  184. const u_int8_t *region1_bytes = region1->GetMemory();
  185. ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0);
  186. }
  187. // One thread --- and its requisite entourage.
  188. TEST(Dump, OneThread) {
  189. Dump dump(0, kLittleEndian);
  190. Memory stack(dump, 0x2326a0fa);
  191. stack.Append("stack for thread");
  192. MDRawContextX86 raw_context;
  193. raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
  194. raw_context.edi = 0x3ecba80d;
  195. raw_context.esi = 0x382583b9;
  196. raw_context.ebx = 0x7fccc03f;
  197. raw_context.edx = 0xf62f8ec2;
  198. raw_context.ecx = 0x46a6a6a8;
  199. raw_context.eax = 0x6a5025e2;
  200. raw_context.ebp = 0xd9fabb4a;
  201. raw_context.eip = 0x6913f540;
  202. raw_context.cs = 0xbffe6eda;
  203. raw_context.eflags = 0xb2ce1e2d;
  204. raw_context.esp = 0x659caaa4;
  205. raw_context.ss = 0x2e951ef7;
  206. Context context(dump, raw_context);
  207. Thread thread(dump, 0xa898f11b, stack, context,
  208. 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
  209. dump.Add(&stack);
  210. dump.Add(&context);
  211. dump.Add(&thread);
  212. dump.Finish();
  213. string contents;
  214. ASSERT_TRUE(dump.GetContents(&contents));
  215. istringstream minidump_stream(contents);
  216. Minidump minidump(minidump_stream);
  217. ASSERT_TRUE(minidump.Read());
  218. ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
  219. MinidumpMemoryList *md_memory_list = minidump.GetMemoryList();
  220. ASSERT_TRUE(md_memory_list != NULL);
  221. ASSERT_EQ(1U, md_memory_list->region_count());
  222. MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0);
  223. ASSERT_EQ(0x2326a0faU, md_region->GetBase());
  224. ASSERT_EQ(16U, md_region->GetSize());
  225. const u_int8_t *region_bytes = md_region->GetMemory();
  226. ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0);
  227. MinidumpThreadList *thread_list = minidump.GetThreadList();
  228. ASSERT_TRUE(thread_list != NULL);
  229. ASSERT_EQ(1U, thread_list->thread_count());
  230. MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0);
  231. ASSERT_TRUE(md_thread != NULL);
  232. u_int32_t thread_id;
  233. ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
  234. ASSERT_EQ(0xa898f11bU, thread_id);
  235. MinidumpMemoryRegion *md_stack = md_thread->GetMemory();
  236. ASSERT_TRUE(md_stack != NULL);
  237. ASSERT_EQ(0x2326a0faU, md_stack->GetBase());
  238. ASSERT_EQ(16U, md_stack->GetSize());
  239. const u_int8_t *md_stack_bytes = md_stack->GetMemory();
  240. ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0);
  241. MinidumpContext *md_context = md_thread->GetContext();
  242. ASSERT_TRUE(md_context != NULL);
  243. ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
  244. const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
  245. ASSERT_TRUE(md_raw_context != NULL);
  246. ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
  247. (md_raw_context->context_flags
  248. & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
  249. EXPECT_EQ(0x3ecba80dU, raw_context.edi);
  250. EXPECT_EQ(0x382583b9U, raw_context.esi);
  251. EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
  252. EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
  253. EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
  254. EXPECT_EQ(0x6a5025e2U, raw_context.eax);
  255. EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
  256. EXPECT_EQ(0x6913f540U, raw_context.eip);
  257. EXPECT_EQ(0xbffe6edaU, raw_context.cs);
  258. EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
  259. EXPECT_EQ(0x659caaa4U, raw_context.esp);
  260. EXPECT_EQ(0x2e951ef7U, raw_context.ss);
  261. }
  262. TEST(Dump, OneModule) {
  263. static const MDVSFixedFileInfo fixed_file_info = {
  264. 0xb2fba33a, // signature
  265. 0x33d7a728, // struct_version
  266. 0x31afcb20, // file_version_hi
  267. 0xe51cdab1, // file_version_lo
  268. 0xd1ea6907, // product_version_hi
  269. 0x03032857, // product_version_lo
  270. 0x11bf71d7, // file_flags_mask
  271. 0x5fb8cdbf, // file_flags
  272. 0xe45d0d5d, // file_os
  273. 0x107d9562, // file_type
  274. 0x5a8844d4, // file_subtype
  275. 0xa8d30b20, // file_date_hi
  276. 0x651c3e4e // file_date_lo
  277. };
  278. Dump dump(0, kBigEndian);
  279. String module_name(dump, "single module");
  280. Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
  281. module_name,
  282. 0xb1054d2a,
  283. 0x34571371,
  284. fixed_file_info, // from synth_minidump_unittest_data.h
  285. NULL, NULL);
  286. dump.Add(&module);
  287. dump.Add(&module_name);
  288. dump.Finish();
  289. string contents;
  290. ASSERT_TRUE(dump.GetContents(&contents));
  291. istringstream minidump_stream(contents);
  292. Minidump minidump(minidump_stream);
  293. ASSERT_TRUE(minidump.Read());
  294. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  295. const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
  296. ASSERT_TRUE(dir != NULL);
  297. EXPECT_EQ((u_int32_t) MD_MODULE_LIST_STREAM, dir->stream_type);
  298. MinidumpModuleList *md_module_list = minidump.GetModuleList();
  299. ASSERT_TRUE(md_module_list != NULL);
  300. ASSERT_EQ(1U, md_module_list->module_count());
  301. const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
  302. ASSERT_TRUE(md_module != NULL);
  303. ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
  304. ASSERT_EQ(0xada542bd, md_module->size());
  305. ASSERT_EQ("single module", md_module->code_file());
  306. const MDRawModule *md_raw_module = md_module->module();
  307. ASSERT_TRUE(md_raw_module != NULL);
  308. ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
  309. ASSERT_EQ(0x34571371U, md_raw_module->checksum);
  310. ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
  311. sizeof(fixed_file_info)) == 0);
  312. }
  313. TEST(Dump, OneSystemInfo) {
  314. Dump dump(0, kLittleEndian);
  315. String csd_version(dump, "Petulant Pierogi");
  316. SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
  317. dump.Add(&system_info);
  318. dump.Add(&csd_version);
  319. dump.Finish();
  320. string contents;
  321. ASSERT_TRUE(dump.GetContents(&contents));
  322. istringstream minidump_stream(contents);
  323. Minidump minidump(minidump_stream);
  324. ASSERT_TRUE(minidump.Read());
  325. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  326. const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
  327. ASSERT_TRUE(dir != NULL);
  328. EXPECT_EQ((u_int32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type);
  329. MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo();
  330. ASSERT_TRUE(md_system_info != NULL);
  331. ASSERT_EQ("windows", md_system_info->GetOS());
  332. ASSERT_EQ("x86", md_system_info->GetCPU());
  333. ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion());
  334. ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor());
  335. }
  336. TEST(Dump, BigDump) {
  337. Dump dump(0, kLittleEndian);
  338. // A SystemInfo stream.
  339. String csd_version(dump, "Munificent Macaque");
  340. SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
  341. dump.Add(&csd_version);
  342. dump.Add(&system_info);
  343. // Five threads!
  344. Memory stack0(dump, 0x70b9ebfc);
  345. stack0.Append("stack for thread zero");
  346. MDRawContextX86 raw_context0;
  347. raw_context0.context_flags = MD_CONTEXT_X86_INTEGER;
  348. raw_context0.eip = 0xaf0709e4;
  349. Context context0(dump, raw_context0);
  350. Thread thread0(dump, 0xbbef4432, stack0, context0,
  351. 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL);
  352. dump.Add(&stack0);
  353. dump.Add(&context0);
  354. dump.Add(&thread0);
  355. Memory stack1(dump, 0xf988cc45);
  356. stack1.Append("stack for thread one");
  357. MDRawContextX86 raw_context1;
  358. raw_context1.context_flags = MD_CONTEXT_X86_INTEGER;
  359. raw_context1.eip = 0xe4f56f81;
  360. Context context1(dump, raw_context1);
  361. Thread thread1(dump, 0x657c3f58, stack1, context1,
  362. 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL);
  363. dump.Add(&stack1);
  364. dump.Add(&context1);
  365. dump.Add(&thread1);
  366. Memory stack2(dump, 0xc8a92e7c);
  367. stack2.Append("stack for thread two");
  368. MDRawContextX86 raw_context2;
  369. raw_context2.context_flags = MD_CONTEXT_X86_INTEGER;
  370. raw_context2.eip = 0xb336a438;
  371. Context context2(dump, raw_context2);
  372. Thread thread2(dump, 0xdf4b8a71, stack2, context2,
  373. 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL);
  374. dump.Add(&stack2);
  375. dump.Add(&context2);
  376. dump.Add(&thread2);
  377. Memory stack3(dump, 0x36d08e08);
  378. stack3.Append("stack for thread three");
  379. MDRawContextX86 raw_context3;
  380. raw_context3.context_flags = MD_CONTEXT_X86_INTEGER;
  381. raw_context3.eip = 0xdf99a60c;
  382. Context context3(dump, raw_context3);
  383. Thread thread3(dump, 0x86e6c341, stack3, context3,
  384. 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL);
  385. dump.Add(&stack3);
  386. dump.Add(&context3);
  387. dump.Add(&thread3);
  388. Memory stack4(dump, 0x1e0ab4fa);
  389. stack4.Append("stack for thread four");
  390. MDRawContextX86 raw_context4;
  391. raw_context4.context_flags = MD_CONTEXT_X86_INTEGER;
  392. raw_context4.eip = 0xaa646267;
  393. Context context4(dump, raw_context4);
  394. Thread thread4(dump, 0x261a28d4, stack4, context4,
  395. 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL);
  396. dump.Add(&stack4);
  397. dump.Add(&context4);
  398. dump.Add(&thread4);
  399. // Three modules!
  400. String module1_name(dump, "module one");
  401. Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name);
  402. dump.Add(&module1_name);
  403. dump.Add(&module1);
  404. String module2_name(dump, "module two");
  405. Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name);
  406. dump.Add(&module2_name);
  407. dump.Add(&module2);
  408. String module3_name(dump, "module three");
  409. Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name);
  410. dump.Add(&module3_name);
  411. dump.Add(&module3);
  412. // Add one more memory region, on top of the five stacks.
  413. Memory memory5(dump, 0x61979e828040e564ULL);
  414. memory5.Append("contents of memory 5");
  415. dump.Add(&memory5);
  416. dump.Finish();
  417. string contents;
  418. ASSERT_TRUE(dump.GetContents(&contents));
  419. istringstream minidump_stream(contents);
  420. Minidump minidump(minidump_stream);
  421. ASSERT_TRUE(minidump.Read());
  422. ASSERT_EQ(4U, minidump.GetDirectoryEntryCount());
  423. // Check the threads.
  424. MinidumpThreadList *thread_list = minidump.GetThreadList();
  425. ASSERT_TRUE(thread_list != NULL);
  426. ASSERT_EQ(5U, thread_list->thread_count());
  427. u_int32_t thread_id;
  428. ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id));
  429. ASSERT_EQ(0xbbef4432U, thread_id);
  430. ASSERT_EQ(0x70b9ebfcU,
  431. thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase());
  432. ASSERT_EQ(0xaf0709e4U,
  433. thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86()
  434. ->eip);
  435. ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id));
  436. ASSERT_EQ(0x657c3f58U, thread_id);
  437. ASSERT_EQ(0xf988cc45U,
  438. thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase());
  439. ASSERT_EQ(0xe4f56f81U,
  440. thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86()
  441. ->eip);
  442. ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id));
  443. ASSERT_EQ(0xdf4b8a71U, thread_id);
  444. ASSERT_EQ(0xc8a92e7cU,
  445. thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase());
  446. ASSERT_EQ(0xb336a438U,
  447. thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86()
  448. ->eip);
  449. ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id));
  450. ASSERT_EQ(0x86e6c341U, thread_id);
  451. ASSERT_EQ(0x36d08e08U,
  452. thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase());
  453. ASSERT_EQ(0xdf99a60cU,
  454. thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86()
  455. ->eip);
  456. ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id));
  457. ASSERT_EQ(0x261a28d4U, thread_id);
  458. ASSERT_EQ(0x1e0ab4faU,
  459. thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase());
  460. ASSERT_EQ(0xaa646267U,
  461. thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86()
  462. ->eip);
  463. // Check the modules.
  464. MinidumpModuleList *md_module_list = minidump.GetModuleList();
  465. ASSERT_TRUE(md_module_list != NULL);
  466. ASSERT_EQ(3U, md_module_list->module_count());
  467. EXPECT_EQ(0xeb77da57b5d4cbdaULL,
  468. md_module_list->GetModuleAtIndex(0)->base_address());
  469. EXPECT_EQ(0x8675884adfe5ac90ULL,
  470. md_module_list->GetModuleAtIndex(1)->base_address());
  471. EXPECT_EQ(0x95fc1544da321b6cULL,
  472. md_module_list->GetModuleAtIndex(2)->base_address());
  473. }
  474. TEST(Dump, OneMemoryInfo) {
  475. Dump dump(0, kBigEndian);
  476. Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM);
  477. // Add the MDRawMemoryInfoList header.
  478. const u_int64_t kNumberOfEntries = 1;
  479. stream.D32(sizeof(MDRawMemoryInfoList)) // size_of_header
  480. .D32(sizeof(MDRawMemoryInfo)) // size_of_entry
  481. .D64(kNumberOfEntries); // number_of_entries
  482. // Now add a MDRawMemoryInfo entry.
  483. const u_int64_t kBaseAddress = 0x1000;
  484. const u_int64_t kRegionSize = 0x2000;
  485. stream.D64(kBaseAddress) // base_address
  486. .D64(kBaseAddress) // allocation_base
  487. .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // allocation_protection
  488. .D32(0) // __alignment1
  489. .D64(kRegionSize) // region_size
  490. .D32(MD_MEMORY_STATE_COMMIT) // state
  491. .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // protection
  492. .D32(MD_MEMORY_TYPE_PRIVATE) // type
  493. .D32(0); // __alignment2
  494. dump.Add(&stream);
  495. dump.Finish();
  496. string contents;
  497. ASSERT_TRUE(dump.GetContents(&contents));
  498. istringstream minidump_stream(contents);
  499. Minidump minidump(minidump_stream);
  500. ASSERT_TRUE(minidump.Read());
  501. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  502. const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
  503. ASSERT_TRUE(dir != NULL);
  504. EXPECT_EQ((u_int32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type);
  505. MinidumpMemoryInfoList *info_list = minidump.GetMemoryInfoList();
  506. ASSERT_TRUE(info_list != NULL);
  507. ASSERT_EQ(1U, info_list->info_count());
  508. const MinidumpMemoryInfo *info1 = info_list->GetMemoryInfoAtIndex(0);
  509. ASSERT_EQ(kBaseAddress, info1->GetBase());
  510. ASSERT_EQ(kRegionSize, info1->GetSize());
  511. ASSERT_TRUE(info1->IsExecutable());
  512. ASSERT_TRUE(info1->IsWritable());
  513. // Should get back the same memory region here.
  514. const MinidumpMemoryInfo *info2 =
  515. info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2);
  516. ASSERT_EQ(kBaseAddress, info2->GetBase());
  517. ASSERT_EQ(kRegionSize, info2->GetSize());
  518. }
  519. TEST(Dump, OneExceptionX86) {
  520. Dump dump(0, kLittleEndian);
  521. MDRawContextX86 raw_context;
  522. raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
  523. raw_context.edi = 0x3ecba80d;
  524. raw_context.esi = 0x382583b9;
  525. raw_context.ebx = 0x7fccc03f;
  526. raw_context.edx = 0xf62f8ec2;
  527. raw_context.ecx = 0x46a6a6a8;
  528. raw_context.eax = 0x6a5025e2;
  529. raw_context.ebp = 0xd9fabb4a;
  530. raw_context.eip = 0x6913f540;
  531. raw_context.cs = 0xbffe6eda;
  532. raw_context.eflags = 0xb2ce1e2d;
  533. raw_context.esp = 0x659caaa4;
  534. raw_context.ss = 0x2e951ef7;
  535. Context context(dump, raw_context);
  536. Exception exception(dump, context,
  537. 0x1234abcd, // thread id
  538. 0xdcba4321, // exception code
  539. 0xf0e0d0c0, // exception flags
  540. 0x0919a9b9c9d9e9f9ULL); // exception address
  541. dump.Add(&context);
  542. dump.Add(&exception);
  543. dump.Finish();
  544. string contents;
  545. ASSERT_TRUE(dump.GetContents(&contents));
  546. istringstream minidump_stream(contents);
  547. Minidump minidump(minidump_stream);
  548. ASSERT_TRUE(minidump.Read());
  549. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  550. MinidumpException *md_exception = minidump.GetException();
  551. ASSERT_TRUE(md_exception != NULL);
  552. u_int32_t thread_id;
  553. ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
  554. ASSERT_EQ(0x1234abcd, thread_id);
  555. const MDRawExceptionStream* raw_exception = md_exception->exception();
  556. ASSERT_TRUE(raw_exception != NULL);
  557. EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
  558. EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
  559. EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
  560. raw_exception->exception_record.exception_address);
  561. MinidumpContext *md_context = md_exception->GetContext();
  562. ASSERT_TRUE(md_context != NULL);
  563. ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
  564. const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
  565. ASSERT_TRUE(md_raw_context != NULL);
  566. ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
  567. (md_raw_context->context_flags
  568. & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
  569. EXPECT_EQ(0x3ecba80dU, raw_context.edi);
  570. EXPECT_EQ(0x382583b9U, raw_context.esi);
  571. EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
  572. EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
  573. EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
  574. EXPECT_EQ(0x6a5025e2U, raw_context.eax);
  575. EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
  576. EXPECT_EQ(0x6913f540U, raw_context.eip);
  577. EXPECT_EQ(0xbffe6edaU, raw_context.cs);
  578. EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
  579. EXPECT_EQ(0x659caaa4U, raw_context.esp);
  580. EXPECT_EQ(0x2e951ef7U, raw_context.ss);
  581. }
  582. TEST(Dump, OneExceptionX86XState) {
  583. Dump dump(0, kLittleEndian);
  584. MDRawContextX86 raw_context;
  585. raw_context.context_flags = MD_CONTEXT_X86_INTEGER |
  586. MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE;
  587. raw_context.edi = 0x3ecba80d;
  588. raw_context.esi = 0x382583b9;
  589. raw_context.ebx = 0x7fccc03f;
  590. raw_context.edx = 0xf62f8ec2;
  591. raw_context.ecx = 0x46a6a6a8;
  592. raw_context.eax = 0x6a5025e2;
  593. raw_context.ebp = 0xd9fabb4a;
  594. raw_context.eip = 0x6913f540;
  595. raw_context.cs = 0xbffe6eda;
  596. raw_context.eflags = 0xb2ce1e2d;
  597. raw_context.esp = 0x659caaa4;
  598. raw_context.ss = 0x2e951ef7;
  599. Context context(dump, raw_context);
  600. Exception exception(dump, context,
  601. 0x1234abcd, // thread id
  602. 0xdcba4321, // exception code
  603. 0xf0e0d0c0, // exception flags
  604. 0x0919a9b9c9d9e9f9ULL); // exception address
  605. dump.Add(&context);
  606. dump.Add(&exception);
  607. dump.Finish();
  608. string contents;
  609. ASSERT_TRUE(dump.GetContents(&contents));
  610. istringstream minidump_stream(contents);
  611. Minidump minidump(minidump_stream);
  612. ASSERT_TRUE(minidump.Read());
  613. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  614. MinidumpException *md_exception = minidump.GetException();
  615. ASSERT_TRUE(md_exception != NULL);
  616. u_int32_t thread_id;
  617. ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
  618. ASSERT_EQ(0x1234abcd, thread_id);
  619. const MDRawExceptionStream* raw_exception = md_exception->exception();
  620. ASSERT_TRUE(raw_exception != NULL);
  621. EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
  622. EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
  623. EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
  624. raw_exception->exception_record.exception_address);
  625. MinidumpContext *md_context = md_exception->GetContext();
  626. ASSERT_TRUE(md_context != NULL);
  627. ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
  628. const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
  629. ASSERT_TRUE(md_raw_context != NULL);
  630. ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
  631. (md_raw_context->context_flags
  632. & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
  633. EXPECT_EQ(0x3ecba80dU, raw_context.edi);
  634. EXPECT_EQ(0x382583b9U, raw_context.esi);
  635. EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
  636. EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
  637. EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
  638. EXPECT_EQ(0x6a5025e2U, raw_context.eax);
  639. EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
  640. EXPECT_EQ(0x6913f540U, raw_context.eip);
  641. EXPECT_EQ(0xbffe6edaU, raw_context.cs);
  642. EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
  643. EXPECT_EQ(0x659caaa4U, raw_context.esp);
  644. EXPECT_EQ(0x2e951ef7U, raw_context.ss);
  645. }
  646. TEST(Dump, OneExceptionARM) {
  647. Dump dump(0, kLittleEndian);
  648. MDRawContextARM raw_context;
  649. raw_context.context_flags = MD_CONTEXT_ARM_INTEGER;
  650. raw_context.iregs[0] = 0x3ecba80d;
  651. raw_context.iregs[1] = 0x382583b9;
  652. raw_context.iregs[2] = 0x7fccc03f;
  653. raw_context.iregs[3] = 0xf62f8ec2;
  654. raw_context.iregs[4] = 0x46a6a6a8;
  655. raw_context.iregs[5] = 0x6a5025e2;
  656. raw_context.iregs[6] = 0xd9fabb4a;
  657. raw_context.iregs[7] = 0x6913f540;
  658. raw_context.iregs[8] = 0xbffe6eda;
  659. raw_context.iregs[9] = 0xb2ce1e2d;
  660. raw_context.iregs[10] = 0x659caaa4;
  661. raw_context.iregs[11] = 0xf0e0d0c0;
  662. raw_context.iregs[12] = 0xa9b8c7d6;
  663. raw_context.iregs[13] = 0x12345678;
  664. raw_context.iregs[14] = 0xabcd1234;
  665. raw_context.iregs[15] = 0x10203040;
  666. raw_context.cpsr = 0x2e951ef7;
  667. Context context(dump, raw_context);
  668. Exception exception(dump, context,
  669. 0x1234abcd, // thread id
  670. 0xdcba4321, // exception code
  671. 0xf0e0d0c0, // exception flags
  672. 0x0919a9b9c9d9e9f9ULL); // exception address
  673. dump.Add(&context);
  674. dump.Add(&exception);
  675. dump.Finish();
  676. string contents;
  677. ASSERT_TRUE(dump.GetContents(&contents));
  678. istringstream minidump_stream(contents);
  679. Minidump minidump(minidump_stream);
  680. ASSERT_TRUE(minidump.Read());
  681. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  682. MinidumpException *md_exception = minidump.GetException();
  683. ASSERT_TRUE(md_exception != NULL);
  684. u_int32_t thread_id;
  685. ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
  686. ASSERT_EQ(0x1234abcd, thread_id);
  687. const MDRawExceptionStream* raw_exception = md_exception->exception();
  688. ASSERT_TRUE(raw_exception != NULL);
  689. EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
  690. EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
  691. EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
  692. raw_exception->exception_record.exception_address);
  693. MinidumpContext *md_context = md_exception->GetContext();
  694. ASSERT_TRUE(md_context != NULL);
  695. ASSERT_EQ((u_int32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
  696. const MDRawContextARM *md_raw_context = md_context->GetContextARM();
  697. ASSERT_TRUE(md_raw_context != NULL);
  698. ASSERT_EQ((u_int32_t) MD_CONTEXT_ARM_INTEGER,
  699. (md_raw_context->context_flags
  700. & MD_CONTEXT_ARM_INTEGER));
  701. EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
  702. EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
  703. EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
  704. EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
  705. EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
  706. EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
  707. EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
  708. EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
  709. EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
  710. EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
  711. EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
  712. EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
  713. EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
  714. EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
  715. EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
  716. EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
  717. EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
  718. }
  719. TEST(Dump, OneExceptionARMOldFlags) {
  720. Dump dump(0, kLittleEndian);
  721. MDRawContextARM raw_context;
  722. // MD_CONTEXT_ARM_INTEGER, but with _OLD
  723. raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002;
  724. raw_context.iregs[0] = 0x3ecba80d;
  725. raw_context.iregs[1] = 0x382583b9;
  726. raw_context.iregs[2] = 0x7fccc03f;
  727. raw_context.iregs[3] = 0xf62f8ec2;
  728. raw_context.iregs[4] = 0x46a6a6a8;
  729. raw_context.iregs[5] = 0x6a5025e2;
  730. raw_context.iregs[6] = 0xd9fabb4a;
  731. raw_context.iregs[7] = 0x6913f540;
  732. raw_context.iregs[8] = 0xbffe6eda;
  733. raw_context.iregs[9] = 0xb2ce1e2d;
  734. raw_context.iregs[10] = 0x659caaa4;
  735. raw_context.iregs[11] = 0xf0e0d0c0;
  736. raw_context.iregs[12] = 0xa9b8c7d6;
  737. raw_context.iregs[13] = 0x12345678;
  738. raw_context.iregs[14] = 0xabcd1234;
  739. raw_context.iregs[15] = 0x10203040;
  740. raw_context.cpsr = 0x2e951ef7;
  741. Context context(dump, raw_context);
  742. Exception exception(dump, context,
  743. 0x1234abcd, // thread id
  744. 0xdcba4321, // exception code
  745. 0xf0e0d0c0, // exception flags
  746. 0x0919a9b9c9d9e9f9ULL); // exception address
  747. dump.Add(&context);
  748. dump.Add(&exception);
  749. dump.Finish();
  750. string contents;
  751. ASSERT_TRUE(dump.GetContents(&contents));
  752. istringstream minidump_stream(contents);
  753. Minidump minidump(minidump_stream);
  754. ASSERT_TRUE(minidump.Read());
  755. ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
  756. MinidumpException *md_exception = minidump.GetException();
  757. ASSERT_TRUE(md_exception != NULL);
  758. u_int32_t thread_id;
  759. ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
  760. ASSERT_EQ(0x1234abcd, thread_id);
  761. const MDRawExceptionStream* raw_exception = md_exception->exception();
  762. ASSERT_TRUE(raw_exception != NULL);
  763. EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
  764. EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
  765. EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
  766. raw_exception->exception_record.exception_address);
  767. MinidumpContext *md_context = md_exception->GetContext();
  768. ASSERT_TRUE(md_context != NULL);
  769. ASSERT_EQ((u_int32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
  770. const MDRawContextARM *md_raw_context = md_context->GetContextARM();
  771. ASSERT_TRUE(md_raw_context != NULL);
  772. ASSERT_EQ((u_int32_t) MD_CONTEXT_ARM_INTEGER,
  773. (md_raw_context->context_flags
  774. & MD_CONTEXT_ARM_INTEGER));
  775. EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
  776. EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
  777. EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
  778. EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
  779. EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
  780. EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
  781. EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
  782. EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
  783. EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
  784. EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
  785. EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
  786. EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
  787. EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
  788. EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
  789. EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
  790. EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
  791. EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
  792. }
  793. } // namespace