blob: 7d176a2e5492fa3d58bcbb51a22c0adeaa63996f [file] [log] [blame]
Elliott Hughes13f5a582011-09-06 13:39:14 -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 */
16
17#include "logging.h"
18
19#include "runtime.h"
Elliott Hughes5fe594f2011-09-08 12:33:17 -070020#include "thread.h"
Elliott Hughes13f5a582011-09-06 13:39:14 -070021#include "utils.h"
22
Elliott Hughesf5a7a472011-10-07 14:31:02 -070023namespace art {
Elliott Hughes5fe594f2011-09-08 12:33:17 -070024
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -080025LogVerbosity gLogVerbosity;
26
Elliott Hughes72395bf2012-04-24 13:45:26 -070027static bool gInitLoggingCalled = false;
28static LogSeverity gMinimumLogSeverity = INFO;
29
Elliott Hughesb3bd5f02012-03-08 21:05:27 -080030static Mutex& GetLoggingLock() {
31 static Mutex logging_lock("LogMessage lock");
32 return logging_lock;
Elliott Hughes5fe594f2011-09-08 12:33:17 -070033}
34
Elliott Hughes72395bf2012-04-24 13:45:26 -070035// Configure logging based on ANDROID_LOG_TAGS environment variable.
36// We need to parse a string that looks like
37//
38// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
39//
40// The tag (or '*' for the global level) comes first, followed by a colon
41// and a letter indicating the minimum priority level we're expected to log.
42// This can be used to reveal or conceal logs with specific tags.
43void InitLogging() {
44 gInitLoggingCalled = true;
45 const char* tags = getenv("ANDROID_LOG_TAGS");
46 if (tags == NULL) {
47 return;
48 }
49
50 std::vector<std::string> specs;
51 Split(tags, ' ', specs);
52 for (size_t i = 0; i < specs.size(); ++i) {
53 // "tag-pattern:[vdiwefs]"
54 std::string spec(specs[i]);
55 if (spec.size() == 3 && StartsWith(spec, "*:")) {
56 switch (spec[2]) {
57 case 'v': gMinimumLogSeverity = VERBOSE; continue;
58 case 'd': gMinimumLogSeverity = DEBUG; continue;
59 case 'i': gMinimumLogSeverity = INFO; continue;
60 case 'w': gMinimumLogSeverity = WARNING; continue;
61 case 'e': gMinimumLogSeverity = ERROR; continue;
62 case 'f': gMinimumLogSeverity = FATAL; continue;
63 // liblog will even suppress FATAL if you say 's' for silent, but that's crazy!
64 case 's': gMinimumLogSeverity = FATAL; continue;
65 }
66 }
67 LOG(FATAL) << "unsupported '" << spec << "' in ANDROID_LOG_TAGS (" << tags << ")";
68 }
69}
70
Elliott Hughes13f5a582011-09-06 13:39:14 -070071LogMessage::~LogMessage() {
Elliott Hughes72395bf2012-04-24 13:45:26 -070072 if (data_->severity < gMinimumLogSeverity) {
73 return; // No need to format something we're not going to output.
74 }
75
Elliott Hughes5fe594f2011-09-08 12:33:17 -070076 // Finish constructing the message.
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070077 if (data_->error != -1) {
78 data_->buffer << ": " << strerror(data_->error);
Elliott Hughes13f5a582011-09-06 13:39:14 -070079 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070080 std::string msg(data_->buffer.str());
Elliott Hughes5fe594f2011-09-08 12:33:17 -070081
82 // Do the actual logging with the lock held.
83 {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080084 MutexLock mu(GetLoggingLock());
Elliott Hughes5fe594f2011-09-08 12:33:17 -070085 if (msg.find('\n') == std::string::npos) {
86 LogLine(msg.c_str());
87 } else {
88 msg += '\n';
89 size_t i = 0;
90 while (i < msg.size()) {
91 size_t nl = msg.find('\n', i);
92 msg[nl] = '\0';
93 LogLine(&msg[i]);
94 i = nl + 1;
95 }
Elliott Hughes13f5a582011-09-06 13:39:14 -070096 }
97 }
98
Elliott Hughes5fe594f2011-09-08 12:33:17 -070099 // Abort if necessary.
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700100 if (data_->severity == FATAL) {
Elliott Hughes8593fdb2012-04-21 20:53:44 -0700101 Runtime::Abort();
Elliott Hughes13f5a582011-09-06 13:39:14 -0700102 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700103
104 delete data_;
Elliott Hughes13f5a582011-09-06 13:39:14 -0700105}
106
107std::ostream& LogMessage::stream() {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700108 return data_->buffer;
Elliott Hughes13f5a582011-09-06 13:39:14 -0700109}
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700110
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700111HexDump::HexDump(const void* address, size_t byte_count, bool show_actual_addresses)
112 : address_(address), byte_count_(byte_count), show_actual_addresses_(show_actual_addresses) {
113}
114
115void HexDump::Dump(std::ostream& os) const {
116 if (byte_count_ == 0) {
117 return;
118 }
119
Brian Carlstrom93235f72012-03-29 22:48:15 -0700120 if (address_ == NULL) {
121 os << "00000000:";
122 return;
123 }
124
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700125 static const char gHexDigit[] = "0123456789abcdef";
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700126 const unsigned char* addr = reinterpret_cast<const unsigned char*>(address_);
Elliott Hughes21f32d72011-11-09 17:44:13 -0800127 char out[76]; /* exact fit */
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700128 unsigned int offset; /* offset to show while printing */
129
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700130 if (show_actual_addresses_) {
Elliott Hughes398f64b2012-03-26 18:05:48 -0700131 offset = reinterpret_cast<int>(addr);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700132 } else {
133 offset = 0;
134 }
135 memset(out, ' ', sizeof(out)-1);
136 out[8] = ':';
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700137 out[sizeof(out)-1] = '\0';
138
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700139 size_t byte_count = byte_count_;
Elliott Hughes398f64b2012-03-26 18:05:48 -0700140 int gap = static_cast<int>(offset & 0x0f);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700141 while (byte_count) {
142 unsigned int lineOffset = offset & ~0x0f;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700143
144 char* hex = out;
145 char* asc = out + 59;
146
Elliott Hughes398f64b2012-03-26 18:05:48 -0700147 for (int i = 0; i < 8; i++) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700148 *hex++ = gHexDigit[lineOffset >> 28];
149 lineOffset <<= 4;
150 }
151 hex++;
152 hex++;
153
Elliott Hughes398f64b2012-03-26 18:05:48 -0700154 int count = std::min(static_cast<int>(byte_count), 16 - gap);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700155 CHECK_NE(count, 0);
156 CHECK_LE(count + gap, 16);
157
158 if (gap) {
159 /* only on first line */
160 hex += gap * 3;
161 asc += gap;
162 }
163
Elliott Hughes398f64b2012-03-26 18:05:48 -0700164 int i;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700165 for (i = gap ; i < count+gap; i++) {
166 *hex++ = gHexDigit[*addr >> 4];
167 *hex++ = gHexDigit[*addr & 0x0f];
168 hex++;
Elliott Hughes398f64b2012-03-26 18:05:48 -0700169 if (*addr >= 0x20 && *addr < 0x7f /*isprint(*addr)*/) {
170 *asc++ = *addr;
171 } else {
172 *asc++ = '.';
173 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700174 addr++;
175 }
Elliott Hughes398f64b2012-03-26 18:05:48 -0700176 for (; i < 16; i++) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700177 /* erase extra stuff; only happens on last line */
178 *hex++ = ' ';
179 *hex++ = ' ';
180 hex++;
181 *asc++ = ' ';
182 }
183
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700184 os << out;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700185
186 gap = 0;
187 byte_count -= count;
188 offset += count;
189 }
190}
191
Elliott Hughesbfbf0e22012-03-29 18:09:19 -0700192std::ostream& operator<<(std::ostream& os, const HexDump& rhs) {
193 rhs.Dump(os);
194 return os;
195}
196
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700197} // namespace art