diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-08-01 12:59:39 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-08-04 12:40:43 +0000 |
commit | 28b1110370900897ab652cb420c371fab8857ad4 (patch) | |
tree | 41b32127d23b0df4f2add2a27e12dc87bddb260e /chromium/third_party/crashpad | |
parent | 399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (diff) | |
download | qtwebengine-chromium-28b1110370900897ab652cb420c371fab8857ad4.tar.gz |
BASELINE: Update Chromium to 53.0.2785.41
Also adds a few extra files for extensions.
Change-Id: Iccdd55d98660903331cf8b7b29188da781830af4
Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/crashpad')
21 files changed, 230 insertions, 138 deletions
diff --git a/chromium/third_party/crashpad/README.chromium b/chromium/third_party/crashpad/README.chromium index 05e47ab6db8..faa4596f4db 100644 --- a/chromium/third_party/crashpad/README.chromium +++ b/chromium/third_party/crashpad/README.chromium @@ -2,7 +2,7 @@ Name: Crashpad Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 00d458adaf3868999eeab5341fce5bedb81d17a1 +Revision: 495a64fcdb7c979fe0f46eeaa1017087589d67cb License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes diff --git a/chromium/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc b/chromium/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc index c33020e5acf..b9c6d1118d1 100644 --- a/chromium/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc +++ b/chromium/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc @@ -51,16 +51,12 @@ unsigned int CrashReportExceptionHandler::ExceptionHandlerServerException( ProcessSnapshotWin process_snapshot; if (!process_snapshot.Initialize(process, ProcessSuspensionState::kSuspended, + exception_information_address, debug_critical_section_address)) { LOG(WARNING) << "ProcessSnapshotWin::Initialize failed"; return kFailedTerminationCode; } - if (!process_snapshot.InitializeException(exception_information_address)) { - LOG(WARNING) << "ProcessSnapshotWin::InitializeException failed"; - return kFailedTerminationCode; - } - // Now that we have the exception information, even if something else fails we // can terminate the process with the correct exit code. const unsigned int termination_code = diff --git a/chromium/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc b/chromium/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc index 6f32dd41e4a..af607c3281b 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc @@ -78,7 +78,7 @@ CrashpadInfoClientOptions SelfProcessSnapshotAndGetCrashpadOptions() { #elif defined(OS_WIN) ProcessSnapshotWin process_snapshot; EXPECT_TRUE(process_snapshot.Initialize( - GetCurrentProcess(), ProcessSuspensionState::kRunning, 0)); + GetCurrentProcess(), ProcessSuspensionState::kRunning, 0, 0)); #else #error Port. #endif // OS_MACOSX diff --git a/chromium/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc b/chromium/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc index 9b07e904ea8..9837a9c53e5 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc @@ -122,7 +122,7 @@ bool MachOImageSegmentReader::Initialize(ProcessReader* process_reader, if (section_segment_name != segment_name) { // cl_kernels modules (for OpenCL) aren’t ld output, and they’re formatted - // incorrectly on OS X 10.10 and 10.11. They have a single __TEXT segment, + // incorrectly on OS X 10.10 and later. They have a single __TEXT segment, // but one of the sections within it claims to belong to the __LD segment. // This mismatch shouldn’t happen. This errant section also has the // S_ATTR_DEBUG flag set, which shouldn’t happen unless all of the other @@ -136,7 +136,7 @@ bool MachOImageSegmentReader::Initialize(ProcessReader* process_reader, bool ok = false; if (file_type == MH_BUNDLE && module_name == "cl_kernels") { int mac_os_x_minor_version = MacOSXMinorVersion(); - if ((mac_os_x_minor_version == 10 || mac_os_x_minor_version == 11) && + if ((mac_os_x_minor_version >= 10 && mac_os_x_minor_version <= 12) && segment_name == SEG_TEXT && section_segment_name == "__LD" && section_name == "__compact_unwind" && @@ -173,27 +173,6 @@ bool MachOImageSegmentReader::Initialize(ProcessReader* process_reader, return false; } - uint32_t section_type = (section.flags & SECTION_TYPE); - bool zero_fill = section_type == S_ZEROFILL || - section_type == S_GB_ZEROFILL || - section_type == S_THREAD_LOCAL_ZEROFILL; - - // Zero-fill section types aren’t mapped from the file, so their |offset| - // fields are irrelevant and are typically 0. - if (!zero_fill && - section.offset - segment_command_.fileoff != - section.addr - segment_command_.vmaddr) { - LOG(WARNING) << base::StringPrintf( - "section type 0x%x at 0x%llx has unexpected offset " - "0x%x in segment at 0x%llx with offset 0x%llx", - section_type, - section.addr, - section.offset, - segment_command_.vmaddr, - segment_command_.fileoff) << section_info; - return false; - } - const auto insert_result = section_map_.insert(std::make_pair(section_name, section_index)); if (!insert_result.second) { diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc b/chromium/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc index 0592f26438d..a114d392e16 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc @@ -15,9 +15,24 @@ #include <windows.h> #include "base/logging.h" +#include "client/crashpad_info.h" #include "util/file/file_io.h" #include "util/win/scoped_handle.h" +DWORD WINAPI LotsOfReferencesThreadProc(void* param) { + LONG* count = reinterpret_cast<LONG*>(param); + + // Allocate a bunch of pointers to things on the stack. + int* pointers[1000]; + for (int i = 0; i < arraysize(pointers); ++i) { + pointers[i] = new int[2048]; + } + + InterlockedIncrement(count); + Sleep(INFINITE); + return 0; +} + int wmain(int argc, wchar_t* argv[]) { CHECK_EQ(argc, 2); @@ -26,11 +41,45 @@ int wmain(int argc, wchar_t* argv[]) { PCHECK(LoadLibrary(L"crashpad_snapshot_test_image_reader_module.dll")) << "LoadLibrary"; + // Create threads with lots of stack pointers to memory. This is used to + // verify the cap on pointed-to memory. + LONG thread_ready_count = 0; + crashpad::ScopedKernelHANDLE threads[100]; + for (int i = 0; i < arraysize(threads); ++i) { + threads[i].reset(CreateThread(nullptr, + 0, + &LotsOfReferencesThreadProc, + reinterpret_cast<void*>(&thread_ready_count), + 0, + nullptr)); + if (!threads[i].is_valid()) { + PLOG(ERROR) << "CreateThread"; + return 1; + } + } + + for (;;) { + if (InterlockedCompareExchange(&thread_ready_count, + arraysize(threads), + arraysize(threads) == arraysize(threads))) { + // All threads have allocated their references. + break; + } + Sleep(10); + } + + crashpad::CrashpadInfo* crashpad_info = + crashpad::CrashpadInfo::GetCrashpadInfo(); + crashpad_info->set_gather_indirectly_referenced_memory( + crashpad::TriState::kEnabled, 100000); + + // Tell the parent process we're ready to proceed. HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); PCHECK(out != INVALID_HANDLE_VALUE) << "GetStdHandle"; char c = ' '; crashpad::CheckedWriteFile(out, &c, sizeof(c)); + // Parent process says we can exit. CHECK_EQ(WAIT_OBJECT_0, WaitForSingleObject(done.get(), INFINITE)); return 0; diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/end_to_end_test.py b/chromium/third_party/crashpad/crashpad/snapshot/win/end_to_end_test.py index a5540e58fcf..1fa820e7d1f 100755 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/end_to_end_test.py +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/end_to_end_test.py @@ -325,7 +325,10 @@ def RunTests(cdb_path, 'other program dump exception code') out.Check('!Sleep', 'other program reasonable location') out.Check('hanging_program!Thread1', 'other program dump right thread') - out.Check('\. 1 Id', 'other program exception on correct thread') + out.Check('\. 1 Id.*Suspend: 0 ', + 'other program exception on correct thread and correct suspend') + out.Check(' 4 Id.*Suspend: 0 ', + 'other program injection thread correct suspend') out = CdbRun(cdb_path, other_program_no_exception_path, '.ecxr;k') out.Check('Unknown exception - code 0cca11ed', diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc b/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc index ca29e1f0e80..c0d63bad496 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc @@ -72,8 +72,7 @@ ExceptionSnapshotWin::~ExceptionSnapshotWin() { bool ExceptionSnapshotWin::Initialize( ProcessReaderWin* process_reader, DWORD thread_id, - WinVMAddress exception_pointers_address, - const PointerVector<internal::ThreadSnapshotWin>& threads) { + WinVMAddress exception_pointers_address) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); const ProcessReaderWin::Thread* thread = nullptr; @@ -98,9 +97,9 @@ bool ExceptionSnapshotWin::Initialize( if (is_64_bit) { if (!InitializeFromExceptionPointers<EXCEPTION_RECORD64, process_types::EXCEPTION_POINTERS64>( - *process_reader, + process_reader, exception_pointers_address, - threads, + thread_id, &NativeContextToCPUContext64)) { return false; } @@ -109,9 +108,9 @@ bool ExceptionSnapshotWin::Initialize( if (!is_64_bit) { if (!InitializeFromExceptionPointers<EXCEPTION_RECORD32, process_types::EXCEPTION_POINTERS32>( - *process_reader, + process_reader, exception_pointers_address, - threads, + thread_id, &NativeContextToCPUContext32)) { return false; } @@ -168,16 +167,16 @@ template <class ExceptionRecordType, class ExceptionPointersType, class ContextType> bool ExceptionSnapshotWin::InitializeFromExceptionPointers( - const ProcessReaderWin& process_reader, + ProcessReaderWin* process_reader, WinVMAddress exception_pointers_address, - const PointerVector<internal::ThreadSnapshotWin>& threads, + DWORD exception_thread_id, void (*native_to_cpu_context)(const ContextType& context_record, CPUContext* context, CPUContextUnion* context_union)) { ExceptionPointersType exception_pointers; - if (!process_reader.ReadMemory(exception_pointers_address, - sizeof(exception_pointers), - &exception_pointers)) { + if (!process_reader->ReadMemory(exception_pointers_address, + sizeof(exception_pointers), + &exception_pointers)) { LOG(ERROR) << "EXCEPTION_POINTERS read failed"; return false; } @@ -187,7 +186,7 @@ bool ExceptionSnapshotWin::InitializeFromExceptionPointers( } ExceptionRecordType first_record; - if (!process_reader.ReadMemory( + if (!process_reader->ReadMemory( static_cast<WinVMAddress>(exception_pointers.ExceptionRecord), sizeof(first_record), &first_record)) { @@ -195,35 +194,35 @@ bool ExceptionSnapshotWin::InitializeFromExceptionPointers( return false; } - if (first_record.ExceptionCode == CrashpadClient::kTriggeredExceptionCode && - first_record.NumberParameters == 2 && - first_record.ExceptionInformation[0] != 0) { + const bool triggered_by_client = + first_record.ExceptionCode == CrashpadClient::kTriggeredExceptionCode && + first_record.NumberParameters == 2; + if (triggered_by_client) + process_reader->DecrementThreadSuspendCounts(exception_thread_id); + + if (triggered_by_client && first_record.ExceptionInformation[0] != 0) { // This special exception code indicates that the target was crashed by // another client calling CrashpadClient::DumpAndCrashTargetProcess(). In // this case the parameters are a thread id and an exception code which we // use to fabricate a new exception record. using ArgumentType = decltype(first_record.ExceptionInformation[0]); - const ArgumentType thread_id = first_record.ExceptionInformation[0]; + const ArgumentType blame_thread_id = first_record.ExceptionInformation[0]; exception_code_ = static_cast<DWORD>(first_record.ExceptionInformation[1]); exception_flags_ = EXCEPTION_NONCONTINUABLE; - for (const auto* thread : threads) { - if (thread->ThreadID() == thread_id) { - thread_id_ = thread_id; - exception_address_ = thread->Context()->InstructionPointer(); - context_.architecture = thread->Context()->architecture; - if (context_.architecture == kCPUArchitectureX86_64) { - context_union_.x86_64 = *thread->Context()->x86_64; - context_.x86_64 = &context_union_.x86_64; - } else { - context_union_.x86 = *thread->Context()->x86; - context_.x86 = &context_union_.x86; - } + for (const auto& thread : process_reader->Threads()) { + if (thread.id == blame_thread_id) { + thread_id_ = blame_thread_id; + native_to_cpu_context( + *reinterpret_cast<const ContextType*>(&thread.context), + &context_, + &context_union_); + exception_address_ = context_.InstructionPointer(); break; } } if (exception_address_ == 0) { - LOG(WARNING) << "thread " << thread_id << " not found"; + LOG(WARNING) << "thread " << blame_thread_id << " not found"; return false; } } else { @@ -239,7 +238,7 @@ bool ExceptionSnapshotWin::InitializeFromExceptionPointers( } ContextType context_record; - if (!process_reader.ReadMemory( + if (!process_reader->ReadMemory( static_cast<WinVMAddress>(exception_pointers.ContextRecord), sizeof(context_record), &context_record)) { diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h b/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h index 8ff7d3811ab..3ccf38ae5d2 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h @@ -57,12 +57,15 @@ class ExceptionSnapshotWin final : public ExceptionSnapshot { //! `EXCEPTION_POINTERS` record in the target process, passed through from //! the exception handler. //! + //! \note If the exception was triggered by + //! CrashpadClient::DumpAndCrashTargetProcess(), this has the side-effect + //! of correcting the thread suspend counts for \a process_reader. + //! //! \return `true` if the snapshot could be created, `false` otherwise with //! an appropriate message logged. bool Initialize(ProcessReaderWin* process_reader, DWORD thread_id, - WinVMAddress exception_pointers, - const PointerVector<internal::ThreadSnapshotWin>& threads); + WinVMAddress exception_pointers); // ExceptionSnapshot: @@ -79,9 +82,9 @@ class ExceptionSnapshotWin final : public ExceptionSnapshot { class ExceptionPointersType, class ContextType> bool InitializeFromExceptionPointers( - const ProcessReaderWin& process_reader, + ProcessReaderWin* process_reader, WinVMAddress exception_pointers_address, - const PointerVector<internal::ThreadSnapshotWin>& threads, + DWORD exception_thread_id, void (*native_to_cpu_context)(const ContextType& context_record, CPUContext* context, CPUContextUnion* context_union)); diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc b/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc index 5c3b0609e44..88612df3176 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc @@ -91,8 +91,8 @@ class CrashingDelegate : public ExceptionHandlerServer::Delegate { ProcessSnapshotWin snapshot; snapshot.Initialize(process, ProcessSuspensionState::kSuspended, + exception_information_address, debug_critical_section_address); - snapshot.InitializeException(exception_information_address); // Confirm the exception record was read correctly. EXPECT_NE(snapshot.Exception()->ThreadID(), 0u); @@ -190,8 +190,8 @@ class SimulateDelegate : public ExceptionHandlerServer::Delegate { ProcessSnapshotWin snapshot; snapshot.Initialize(process, ProcessSuspensionState::kSuspended, + exception_information_address, debug_critical_section_address); - snapshot.InitializeException(exception_information_address); EXPECT_TRUE(snapshot.Exception()); EXPECT_EQ(0x517a7ed, snapshot.Exception()->Exception()); diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc b/chromium/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc index b623eccf44c..d6d56596f54 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc @@ -62,7 +62,7 @@ void TestExtraMemoryRanges(TestType type, ProcessSnapshotWin snapshot; ASSERT_TRUE(snapshot.Initialize( - child.process_handle(), ProcessSuspensionState::kRunning, 0)); + child.process_handle(), ProcessSuspensionState::kRunning, 0, 0)); // Verify the extra memory ranges set via the CrashpadInfo interface. std::set<CheckedRange<uint64_t>> all_ranges; diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc b/chromium/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc index da43a8a8c98..b7bae6ac22d 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc @@ -326,6 +326,16 @@ const ProcessInfo& ProcessReaderWin::GetProcessInfo() const { return process_info_; } +void ProcessReaderWin::DecrementThreadSuspendCounts(uint64_t except_thread_id) { + Threads(); + for (auto& thread : threads_) { + if (thread.id != except_thread_id) { + DCHECK_GT(thread.suspend_count, 0u); + --thread.suspend_count; + } + } +} + template <class Traits> void ProcessReaderWin::ReadThreadData(bool is_64_reading_32) { DCHECK(threads_.empty()); diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/process_reader_win.h b/chromium/third_party/crashpad/crashpad/snapshot/win/process_reader_win.h index e2f1b01a45f..1794a51a827 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/process_reader_win.h +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/process_reader_win.h @@ -132,6 +132,13 @@ class ProcessReaderWin { //! \return A ProcessInfo object for the process being read. const ProcessInfo& GetProcessInfo() const; + //! \brief Decrements the thread suspend counts for all thread ids other than + //! \a except_thread_id. + //! + //! Used to adjust the thread suspend count to correspond to the actual values + //! for the process before Crashpad got involved. + void DecrementThreadSuspendCounts(uint64_t except_thread_id); + private: template <class Traits> void ReadThreadData(bool is_64_reading_32); diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc b/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc index 4601db01867..63543c764bc 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc @@ -20,6 +20,7 @@ #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "snapshot/win/exception_snapshot_win.h" #include "snapshot/win/memory_snapshot_win.h" #include "snapshot/win/module_snapshot_win.h" #include "util/win/nt_internals.h" @@ -50,6 +51,7 @@ ProcessSnapshotWin::~ProcessSnapshotWin() { bool ProcessSnapshotWin::Initialize( HANDLE process, ProcessSuspensionState suspension_state, + WinVMAddress exception_information_address, WinVMAddress debug_critical_section_address) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); @@ -58,6 +60,25 @@ bool ProcessSnapshotWin::Initialize( if (!process_reader_.Initialize(process, suspension_state)) return false; + if (exception_information_address != 0) { + ExceptionInformation exception_information = {}; + if (!process_reader_.ReadMemory(exception_information_address, + sizeof(exception_information), + &exception_information)) { + LOG(WARNING) << "ReadMemory ExceptionInformation failed"; + return false; + } + + exception_.reset(new internal::ExceptionSnapshotWin()); + if (!exception_->Initialize(&process_reader_, + exception_information.thread_id, + exception_information.exception_pointers)) { + exception_.reset(); + return false; + } + } + + system_.Initialize(&process_reader_); if (process_reader_.Is64Bit()) { @@ -92,31 +113,6 @@ bool ProcessSnapshotWin::Initialize( return true; } -bool ProcessSnapshotWin::InitializeException( - WinVMAddress exception_information_address) { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - DCHECK(!exception_); - - ExceptionInformation exception_information; - if (!process_reader_.ReadMemory(exception_information_address, - sizeof(exception_information), - &exception_information)) { - LOG(WARNING) << "ReadMemory ExceptionInformation failed"; - return false; - } - - exception_.reset(new internal::ExceptionSnapshotWin()); - if (!exception_->Initialize(&process_reader_, - exception_information.thread_id, - exception_information.exception_pointers, - threads_)) { - exception_.reset(); - return false; - } - - return true; -} - void ProcessSnapshotWin::GetCrashpadOptions( CrashpadInfoClientOptions* options) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); @@ -237,13 +233,13 @@ void ProcessSnapshotWin::InitializeThreads( uint32_t indirectly_referenced_memory_cap) { const std::vector<ProcessReaderWin::Thread>& process_reader_threads = process_reader_.Threads(); + uint32_t* budget_remaining_pointer = nullptr; + uint32_t budget_remaining = indirectly_referenced_memory_cap; + if (gather_indirectly_referenced_memory) + budget_remaining_pointer = &budget_remaining; for (const ProcessReaderWin::Thread& process_reader_thread : process_reader_threads) { auto thread = base::WrapUnique(new internal::ThreadSnapshotWin()); - uint32_t* budget_remaining_pointer = nullptr; - uint32_t budget_remaining = indirectly_referenced_memory_cap; - if (gather_indirectly_referenced_memory) - budget_remaining_pointer = &budget_remaining; if (thread->Initialize(&process_reader_, process_reader_thread, budget_remaining_pointer)) { diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.h b/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.h index 2158f062054..8ae593352c9 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.h +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.h @@ -62,6 +62,9 @@ class ProcessSnapshotWin final : public ProcessSnapshot { //! \param[in] process The handle to create a snapshot from. //! \param[in] suspension_state Whether \a process has been suspended by the //! caller. + //! \param[in] exception_information_address The address in the client + //! process's address space of an ExceptionInformation structure. May be + //! `0`, in which case no exception data will be recorded. //! \param[in] debug_critical_section_address The address in the target //! process's address space of a `CRITICAL_SECTION` allocated with valid //! `.DebugInfo`. Used as a starting point to walk the process's locks. @@ -73,23 +76,9 @@ class ProcessSnapshotWin final : public ProcessSnapshot { //! \sa ScopedProcessSuspend bool Initialize(HANDLE process, ProcessSuspensionState suspension_state, + WinVMAddress exception_information_address, WinVMAddress debug_critical_section_address); - //! \brief Initializes the object's exception. - //! - //! This populates the data to be returned by Exception(). - //! - //! This method must not be called until after a successful call to - //! Initialize(). - //! - //! \param[in] exception_information_address The address in the client - //! process's address space of an ExceptionInformation structure. - //! - //! \return `true` if the exception information could be initialized, `false` - //! otherwise with an appropriate message logged. When this method returns - //! `false`, the ProcessSnapshotWin object's validity remains unchanged. - bool InitializeException(WinVMAddress exception_information_address); - //! \brief Sets the value to be returned by ReportID(). //! //! The crash report ID is under the control of the snapshot producer, which diff --git a/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc b/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc index dc253bd24e3..76b5905b4b8 100644 --- a/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc +++ b/chromium/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc @@ -54,7 +54,7 @@ void TestImageReaderChild(const base::string16& directory_modification) { ProcessSnapshotWin process_snapshot; ASSERT_TRUE(process_snapshot.Initialize( - child.process_handle(), ProcessSuspensionState::kSuspended, 0)); + child.process_handle(), ProcessSuspensionState::kSuspended, 0, 0)); ASSERT_GE(process_snapshot.Modules().size(), 2u); @@ -85,6 +85,22 @@ void TestImageReaderChild(const base::string16& directory_modification) { 0, pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix)); + // Sum the size of the extra memory in all the threads and confirm it's near + // the limit that the child process set in its CrashpadInfo. + EXPECT_GE(process_snapshot.Threads().size(), 100u); + + size_t extra_memory_total = 0; + for (const auto* thread : process_snapshot.Threads()) { + for (const auto* extra_memory : thread->ExtraMemory()) { + extra_memory_total += extra_memory->Size(); + } + } + + // We confirm we gathered less than 1M of extra data. The cap is set to only + // 100K, but there are other "extra memory" regions that aren't included in + // the cap. (Completely uncapped it would be > 10M.) + EXPECT_LT(extra_memory_total, 1000000u); + // Tell the child it can terminate. SetEvent(done.get()); } diff --git a/chromium/third_party/crashpad/crashpad/tools/generate_dump.cc b/chromium/third_party/crashpad/crashpad/tools/generate_dump.cc index 399216106af..11fe0ca535a 100644 --- a/chromium/third_party/crashpad/crashpad/tools/generate_dump.cc +++ b/chromium/third_party/crashpad/crashpad/tools/generate_dump.cc @@ -187,6 +187,7 @@ int GenerateDumpMain(int argc, char* argv[]) { options.suspend ? ProcessSuspensionState::kSuspended : ProcessSuspensionState::kRunning, + 0, 0)) { return EXIT_FAILURE; } diff --git a/chromium/third_party/crashpad/crashpad/util/thread/worker_thread_test.cc b/chromium/third_party/crashpad/crashpad/util/thread/worker_thread_test.cc index 24f0cb3d090..0cbee187fbc 100644 --- a/chromium/third_party/crashpad/crashpad/util/thread/worker_thread_test.cc +++ b/chromium/third_party/crashpad/crashpad/util/thread/worker_thread_test.cc @@ -34,10 +34,13 @@ class WorkDelegate : public WorkerThread::Delegate { semaphore_.Signal(); } - //! \brief Suspends the calling thread until the DoWork() has been called - //! the specified number of times. - void WaitForWorkCount(int times) { + void SetDesiredWorkCount(int times) { waiting_for_count_ = times; + } + + //! \brief Suspends the calling thread until the DoWork() has been called + //! the number of times specified by SetDesiredWorkCount(). + void WaitForWorkCount() { semaphore_.Wait(); } @@ -56,10 +59,11 @@ TEST(WorkerThread, DoWork) { WorkerThread thread(0.05, &delegate); uint64_t start = ClockMonotonicNanoseconds(); + delegate.SetDesiredWorkCount(2); thread.Start(0); EXPECT_TRUE(thread.is_running()); - delegate.WaitForWorkCount(2); + delegate.WaitForWorkCount(); thread.Stop(); EXPECT_FALSE(thread.is_running()); @@ -80,15 +84,17 @@ TEST(WorkerThread, Restart) { WorkDelegate delegate; WorkerThread thread(0.05, &delegate); + delegate.SetDesiredWorkCount(1); thread.Start(0); EXPECT_TRUE(thread.is_running()); - delegate.WaitForWorkCount(1); + delegate.WaitForWorkCount(); thread.Stop(); ASSERT_FALSE(thread.is_running()); + delegate.SetDesiredWorkCount(2); thread.Start(0); - delegate.WaitForWorkCount(2); + delegate.WaitForWorkCount(); thread.Stop(); ASSERT_FALSE(thread.is_running()); } @@ -97,16 +103,18 @@ TEST(WorkerThread, DoWorkNow) { WorkDelegate delegate; WorkerThread thread(100, &delegate); + delegate.SetDesiredWorkCount(1); thread.Start(0); EXPECT_TRUE(thread.is_running()); uint64_t start = ClockMonotonicNanoseconds(); - delegate.WaitForWorkCount(1); + delegate.WaitForWorkCount(); EXPECT_EQ(1, delegate.work_count()); + delegate.SetDesiredWorkCount(2); thread.DoWorkNow(); - delegate.WaitForWorkCount(2); + delegate.WaitForWorkCount(); thread.Stop(); EXPECT_EQ(2, delegate.work_count()); @@ -119,11 +127,12 @@ TEST(WorkerThread, DoWorkNowAtStart) { uint64_t start = ClockMonotonicNanoseconds(); + delegate.SetDesiredWorkCount(1); thread.Start(100); EXPECT_TRUE(thread.is_running()); thread.DoWorkNow(); - delegate.WaitForWorkCount(1); + delegate.WaitForWorkCount(); EXPECT_EQ(1, delegate.work_count()); EXPECT_GE(100 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start); diff --git a/chromium/third_party/crashpad/crashpad/util/win/nt_internals.cc b/chromium/third_party/crashpad/crashpad/util/win/nt_internals.cc index 8cf96a450f9..12201620e83 100644 --- a/chromium/third_party/crashpad/crashpad/util/win/nt_internals.cc +++ b/chromium/third_party/crashpad/crashpad/util/win/nt_internals.cc @@ -38,6 +38,10 @@ NTSTATUS NTAPI NtOpenThread(HANDLE* ThreadHandle, OBJECT_ATTRIBUTES* ObjectAttributes, CLIENT_ID* ClientId); +NTSTATUS NTAPI NtSuspendProcess(HANDLE); + +NTSTATUS NTAPI NtResumeProcess(HANDLE); + void* NTAPI RtlGetUnloadEventTrace(); namespace crashpad { @@ -129,6 +133,18 @@ NTSTATUS NtQueryObject(HANDLE handle, return_length); } +NTSTATUS NtSuspendProcess(HANDLE handle) { + static const auto nt_suspend_process = + GET_FUNCTION_REQUIRED(L"ntdll.dll", ::NtSuspendProcess); + return nt_suspend_process(handle); +} + +NTSTATUS NtResumeProcess(HANDLE handle) { + static const auto nt_resume_process = + GET_FUNCTION_REQUIRED(L"ntdll.dll", ::NtResumeProcess); + return nt_resume_process(handle); +} + template <class Traits> RTL_UNLOAD_EVENT_TRACE<Traits>* RtlGetUnloadEventTrace() { static const auto rtl_get_unload_event_trace = diff --git a/chromium/third_party/crashpad/crashpad/util/win/nt_internals.h b/chromium/third_party/crashpad/crashpad/util/win/nt_internals.h index 3ced5cc3385..0a80fd533a7 100644 --- a/chromium/third_party/crashpad/crashpad/util/win/nt_internals.h +++ b/chromium/third_party/crashpad/crashpad/util/win/nt_internals.h @@ -71,6 +71,10 @@ NTSTATUS NtQueryObject(HANDLE handle, ULONG object_information_length, ULONG* return_length); +NTSTATUS NtSuspendProcess(HANDLE handle); + +NTSTATUS NtResumeProcess(HANDLE handle); + // From https://msdn.microsoft.com/en-us/library/bb432428(VS.85).aspx and // http://processhacker.sourceforge.net/doc/struct___r_t_l___u_n_l_o_a_d___e_v_e_n_t___t_r_a_c_e.html #define RTL_UNLOAD_EVENT_TRACE_NUMBER 64 diff --git a/chromium/third_party/crashpad/crashpad/util/win/process_info.cc b/chromium/third_party/crashpad/crashpad/util/win/process_info.cc index fc76bb2887b..d05a23d11c2 100644 --- a/chromium/third_party/crashpad/crashpad/util/win/process_info.cc +++ b/chromium/third_party/crashpad/crashpad/util/win/process_info.cc @@ -633,14 +633,27 @@ std::vector<CheckedRange<WinVMAddress, WinVMSize>> GetReadableRangesOfMemoryMap( const ProcessInfo::MemoryBasicInformation64Vector& memory_info) { using Range = CheckedRange<WinVMAddress, WinVMSize>; + // Constructing Ranges and using OverlapsRange() is very, very slow in Debug + // builds, so do a manual check in this loop. The ranges are still validated + // by a CheckedRange before being returned. + WinVMAddress range_base = range.base(); + WinVMAddress range_end = range.end(); + // Find all the ranges that overlap the target range, maintaining their order. ProcessInfo::MemoryBasicInformation64Vector overlapping; - for (const auto& mi : memory_info) { + const size_t size = memory_info.size(); + + // This loop is written in an ugly fashion to make Debug performance + // reasonable. + const MEMORY_BASIC_INFORMATION64* begin = &memory_info[0]; + for (size_t i = 0; i < size; ++i) { + const MEMORY_BASIC_INFORMATION64& mi = *(begin + i); static_assert(std::is_same<decltype(mi.BaseAddress), WinVMAddress>::value, "expected range address to be WinVMAddress"); static_assert(std::is_same<decltype(mi.RegionSize), WinVMSize>::value, "expected range size to be WinVMSize"); - if (range.OverlapsRange(Range(mi.BaseAddress, mi.RegionSize))) + WinVMAddress mi_end = mi.BaseAddress + mi.RegionSize; + if (range_base < mi_end && mi.BaseAddress < range_end) overlapping.push_back(mi); } if (overlapping.empty()) diff --git a/chromium/third_party/crashpad/crashpad/util/win/scoped_process_suspend.cc b/chromium/third_party/crashpad/crashpad/util/win/scoped_process_suspend.cc index 4450efb5256..fc75ce02044 100644 --- a/chromium/third_party/crashpad/crashpad/util/win/scoped_process_suspend.cc +++ b/chromium/third_party/crashpad/crashpad/util/win/scoped_process_suspend.cc @@ -16,26 +16,28 @@ #include <winternl.h> -#include "base/logging.h" +#include "util/win/nt_internals.h" +#include "util/win/ntstatus_logging.h" namespace crashpad { -ScopedProcessSuspend::ScopedProcessSuspend(HANDLE process) : process_(process) { - typedef NTSTATUS(__stdcall * NtSuspendProcessFunc)(HANDLE); - static NtSuspendProcessFunc func = reinterpret_cast<NtSuspendProcessFunc>( - GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtSuspendProcess")); - NTSTATUS status = func(process_); - if (status) - LOG(ERROR) << "NtSuspendProcess, ntstatus=" << status; +ScopedProcessSuspend::ScopedProcessSuspend(HANDLE process) { + NTSTATUS status = NtSuspendProcess(process); + if (NT_SUCCESS(status)) { + process_ = process; + } else { + process_ = nullptr; + NTSTATUS_LOG(ERROR, status) << "NtSuspendProcess"; + } } ScopedProcessSuspend::~ScopedProcessSuspend() { - typedef NTSTATUS(__stdcall * NtResumeProcessFunc)(HANDLE); - static NtResumeProcessFunc func = reinterpret_cast<NtResumeProcessFunc>( - GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtResumeProcess")); - NTSTATUS status = func(process_); - if (status) - LOG(ERROR) << "NtResumeProcess, ntstatus=" << status; + if (process_) { + NTSTATUS status = NtResumeProcess(process_); + if (!NT_SUCCESS(status)) { + NTSTATUS_LOG(ERROR, status) << "NtResumeProcess"; + } + } } } // namespace crashpad |