Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 #include "chrome_frame/crash_reporting/nt_loader.h" | 4 #include "chrome_frame/crash_reporting/nt_loader.h" |
| 5 | 5 |
| 6 #include <tlhelp32.h> | 6 #include <tlhelp32.h> |
| 7 #include <winnt.h> | 7 #include <winnt.h> |
| 8 #include <base/at_exit.h> | 8 #include <base/at_exit.h> |
| 9 #include <base/scoped_handle.h> | 9 #include <base/scoped_handle.h> |
| 10 #include <base/string_util.h> | |
| 10 #include <base/sys_info.h> | 11 #include <base/sys_info.h> |
| 11 #include <base/thread.h> | 12 #include <base/thread.h> |
| 12 #include "chrome_frame/crash_reporting/crash_dll.h" | 13 #include "chrome_frame/crash_reporting/crash_dll.h" |
| 13 #include "gtest/gtest.h" | 14 #include "gtest/gtest.h" |
| 14 | 15 |
| 15 namespace { | 16 namespace { |
| 16 void AssertIsCriticalSection(CRITICAL_SECTION* critsec) { | 17 void AssertIsCriticalSection(CRITICAL_SECTION* critsec) { |
| 17 // Assert on some of the internals of the debug info if it has one. | 18 // Assert on some of the internals of the debug info if it has one. |
| 18 RTL_CRITICAL_SECTION_DEBUG* debug = critsec->DebugInfo; | 19 RTL_CRITICAL_SECTION_DEBUG* debug = critsec->DebugInfo; |
| 19 if (debug) { | 20 if (debug) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 CRITICAL_SECTION* loader_lock = GetLoaderLock(); | 110 CRITICAL_SECTION* loader_lock = GetLoaderLock(); |
| 110 | 111 |
| 111 EXPECT_FALSE(OwnsLoaderLock()); | 112 EXPECT_FALSE(OwnsLoaderLock()); |
| 112 EnterCriticalSection(loader_lock); | 113 EnterCriticalSection(loader_lock); |
| 113 EXPECT_TRUE(OwnsLoaderLock()); | 114 EXPECT_TRUE(OwnsLoaderLock()); |
| 114 LeaveCriticalSection(loader_lock); | 115 LeaveCriticalSection(loader_lock); |
| 115 EXPECT_FALSE(OwnsLoaderLock()); | 116 EXPECT_FALSE(OwnsLoaderLock()); |
| 116 } | 117 } |
| 117 | 118 |
| 118 TEST(NtLoader, GetLoaderEntry) { | 119 TEST(NtLoader, GetLoaderEntry) { |
| 119 ScopedEnterCriticalSection lock(GetLoaderLock()); | |
| 120 | |
| 121 // Get all modules in the current process. | 120 // Get all modules in the current process. |
| 122 ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, | 121 ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, |
| 123 ::GetCurrentProcessId())); | 122 ::GetCurrentProcessId())); |
| 124 EXPECT_TRUE(snap.Get() != NULL); | 123 EXPECT_TRUE(snap.Get() != NULL); |
| 125 | 124 |
| 126 // Walk them, while checking we get an entry for each, and that it | 125 // Walk them, while checking we get an entry for each, and that it |
| 127 // contains sane information. | 126 // contains sane information. |
| 128 MODULEENTRY32 module = { sizeof(module) }; | 127 MODULEENTRY32 module = { sizeof(module) }; |
| 129 ASSERT_TRUE(::Module32First(snap.Get(), &module)); | 128 ASSERT_TRUE(::Module32First(snap.Get(), &module)); |
| 130 do { | 129 do { |
| 130 ScopedEnterCriticalSection lock(GetLoaderLock()); | |
| 131 | |
| 131 nt_loader::LDR_DATA_TABLE_ENTRY* entry = | 132 nt_loader::LDR_DATA_TABLE_ENTRY* entry = |
| 132 nt_loader::GetLoaderEntry(module.hModule); | 133 nt_loader::GetLoaderEntry(module.hModule); |
| 133 ASSERT_TRUE(entry != NULL); | 134 ASSERT_TRUE(entry != NULL); |
| 134 ASSERT_EQ(module.hModule, reinterpret_cast<HMODULE>(entry->DllBase)); | 135 EXPECT_EQ(module.hModule, reinterpret_cast<HMODULE>(entry->DllBase)); |
| 135 ASSERT_STREQ(module.szModule, | 136 EXPECT_STREQ(module.szModule, |
| 136 FromUnicodeString(entry->BaseDllName).c_str()); | 137 FromUnicodeString(entry->BaseDllName).c_str()); |
| 137 ASSERT_STREQ(module.szExePath, | 138 EXPECT_STREQ(module.szExePath, |
| 138 FromUnicodeString(entry->FullDllName).c_str()); | 139 FromUnicodeString(entry->FullDllName).c_str()); |
| 140 | |
| 141 ULONG flags = entry->Flags; | |
| 142 | |
| 143 // All entries should have this flag set. | |
| 144 ASSERT_TRUE(flags & LDRP_ENTRY_PROCESSED); | |
| 145 | |
| 146 if (0 == (flags & LDRP_IMAGE_DLL)) { | |
|
robertshield
2010/03/11 22:10:56
nit: if you feel like it, and are bored, and are v
Sigurður Ásgeirsson
2010/03/11 22:13:52
Adding a TODO.
| |
| 147 // Dlls have the LDRP_IMAGE_DLL flag set, any module that doesn't | |
| 148 // have that flag has to be the main executable. | |
| 149 EXPECT_TRUE(module.hModule == ::GetModuleHandle(NULL)); | |
| 150 } else { | |
| 151 // Since we're not currently loading any modules, all loaded | |
| 152 // modules should either have the LDRP_PROCESS_ATTACH_CALLED, | |
| 153 // or a NULL entrypoint. | |
| 154 if (entry->EntryPoint == NULL) { | |
| 155 EXPECT_FALSE(flags & LDRP_PROCESS_ATTACH_CALLED); | |
| 156 } else { | |
| 157 // Shimeng.dll is an exception to the above, it's loaded | |
| 158 // in a special way, see e.g. http://www.alex-ionescu.com/?p=41 | |
| 159 // for details. | |
| 160 bool is_shimeng = LowerCaseEqualsASCII( | |
| 161 FromUnicodeString(entry->BaseDllName), "shimeng.dll"); | |
| 162 | |
| 163 EXPECT_TRUE(is_shimeng || (flags & LDRP_PROCESS_ATTACH_CALLED)); | |
| 164 } | |
| 165 } | |
| 166 | |
| 139 } while(::Module32Next(snap.Get(), &module)); | 167 } while(::Module32Next(snap.Get(), &module)); |
| 140 } | 168 } |
| 141 | 169 |
| 142 namespace { | 170 namespace { |
| 143 | 171 |
| 144 typedef void (*ExceptionFunction)(EXCEPTION_POINTERS* ex_ptrs); | 172 typedef void (*ExceptionFunction)(EXCEPTION_POINTERS* ex_ptrs); |
| 145 | 173 |
| 146 class NtLoaderTest: public testing::Test { | 174 class NtLoaderTest: public testing::Test { |
| 147 public: | 175 public: |
| 148 NtLoaderTest() : veh_id_(NULL), exception_function_(NULL) { | 176 NtLoaderTest() : veh_id_(NULL), exception_function_(NULL) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 void* veh_id_; | 220 void* veh_id_; |
| 193 ExceptionFunction exception_function_; | 221 ExceptionFunction exception_function_; |
| 194 | 222 |
| 195 static NtLoaderTest* current_; | 223 static NtLoaderTest* current_; |
| 196 static DWORD main_thread_; | 224 static DWORD main_thread_; |
| 197 }; | 225 }; |
| 198 | 226 |
| 199 NtLoaderTest* NtLoaderTest::current_ = NULL; | 227 NtLoaderTest* NtLoaderTest::current_ = NULL; |
| 200 DWORD NtLoaderTest::main_thread_ = ::GetCurrentThreadId(); | 228 DWORD NtLoaderTest::main_thread_ = ::GetCurrentThreadId(); |
| 201 | 229 |
| 202 const wchar_t kCrashDllName[] = L"crash_dll.dll"; | |
| 203 | |
| 204 } // namespace | 230 } // namespace |
| 205 | 231 |
| 206 static int exceptions_handled = 0; | 232 static int exceptions_handled = 0; |
| 207 static void OnCrashDuringLoadLibrary(EXCEPTION_POINTERS* ex_ptrs) { | 233 static void OnCrashDuringLoadLibrary(EXCEPTION_POINTERS* ex_ptrs) { |
| 208 ASSERT_EQ(STATUS_ACCESS_VIOLATION, ex_ptrs->ExceptionRecord->ExceptionCode); | 234 ASSERT_EQ(STATUS_ACCESS_VIOLATION, ex_ptrs->ExceptionRecord->ExceptionCode); |
| 209 ASSERT_EQ(2, ex_ptrs->ExceptionRecord->NumberParameters); | 235 ASSERT_EQ(2, ex_ptrs->ExceptionRecord->NumberParameters); |
| 210 ASSERT_EQ(EXCEPTION_WRITE_FAULT, | 236 ASSERT_EQ(EXCEPTION_WRITE_FAULT, |
| 211 ex_ptrs->ExceptionRecord->ExceptionInformation[0]); | 237 ex_ptrs->ExceptionRecord->ExceptionInformation[0]); |
| 212 ASSERT_EQ(kCrashAddress, | 238 ASSERT_EQ(kCrashAddress, |
| 213 ex_ptrs->ExceptionRecord->ExceptionInformation[1]); | 239 ex_ptrs->ExceptionRecord->ExceptionInformation[1]); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 | 299 |
| 274 exceptions_handled = 0; | 300 exceptions_handled = 0; |
| 275 set_exception_function(OnCrashDuringUnloadLibrary); | 301 set_exception_function(OnCrashDuringUnloadLibrary); |
| 276 | 302 |
| 277 // We should crash during unload. | 303 // We should crash during unload. |
| 278 if (module != NULL) | 304 if (module != NULL) |
| 279 ::FreeLibrary(module); | 305 ::FreeLibrary(module); |
| 280 | 306 |
| 281 EXPECT_EQ(1, exceptions_handled); | 307 EXPECT_EQ(1, exceptions_handled); |
| 282 } | 308 } |
| OLD | NEW |