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