logging.h revision 916041f1ea33f5cb9de869d28dcdfaa390095c32
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 (::art::EagerEvaluator<typeof(LHS), typeof(RHS)> _values(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 129// 130// Implementation details beyond this point. 131// 132 133namespace art { 134 135template <typename LHS, typename RHS> 136struct EagerEvaluator { 137 EagerEvaluator(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) { } 138 LHS lhs; 139 RHS rhs; 140}; 141 142// We want char*s to be treated as pointers, not strings. If you want them treated like strings, 143// you'd need to use CHECK_STREQ and CHECK_STRNE anyway to compare the characters rather than their 144// addresses. We could express this more succinctly with std::remove_const, but this is quick and 145// easy to understand, and works before we have C++0x. We rely on signed/unsigned warnings to 146// protect you against combinations not explicitly listed below. 147#define EAGER_PTR_EVALUATOR(T1, T2) \ 148 template <> struct EagerEvaluator<T1, T2> { \ 149 EagerEvaluator(T1 lhs, T2 rhs) \ 150 : lhs(reinterpret_cast<const void*>(lhs)), \ 151 rhs(reinterpret_cast<const void*>(rhs)) { } \ 152 const void* lhs; \ 153 const void* rhs; \ 154 } 155EAGER_PTR_EVALUATOR(const char*, const char*); 156EAGER_PTR_EVALUATOR(const char*, char*); 157EAGER_PTR_EVALUATOR(char*, const char*); 158EAGER_PTR_EVALUATOR(char*, char*); 159EAGER_PTR_EVALUATOR(const unsigned char*, const unsigned char*); 160EAGER_PTR_EVALUATOR(const unsigned char*, unsigned char*); 161EAGER_PTR_EVALUATOR(unsigned char*, const unsigned char*); 162EAGER_PTR_EVALUATOR(unsigned char*, unsigned char*); 163EAGER_PTR_EVALUATOR(const signed char*, const signed char*); 164EAGER_PTR_EVALUATOR(const signed char*, signed char*); 165EAGER_PTR_EVALUATOR(signed char*, const signed char*); 166EAGER_PTR_EVALUATOR(signed char*, signed char*); 167 168// This indirection greatly reduces the stack impact of having 169// lots of checks/logging in a function. 170struct LogMessageData { 171 public: 172 LogMessageData(const char* file, int line, LogSeverity severity, int error); 173 std::ostringstream buffer; 174 const char* const file; 175 const int line_number; 176 const LogSeverity severity; 177 const int error; 178 179 private: 180 DISALLOW_COPY_AND_ASSIGN(LogMessageData); 181}; 182 183class LogMessage { 184 public: 185 LogMessage(const char* file, int line, LogSeverity severity, int error) 186 : data_(new LogMessageData(file, line, severity, error)) { 187 } 188 189 ~LogMessage() LOCKS_EXCLUDED(Locks::logging_lock_); 190 191 std::ostream& stream() { 192 return data_->buffer; 193 } 194 195 private: 196 static void LogLine(const LogMessageData& data, const char*); 197 198 const UniquePtr<LogMessageData> data_; 199 200 friend void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context); 201 friend class Mutex; 202 DISALLOW_COPY_AND_ASSIGN(LogMessage); 203}; 204 205// Prints a hex dump in this format: 206// 207// 01234560: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef 208// 01234568: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef 209class HexDump { 210 public: 211 HexDump(const void* address, size_t byte_count, bool show_actual_addresses = false); 212 void Dump(std::ostream& os) const; 213 214 private: 215 const void* address_; 216 size_t byte_count_; 217 bool show_actual_addresses_; 218 219 DISALLOW_COPY_AND_ASSIGN(HexDump); 220}; 221std::ostream& operator<<(std::ostream& os, const HexDump& rhs); 222 223// A convenience to allow any class with a "Dump(std::ostream& os)" member function 224// but without an operator<< to be used as if it had an operator<<. Use like this: 225// 226// os << Dumpable<MyType>(my_type_instance); 227// 228template<typename T> 229class Dumpable { 230 public: 231 explicit Dumpable(T& value) : value_(value) { 232 } 233 234 void Dump(std::ostream& os) const { 235 value_.Dump(os); 236 } 237 238 private: 239 T& value_; 240 241 DISALLOW_COPY_AND_ASSIGN(Dumpable); 242}; 243 244template<typename T> 245std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) { 246 rhs.Dump(os); 247 return os; 248} 249 250template<typename T> 251class MutatorLockedDumpable { 252 public: 253 explicit MutatorLockedDumpable(T& value) 254 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : value_(value) { 255 } 256 257 void Dump(std::ostream& os) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 258 value_.Dump(os); 259 } 260 261 private: 262 T& value_; 263 264 DISALLOW_COPY_AND_ASSIGN(MutatorLockedDumpable); 265}; 266 267template<typename T> 268std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs) 269// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) however annotalysis 270// currently fails for this. 271 NO_THREAD_SAFETY_ANALYSIS { 272 rhs.Dump(os); 273 return os; 274} 275 276// Helps you use operator<< in a const char*-like context such as our various 'F' methods with 277// format strings. 278template<typename T> 279class ToStr { 280 public: 281 explicit ToStr(const T& value) { 282 std::ostringstream os; 283 os << value; 284 s_ = os.str(); 285 } 286 287 const char* c_str() const { 288 return s_.c_str(); 289 } 290 291 const std::string& str() const { 292 return s_; 293 } 294 295 private: 296 std::string s_; 297 DISALLOW_COPY_AND_ASSIGN(ToStr); 298}; 299 300// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code, 301// and the "-verbose:" command line argument. 302struct LogVerbosity { 303 bool class_linker; // Enabled with "-verbose:class". 304 bool compiler; 305 bool heap; 306 bool gc; 307 bool jdwp; 308 bool jni; 309 bool monitor; 310 bool startup; 311 bool third_party_jni; // Enabled with "-verbose:third-party-jni". 312 bool threads; 313}; 314 315extern LogVerbosity gLogVerbosity; 316 317// Used on fatal exit. Prevents recursive aborts. Allows us to disable 318// some error checking to ensure fatal shutdown makes forward progress. 319extern unsigned int gAborting; 320 321extern void InitLogging(char* argv[]); 322 323extern const char* GetCmdLine(); 324extern const char* ProgramInvocationName(); 325extern const char* ProgramInvocationShortName(); 326 327} // namespace art 328 329#endif // ART_RUNTIME_BASE_LOGGING_H_ 330