Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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.
30 #include <windows.h>
31 #include <objbase.h>
32 #include <dbghelp.h>
34 #include "client/windows/crash_generation/minidump_generator.h"
35 #include "client/windows/unittests/dump_analysis.h" // NOLINT
37 #include "gtest/gtest.h"
39 namespace {
41 // Minidump with stacks, PEB, TEB, and unloaded module list.
42 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
43 MiniDumpWithProcessThreadData | // Get PEB and TEB.
44 MiniDumpWithUnloadedModules); // Get unloaded modules when available.
46 // Minidump with all of the above, plus memory referenced from stack.
47 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
48 MiniDumpWithProcessThreadData | // Get PEB and TEB.
49 MiniDumpWithUnloadedModules | // Get unloaded modules when available.
50 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack.
52 // Large dump with all process memory.
53 const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
54 MiniDumpWithFullMemory | // Full memory from process.
55 MiniDumpWithProcessThreadData | // Get PEB and TEB.
56 MiniDumpWithHandleData | // Get all handle information.
57 MiniDumpWithUnloadedModules); // Get unloaded modules when available.
59 class MinidumpTest: public testing::Test {
60 public:
61 MinidumpTest() {
62 wchar_t temp_dir_path[ MAX_PATH ] = {0};
63 ::GetTempPath(MAX_PATH, temp_dir_path);
64 dump_path_ = temp_dir_path;
65 }
67 virtual void SetUp() {
68 // Make sure URLMon isn't loaded into our process.
69 ASSERT_EQ(NULL, ::GetModuleHandle(L"urlmon.dll"));
71 // Then load and unload it to ensure we have something to
72 // stock the unloaded module list with.
73 HMODULE urlmon = ::LoadLibrary(L"urlmon.dll");
74 ASSERT_TRUE(urlmon != NULL);
75 ASSERT_TRUE(::FreeLibrary(urlmon));
76 }
78 virtual void TearDown() {
79 if (!dump_file_.empty()) {
80 ::DeleteFile(dump_file_.c_str());
81 dump_file_ = L"";
82 }
83 if (!full_dump_file_.empty()) {
84 ::DeleteFile(full_dump_file_.c_str());
85 full_dump_file_ = L"";
86 }
87 }
89 bool WriteDump(ULONG flags) {
90 using google_breakpad::MinidumpGenerator;
92 // Fake exception is access violation on write to this.
93 EXCEPTION_RECORD ex_record = {
94 STATUS_ACCESS_VIOLATION, // ExceptionCode
95 0, // ExceptionFlags
96 NULL, // ExceptionRecord;
97 reinterpret_cast<void*>(0xCAFEBABE), // ExceptionAddress;
98 2, // NumberParameters;
99 { EXCEPTION_WRITE_FAULT, reinterpret_cast<ULONG_PTR>(this) }
100 };
101 CONTEXT ctx_record = {};
102 EXCEPTION_POINTERS ex_ptrs = {
103 &ex_record,
104 &ctx_record,
105 };
107 MinidumpGenerator generator(dump_path_);
109 // And write a dump
110 bool result = generator.WriteMinidump(::GetCurrentProcess(),
111 ::GetCurrentProcessId(),
112 ::GetCurrentThreadId(),
113 ::GetCurrentThreadId(),
114 &ex_ptrs,
115 NULL,
116 static_cast<MINIDUMP_TYPE>(flags),
117 TRUE,
118 &dump_file_,
119 &full_dump_file_);
120 return result == TRUE;
121 }
123 protected:
124 std::wstring dump_file_;
125 std::wstring full_dump_file_;
127 std::wstring dump_path_;
128 };
130 // We need to be able to get file information from Windows
131 bool HasFileInfo(const std::wstring& file_path) {
132 DWORD dummy;
133 const wchar_t* path = file_path.c_str();
134 DWORD length = ::GetFileVersionInfoSize(path, &dummy);
135 if (length == 0)
136 return NULL;
138 void* data = calloc(length, 1);
139 if (!data)
140 return false;
142 if (!::GetFileVersionInfo(path, dummy, length, data)) {
143 free(data);
144 return false;
145 }
147 void* translate = NULL;
148 UINT page_count;
149 BOOL query_result = VerQueryValue(
150 data,
151 L"\\VarFileInfo\\Translation",
152 static_cast<void**>(&translate),
153 &page_count);
155 free(data);
156 if (query_result && translate) {
157 return true;
158 } else {
159 return false;
160 }
161 }
163 TEST_F(MinidumpTest, Version) {
164 API_VERSION* version = ::ImagehlpApiVersion();
166 HMODULE dbg_help = ::GetModuleHandle(L"dbghelp.dll");
167 ASSERT_TRUE(dbg_help != NULL);
169 wchar_t dbg_help_file[1024] = {};
170 ASSERT_TRUE(::GetModuleFileName(dbg_help,
171 dbg_help_file,
172 sizeof(dbg_help_file) /
173 sizeof(*dbg_help_file)));
174 ASSERT_TRUE(HasFileInfo(std::wstring(dbg_help_file)) != NULL);
176 // LOG(INFO) << "DbgHelp.dll version: " << file_info->file_version();
177 }
179 TEST_F(MinidumpTest, Normal) {
180 EXPECT_TRUE(WriteDump(MiniDumpNormal));
181 DumpAnalysis mini(dump_file_);
183 // We expect threads, modules and some memory.
184 EXPECT_TRUE(mini.HasStream(ThreadListStream));
185 EXPECT_TRUE(mini.HasStream(ModuleListStream));
186 EXPECT_TRUE(mini.HasStream(MemoryListStream));
187 EXPECT_TRUE(mini.HasStream(ExceptionStream));
188 EXPECT_TRUE(mini.HasStream(SystemInfoStream));
189 EXPECT_TRUE(mini.HasStream(MiscInfoStream));
191 EXPECT_FALSE(mini.HasStream(ThreadExListStream));
192 EXPECT_FALSE(mini.HasStream(Memory64ListStream));
193 EXPECT_FALSE(mini.HasStream(CommentStreamA));
194 EXPECT_FALSE(mini.HasStream(CommentStreamW));
195 EXPECT_FALSE(mini.HasStream(HandleDataStream));
196 EXPECT_FALSE(mini.HasStream(FunctionTableStream));
197 EXPECT_FALSE(mini.HasStream(UnloadedModuleListStream));
198 EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
199 EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
200 EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
201 EXPECT_FALSE(mini.HasStream(TokenStream));
203 // We expect no PEB nor TEBs in this dump.
204 EXPECT_FALSE(mini.HasTebs());
205 EXPECT_FALSE(mini.HasPeb());
207 // We expect no off-stack memory in this dump.
208 EXPECT_FALSE(mini.HasMemory(this));
209 }
211 TEST_F(MinidumpTest, SmallDump) {
212 ASSERT_TRUE(WriteDump(kSmallDumpType));
213 DumpAnalysis mini(dump_file_);
215 EXPECT_TRUE(mini.HasStream(ThreadListStream));
216 EXPECT_TRUE(mini.HasStream(ModuleListStream));
217 EXPECT_TRUE(mini.HasStream(MemoryListStream));
218 EXPECT_TRUE(mini.HasStream(ExceptionStream));
219 EXPECT_TRUE(mini.HasStream(SystemInfoStream));
220 EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
221 EXPECT_TRUE(mini.HasStream(MiscInfoStream));
223 // We expect PEB and TEBs in this dump.
224 EXPECT_TRUE(mini.HasTebs());
225 EXPECT_TRUE(mini.HasPeb());
227 EXPECT_FALSE(mini.HasStream(ThreadExListStream));
228 EXPECT_FALSE(mini.HasStream(Memory64ListStream));
229 EXPECT_FALSE(mini.HasStream(CommentStreamA));
230 EXPECT_FALSE(mini.HasStream(CommentStreamW));
231 EXPECT_FALSE(mini.HasStream(HandleDataStream));
232 EXPECT_FALSE(mini.HasStream(FunctionTableStream));
233 EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
234 EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
235 EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
236 EXPECT_FALSE(mini.HasStream(TokenStream));
238 // We expect no off-stack memory in this dump.
239 EXPECT_FALSE(mini.HasMemory(this));
240 }
242 TEST_F(MinidumpTest, LargerDump) {
243 ASSERT_TRUE(WriteDump(kLargerDumpType));
244 DumpAnalysis mini(dump_file_);
246 // The dump should have all of these streams.
247 EXPECT_TRUE(mini.HasStream(ThreadListStream));
248 EXPECT_TRUE(mini.HasStream(ModuleListStream));
249 EXPECT_TRUE(mini.HasStream(MemoryListStream));
250 EXPECT_TRUE(mini.HasStream(ExceptionStream));
251 EXPECT_TRUE(mini.HasStream(SystemInfoStream));
252 EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
253 EXPECT_TRUE(mini.HasStream(MiscInfoStream));
255 // We expect memory referenced by stack in this dump.
256 EXPECT_TRUE(mini.HasMemory(this));
258 // We expect PEB and TEBs in this dump.
259 EXPECT_TRUE(mini.HasTebs());
260 EXPECT_TRUE(mini.HasPeb());
262 EXPECT_FALSE(mini.HasStream(ThreadExListStream));
263 EXPECT_FALSE(mini.HasStream(Memory64ListStream));
264 EXPECT_FALSE(mini.HasStream(CommentStreamA));
265 EXPECT_FALSE(mini.HasStream(CommentStreamW));
266 EXPECT_FALSE(mini.HasStream(HandleDataStream));
267 EXPECT_FALSE(mini.HasStream(FunctionTableStream));
268 EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
269 EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
270 EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
271 EXPECT_FALSE(mini.HasStream(TokenStream));
272 }
274 TEST_F(MinidumpTest, FullDump) {
275 ASSERT_TRUE(WriteDump(kFullDumpType));
276 ASSERT_TRUE(dump_file_ != L"");
277 ASSERT_TRUE(full_dump_file_ != L"");
278 DumpAnalysis mini(dump_file_);
279 DumpAnalysis full(full_dump_file_);
281 // Either dumps can contain part of the information.
283 // The dump should have all of these streams.
284 EXPECT_TRUE(mini.HasStream(ThreadListStream));
285 EXPECT_TRUE(full.HasStream(ThreadListStream));
286 EXPECT_TRUE(mini.HasStream(ModuleListStream));
287 EXPECT_TRUE(full.HasStream(ModuleListStream));
288 EXPECT_TRUE(mini.HasStream(ExceptionStream));
289 EXPECT_TRUE(full.HasStream(ExceptionStream));
290 EXPECT_TRUE(mini.HasStream(SystemInfoStream));
291 EXPECT_TRUE(full.HasStream(SystemInfoStream));
292 EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
293 EXPECT_TRUE(full.HasStream(UnloadedModuleListStream));
294 EXPECT_TRUE(mini.HasStream(MiscInfoStream));
295 EXPECT_TRUE(full.HasStream(MiscInfoStream));
296 EXPECT_TRUE(mini.HasStream(HandleDataStream));
297 EXPECT_TRUE(full.HasStream(HandleDataStream));
299 // We expect memory referenced by stack in this dump.
300 EXPECT_FALSE(mini.HasMemory(this));
301 EXPECT_TRUE(full.HasMemory(this));
303 // We expect PEB and TEBs in this dump.
304 EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
305 EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
307 EXPECT_TRUE(mini.HasStream(MemoryListStream));
308 EXPECT_TRUE(full.HasStream(Memory64ListStream));
309 EXPECT_FALSE(mini.HasStream(Memory64ListStream));
310 EXPECT_FALSE(full.HasStream(MemoryListStream));
312 // This is the only place we don't use OR because we want both not
313 // to have the streams.
314 EXPECT_FALSE(mini.HasStream(ThreadExListStream));
315 EXPECT_FALSE(full.HasStream(ThreadExListStream));
316 EXPECT_FALSE(mini.HasStream(CommentStreamA));
317 EXPECT_FALSE(full.HasStream(CommentStreamA));
318 EXPECT_FALSE(mini.HasStream(CommentStreamW));
319 EXPECT_FALSE(full.HasStream(CommentStreamW));
320 EXPECT_FALSE(mini.HasStream(FunctionTableStream));
321 EXPECT_FALSE(full.HasStream(FunctionTableStream));
322 EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
323 EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
324 EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
325 EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
326 EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
327 EXPECT_FALSE(full.HasStream(HandleOperationListStream));
328 EXPECT_FALSE(mini.HasStream(TokenStream));
329 EXPECT_FALSE(full.HasStream(TokenStream));
330 }
332 } // namespace