Index: base/logging.h |
diff --git a/base/logging.h b/base/logging.h |
index 6f30bcbe4f736f989bad178ac3d96ed70bf08943..7df12de24dcb2ca05546511da7deb3f1cf1b4618 100644 |
--- a/base/logging.h |
+++ b/base/logging.h |
@@ -496,9 +496,59 @@ class CheckOpResult { |
std::string* message_; |
}; |
-// Crashes in the fastest, simplest possible way with no attempt at logging. |
+// Crashes in the fastest possible way with no attempt at logging. |
+// There are different constraints to satisfy here, see http://crbug.com/664209 |
+// for more context: |
+// - The trap instructions, and hence the PC value at crash time, have to be |
+// distinct and not get folded into the same opcode by the compiler. |
+// On Linux/Android this is tricky because GCC still folds identical |
+// asm volatile blocks. The workaround is generating distinct opcodes for |
+// each CHECK using the __COUNTER__ macro. |
+// - The debug info for the trap instruction has to be attributed to the source |
+// line that has the CHECK(), to make crash reports actionable. This rules |
+// out the ability of using a inline function, at least as long as clang |
+// doesn't support attribute(artificial). |
+// - Failed CHECKs should produce a signal that is distinguishable from an |
+// invalid memory access, to improve the actionability of crash reports. |
+// - 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. |
+// - When debugging, developers shouldn't be able to accidentally step over a |
+// CHECK. This is achieved by putting opcodes that will cause a non |
+// continuable exception after the actual trap instruction. |
+// - Don't cause too much binary bloat. |
#if defined(COMPILER_GCC) |
-#define IMMEDIATE_CRASH() __builtin_trap() |
+ |
+#if defined(ARCH_CPU_X86_FAMILY) |
+// int 3 will generate a SIGTRAP. |
+#define TRAP_SEQUENCE() \ |
+ asm volatile("int3; ud2; push %0;" ::"i"((uint8_t)__COUNTER__)) |
Mark Mentovai
2017/02/17 15:04:33
I suggested a fundamental type because this header
Primiano Tucci (use gerrit)
2017/02/17 15:08:47
Ah right. fixed both the cast and switched to unsi
|
+ |
+#elif defined(ARCH_CPU_ARMEL) |
+// bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running |
+// as a 32 bit userspace app on arm64. There doesn't seem to be any way to |
+// cause a SIGTRAP from userspace without using a syscall (which would be a |
+// problem for sandboxing). |
+#define TRAP_SEQUENCE() \ |
+ asm volatile("bkpt #0; udf %0;" ::"i"(__COUNTER__ % 256)) |
+ |
+#elif defined(ARCH_CPU_ARM64) |
+ |
+// This will always generate a SIGTRAP on arm64. |
+#define TRAP_SEQUENCE() \ |
+ asm volatile("brk #0; hlt %0;" ::"i"(__COUNTER__ % 65536)) |
+#else |
+// Crash report accuracy will not be guaranteed on other architectures, but at |
+// least this will crash as expected. |
+#define TRAP_SEQUENCE() __builtin_trap() |
+#endif |
+ |
+#define IMMEDIATE_CRASH() \ |
+ ({ \ |
+ TRAP_SEQUENCE(); \ |
+ __builtin_unreachable(); \ |
+ }) |
+ |
#elif defined(COMPILER_MSVC) |
#define IMMEDIATE_CRASH() __debugbreak() |
#else |