| OLD | NEW | 
|---|
| 1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 
| 2 // | 2 // | 
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. | 
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at | 
| 6 // | 6 // | 
| 7 //     http://www.apache.org/licenses/LICENSE-2.0 | 7 //     http://www.apache.org/licenses/LICENSE-2.0 | 
| 8 // | 8 // | 
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software | 
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, | 
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and | 
| 13 // limitations under the License. | 13 // limitations under the License. | 
| 14 | 14 | 
| 15 #include "util/win/process_info.h" | 15 #include "util/win/process_info.h" | 
| 16 | 16 | 
| 17 #include <imagehlp.h> | 17 #include <imagehlp.h> | 
|  | 18 #include <intrin.h> | 
| 18 #include <wchar.h> | 19 #include <wchar.h> | 
| 19 | 20 | 
| 20 #include "base/files/file_path.h" | 21 #include "base/files/file_path.h" | 
| 21 #include "build/build_config.h" | 22 #include "build/build_config.h" | 
| 22 #include "gtest/gtest.h" | 23 #include "gtest/gtest.h" | 
| 23 #include "test/paths.h" | 24 #include "test/paths.h" | 
| 24 #include "test/win/child_launcher.h" | 25 #include "test/win/child_launcher.h" | 
| 25 #include "util/file/file_io.h" | 26 #include "util/file/file_io.h" | 
| 26 #include "util/misc/uuid.h" | 27 #include "util/misc/uuid.h" | 
| 27 #include "util/win/scoped_handle.h" | 28 #include "util/win/scoped_handle.h" | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 48   if (!is_wow64_process) | 49   if (!is_wow64_process) | 
| 49     return false; | 50     return false; | 
| 50   BOOL is_wow64; | 51   BOOL is_wow64; | 
| 51   if (!is_wow64_process(process_handle, &is_wow64)) { | 52   if (!is_wow64_process(process_handle, &is_wow64)) { | 
| 52     PLOG(ERROR) << "IsWow64Process"; | 53     PLOG(ERROR) << "IsWow64Process"; | 
| 53     return false; | 54     return false; | 
| 54   } | 55   } | 
| 55   return is_wow64; | 56   return is_wow64; | 
| 56 } | 57 } | 
| 57 | 58 | 
|  | 59 void VerifyAddressInInCodePage(const ProcessInfo& process_info, | 
|  | 60                                WinVMAddress code_address) { | 
|  | 61   // Make sure the child code address is an code page address with the right | 
|  | 62   // information. | 
|  | 63   const std::vector<ProcessInfo::MemoryInfo>& memory_info = | 
|  | 64       process_info.MemoryInformation(); | 
|  | 65   bool found_region = false; | 
|  | 66   for (const auto& mi : memory_info) { | 
|  | 67     if (mi.base_address <= code_address && | 
|  | 68         mi.base_address + mi.region_size > code_address) { | 
|  | 69       EXPECT_EQ(MEM_COMMIT, mi.state); | 
|  | 70       EXPECT_EQ(PAGE_EXECUTE_READ, mi.protect); | 
|  | 71       EXPECT_EQ(MEM_IMAGE, mi.type); | 
|  | 72       EXPECT_FALSE(found_region); | 
|  | 73       found_region = true; | 
|  | 74     } | 
|  | 75   } | 
|  | 76   EXPECT_TRUE(found_region); | 
|  | 77 } | 
|  | 78 | 
| 58 TEST(ProcessInfo, Self) { | 79 TEST(ProcessInfo, Self) { | 
| 59   ProcessInfo process_info; | 80   ProcessInfo process_info; | 
| 60   ASSERT_TRUE(process_info.Initialize(GetCurrentProcess())); | 81   ASSERT_TRUE(process_info.Initialize(GetCurrentProcess())); | 
| 61   EXPECT_EQ(GetCurrentProcessId(), process_info.ProcessID()); | 82   EXPECT_EQ(GetCurrentProcessId(), process_info.ProcessID()); | 
| 62   EXPECT_GT(process_info.ParentProcessID(), 0u); | 83   EXPECT_GT(process_info.ParentProcessID(), 0u); | 
| 63 | 84 | 
| 64 #if defined(ARCH_CPU_64_BITS) | 85 #if defined(ARCH_CPU_64_BITS) | 
| 65   EXPECT_TRUE(process_info.Is64Bit()); | 86   EXPECT_TRUE(process_info.Is64Bit()); | 
| 66   EXPECT_FALSE(process_info.IsWow64()); | 87   EXPECT_FALSE(process_info.IsWow64()); | 
| 67 #else | 88 #else | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 94             reinterpret_cast<uintptr_t>(GetModuleHandle(L"ntdll.dll"))); | 115             reinterpret_cast<uintptr_t>(GetModuleHandle(L"ntdll.dll"))); | 
| 95 | 116 | 
| 96   EXPECT_GT(modules[0].size, 0); | 117   EXPECT_GT(modules[0].size, 0); | 
| 97   EXPECT_GT(modules[1].size, 0); | 118   EXPECT_GT(modules[1].size, 0); | 
| 98 | 119 | 
| 99   EXPECT_EQ(modules[0].timestamp, | 120   EXPECT_EQ(modules[0].timestamp, | 
| 100             GetTimestampForModule(GetModuleHandle(nullptr))); | 121             GetTimestampForModule(GetModuleHandle(nullptr))); | 
| 101   // System modules are forced to particular stamps and the file header values | 122   // System modules are forced to particular stamps and the file header values | 
| 102   // don't match the on-disk times. Just make sure we got some data here. | 123   // don't match the on-disk times. Just make sure we got some data here. | 
| 103   EXPECT_GT(modules[1].timestamp, 0); | 124   EXPECT_GT(modules[1].timestamp, 0); | 
|  | 125 | 
|  | 126   // Find something we know is a code address and confirm expected memory | 
|  | 127   // information settings. | 
|  | 128   VerifyAddressInInCodePage(process_info, | 
|  | 129                             reinterpret_cast<WinVMAddress>(_ReturnAddress())); | 
| 104 } | 130 } | 
| 105 | 131 | 
| 106 void TestOtherProcess(const base::string16& directory_modification) { | 132 void TestOtherProcess(const base::string16& directory_modification) { | 
| 107   ProcessInfo process_info; | 133   ProcessInfo process_info; | 
| 108 | 134 | 
| 109   UUID started_uuid(UUID::InitializeWithNewTag{}); |  | 
| 110   UUID done_uuid(UUID::InitializeWithNewTag{}); | 135   UUID done_uuid(UUID::InitializeWithNewTag{}); | 
| 111 | 136 | 
| 112   ScopedKernelHANDLE started( |  | 
| 113       CreateEvent(nullptr, true, false, started_uuid.ToString16().c_str())); |  | 
| 114   ASSERT_TRUE(started.get()); |  | 
| 115   ScopedKernelHANDLE done( | 137   ScopedKernelHANDLE done( | 
| 116       CreateEvent(nullptr, true, false, done_uuid.ToString16().c_str())); | 138       CreateEvent(nullptr, true, false, done_uuid.ToString16().c_str())); | 
| 117   ASSERT_TRUE(done.get()); | 139   ASSERT_TRUE(done.get()); | 
| 118 | 140 | 
| 119   base::FilePath test_executable = Paths::Executable(); | 141   base::FilePath test_executable = Paths::Executable(); | 
| 120 | 142 | 
| 121   std::wstring child_test_executable = | 143   std::wstring child_test_executable = | 
| 122       test_executable.DirName() | 144       test_executable.DirName() | 
| 123           .Append(directory_modification) | 145           .Append(directory_modification) | 
| 124           .Append(test_executable.BaseName().RemoveFinalExtension().value() + | 146           .Append(test_executable.BaseName().RemoveFinalExtension().value() + | 
| 125                   L"_process_info_test_child.exe") | 147                   L"_process_info_test_child.exe") | 
| 126           .value(); | 148           .value(); | 
| 127 | 149 | 
| 128   std::wstring args; | 150   std::wstring args; | 
| 129   AppendCommandLineArgument(started_uuid.ToString16(), &args); |  | 
| 130   args += L" "; |  | 
| 131   AppendCommandLineArgument(done_uuid.ToString16(), &args); | 151   AppendCommandLineArgument(done_uuid.ToString16(), &args); | 
| 132 | 152 | 
| 133   ChildLauncher child(child_test_executable, args); | 153   ChildLauncher child(child_test_executable, args); | 
| 134   child.Start(); | 154   child.Start(); | 
| 135 | 155 | 
| 136   // Wait until the test has completed initialization. | 156   // The child sends us a code address we can look up in the memory map. | 
| 137   ASSERT_EQ(WaitForSingleObject(started.get(), INFINITE), WAIT_OBJECT_0); | 157   WinVMAddress code_address; | 
|  | 158   CheckedReadFile( | 
|  | 159       child.stdout_read_handle(), &code_address, sizeof(code_address)); | 
| 138 | 160 | 
| 139   ASSERT_TRUE(process_info.Initialize(child.process_handle())); | 161   ASSERT_TRUE(process_info.Initialize(child.process_handle())); | 
| 140 | 162 | 
| 141   // Tell the test it's OK to shut down now that we've read our data. | 163   // Tell the test it's OK to shut down now that we've read our data. | 
| 142   SetEvent(done.get()); | 164   EXPECT_TRUE(SetEvent(done.get())); | 
| 143 | 165 | 
| 144   std::vector<ProcessInfo::Module> modules; | 166   std::vector<ProcessInfo::Module> modules; | 
| 145   EXPECT_TRUE(process_info.Modules(&modules)); | 167   EXPECT_TRUE(process_info.Modules(&modules)); | 
| 146   ASSERT_GE(modules.size(), 3u); | 168   ASSERT_GE(modules.size(), 3u); | 
| 147   std::wstring child_name = L"\\crashpad_util_test_process_info_test_child.exe"; | 169   std::wstring child_name = L"\\crashpad_util_test_process_info_test_child.exe"; | 
| 148   ASSERT_GE(modules[0].name.size(), child_name.size()); | 170   ASSERT_GE(modules[0].name.size(), child_name.size()); | 
| 149   EXPECT_EQ(child_name, | 171   EXPECT_EQ(child_name, | 
| 150             modules[0].name.substr(modules[0].name.size() - child_name.size())); | 172             modules[0].name.substr(modules[0].name.size() - child_name.size())); | 
| 151   ASSERT_GE(modules[1].name.size(), wcslen(kNtdllName)); | 173   ASSERT_GE(modules[1].name.size(), wcslen(kNtdllName)); | 
| 152   EXPECT_EQ( | 174   EXPECT_EQ( | 
| 153       kNtdllName, | 175       kNtdllName, | 
| 154       modules[1].name.substr(modules[1].name.size() - wcslen(kNtdllName))); | 176       modules[1].name.substr(modules[1].name.size() - wcslen(kNtdllName))); | 
| 155   // lz32.dll is an uncommonly-used-but-always-available module that the test | 177   // lz32.dll is an uncommonly-used-but-always-available module that the test | 
| 156   // binary manually loads. | 178   // binary manually loads. | 
| 157   const wchar_t kLz32dllName[] = L"\\lz32.dll"; | 179   const wchar_t kLz32dllName[] = L"\\lz32.dll"; | 
| 158   ASSERT_GE(modules.back().name.size(), wcslen(kLz32dllName)); | 180   ASSERT_GE(modules.back().name.size(), wcslen(kLz32dllName)); | 
| 159   EXPECT_EQ(kLz32dllName, | 181   EXPECT_EQ(kLz32dllName, | 
| 160             modules.back().name.substr(modules.back().name.size() - | 182             modules.back().name.substr(modules.back().name.size() - | 
| 161                                        wcslen(kLz32dllName))); | 183                                        wcslen(kLz32dllName))); | 
|  | 184 | 
|  | 185   VerifyAddressInInCodePage(process_info, code_address); | 
| 162 } | 186 } | 
| 163 | 187 | 
| 164 TEST(ProcessInfo, OtherProcess) { | 188 TEST(ProcessInfo, OtherProcess) { | 
| 165   TestOtherProcess(FILE_PATH_LITERAL(".")); | 189   TestOtherProcess(FILE_PATH_LITERAL(".")); | 
| 166 } | 190 } | 
| 167 | 191 | 
| 168 #if defined(ARCH_CPU_64_BITS) | 192 #if defined(ARCH_CPU_64_BITS) | 
| 169 TEST(ProcessInfo, OtherProcessWOW64) { | 193 TEST(ProcessInfo, OtherProcessWOW64) { | 
| 170 #ifndef NDEBUG | 194 #ifndef NDEBUG | 
| 171   TestOtherProcess(FILE_PATH_LITERAL("..\\..\\out\\Debug")); | 195   TestOtherProcess(FILE_PATH_LITERAL("..\\..\\out\\Debug")); | 
| 172 #else | 196 #else | 
| 173   TestOtherProcess(FILE_PATH_LITERAL("..\\..\\out\\Release")); | 197   TestOtherProcess(FILE_PATH_LITERAL("..\\..\\out\\Release")); | 
| 174 #endif | 198 #endif | 
| 175 } | 199 } | 
| 176 #endif  // ARCH_CPU_64_BITS | 200 #endif  // ARCH_CPU_64_BITS | 
| 177 | 201 | 
| 178 }  // namespace | 202 }  // namespace | 
| 179 }  // namespace test | 203 }  // namespace test | 
| 180 }  // namespace crashpad | 204 }  // namespace crashpad | 
| OLD | NEW | 
|---|