1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/minidump_test.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,332 @@ 1.4 +// Copyright (c) 2010, Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +#include <windows.h> 1.34 +#include <objbase.h> 1.35 +#include <dbghelp.h> 1.36 + 1.37 +#include "client/windows/crash_generation/minidump_generator.h" 1.38 +#include "client/windows/unittests/dump_analysis.h" // NOLINT 1.39 + 1.40 +#include "gtest/gtest.h" 1.41 + 1.42 +namespace { 1.43 + 1.44 +// Minidump with stacks, PEB, TEB, and unloaded module list. 1.45 +const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>( 1.46 + MiniDumpWithProcessThreadData | // Get PEB and TEB. 1.47 + MiniDumpWithUnloadedModules); // Get unloaded modules when available. 1.48 + 1.49 +// Minidump with all of the above, plus memory referenced from stack. 1.50 +const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( 1.51 + MiniDumpWithProcessThreadData | // Get PEB and TEB. 1.52 + MiniDumpWithUnloadedModules | // Get unloaded modules when available. 1.53 + MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack. 1.54 + 1.55 +// Large dump with all process memory. 1.56 +const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>( 1.57 + MiniDumpWithFullMemory | // Full memory from process. 1.58 + MiniDumpWithProcessThreadData | // Get PEB and TEB. 1.59 + MiniDumpWithHandleData | // Get all handle information. 1.60 + MiniDumpWithUnloadedModules); // Get unloaded modules when available. 1.61 + 1.62 +class MinidumpTest: public testing::Test { 1.63 + public: 1.64 + MinidumpTest() { 1.65 + wchar_t temp_dir_path[ MAX_PATH ] = {0}; 1.66 + ::GetTempPath(MAX_PATH, temp_dir_path); 1.67 + dump_path_ = temp_dir_path; 1.68 + } 1.69 + 1.70 + virtual void SetUp() { 1.71 + // Make sure URLMon isn't loaded into our process. 1.72 + ASSERT_EQ(NULL, ::GetModuleHandle(L"urlmon.dll")); 1.73 + 1.74 + // Then load and unload it to ensure we have something to 1.75 + // stock the unloaded module list with. 1.76 + HMODULE urlmon = ::LoadLibrary(L"urlmon.dll"); 1.77 + ASSERT_TRUE(urlmon != NULL); 1.78 + ASSERT_TRUE(::FreeLibrary(urlmon)); 1.79 + } 1.80 + 1.81 + virtual void TearDown() { 1.82 + if (!dump_file_.empty()) { 1.83 + ::DeleteFile(dump_file_.c_str()); 1.84 + dump_file_ = L""; 1.85 + } 1.86 + if (!full_dump_file_.empty()) { 1.87 + ::DeleteFile(full_dump_file_.c_str()); 1.88 + full_dump_file_ = L""; 1.89 + } 1.90 + } 1.91 + 1.92 + bool WriteDump(ULONG flags) { 1.93 + using google_breakpad::MinidumpGenerator; 1.94 + 1.95 + // Fake exception is access violation on write to this. 1.96 + EXCEPTION_RECORD ex_record = { 1.97 + STATUS_ACCESS_VIOLATION, // ExceptionCode 1.98 + 0, // ExceptionFlags 1.99 + NULL, // ExceptionRecord; 1.100 + reinterpret_cast<void*>(0xCAFEBABE), // ExceptionAddress; 1.101 + 2, // NumberParameters; 1.102 + { EXCEPTION_WRITE_FAULT, reinterpret_cast<ULONG_PTR>(this) } 1.103 + }; 1.104 + CONTEXT ctx_record = {}; 1.105 + EXCEPTION_POINTERS ex_ptrs = { 1.106 + &ex_record, 1.107 + &ctx_record, 1.108 + }; 1.109 + 1.110 + MinidumpGenerator generator(dump_path_); 1.111 + 1.112 + // And write a dump 1.113 + bool result = generator.WriteMinidump(::GetCurrentProcess(), 1.114 + ::GetCurrentProcessId(), 1.115 + ::GetCurrentThreadId(), 1.116 + ::GetCurrentThreadId(), 1.117 + &ex_ptrs, 1.118 + NULL, 1.119 + static_cast<MINIDUMP_TYPE>(flags), 1.120 + TRUE, 1.121 + &dump_file_, 1.122 + &full_dump_file_); 1.123 + return result == TRUE; 1.124 + } 1.125 + 1.126 + protected: 1.127 + std::wstring dump_file_; 1.128 + std::wstring full_dump_file_; 1.129 + 1.130 + std::wstring dump_path_; 1.131 +}; 1.132 + 1.133 +// We need to be able to get file information from Windows 1.134 +bool HasFileInfo(const std::wstring& file_path) { 1.135 + DWORD dummy; 1.136 + const wchar_t* path = file_path.c_str(); 1.137 + DWORD length = ::GetFileVersionInfoSize(path, &dummy); 1.138 + if (length == 0) 1.139 + return NULL; 1.140 + 1.141 + void* data = calloc(length, 1); 1.142 + if (!data) 1.143 + return false; 1.144 + 1.145 + if (!::GetFileVersionInfo(path, dummy, length, data)) { 1.146 + free(data); 1.147 + return false; 1.148 + } 1.149 + 1.150 + void* translate = NULL; 1.151 + UINT page_count; 1.152 + BOOL query_result = VerQueryValue( 1.153 + data, 1.154 + L"\\VarFileInfo\\Translation", 1.155 + static_cast<void**>(&translate), 1.156 + &page_count); 1.157 + 1.158 + free(data); 1.159 + if (query_result && translate) { 1.160 + return true; 1.161 + } else { 1.162 + return false; 1.163 + } 1.164 +} 1.165 + 1.166 +TEST_F(MinidumpTest, Version) { 1.167 + API_VERSION* version = ::ImagehlpApiVersion(); 1.168 + 1.169 + HMODULE dbg_help = ::GetModuleHandle(L"dbghelp.dll"); 1.170 + ASSERT_TRUE(dbg_help != NULL); 1.171 + 1.172 + wchar_t dbg_help_file[1024] = {}; 1.173 + ASSERT_TRUE(::GetModuleFileName(dbg_help, 1.174 + dbg_help_file, 1.175 + sizeof(dbg_help_file) / 1.176 + sizeof(*dbg_help_file))); 1.177 + ASSERT_TRUE(HasFileInfo(std::wstring(dbg_help_file)) != NULL); 1.178 + 1.179 +// LOG(INFO) << "DbgHelp.dll version: " << file_info->file_version(); 1.180 +} 1.181 + 1.182 +TEST_F(MinidumpTest, Normal) { 1.183 + EXPECT_TRUE(WriteDump(MiniDumpNormal)); 1.184 + DumpAnalysis mini(dump_file_); 1.185 + 1.186 + // We expect threads, modules and some memory. 1.187 + EXPECT_TRUE(mini.HasStream(ThreadListStream)); 1.188 + EXPECT_TRUE(mini.HasStream(ModuleListStream)); 1.189 + EXPECT_TRUE(mini.HasStream(MemoryListStream)); 1.190 + EXPECT_TRUE(mini.HasStream(ExceptionStream)); 1.191 + EXPECT_TRUE(mini.HasStream(SystemInfoStream)); 1.192 + EXPECT_TRUE(mini.HasStream(MiscInfoStream)); 1.193 + 1.194 + EXPECT_FALSE(mini.HasStream(ThreadExListStream)); 1.195 + EXPECT_FALSE(mini.HasStream(Memory64ListStream)); 1.196 + EXPECT_FALSE(mini.HasStream(CommentStreamA)); 1.197 + EXPECT_FALSE(mini.HasStream(CommentStreamW)); 1.198 + EXPECT_FALSE(mini.HasStream(HandleDataStream)); 1.199 + EXPECT_FALSE(mini.HasStream(FunctionTableStream)); 1.200 + EXPECT_FALSE(mini.HasStream(UnloadedModuleListStream)); 1.201 + EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); 1.202 + EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); 1.203 + EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); 1.204 + EXPECT_FALSE(mini.HasStream(TokenStream)); 1.205 + 1.206 + // We expect no PEB nor TEBs in this dump. 1.207 + EXPECT_FALSE(mini.HasTebs()); 1.208 + EXPECT_FALSE(mini.HasPeb()); 1.209 + 1.210 + // We expect no off-stack memory in this dump. 1.211 + EXPECT_FALSE(mini.HasMemory(this)); 1.212 +} 1.213 + 1.214 +TEST_F(MinidumpTest, SmallDump) { 1.215 + ASSERT_TRUE(WriteDump(kSmallDumpType)); 1.216 + DumpAnalysis mini(dump_file_); 1.217 + 1.218 + EXPECT_TRUE(mini.HasStream(ThreadListStream)); 1.219 + EXPECT_TRUE(mini.HasStream(ModuleListStream)); 1.220 + EXPECT_TRUE(mini.HasStream(MemoryListStream)); 1.221 + EXPECT_TRUE(mini.HasStream(ExceptionStream)); 1.222 + EXPECT_TRUE(mini.HasStream(SystemInfoStream)); 1.223 + EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream)); 1.224 + EXPECT_TRUE(mini.HasStream(MiscInfoStream)); 1.225 + 1.226 + // We expect PEB and TEBs in this dump. 1.227 + EXPECT_TRUE(mini.HasTebs()); 1.228 + EXPECT_TRUE(mini.HasPeb()); 1.229 + 1.230 + EXPECT_FALSE(mini.HasStream(ThreadExListStream)); 1.231 + EXPECT_FALSE(mini.HasStream(Memory64ListStream)); 1.232 + EXPECT_FALSE(mini.HasStream(CommentStreamA)); 1.233 + EXPECT_FALSE(mini.HasStream(CommentStreamW)); 1.234 + EXPECT_FALSE(mini.HasStream(HandleDataStream)); 1.235 + EXPECT_FALSE(mini.HasStream(FunctionTableStream)); 1.236 + EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); 1.237 + EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); 1.238 + EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); 1.239 + EXPECT_FALSE(mini.HasStream(TokenStream)); 1.240 + 1.241 + // We expect no off-stack memory in this dump. 1.242 + EXPECT_FALSE(mini.HasMemory(this)); 1.243 +} 1.244 + 1.245 +TEST_F(MinidumpTest, LargerDump) { 1.246 + ASSERT_TRUE(WriteDump(kLargerDumpType)); 1.247 + DumpAnalysis mini(dump_file_); 1.248 + 1.249 + // The dump should have all of these streams. 1.250 + EXPECT_TRUE(mini.HasStream(ThreadListStream)); 1.251 + EXPECT_TRUE(mini.HasStream(ModuleListStream)); 1.252 + EXPECT_TRUE(mini.HasStream(MemoryListStream)); 1.253 + EXPECT_TRUE(mini.HasStream(ExceptionStream)); 1.254 + EXPECT_TRUE(mini.HasStream(SystemInfoStream)); 1.255 + EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream)); 1.256 + EXPECT_TRUE(mini.HasStream(MiscInfoStream)); 1.257 + 1.258 + // We expect memory referenced by stack in this dump. 1.259 + EXPECT_TRUE(mini.HasMemory(this)); 1.260 + 1.261 + // We expect PEB and TEBs in this dump. 1.262 + EXPECT_TRUE(mini.HasTebs()); 1.263 + EXPECT_TRUE(mini.HasPeb()); 1.264 + 1.265 + EXPECT_FALSE(mini.HasStream(ThreadExListStream)); 1.266 + EXPECT_FALSE(mini.HasStream(Memory64ListStream)); 1.267 + EXPECT_FALSE(mini.HasStream(CommentStreamA)); 1.268 + EXPECT_FALSE(mini.HasStream(CommentStreamW)); 1.269 + EXPECT_FALSE(mini.HasStream(HandleDataStream)); 1.270 + EXPECT_FALSE(mini.HasStream(FunctionTableStream)); 1.271 + EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); 1.272 + EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); 1.273 + EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); 1.274 + EXPECT_FALSE(mini.HasStream(TokenStream)); 1.275 +} 1.276 + 1.277 +TEST_F(MinidumpTest, FullDump) { 1.278 + ASSERT_TRUE(WriteDump(kFullDumpType)); 1.279 + ASSERT_TRUE(dump_file_ != L""); 1.280 + ASSERT_TRUE(full_dump_file_ != L""); 1.281 + DumpAnalysis mini(dump_file_); 1.282 + DumpAnalysis full(full_dump_file_); 1.283 + 1.284 + // Either dumps can contain part of the information. 1.285 + 1.286 + // The dump should have all of these streams. 1.287 + EXPECT_TRUE(mini.HasStream(ThreadListStream)); 1.288 + EXPECT_TRUE(full.HasStream(ThreadListStream)); 1.289 + EXPECT_TRUE(mini.HasStream(ModuleListStream)); 1.290 + EXPECT_TRUE(full.HasStream(ModuleListStream)); 1.291 + EXPECT_TRUE(mini.HasStream(ExceptionStream)); 1.292 + EXPECT_TRUE(full.HasStream(ExceptionStream)); 1.293 + EXPECT_TRUE(mini.HasStream(SystemInfoStream)); 1.294 + EXPECT_TRUE(full.HasStream(SystemInfoStream)); 1.295 + EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream)); 1.296 + EXPECT_TRUE(full.HasStream(UnloadedModuleListStream)); 1.297 + EXPECT_TRUE(mini.HasStream(MiscInfoStream)); 1.298 + EXPECT_TRUE(full.HasStream(MiscInfoStream)); 1.299 + EXPECT_TRUE(mini.HasStream(HandleDataStream)); 1.300 + EXPECT_TRUE(full.HasStream(HandleDataStream)); 1.301 + 1.302 + // We expect memory referenced by stack in this dump. 1.303 + EXPECT_FALSE(mini.HasMemory(this)); 1.304 + EXPECT_TRUE(full.HasMemory(this)); 1.305 + 1.306 + // We expect PEB and TEBs in this dump. 1.307 + EXPECT_TRUE(mini.HasTebs() || full.HasTebs()); 1.308 + EXPECT_TRUE(mini.HasPeb() || full.HasPeb()); 1.309 + 1.310 + EXPECT_TRUE(mini.HasStream(MemoryListStream)); 1.311 + EXPECT_TRUE(full.HasStream(Memory64ListStream)); 1.312 + EXPECT_FALSE(mini.HasStream(Memory64ListStream)); 1.313 + EXPECT_FALSE(full.HasStream(MemoryListStream)); 1.314 + 1.315 + // This is the only place we don't use OR because we want both not 1.316 + // to have the streams. 1.317 + EXPECT_FALSE(mini.HasStream(ThreadExListStream)); 1.318 + EXPECT_FALSE(full.HasStream(ThreadExListStream)); 1.319 + EXPECT_FALSE(mini.HasStream(CommentStreamA)); 1.320 + EXPECT_FALSE(full.HasStream(CommentStreamA)); 1.321 + EXPECT_FALSE(mini.HasStream(CommentStreamW)); 1.322 + EXPECT_FALSE(full.HasStream(CommentStreamW)); 1.323 + EXPECT_FALSE(mini.HasStream(FunctionTableStream)); 1.324 + EXPECT_FALSE(full.HasStream(FunctionTableStream)); 1.325 + EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); 1.326 + EXPECT_FALSE(full.HasStream(MemoryInfoListStream)); 1.327 + EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); 1.328 + EXPECT_FALSE(full.HasStream(ThreadInfoListStream)); 1.329 + EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); 1.330 + EXPECT_FALSE(full.HasStream(HandleOperationListStream)); 1.331 + EXPECT_FALSE(mini.HasStream(TokenStream)); 1.332 + EXPECT_FALSE(full.HasStream(TokenStream)); 1.333 +} 1.334 + 1.335 +} // namespace