Index: base/logging.h |
diff --git a/base/logging.h b/base/logging.h |
index 5174e6d375540cd0f0bf355034c17812a66bf37b..986eeba88b80261118807ef4d1ff8beb574a22f6 100644 |
--- a/base/logging.h |
+++ b/base/logging.h |
@@ -462,8 +462,47 @@ class CheckOpResult { |
// Crashes in the fastest, simplest possible way with no attempt at logging. |
#if defined(COMPILER_GCC) || defined(__clang__) |
-#define IMMEDIATE_CRASH() __builtin_trap() |
+ |
+// This is to make sure that the crash report can pinpoint to the right source |
+// line even in presence of multiple CHECK()s in the same function. See |
+// http://crbug.com/664209 for more context. |
+// There are three things we need to guarantee here: |
+// - The trap instructions, and hence the PC value at crash time, are distinct |
+// and don't get collapsed into the same op due to compiler optimizations. |
+// - The debug line info for the trap instructions get attributed to the caller |
+// of CHECK(), to make sure that crash reports show actionable data. This in |
+// practice rules out the ability of using a inline function, at least as |
+// long as clang doesn't support attribute(artificial). |
+// - The compiler should treat the CHECK as no-return instructions, so that the |
+// trap code can be efficiently packed in the prologue of the function and |
+// doesn't interfere with the main execution flow. |
+// Code-wise: |
+// - asm volatile seems to be enough to make the compiler emit distinct |
+// instructions for each CHECK() and not fold them together. |
+// - the actual instructions (e.g., "ud2") are borrowed from implementation of |
+// __builtin_trap() in the various toolchain. |
+// either a SIGTRAP or a SIGABRT depending on the platform. |
Mark Mentovai
2017/02/13 16:22:09
On x86 and x86_64, ud2 will be SIGILL. That’s good
|
+// - __builtin_unreachable() enables no-return optimizations. |
+ |
+#if defined(ARCH_CPU_X86_FAMILY) |
+#define TRAP_INSTRUCTION() asm volatile("ud2" ::: "memory") |
+#elif defined(ARCH_CPU_ARMEL) |
+#define TRAP_INSTRUCTION() asm volatile("udf $0xff" ::: "memory") |
+#elif defined(ARCH_CPU_ARM64) |
+#define TRAP_INSTRUCTION() asm volatile("brk #0x3e8" ::: "memory") |
#else |
+// Crash report accuracy will not be guaranteed on other architectures, but at |
+// least this will crash as expected. |
+#define TRAP_INSTRUCTION() __builtin_trap() |
+#endif |
+ |
+#define IMMEDIATE_CRASH() \ |
+ ({ \ |
+ TRAP_INSTRUCTION(); \ |
+ __builtin_unreachable(); \ |
+ }) |
+ |
+#else // defined(COMPILER_GCC) || defined(__clang__) |
#define IMMEDIATE_CRASH() ((void)(*(volatile char*)0 = 0)) |
#endif |