Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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_ |
| OLD | NEW |