Commit 5ff4f2c0 authored by Siddhartha's avatar Siddhartha Committed by Commit Bot

Android: Record metrics to understand why unwinding fails

TBR=wittman@chromium.org
BUG=859260

Change-Id: Ife938d536ca036364b20464055479e949813c75b
Reviewed-on: https://chromium-review.googlesource.com/1228785
Commit-Queue: Siddhartha S <ssid@chromium.org>
Reviewed-by: default avatarSteven Holte <holte@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593409}
parent 44728781
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/debug/proc_maps_linux.h" #include "base/debug/proc_maps_linux.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/cfi_backtrace_android.h" #include "base/trace_event/cfi_backtrace_android.h"
#include "libunwind.h" #include "libunwind.h"
...@@ -24,6 +25,22 @@ using base::debug::MappedMemoryRegion; ...@@ -24,6 +25,22 @@ using base::debug::MappedMemoryRegion;
namespace { namespace {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class SamplingProfilerUnwindResult {
kFutexSignalFailed = 0,
kStackCopyFailed = 1,
kUnwindInitFailed = 2,
kHandlerUnwindFailed = 3,
kFirstFrameUnmapped = 4,
kMaxValue = kFirstFrameUnmapped,
};
void RecordUnwindResult(SamplingProfilerUnwindResult result) {
UMA_HISTOGRAM_ENUMERATION("BackgroundTracing.SamplingProfilerUnwindResult",
result);
}
// Waitable event implementation with futex and without DCHECK(s), since signal // Waitable event implementation with futex and without DCHECK(s), since signal
// handlers cannot allocate memory or use pthread api. // handlers cannot allocate memory or use pthread api.
class AsyncSafeWaitableEvent { class AsyncSafeWaitableEvent {
...@@ -102,6 +119,8 @@ size_t TraceStackWithContext(unw_cursor_t* cursor, ...@@ -102,6 +119,8 @@ size_t TraceStackWithContext(unw_cursor_t* cursor,
// library. // library.
return depth + return depth +
cfi_unwinder->Unwind(ip, sp, out_trace + depth, max_depth - depth); cfi_unwinder->Unwind(ip, sp, out_trace + depth, max_depth - depth);
} else if (depth == 0) {
RecordUnwindResult(SamplingProfilerUnwindResult::kFirstFrameUnmapped);
} }
return depth; return depth;
} }
...@@ -281,13 +300,16 @@ size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid, ...@@ -281,13 +300,16 @@ size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid,
bool changed = sigaction(SIGURG, &oact, &act) == 0; bool changed = sigaction(SIGURG, &oact, &act) == 0;
DCHECK(changed); DCHECK(changed);
if (!finished_waiting) { if (!finished_waiting) {
RecordUnwindResult(SamplingProfilerUnwindResult::kFutexSignalFailed);
NOTREACHED(); NOTREACHED();
return 0; return 0;
} }
} }
base::subtle::Release_Store(&g_handler_params, 0); base::subtle::Release_Store(&g_handler_params, 0);
if (!copied) if (!copied) {
RecordUnwindResult(SamplingProfilerUnwindResult::kStackCopyFailed);
return 0; return 0;
}
// Context contains list of saved registers. Replace the SP to the copied // Context contains list of saved registers. Replace the SP to the copied
// stack. The SP should be one of the first 16 registers. // stack. The SP should be one of the first 16 registers.
...@@ -304,8 +326,10 @@ size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid, ...@@ -304,8 +326,10 @@ size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid,
// Initialize an unwind cursor on copied stack. // Initialize an unwind cursor on copied stack.
unw_cursor_t cursor; unw_cursor_t cursor;
if (unw_init_local(&cursor, &context) != 0) if (unw_init_local(&cursor, &context) != 0) {
RecordUnwindResult(SamplingProfilerUnwindResult::kUnwindInitFailed);
return 0; return 0;
}
uintptr_t ip = 0; uintptr_t ip = 0;
unw_get_reg(&cursor, UNW_REG_SP, &sp); unw_get_reg(&cursor, UNW_REG_SP, &sp);
DCHECK_EQ(sp, reinterpret_cast<uintptr_t>(stack_copy_buffer.get())); DCHECK_EQ(sp, reinterpret_cast<uintptr_t>(stack_copy_buffer.get()));
...@@ -317,8 +341,10 @@ size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid, ...@@ -317,8 +341,10 @@ size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid,
auto* cfi_unwinder = CFIBacktraceAndroid::GetInitializedInstance(); auto* cfi_unwinder = CFIBacktraceAndroid::GetInitializedInstance();
static CFIBacktraceAndroid::CFIRow cfi; static CFIBacktraceAndroid::CFIRow cfi;
static bool found = GetCFIForPC(cfi_unwinder, ip, &cfi); static bool found = GetCFIForPC(cfi_unwinder, ip, &cfi);
if (!found) if (!found) {
RecordUnwindResult(SamplingProfilerUnwindResult::kHandlerUnwindFailed);
return 0; return 0;
}
sp = sp + cfi.cfa_offset; sp = sp + cfi.cfa_offset;
memcpy(&ip, reinterpret_cast<uintptr_t*>(sp - cfi.ra_offset), memcpy(&ip, reinterpret_cast<uintptr_t*>(sp - cfi.ra_offset),
sizeof(uintptr_t)); sizeof(uintptr_t));
......
...@@ -43002,6 +43002,15 @@ Called by update_net_trust_anchors.py.--> ...@@ -43002,6 +43002,15 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="NOT_SUPPORTED"/> <int value="4" label="NOT_SUPPORTED"/>
</enum> </enum>
<enum name="SamplingProfilerUnwindResult">
<summary>Track reason for unwind failures in sampling profiler.</summary>
<int value="0" label="Futex wait for signal handler failed."/>
<int value="1" label="Stack segment was not found or too large to copy."/>
<int value="2" label="Unwind initialization failed."/>
<int value="3" label="Unwind info for signal handler missing."/>
<int value="4" label="First frame of stack isn't mapped."/>
</enum>
<enum name="SavePasswordPromptResponseType"> <enum name="SavePasswordPromptResponseType">
<int value="0" label="NO_RESPONSE"/> <int value="0" label="NO_RESPONSE"/>
<int value="1" label="REMEMBER_PASSWORD"/> <int value="1" label="REMEMBER_PASSWORD"/>
...@@ -8169,6 +8169,12 @@ uploading your change for review. ...@@ -8169,6 +8169,12 @@ uploading your change for review.
</summary> </summary>
</histogram> </histogram>
<histogram name="BackgroundTracing.SamplingProfilerUnwindResult"
enum="SamplingProfilerUnwindResult" expires_after="M71">
<owner>ssid@chromium.org</owner>
<summary>Records the reason for unwind failues in sampling profiler.</summary>
</histogram>
<histogram name="BatteryStatus.NumberBatteriesLinux" <histogram name="BatteryStatus.NumberBatteriesLinux"
enum="BatteryStatusNumberBatteries"> enum="BatteryStatusNumberBatteries">
<owner>timvolodine@chromium.org</owner> <owner>timvolodine@chromium.org</owner>
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