blob: ade8d34ed60e9d49521a9d48cd44c38c29c4dfd6 [file] [log] [blame]
Elliott Hughes42ee1422011-09-06 12:33:32 -07001/*
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 */
Carl Shapiro6c21dc12011-06-20 15:20:52 -070016
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_BASE_LOGGING_H_
18#define ART_RUNTIME_BASE_LOGGING_H_
Carl Shapiro6c21dc12011-06-20 15:20:52 -070019
Elliott Hugheseb4f6142011-07-15 17:43:51 -070020#include <cerrno>
21#include <cstring>
Carl Shapiro6c21dc12011-06-20 15:20:52 -070022#include <iostream> // NOLINT
Elliott Hugheseb4f6142011-07-15 17:43:51 -070023#include <sstream>
Brian Carlstromaf1b8922012-11-27 15:19:57 -080024#include <signal.h>
Elliott Hughes76160052012-12-12 16:31:20 -080025#include "base/macros.h"
Elliott Hugheseb4f6142011-07-15 17:43:51 -070026#include "log_severity.h"
Sebastien Hertz916041f2013-08-05 16:17:42 +020027#include "UniquePtr.h"
Carl Shapiro6c21dc12011-06-20 15:20:52 -070028
29#define CHECK(x) \
Ian Rogerscaab8c42011-10-12 12:11:18 -070030 if (UNLIKELY(!(x))) \
Elliott Hughesf5a7a472011-10-07 14:31:02 -070031 ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
Elliott Hughes710a0cb2011-08-16 14:32:37 -070032 << "Check failed: " #x << " "
Elliott Hugheseb4f6142011-07-15 17:43:51 -070033
Elliott Hughes1f359b02011-07-17 14:27:17 -070034#define CHECK_OP(LHS, RHS, OP) \
Mathieu Chartier9b3c3cd2013-08-12 17:41:54 -070035 for (auto _values = ::art::MakeEagerEvaluator(LHS, RHS); \
Elliott Hughes362f9bc2011-10-17 18:56:41 -070036 UNLIKELY(!(_values.lhs OP _values.rhs)); /* empty */) \
Elliott Hughesf5a7a472011-10-07 14:31:02 -070037 ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \
38 << "Check failed: " << #LHS << " " << #OP << " " << #RHS \
39 << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") "
Elliott Hughes1f359b02011-07-17 14:27:17 -070040
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, >)
Elliott Hugheseb4f6142011-07-15 17:43:51 -070047
48#define CHECK_STROP(s1, s2, sense) \
Ian Rogerscaab8c42011-10-12 12:11:18 -070049 if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \
Elliott Hughesf5a7a472011-10-07 14:31:02 -070050 LOG(FATAL) << "Check failed: " \
51 << "\"" << s1 << "\"" \
52 << (sense ? " == " : " != ") \
53 << "\"" << s2 << "\""
Carl Shapiro6c21dc12011-06-20 15:20:52 -070054
Elliott Hughes1f359b02011-07-17 14:27:17 -070055#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true)
56#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false)
57
Elliott Hughes8d768a92011-09-14 16:35:25 -070058#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
Carl Shapiro6c21dc12011-06-20 15:20:52 -070067#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)
Elliott Hugheseb4f6142011-07-15 17:43:51 -070076#define DCHECK_STREQ(s1, s2) CHECK_STREQ(s1, s2)
77#define DCHECK_STRNE(s1, s2) CHECK_STRNE(s1, s2)
Carl Shapiro6c21dc12011-06-20 15:20:52 -070078
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
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700113#define DCHECK_STRNE(str1, str2) \
114 while (false) \
115 CHECK_STRNE(str1, str2)
116
Carl Shapiro6c21dc12011-06-20 15:20:52 -0700117#endif
118
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700119#define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream()
120#define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream()
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700121
Carl Shapiro6c21dc12011-06-20 15:20:52 -0700122#define LG LOG(INFO)
123
Elliott Hughes8d768a92011-09-14 16:35:25 -0700124#define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
Elliott Hughes53b61312011-08-12 18:28:20 -0700125
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800126#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
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700129//
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
Elliott Hughesaa6a5882012-01-13 19:39:16 -0800142// 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
Mathieu Chartier9b3c3cd2013-08-12 17:41:54 -0700168template <typename LHS, typename RHS>
169EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
170 return EagerEvaluator<LHS, RHS>(lhs, rhs);
171}
172
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700173// This indirection greatly reduces the stack impact of having
174// lots of checks/logging in a function.
175struct LogMessageData {
176 public:
Brian Carlstromaf1b8922012-11-27 15:19:57 -0800177 LogMessageData(const char* file, int line, LogSeverity severity, int error);
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700178 std::ostringstream buffer;
Ian Rogersc4ee12e2013-05-16 11:19:53 -0700179 const char* const file;
180 const int line_number;
181 const LogSeverity severity;
182 const int error;
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700183
184 private:
185 DISALLOW_COPY_AND_ASSIGN(LogMessageData);
186};
187
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700188class LogMessage {
189 public:
Brian Carlstromaf1b8922012-11-27 15:19:57 -0800190 LogMessage(const char* file, int line, LogSeverity severity, int error)
191 : data_(new LogMessageData(file, line, severity, error)) {
192 }
Sebastien Hertz74c07042013-05-17 14:04:12 +0200193
Ian Rogersb726dcb2012-09-05 08:57:23 -0700194 ~LogMessage() LOCKS_EXCLUDED(Locks::logging_lock_);
Sebastien Hertz74c07042013-05-17 14:04:12 +0200195
196 std::ostream& stream() {
197 return data_->buffer;
198 }
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700199
200 private:
Brian Carlstromaf1b8922012-11-27 15:19:57 -0800201 static void LogLine(const LogMessageData& data, const char*);
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700202
Sebastien Hertz916041f2013-08-05 16:17:42 +0200203 const UniquePtr<LogMessageData> data_;
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700204
Brian Carlstromaf1b8922012-11-27 15:19:57 -0800205 friend void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context);
Ian Rogersc4ee12e2013-05-16 11:19:53 -0700206 friend class Mutex;
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700207 DISALLOW_COPY_AND_ASSIGN(LogMessage);
208};
209
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700210// Prints a hex dump in this format:
211//
212// 01234560: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
213// 01234568: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
214class HexDump {
215 public:
216 HexDump(const void* address, size_t byte_count, bool show_actual_addresses = false);
217 void Dump(std::ostream& os) const;
218
219 private:
220 const void* address_;
221 size_t byte_count_;
222 bool show_actual_addresses_;
Elliott Hughes878820f2012-03-29 20:00:04 -0700223
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700224 DISALLOW_COPY_AND_ASSIGN(HexDump);
225};
226std::ostream& operator<<(std::ostream& os, const HexDump& rhs);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700227
Elliott Hughese0918552011-10-28 17:18:29 -0700228// A convenience to allow any class with a "Dump(std::ostream& os)" member function
229// but without an operator<< to be used as if it had an operator<<. Use like this:
230//
231// os << Dumpable<MyType>(my_type_instance);
232//
233template<typename T>
234class Dumpable {
235 public:
236 explicit Dumpable(T& value) : value_(value) {
237 }
238
239 void Dump(std::ostream& os) const {
240 value_.Dump(os);
241 }
242
243 private:
244 T& value_;
Shih-wei Liao24782c62012-01-08 12:46:11 -0800245
Elliott Hughese0918552011-10-28 17:18:29 -0700246 DISALLOW_COPY_AND_ASSIGN(Dumpable);
247};
248
249template<typename T>
250std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) {
251 rhs.Dump(os);
252 return os;
253}
254
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700255template<typename T>
256class MutatorLockedDumpable {
257 public:
258 explicit MutatorLockedDumpable(T& value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700259 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : value_(value) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700260 }
261
Ian Rogersb726dcb2012-09-05 08:57:23 -0700262 void Dump(std::ostream& os) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700263 value_.Dump(os);
264 }
265
266 private:
267 T& value_;
268
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700269 DISALLOW_COPY_AND_ASSIGN(MutatorLockedDumpable);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700270};
271
272template<typename T>
273std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700274// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) however annotalysis
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700275// currently fails for this.
276 NO_THREAD_SAFETY_ANALYSIS {
277 rhs.Dump(os);
278 return os;
279}
280
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700281// Helps you use operator<< in a const char*-like context such as our various 'F' methods with
282// format strings.
283template<typename T>
284class ToStr {
285 public:
Elliott Hughes74847412012-06-20 18:10:21 -0700286 explicit ToStr(const T& value) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700287 std::ostringstream os;
288 os << value;
289 s_ = os.str();
290 }
291
292 const char* c_str() const {
293 return s_.c_str();
294 }
295
296 const std::string& str() const {
297 return s_;
298 }
299
300 private:
301 std::string s_;
302 DISALLOW_COPY_AND_ASSIGN(ToStr);
303};
304
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800305// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
306// and the "-verbose:" command line argument.
307struct LogVerbosity {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700308 bool class_linker; // Enabled with "-verbose:class".
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800309 bool compiler;
310 bool heap;
311 bool gc;
312 bool jdwp;
313 bool jni;
314 bool monitor;
315 bool startup;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700316 bool third_party_jni; // Enabled with "-verbose:third-party-jni".
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800317 bool threads;
318};
319
320extern LogVerbosity gLogVerbosity;
Brian Carlstrom81b88712012-11-05 19:21:30 -0800321
322// Used on fatal exit. Prevents recursive aborts. Allows us to disable
323// some error checking to ensure fatal shutdown makes forward progress.
Ian Rogersf08e4732013-04-09 09:45:49 -0700324extern unsigned int gAborting;
Brian Carlstrom81b88712012-11-05 19:21:30 -0800325
Elliott Hughes0d39c122012-06-06 16:41:17 -0700326extern void InitLogging(char* argv[]);
327
328extern const char* GetCmdLine();
329extern const char* ProgramInvocationName();
330extern const char* ProgramInvocationShortName();
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800331
Elliott Hughes3ea7e992011-10-11 18:48:16 -0700332} // namespace art
333
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700334#endif // ART_RUNTIME_BASE_LOGGING_H_