Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: base/logging.h

Issue 2705053002: [Reland] base: make CHECK macros trap at distinct addresses in official builds (Closed)
Patch Set: rebase Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/logging_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_LOGGING_H_ 5 #ifndef BASE_LOGGING_H_
6 #define BASE_LOGGING_H_ 6 #define BASE_LOGGING_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <cassert> 10 #include <cassert>
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 CheckOpResult(std::string* message) : message_(message) {} 489 CheckOpResult(std::string* message) : message_(message) {}
490 // Returns true if the check succeeded. 490 // Returns true if the check succeeded.
491 operator bool() const { return !message_; } 491 operator bool() const { return !message_; }
492 // Returns the message. 492 // Returns the message.
493 std::string* message() { return message_; } 493 std::string* message() { return message_; }
494 494
495 private: 495 private:
496 std::string* message_; 496 std::string* message_;
497 }; 497 };
498 498
499 // Crashes in the fastest, simplest possible way with no attempt at logging. 499 // Crashes in the fastest possible way with no attempt at logging.
500 // There are different constraints to satisfy here, see http://crbug.com/664209
501 // for more context:
502 // - The trap instructions, and hence the PC value at crash time, have to be
503 // distinct and not get folded into the same opcode by the compiler.
504 // On Linux/Android this is tricky because GCC still folds identical
505 // asm volatile blocks. The workaround is generating distinct opcodes for
506 // each CHECK using the __COUNTER__ macro.
507 // - The debug info for the trap instruction has to be attributed to the source
508 // line that has the CHECK(), to make crash reports actionable. This rules
509 // out the ability of using a inline function, at least as long as clang
510 // doesn't support attribute(artificial).
511 // - Failed CHECKs should produce a signal that is distinguishable from an
512 // invalid memory access, to improve the actionability of crash reports.
513 // - The compiler should treat the CHECK as no-return instructions, so that the
514 // trap code can be efficiently packed in the prologue of the function and
515 // doesn't interfere with the main execution flow.
516 // - When debugging, developers shouldn't be able to accidentally step over a
517 // CHECK. This is achieved by putting opcodes that will cause a non
518 // continuable exception after the actual trap instruction.
519 // - Don't cause too much binary bloat.
500 #if defined(COMPILER_GCC) 520 #if defined(COMPILER_GCC)
501 #define IMMEDIATE_CRASH() __builtin_trap() 521
522 #if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_NACL)
523 // int 3 will generate a SIGTRAP.
524 #define TRAP_SEQUENCE() \
525 asm volatile( \
526 "int3; ud2; push %0;" ::"i"(static_cast<unsigned char>(__COUNTER__)))
527
528 #elif defined(ARCH_CPU_ARMEL) && !defined(OS_NACL)
529 // bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running
530 // as a 32 bit userspace app on arm64. There doesn't seem to be any way to
531 // cause a SIGTRAP from userspace without using a syscall (which would be a
532 // problem for sandboxing).
533 #define TRAP_SEQUENCE() \
534 asm volatile("bkpt #0; udf %0;" ::"i"(__COUNTER__ % 256))
535
536 #elif defined(ARCH_CPU_ARM64) && !defined(OS_NACL)
537 // This will always generate a SIGTRAP on arm64.
538 #define TRAP_SEQUENCE() \
539 asm volatile("brk #0; hlt %0;" ::"i"(__COUNTER__ % 65536))
540
541 #else
542 // Crash report accuracy will not be guaranteed on other architectures, but at
543 // least this will crash as expected.
544 #define TRAP_SEQUENCE() __builtin_trap()
545 #endif // ARCH_CPU_*
546
547 #define IMMEDIATE_CRASH() \
548 ({ \
549 TRAP_SEQUENCE(); \
550 __builtin_unreachable(); \
551 })
552
502 #elif defined(COMPILER_MSVC) 553 #elif defined(COMPILER_MSVC)
503 554
504 // Clang is cleverer about coalescing int3s, so we need to add a unique-ish 555 // Clang is cleverer about coalescing int3s, so we need to add a unique-ish
505 // instruction following the __debugbreak() to have it emit distinct locations 556 // instruction following the __debugbreak() to have it emit distinct locations
506 // for CHECKs rather than collapsing them all together. It would be nice to use 557 // for CHECKs rather than collapsing them all together. It would be nice to use
507 // a short intrinsic to do this (and perhaps have only one implementation for 558 // a short intrinsic to do this (and perhaps have only one implementation for
508 // both clang and MSVC), however clang-cl currently does not support intrinsics 559 // both clang and MSVC), however clang-cl currently does not support intrinsics
509 // here. Adding the nullptr store to the MSVC path adds unnecessary bloat. 560 // here. Adding the nullptr store to the MSVC path adds unnecessary bloat.
510 // TODO(scottmg): Reinvestigate a short sequence that will work on both 561 // TODO(scottmg): Reinvestigate a short sequence that will work on both
511 // compilers once clang supports more intrinsics. See https://crbug.com/693713. 562 // compilers once clang supports more intrinsics. See https://crbug.com/693713.
512 #if defined(__clang__) 563 #if defined(__clang__)
513 #define IMMEDIATE_CRASH() \ 564 #define IMMEDIATE_CRASH() \
514 (__debugbreak(), (void)(*reinterpret_cast<volatile unsigned char*>(0) = \ 565 (__debugbreak(), (void)(*reinterpret_cast<volatile unsigned char*>(0) = \
Mark Mentovai 2017/02/21 14:21:50 If Lexan supports GCC-style inline asm, we could u
Primiano Tucci (use gerrit) 2017/02/21 14:27:50 Yup, realized the same too late. I just left a com
515 static_cast<unsigned char>(__COUNTER__))) 566 static_cast<unsigned char>(__COUNTER__)))
516 #else 567 #else
517 #define IMMEDIATE_CRASH() __debugbreak() 568 #define IMMEDIATE_CRASH() __debugbreak()
518 #endif // __clang__ 569 #endif // __clang__
519 570
520 #else 571 #else
521 #error Port 572 #error Port
522 #endif 573 #endif
523 574
524 // CHECK dies with a fatal error if condition is not true. It is *not* 575 // CHECK dies with a fatal error if condition is not true. It is *not*
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 #elif NOTIMPLEMENTED_POLICY == 5 1124 #elif NOTIMPLEMENTED_POLICY == 5
1074 #define NOTIMPLEMENTED() do {\ 1125 #define NOTIMPLEMENTED() do {\
1075 static bool logged_once = false;\ 1126 static bool logged_once = false;\
1076 LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG;\ 1127 LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG;\
1077 logged_once = true;\ 1128 logged_once = true;\
1078 } while(0);\ 1129 } while(0);\
1079 EAT_STREAM_PARAMETERS 1130 EAT_STREAM_PARAMETERS
1080 #endif 1131 #endif
1081 1132
1082 #endif // BASE_LOGGING_H_ 1133 #endif // BASE_LOGGING_H_
OLDNEW
« no previous file with comments | « no previous file | base/logging_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698