Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Unified Diff: snapshot/win/exception_snapshot_win_test.cc

Issue 1349313003: win: support x64 reading x86 (wow64) (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: mac Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « snapshot/win/exception_snapshot_win.cc ('k') | snapshot/win/process_reader_win.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: snapshot/win/exception_snapshot_win_test.cc
diff --git a/snapshot/win/exception_snapshot_win_test.cc b/snapshot/win/exception_snapshot_win_test.cc
index db558cde3bb9b262dd1753fd2456b811da91ed13..7d7f18ebfda7b5123b5f429d3a8832c316d809fb 100644
--- a/snapshot/win/exception_snapshot_win_test.cc
+++ b/snapshot/win/exception_snapshot_win_test.cc
@@ -16,11 +16,14 @@
#include <string>
+#include "base/files/file_path.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "client/crashpad_client.h"
#include "gtest/gtest.h"
#include "snapshot/win/process_snapshot_win.h"
+#include "test/paths.h"
#include "test/win/win_child_process.h"
#include "util/thread/thread.h"
#include "util/win/exception_handler_server.h"
@@ -46,56 +49,49 @@ HANDLE DuplicateEvent(HANDLE process, HANDLE event) {
return nullptr;
}
-class ExceptionSnapshotWinTest : public testing::Test {
+class Delegate : public ExceptionHandlerServer::Delegate {
public:
- class Delegate : public ExceptionHandlerServer::Delegate {
- public:
- Delegate(HANDLE server_ready, HANDLE completed_test_event)
- : server_ready_(server_ready),
- completed_test_event_(completed_test_event),
- break_near_(nullptr) {}
- ~Delegate() override {}
-
- void set_break_near(void* break_near) { break_near_ = break_near; }
-
- void ExceptionHandlerServerStarted() override { SetEvent(server_ready_); }
-
- unsigned int ExceptionHandlerServerException(
- HANDLE process,
- WinVMAddress exception_information_address) override {
- ScopedProcessSuspend suspend(process);
- ProcessSnapshotWin snapshot;
- snapshot.Initialize(process, ProcessSuspensionState::kSuspended);
- snapshot.InitializeException(exception_information_address);
-
- // Confirm the exception record was read correctly.
- EXPECT_NE(snapshot.Exception()->ThreadID(), 0u);
- EXPECT_EQ(snapshot.Exception()->Exception(), EXCEPTION_BREAKPOINT);
-
- // Verify the exception happened at the expected location with a bit of
- // slop space to allow for reading the current PC before the exception
- // happens. See CrashingChildProcess::Run().
- const uint64_t kAllowedOffset = 64;
- EXPECT_GT(snapshot.Exception()->ExceptionAddress(),
- reinterpret_cast<uint64_t>(break_near_));
- EXPECT_LT(snapshot.Exception()->ExceptionAddress(),
- reinterpret_cast<uint64_t>(break_near_) + kAllowedOffset);
-
- SetEvent(completed_test_event_);
-
- return snapshot.Exception()->Exception();
- }
-
- private:
- HANDLE server_ready_; // weak
- HANDLE completed_test_event_; // weak
- void* break_near_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
- };
+ Delegate(HANDLE server_ready, HANDLE completed_test_event)
+ : server_ready_(server_ready),
+ completed_test_event_(completed_test_event),
+ break_near_(0) {}
+ ~Delegate() override {}
+
+ void set_break_near(WinVMAddress break_near) { break_near_ = break_near; }
+
+ void ExceptionHandlerServerStarted() override { SetEvent(server_ready_); }
+
+ unsigned int ExceptionHandlerServerException(
+ HANDLE process,
+ WinVMAddress exception_information_address) override {
+ ScopedProcessSuspend suspend(process);
+ ProcessSnapshotWin snapshot;
+ snapshot.Initialize(process, ProcessSuspensionState::kSuspended);
+ snapshot.InitializeException(exception_information_address);
+
+ // Confirm the exception record was read correctly.
+ EXPECT_NE(snapshot.Exception()->ThreadID(), 0u);
+ EXPECT_EQ(snapshot.Exception()->Exception(), EXCEPTION_BREAKPOINT);
+
+ // Verify the exception happened at the expected location with a bit of
+ // slop space to allow for reading the current PC before the exception
+ // happens. See CrashingChildProcess::Run().
+ const uint64_t kAllowedOffset = 64;
+ EXPECT_GT(snapshot.Exception()->ExceptionAddress(), break_near_);
+ EXPECT_LT(snapshot.Exception()->ExceptionAddress(),
+ break_near_ + kAllowedOffset);
+
+ SetEvent(completed_test_event_);
+
+ return snapshot.Exception()->Exception();
+ }
private:
- ScopedKernelHANDLE exception_happened_;
+ HANDLE server_ready_; // weak
+ HANDLE completed_test_event_; // weak
+ WinVMAddress break_near_;
+
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
};
// Runs the ExceptionHandlerServer on a background thread.
@@ -136,51 +132,7 @@ class ScopedStopServerAndJoinThread {
DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread);
};
-std::string ReadString(FileHandle handle) {
- size_t length = 0;
- EXPECT_TRUE(LoggingReadFile(handle, &length, sizeof(length)));
- scoped_ptr<char[]> buffer(new char[length]);
- EXPECT_TRUE(LoggingReadFile(handle, &buffer[0], length));
- return std::string(&buffer[0], length);
-}
-
-void WriteString(FileHandle handle, const std::string& str) {
- size_t length = str.size();
- EXPECT_TRUE(LoggingWriteFile(handle, &length, sizeof(length)));
- EXPECT_TRUE(LoggingWriteFile(handle, &str[0], length));
-}
-
-__declspec(noinline) void* CurrentAddress() {
- return _ReturnAddress();
-}
-
-class CrashingChildProcess final : public WinChildProcess {
- public:
- CrashingChildProcess() : WinChildProcess() {}
- ~CrashingChildProcess() {}
-
- private:
- int Run() override {
- std::string pipe_name = ReadString(ReadPipeHandle());
- CrashpadClient client;
- EXPECT_TRUE(client.SetHandler(pipe_name));
- EXPECT_TRUE(client.UseHandler());
- // Save the address where we're about to crash so the exception handler can
- // verify it's in approximately the right location (with a bit of fudge for
- // the code between here and the __debugbreak()).
- void* break_address = CurrentAddress();
- LoggingWriteFile(WritePipeHandle(), &break_address, sizeof(break_address));
- __debugbreak();
- return 0;
- };
-};
-
-TEST_F(ExceptionSnapshotWinTest, ChildCrash) {
- // Spawn a child process that will immediately crash (once we let it
- // run below by telling it what to connect to).
- WinChildProcess::EntryPoint<CrashingChildProcess>();
- scoped_ptr<WinChildProcess::Handles> handle = WinChildProcess::Launch();
-
+void TestCrashingChild(const base::string16& directory_modification) {
// Set up the registration server on a background thread.
std::string pipe_name = "\\\\.\\pipe\\handler_test_pipe_" +
base::StringPrintf("%08x", GetCurrentProcessId());
@@ -196,19 +148,74 @@ TEST_F(ExceptionSnapshotWinTest, ChildCrash) {
&exception_handler_server, &server_thread);
WaitForSingleObject(server_ready.get(), INFINITE);
- // Allow the child to continue and tell it where to connect to.
- WriteString(handle->write.get(), pipe_name);
+
+ // Spawn a child process, passing it the pipe name to connect to.
+ base::FilePath test_executable = Paths::Executable();
+ std::wstring child_test_executable =
+ test_executable.DirName()
+ .Append(directory_modification)
+ .Append(test_executable.BaseName().RemoveFinalExtension().value() +
+ L"_crashing_child.exe")
+ .value();
+
+ // Create a pipe for the stdout of the child.
+ SECURITY_ATTRIBUTES security_attributes = {0};
+ security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ security_attributes.bInheritHandle = true;
+ HANDLE stdout_read;
+ HANDLE stdout_write;
+ ASSERT_TRUE(CreatePipe(&stdout_read, &stdout_write, &security_attributes, 0));
+ ScopedFileHANDLE read_handle(stdout_read);
+ ScopedFileHANDLE write_handle(stdout_write);
+ ASSERT_TRUE(SetHandleInformation(read_handle.get(), HANDLE_FLAG_INHERIT, 0));
+
+ std::wstring command_line =
+ child_test_executable + L" " + base::UTF8ToUTF16(pipe_name);
+ STARTUPINFO startup_info = {0};
+ startup_info.cb = sizeof(startup_info);
+ startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ startup_info.hStdOutput = write_handle.get();
+ startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+ PROCESS_INFORMATION process_information;
+ ASSERT_TRUE(CreateProcess(child_test_executable.c_str(),
+ &command_line[0],
+ nullptr,
+ nullptr,
+ true,
+ 0,
+ nullptr,
+ nullptr,
+ &startup_info,
+ &process_information));
+ // Take ownership of the two process handles returned.
+ ScopedKernelHANDLE process_main_thread_handle(process_information.hThread);
+ ScopedKernelHANDLE process_handle(process_information.hProcess);
// The child tells us (approximately) where it will crash.
- void* break_near_address;
+ WinVMAddress break_near_address;
LoggingReadFile(
- handle->read.get(), &break_near_address, sizeof(break_near_address));
+ read_handle.get(), &break_near_address, sizeof(break_near_address));
delegate.set_break_near(break_near_address);
// Wait for the child to crash and the exception information to be validated.
WaitForSingleObject(completed.get(), INFINITE);
}
+TEST(ExceptionSnapshotWinTest, ChildCrash) {
+ TestCrashingChild(FILE_PATH_LITERAL("."));
+}
+
+#if defined(ARCH_CPU_64_BITS)
+TEST(ExceptionSnapshotWinTest, ChildCrashWOW64) {
+#ifndef NDEBUG
+ TestCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Debug"));
+#else
+ TestCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Release"));
+#endif
+}
+#endif // ARCH_CPU_64_BITS
+
} // namespace
} // namespace test
} // namespace crashpad
« no previous file with comments | « snapshot/win/exception_snapshot_win.cc ('k') | snapshot/win/process_reader_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698