Commit 915bf1fa authored by Joshua Peraza's avatar Joshua Peraza Committed by Commit Bot

Update Crashpad to 75b672be06c5127f92aab89a2b4422d9ae6f9948

9115494e8aa4 fuchsia: Increase timeout for WorkerThread.DoWork test
dea8fa51d0b5 fuchsia: Changes to allow analyzer-style exception handling
d78bd067c7f3 linux: Initialize a crashing thread's stack from its
             exception context
75b672be06c5 Fix arm build with glibc 2.27

Change-Id: I1187b6c1f651761dc65818c24441943b25b7519c
Reviewed-on: https://chromium-review.googlesource.com/1060117Reviewed-by: default avatarScott Graham <scottmg@chromium.org>
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
Cr-Commit-Position: refs/heads/master@{#559263}
parent bb6902df
......@@ -2,7 +2,7 @@ Name: Crashpad
Short Name: crashpad
URL: https://crashpad.chromium.org/
Version: unknown
Revision: ef6d91b16616df58a2379e55a3f9edecff0b904d
Revision: 75b672be06c5127f92aab89a2b4422d9ae6f9948
License: Apache 2.0
License File: crashpad/LICENSE
Security Critical: yes
......
......@@ -98,13 +98,23 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
deps = [
"handler:crashpad_handler",
"tools:crashpad_database_util",
]
binaries = [
{
name = "crashpad_handler"
},
]
}
package("crashpad_database_util") {
deprecated_system_image = true
deps = [
"tools:crashpad_database_util",
]
binaries = [
{
name = "crashpad_database_util"
},
......
......@@ -60,8 +60,7 @@ CrashReportExceptionHandler::CrashReportExceptionHandler(
CrashReportExceptionHandler::~CrashReportExceptionHandler() {}
bool CrashReportExceptionHandler::HandleException(uint32_t type,
uint64_t process_id,
bool CrashReportExceptionHandler::HandleException(uint64_t process_id,
uint64_t thread_id) {
// TODO(scottmg): This function needs to be instrumented with metrics calls,
// https://crashpad.chromium.org/bug/230.
......@@ -73,20 +72,23 @@ bool CrashReportExceptionHandler::HandleException(uint32_t type,
return false;
}
ScopedTaskSuspend suspend(process.get());
base::ScopedZxHandle thread(GetChildHandleByKoid(process.get(), thread_id));
if (!thread.is_valid()) {
return false;
}
return HandleExceptionHandles(process.get(), thread.get());
}
bool CrashReportExceptionHandler::HandleExceptionHandles(zx_handle_t process,
zx_handle_t thread) {
// Now that the thread has been successfully retrieved, it is possible to
// correctly call zx_task_resume() to continue exception processing, even if
// something else during this function fails.
ScopedZxTaskResumeAfterException resume(thread.get());
ScopedZxTaskResumeAfterException resume(thread);
ProcessSnapshotFuchsia process_snapshot;
if (!process_snapshot.Initialize(process.get())) {
if (!process_snapshot.Initialize(process)) {
return false;
}
......@@ -95,7 +97,7 @@ bool CrashReportExceptionHandler::HandleException(uint32_t type,
if (client_options.crashpad_handler_behavior != TriState::kDisabled) {
zx_exception_report_t report;
zx_status_t status = zx_object_get_info(thread.get(),
zx_status_t status = zx_object_get_info(thread,
ZX_INFO_THREAD_EXCEPTION_REPORT,
&report,
sizeof(report),
......@@ -107,8 +109,7 @@ bool CrashReportExceptionHandler::HandleException(uint32_t type,
return false;
}
DCHECK_EQ(type, report.header.type);
zx_koid_t thread_id = GetKoidForHandle(thread);
if (!process_snapshot.InitializeException(thread_id, report)) {
return false;
}
......
......@@ -16,6 +16,7 @@
#define CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
#include <stdint.h>
#include <zircon/types.h>
#include <map>
#include <string>
......@@ -64,12 +65,24 @@ class CrashReportExceptionHandler {
//! This function is expected to call `zx_task_resume()` in order to complete
//! handling of the exception.
//!
//! \param[in] type The type of exception, a `ZX_EXCP_*` value.
//! \param[in] process_id The koid of the process which sustained the
//! exception.
//! \param[in] thread_id The koid of the thread which sustained the exception.
//! \return `true` on success, or `false` with an error logged.
bool HandleException(uint32_t type, uint64_t process_id, uint64_t thread_id);
bool HandleException(uint64_t process_id, uint64_t thread_id);
//! \brief Called when the exception handler server has caught an exception
//! and wants a crash dump to be taken.
//!
//! This function is expected to call `zx_task_resume()` in order to complete
//! handling of the exception.
//!
//! \param[in] process The handle to the process which sustained the
//! exception.
//! \param[in] thread The handle to the thread of \a process which sustained
//! the exception.
//! \return `true` on success, or `false` with an error logged.
bool HandleExceptionHandles(zx_handle_t process, zx_handle_t thread);
private:
CrashReportDatabase* database_; // weak
......
......@@ -49,8 +49,8 @@ void ExceptionHandlerServer::Run(CrashReportExceptionHandler* handler) {
continue;
}
bool result = handler->HandleException(
packet.type, packet.exception.pid, packet.exception.tid);
bool result =
handler->HandleException(packet.exception.pid, packet.exception.tid);
if (!result) {
LOG(ERROR) << "HandleException failed";
}
......
......@@ -174,4 +174,20 @@ uint64_t CPUContext::InstructionPointer() const {
}
}
uint64_t CPUContext::StackPointer() const {
switch (architecture) {
case kCPUArchitectureX86:
return x86->esp;
case kCPUArchitectureX86_64:
return x86_64->rsp;
case kCPUArchitectureARM:
return arm->sp;
case kCPUArchitectureARM64:
return arm64->sp;
default:
NOTREACHED();
return ~0ull;
}
}
} // namespace crashpad
......@@ -316,6 +316,13 @@ struct CPUContext {
//! context structure.
uint64_t InstructionPointer() const;
//! \brief Returns the stack pointer value from the context structure.
//!
//! This is a CPU architecture-independent method that is capable of
//! recovering the stack pointer from any supported CPU architecture’s
//! context structure.
uint64_t StackPointer() const;
//! \brief The CPU architecture of a context structure. This field controls
//! the expression of the union.
CPUArchitecture architecture;
......
......@@ -101,7 +101,12 @@ void ProcessReaderLinux::Thread::InitializeStack(ProcessReaderLinux* reader) {
#else
#error Port.
#endif
InitializeStackFromSP(reader, stack_pointer);
}
void ProcessReaderLinux::Thread::InitializeStackFromSP(
ProcessReaderLinux* reader,
LinuxVMAddress stack_pointer) {
const MemoryMap* memory_map = reader->GetMemoryMap();
// If we can't find the mapping, it's probably a bad stack pointer
......@@ -267,6 +272,7 @@ const std::vector<ProcessReaderLinux::Module>& ProcessReaderLinux::Modules() {
void ProcessReaderLinux::InitializeThreads() {
DCHECK(threads_.empty());
initialized_threads_ = true;
pid_t pid = ProcessID();
if (pid == getpid()) {
......@@ -324,6 +330,7 @@ void ProcessReaderLinux::InitializeThreads() {
void ProcessReaderLinux::InitializeModules() {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
initialized_modules_ = true;
AuxiliaryVector aux;
if (!aux.Initialize(connection_)) {
......
......@@ -44,6 +44,20 @@ class ProcessReaderLinux {
Thread();
~Thread();
//! \brief Initializes the thread's stack using \a stack_pointer instead of
//! the stack pointer in \a thread_info.
//!
//! This method initializes \a stack_region_address and \a stack_region_size
//! overwriting any values they previously contained. This is useful, for
//! example, if the thread is currently in a signal handler context, which
//! may execute on a different stack than was used before the signal was
//! received.
//!
//! \param[in] reader A process reader for the target process.
//! \param[in] stack_pointer The stack pointer for the stack to initialize.
void InitializeStackFromSP(ProcessReaderLinux* reader,
LinuxVMAddress stack_pointer);
ThreadInfo thread_info;
LinuxVMAddress stack_region_address;
LinuxVMSize stack_region_size;
......
......@@ -69,7 +69,36 @@ bool ProcessSnapshotLinux::InitializeException(
return false;
}
return true;
// The thread's existing snapshot will have captured the stack for the signal
// handler. Replace it with a thread snapshot which captures the stack for the
// exception context.
for (const auto& reader_thread : process_reader_.Threads()) {
if (reader_thread.tid == info.thread_id) {
ProcessReaderLinux::Thread thread = reader_thread;
thread.InitializeStackFromSP(&process_reader_,
exception_->Context()->StackPointer());
auto exc_thread_snapshot =
std::make_unique<internal::ThreadSnapshotLinux>();
if (!exc_thread_snapshot->Initialize(&process_reader_, thread)) {
return false;
}
for (auto& thread_snapshot : threads_) {
if (thread_snapshot->ThreadID() ==
static_cast<uint64_t>(info.thread_id)) {
thread_snapshot.reset(exc_thread_snapshot.release());
return true;
}
}
LOG(ERROR) << "thread not found " << info.thread_id;
return false;
}
}
LOG(ERROR) << "thread not found " << info.thread_id;
return false;
}
void ProcessSnapshotLinux::GetCrashpadOptions(
......
......@@ -71,7 +71,18 @@ TEST(WorkerThread, DoWork) {
thread.Stop();
EXPECT_FALSE(thread.is_running());
EXPECT_GE(1 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);
// Fuchsia's scheduler is very antagonistic. The assumption that the two work
// items complete in some particular amount of time is strictly incorrect, but
// also somewhat useful. The expected time "should" be ~40-50ms with a work
// interval of 0.05s, but on Fuchsia, 1200ms was observed. So, on Fuchsia, use a
// much larger timeout. See https://crashpad.chromium.org/bug/231.
#if defined(OS_FUCHSIA)
constexpr uint64_t kUpperBoundTime = 10;
#else
constexpr uint64_t kUpperBoundTime = 1;
#endif
EXPECT_GE(kUpperBoundTime * kNanosecondsPerSecond,
ClockMonotonicNanoseconds() - start);
}
TEST(WorkerThread, StopBeforeDoWork) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment