// 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 #include #include #include #include "base/logging.h" #include "base/strings/stringprintf.h" #include "client/crashpad_client.h" #include "snapshot/win/process_reader_win.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 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(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, wchar_t* argv[]) { if (argc != 2) { fprintf(stderr, "Usage: %ls \n", argv[0]); return EXIT_FAILURE; } CrashpadClient client; if (!client.SetHandlerIPCPipe(argv[1])) { LOG(ERROR) << "SetHandler"; 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::SelfDestroyingMain(argc, argv); }