| Index: handler/win/self_destroying_test_program.cc
|
| diff --git a/handler/win/self_destroying_test_program.cc b/handler/win/self_destroying_test_program.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d00fa47691173aab46f2d7663bd36989550f0717
|
| --- /dev/null
|
| +++ b/handler/win/self_destroying_test_program.cc
|
| @@ -0,0 +1,97 @@
|
| +// Copyright 2015 The Crashpad Authors. All rights reserved.
|
| +//
|
| +// Licensed under the Apache License, Version 2.0 (the "License");
|
| +// you may not use this file except in compliance with the License.
|
| +// You may obtain a copy of the License at
|
| +//
|
| +// http://www.apache.org/licenses/LICENSE-2.0
|
| +//
|
| +// Unless required by applicable law or agreed to in writing, software
|
| +// distributed under the License is distributed on an "AS IS" BASIS,
|
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +// See the License for the specific language governing permissions and
|
| +// limitations under the License.
|
| +
|
| +#include <malloc.h>
|
| +#include <stdlib.h>
|
| +#include <windows.h>
|
| +#include <winternl.h>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "client/crashpad_client.h"
|
| +#include "snapshot/win/process_reader_win.h"
|
| +#include "tools/tool_support.h"
|
| +
|
| +namespace crashpad {
|
| +namespace {
|
| +
|
| +// We VirtualFree a region in ourselves (the stack) to confirm that the
|
| +// exception reporter captures as much as possible in the minidump and doesn't
|
| +// abort. __debugbreak() immediately after doing so because the process is
|
| +// clearly in a very broken state at this point.
|
| +bool FreeOwnStackAndBreak() {
|
| + ProcessReaderWin process_reader;
|
| + if (!process_reader.Initialize(GetCurrentProcess(),
|
| + ProcessSuspensionState::kRunning)) {
|
| + LOG(ERROR) << "ProcessReaderWin Initialize";
|
| + return false;
|
| + }
|
| +
|
| + const std::vector<ProcessReaderWin::Thread> threads =
|
| + process_reader.Threads();
|
| + if (threads.empty()) {
|
| + LOG(ERROR) << "no threads";
|
| + return false;
|
| + }
|
| +
|
| + // Push the stack up a bit so that hopefully the crash handler can succeed,
|
| + // but won't be able to read the base of the stack.
|
| + _alloca(16384);
|
| +
|
| + // We can't succeed at MEM_RELEASEing this memory, but MEM_DECOMMIT is good
|
| + // enough to make it inaccessible.
|
| + if (!VirtualFree(reinterpret_cast<void*>(threads[0].stack_region_address),
|
| + 100,
|
| + MEM_DECOMMIT)) {
|
| + PLOG(ERROR) << "VirtualFree";
|
| + return false;
|
| + }
|
| +
|
| + // If the VirtualFree() succeeds, we may have already crashed. __debugbreak()
|
| + // just to be sure.
|
| + __debugbreak();
|
| +
|
| + return true;
|
| +}
|
| +
|
| +int SelfDestroyingMain(int argc, char* argv[]) {
|
| + if (argc != 2) {
|
| + fprintf(stderr, "Usage: %s <server_pipe_name>\n", argv[0]);
|
| + return EXIT_FAILURE;
|
| + }
|
| +
|
| + CrashpadClient client;
|
| + if (!client.SetHandler(argv[1])) {
|
| + LOG(ERROR) << "SetHandler";
|
| + return EXIT_FAILURE;
|
| + }
|
| + if (!client.UseHandler()) {
|
| + LOG(ERROR) << "UseHandler";
|
| + return EXIT_FAILURE;
|
| + }
|
| +
|
| + if (!FreeOwnStackAndBreak())
|
| + return EXIT_FAILURE;
|
| +
|
| + // This will never be reached. On success, we'll have crashed above, or
|
| + // otherwise returned before here.
|
| + return EXIT_SUCCESS;
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace crashpad
|
| +
|
| +int wmain(int argc, wchar_t* argv[]) {
|
| + return crashpad::ToolSupport::Wmain(argc, argv, crashpad::SelfDestroyingMain);
|
| +}
|
|
|