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