Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_BASE_LOGGING_H_
     18 #define ART_RUNTIME_BASE_LOGGING_H_
     19 
     20 #include <cerrno>
     21 #include <cstring>
     22 #include <iostream>  // NOLINT
     23 #include <sstream>
     24 #include <signal.h>
     25 #include "base/macros.h"
     26 #include "log_severity.h"
     27 #include "UniquePtr.h"
     28 
     29 #define CHECK(x) \
     30   if (UNLIKELY(!(x))) \
     31     ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
     32         << "Check failed: " #x << " "
     33 
     34 #define CHECK_OP(LHS, RHS, OP) \
     35   for (auto _values = ::art::MakeEagerEvaluator(LHS, RHS); \
     36        UNLIKELY(!(_values.lhs OP _values.rhs)); /* empty */) \
     37     ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
     38         << "Check failed: " << #LHS << " " << #OP << " " << #RHS \
     39         << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") "
     40 
     41 #define CHECK_EQ(x, y) CHECK_OP(x, y, ==)
     42 #define CHECK_NE(x, y) CHECK_OP(x, y, !=)
     43 #define CHECK_LE(x, y) CHECK_OP(x, y, <=)
     44 #define CHECK_LT(x, y) CHECK_OP(x, y, <)
     45 #define CHECK_GE(x, y) CHECK_OP(x, y, >=)
     46 #define CHECK_GT(x, y) CHECK_OP(x, y, >)
     47 
     48 #define CHECK_STROP(s1, s2, sense) \
     49   if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \
     50     LOG(FATAL) << "Check failed: " \
     51                << "\"" << s1 << "\"" \
     52                << (sense ? " == " : " != ") \
     53                << "\"" << s2 << "\""
     54 
     55 #define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
     56 #define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)
     57 
     58 #define CHECK_PTHREAD_CALL(call, args, what) \
     59   do { \
     60     int rc = call args; \
     61     if (rc != 0) { \
     62       errno = rc; \
     63       PLOG(FATAL) << # call << " failed for " << what; \
     64     } \
     65   } while (false)
     66 
     67 #ifndef NDEBUG
     68 
     69 #define DCHECK(x) CHECK(x)
     70 #define DCHECK_EQ(x, y) CHECK_EQ(x, y)
     71 #define DCHECK_NE(x, y) CHECK_NE(x, y)
     72 #define DCHECK_LE(x, y) CHECK_LE(x, y)
     73 #define DCHECK_LT(x, y) CHECK_LT(x, y)
     74 #define DCHECK_GE(x, y) CHECK_GE(x, y)
     75 #define DCHECK_GT(x, y) CHECK_GT(x, y)
     76 #define DCHECK_STREQ(s1, s2) CHECK_STREQ(s1, s2)
     77 #define DCHECK_STRNE(s1, s2) CHECK_STRNE(s1, s2)
     78 
     79 #else  // NDEBUG
     80 
     81 #define DCHECK(condition) \
     82   while (false) \
     83     CHECK(condition)
     84 
     85 #define DCHECK_EQ(val1, val2) \
     86   while (false) \
     87     CHECK_EQ(val1, val2)
     88 
     89 #define DCHECK_NE(val1, val2) \
     90   while (false) \
     91     CHECK_NE(val1, val2)
     92 
     93 #define DCHECK_LE(val1, val2) \
     94   while (false) \
     95     CHECK_LE(val1, val2)
     96 
     97 #define DCHECK_LT(val1, val2) \
     98   while (false) \
     99     CHECK_LT(val1, val2)
    100 
    101 #define DCHECK_GE(val1, val2) \
    102   while (false) \
    103     CHECK_GE(val1, val2)
    104 
    105 #define DCHECK_GT(val1, val2) \
    106   while (false) \
    107     CHECK_GT(val1, val2)
    108 
    109 #define DCHECK_STREQ(str1, str2) \
    110   while (false) \
    111     CHECK_STREQ(str1, str2)
    112 
    113 #define DCHECK_STRNE(str1, str2) \
    114   while (false) \
    115     CHECK_STRNE(str1, str2)
    116 
    117 #endif
    118 
    119 #define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream()
    120 #define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream()
    121 
    122 #define LG LOG(INFO)
    123 
    124 #define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
    125 
    126 #define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module)
    127 #define VLOG(module) if (VLOG_IS_ON(module)) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
    128 #define VLOG_STREAM(module) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream()
    129 
    130 //
    131 // Implementation details beyond this point.
    132 //
    133 
    134 namespace art {
    135 
    136 template <typename LHS, typename RHS>
    137 struct EagerEvaluator {
    138   EagerEvaluator(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) { }
    139   LHS lhs;
    140   RHS rhs;
    141 };
    142 
    143 // We want char*s to be treated as pointers, not strings. If you want them treated like strings,
    144 // you'd need to use CHECK_STREQ and CHECK_STRNE anyway to compare the characters rather than their
    145 // addresses. We could express this more succinctly with std::remove_const, but this is quick and
    146 // easy to understand, and works before we have C++0x. We rely on signed/unsigned warnings to
    147 // protect you against combinations not explicitly listed below.
    148 #define EAGER_PTR_EVALUATOR(T1, T2) \
    149   template <> struct EagerEvaluator<T1, T2> { \
    150     EagerEvaluator(T1 lhs, T2 rhs) \
    151         : lhs(reinterpret_cast<const void*>(lhs)), \
    152           rhs(reinterpret_cast<const void*>(rhs)) { } \
    153     const void* lhs; \
    154     const void* rhs; \
    155   }
    156 EAGER_PTR_EVALUATOR(const char*, const char*);
    157 EAGER_PTR_EVALUATOR(const char*, char*);
    158 EAGER_PTR_EVALUATOR(char*, const char*);
    159 EAGER_PTR_EVALUATOR(char*, char*);
    160 EAGER_PTR_EVALUATOR(const unsigned char*, const unsigned char*);
    161 EAGER_PTR_EVALUATOR(const unsigned char*, unsigned char*);
    162 EAGER_PTR_EVALUATOR(unsigned char*, const unsigned char*);
    163 EAGER_PTR_EVALUATOR(unsigned char*, unsigned char*);
    164 EAGER_PTR_EVALUATOR(const signed char*, const signed char*);
    165 EAGER_PTR_EVALUATOR(const signed char*, signed char*);
    166 EAGER_PTR_EVALUATOR(signed char*, const signed char*);
    167 EAGER_PTR_EVALUATOR(signed char*, signed char*);
    168 
    169 template <typename LHS, typename RHS>
    170 EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
    171   return EagerEvaluator<LHS, RHS>(lhs, rhs);
    172 }
    173 
    174 // This indirection greatly reduces the stack impact of having
    175 // lots of checks/logging in a function.
    176 struct LogMessageData {
    177  public:
    178   LogMessageData(const char* file, int line, LogSeverity severity, int error);
    179   std::ostringstream buffer;
    180   const char* const file;
    181   const int line_number;
    182   const LogSeverity severity;
    183   const int error;
    184 
    185  private:
    186   DISALLOW_COPY_AND_ASSIGN(LogMessageData);
    187 };
    188 
    189 class LogMessage {
    190  public:
    191   LogMessage(const char* file, int line, LogSeverity severity, int error)
    192     : data_(new LogMessageData(file, line, severity, error)) {
    193   }
    194 
    195   ~LogMessage() LOCKS_EXCLUDED(Locks::logging_lock_);
    196 
    197   std::ostream& stream() {
    198     return data_->buffer;
    199   }
    200 
    201  private:
    202   static void LogLine(const LogMessageData& data, const char*);
    203 
    204   const UniquePtr<LogMessageData> data_;
    205 
    206   friend void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context);
    207   friend class Mutex;
    208   DISALLOW_COPY_AND_ASSIGN(LogMessage);
    209 };
    210 
    211 // Prints a hex dump in this format:
    212 //
    213 // 01234560: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff  0123456789abcdef
    214 // 01234568: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff  0123456789abcdef
    215 class HexDump {
    216  public:
    217   HexDump(const void* address, size_t byte_count, bool show_actual_addresses = false);
    218   void Dump(std::ostream& os) const;
    219 
    220  private:
    221   const void* address_;
    222   size_t byte_count_;
    223   bool show_actual_addresses_;
    224 
    225   DISALLOW_COPY_AND_ASSIGN(HexDump);
    226 };
    227 std::ostream& operator<<(std::ostream& os, const HexDump& rhs);
    228 
    229 // A convenience to allow any class with a "Dump(std::ostream& os)" member function
    230 // but without an operator<< to be used as if it had an operator<<. Use like this:
    231 //
    232 //   os << Dumpable<MyType>(my_type_instance);
    233 //
    234 template<typename T>
    235 class Dumpable {
    236  public:
    237   explicit Dumpable(T& value) : value_(value) {
    238   }
    239 
    240   void Dump(std::ostream& os) const {
    241     value_.Dump(os);
    242   }
    243 
    244  private:
    245   T& value_;
    246 
    247   DISALLOW_COPY_AND_ASSIGN(Dumpable);
    248 };
    249 
    250 template<typename T>
    251 std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) {
    252   rhs.Dump(os);
    253   return os;
    254 }
    255 
    256 template<typename T>
    257 class MutatorLockedDumpable {
    258  public:
    259   explicit MutatorLockedDumpable(T& value)
    260       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : value_(value) {
    261   }
    262 
    263   void Dump(std::ostream& os) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    264     value_.Dump(os);
    265   }
    266 
    267  private:
    268   T& value_;
    269 
    270   DISALLOW_COPY_AND_ASSIGN(MutatorLockedDumpable);
    271 };
    272 
    273 template<typename T>
    274 std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs)
    275 // TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) however annotalysis
    276 //       currently fails for this.
    277     NO_THREAD_SAFETY_ANALYSIS {
    278   rhs.Dump(os);
    279   return os;
    280 }
    281 
    282 // Helps you use operator<< in a const char*-like context such as our various 'F' methods with
    283 // format strings.
    284 template<typename T>
    285 class ToStr {
    286  public:
    287   explicit ToStr(const T& value) {
    288     std::ostringstream os;
    289     os << value;
    290     s_ = os.str();
    291   }
    292 
    293   const char* c_str() const {
    294     return s_.c_str();
    295   }
    296 
    297   const std::string& str() const {
    298     return s_;
    299   }
    300 
    301  private:
    302   std::string s_;
    303   DISALLOW_COPY_AND_ASSIGN(ToStr);
    304 };
    305 
    306 // The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
    307 // and the "-verbose:" command line argument.
    308 struct LogVerbosity {
    309   bool class_linker;  // Enabled with "-verbose:class".
    310   bool verifier;
    311   bool compiler;
    312   bool heap;
    313   bool gc;
    314   bool jdwp;
    315   bool jni;
    316   bool monitor;
    317   bool startup;
    318   bool third_party_jni;  // Enabled with "-verbose:third-party-jni".
    319   bool threads;
    320 };
    321 
    322 extern LogVerbosity gLogVerbosity;
    323 
    324 // Used on fatal exit. Prevents recursive aborts. Allows us to disable
    325 // some error checking to ensure fatal shutdown makes forward progress.
    326 extern unsigned int gAborting;
    327 
    328 extern void InitLogging(char* argv[]);
    329 
    330 extern const char* GetCmdLine();
    331 extern const char* ProgramInvocationName();
    332 extern const char* ProgramInvocationShortName();
    333 
    334 }  // namespace art
    335 
    336 #endif  // ART_RUNTIME_BASE_LOGGING_H_
    337