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