toolkit/crashreporter/google-breakpad/src/client/windows/unittests/minidump_test.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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

mercurial