blob: b52e2f2bcaf7c6ed0795f2b6e643345f20fe4fdb [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Elliott Hughes11e45072011-08-16 17:40:46 -070016
Elliott Hughes42ee1422011-09-06 12:33:32 -070017#include "utils.h"
18
Christopher Ferris943af7d2014-01-16 12:41:46 -080019#include <inttypes.h>
Elliott Hughes92b3b562011-09-08 16:32:26 -070020#include <pthread.h>
Brian Carlstroma9f19782011-10-13 00:14:47 -070021#include <sys/stat.h>
Elliott Hughes42ee1422011-09-06 12:33:32 -070022#include <sys/syscall.h>
23#include <sys/types.h>
Brian Carlstrom4cf5e572014-02-25 11:47:48 -080024#include <sys/wait.h>
Elliott Hughes42ee1422011-09-06 12:33:32 -070025#include <unistd.h>
Ian Rogers700a4022014-05-19 16:49:03 -070026#include <memory>
Elliott Hughes42ee1422011-09-06 12:33:32 -070027
Mathieu Chartierc7853442015-03-27 14:35:38 -070028#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070029#include "art_method-inl.h"
Brian Carlstrom6449c622014-02-10 23:48:36 -080030#include "base/stl_util.h"
Elliott Hughes76160052012-12-12 16:31:20 -080031#include "base/unix_file/fd_file.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070032#include "dex_file-inl.h"
Andreas Gampe5073fed2015-08-10 11:40:25 -070033#include "dex_instruction.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070034#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080035#include "mirror/class_loader.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036#include "mirror/object-inl.h"
37#include "mirror/object_array-inl.h"
38#include "mirror/string.h"
Nicolas Geoffray524e7ea2015-10-16 17:13:34 +010039#include "oat_quick_method_header.h"
buzbeec143c552011-08-20 17:38:58 -070040#include "os.h"
Kenny Root067d20f2014-03-05 14:57:21 -080041#include "scoped_thread_state_change.h"
Ian Rogersa6724902013-09-23 09:23:37 -070042#include "utf-inl.h"
Elliott Hughes11e45072011-08-16 17:40:46 -070043
Elliott Hughes4ae722a2012-03-13 11:08:51 -070044#if defined(__APPLE__)
Brian Carlstrom7934ac22013-07-26 10:54:15 -070045#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
Elliott Hughesf1498432012-03-28 19:34:27 -070046#include <sys/syscall.h>
Elliott Hughes4ae722a2012-03-13 11:08:51 -070047#endif
48
Elliott Hughes058a6de2012-05-24 19:13:02 -070049#if defined(__linux__)
Elliott Hughese1aee692012-01-17 16:40:10 -080050#include <linux/unistd.h>
Elliott Hughese1aee692012-01-17 16:40:10 -080051#endif
52
Elliott Hughes11e45072011-08-16 17:40:46 -070053namespace art {
54
Alex Light9c20a142016-08-23 15:05:12 -070055static const uint8_t kBase64Map[256] = {
56 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
57 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
58 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
59 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
60 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
61 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
62 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT
63 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT
64 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
65 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT
66 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT
67 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
70 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
71 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
72 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
73 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
75 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
76 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
77 255, 255, 255, 255
78};
79
80uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
81 std::vector<uint8_t> tmp;
82 uint32_t t = 0, y = 0;
83 int g = 3;
84 for (size_t i = 0; src[i] != '\0'; ++i) {
85 uint8_t c = kBase64Map[src[i] & 0xFF];
86 if (c == 255) continue;
87 // the final = symbols are read and used to trim the remaining bytes
88 if (c == 254) {
89 c = 0;
90 // prevent g < 0 which would potentially allow an overflow later
91 if (--g < 0) {
92 *dst_size = 0;
93 return nullptr;
94 }
95 } else if (g != 3) {
96 // we only allow = to be at the end
97 *dst_size = 0;
98 return nullptr;
99 }
100 t = (t << 6) | c;
101 if (++y == 4) {
102 tmp.push_back((t >> 16) & 255);
103 if (g > 1) {
104 tmp.push_back((t >> 8) & 255);
105 }
106 if (g > 2) {
107 tmp.push_back(t & 255);
108 }
109 y = t = 0;
110 }
111 }
112 if (y != 0) {
113 *dst_size = 0;
114 return nullptr;
115 }
116 std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
117 if (dst_size != nullptr) {
118 *dst_size = tmp.size();
119 } else {
120 *dst_size = 0;
121 }
122 std::copy(tmp.begin(), tmp.end(), dst.get());
123 return dst.release();
124}
125
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800126pid_t GetTid() {
Brian Carlstromf3a26412012-08-24 11:06:02 -0700127#if defined(__APPLE__)
128 uint64_t owner;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700129 CHECK_PTHREAD_CALL(pthread_threadid_np, (nullptr, &owner), __FUNCTION__); // Requires Mac OS 10.6
Brian Carlstromf3a26412012-08-24 11:06:02 -0700130 return owner;
Elliott Hughes323aa862014-08-20 15:00:04 -0700131#elif defined(__BIONIC__)
132 return gettid();
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800133#else
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800134 return syscall(__NR_gettid);
135#endif
136}
137
Elliott Hughes289be852012-06-12 13:57:20 -0700138std::string GetThreadName(pid_t tid) {
139 std::string result;
140 if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700141 result.resize(result.size() - 1); // Lose the trailing '\n'.
Elliott Hughes289be852012-06-12 13:57:20 -0700142 } else {
143 result = "<unknown>";
144 }
145 return result;
146}
147
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700148void GetThreadStack(pthread_t thread, void** stack_base, size_t* stack_size, size_t* guard_size) {
Elliott Hughese1884192012-04-23 12:38:15 -0700149#if defined(__APPLE__)
Brian Carlstrom29212012013-09-12 22:18:30 -0700150 *stack_size = pthread_get_stacksize_np(thread);
Ian Rogers120f1c72012-09-28 17:17:10 -0700151 void* stack_addr = pthread_get_stackaddr_np(thread);
Elliott Hughese1884192012-04-23 12:38:15 -0700152
153 // Check whether stack_addr is the base or end of the stack.
154 // (On Mac OS 10.7, it's the end.)
155 int stack_variable;
156 if (stack_addr > &stack_variable) {
Ian Rogers13735952014-10-08 12:43:28 -0700157 *stack_base = reinterpret_cast<uint8_t*>(stack_addr) - *stack_size;
Elliott Hughese1884192012-04-23 12:38:15 -0700158 } else {
Brian Carlstrom29212012013-09-12 22:18:30 -0700159 *stack_base = stack_addr;
Elliott Hughese1884192012-04-23 12:38:15 -0700160 }
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700161
162 // This is wrong, but there doesn't seem to be a way to get the actual value on the Mac.
163 pthread_attr_t attributes;
164 CHECK_PTHREAD_CALL(pthread_attr_init, (&attributes), __FUNCTION__);
165 CHECK_PTHREAD_CALL(pthread_attr_getguardsize, (&attributes, guard_size), __FUNCTION__);
166 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
Elliott Hughese1884192012-04-23 12:38:15 -0700167#else
168 pthread_attr_t attributes;
Ian Rogers120f1c72012-09-28 17:17:10 -0700169 CHECK_PTHREAD_CALL(pthread_getattr_np, (thread, &attributes), __FUNCTION__);
Brian Carlstrom29212012013-09-12 22:18:30 -0700170 CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, stack_base, stack_size), __FUNCTION__);
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700171 CHECK_PTHREAD_CALL(pthread_attr_getguardsize, (&attributes, guard_size), __FUNCTION__);
Elliott Hughese1884192012-04-23 12:38:15 -0700172 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
Elliott Hughes839cc302014-08-28 10:24:44 -0700173
174#if defined(__GLIBC__)
175 // If we're the main thread, check whether we were run with an unlimited stack. In that case,
176 // glibc will have reported a 2GB stack for our 32-bit process, and our stack overflow detection
177 // will be broken because we'll die long before we get close to 2GB.
178 bool is_main_thread = (::art::GetTid() == getpid());
179 if (is_main_thread) {
180 rlimit stack_limit;
181 if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) {
182 PLOG(FATAL) << "getrlimit(RLIMIT_STACK) failed";
183 }
184 if (stack_limit.rlim_cur == RLIM_INFINITY) {
185 size_t old_stack_size = *stack_size;
186
187 // Use the kernel default limit as our size, and adjust the base to match.
188 *stack_size = 8 * MB;
189 *stack_base = reinterpret_cast<uint8_t*>(*stack_base) + (old_stack_size - *stack_size);
190
191 VLOG(threads) << "Limiting unlimited stack (reported as " << PrettySize(old_stack_size) << ")"
192 << " to " << PrettySize(*stack_size)
193 << " with base " << *stack_base;
194 }
195 }
196#endif
197
Elliott Hughese1884192012-04-23 12:38:15 -0700198#endif
199}
200
Elliott Hughesd92bec42011-09-02 17:04:36 -0700201bool ReadFileToString(const std::string& file_name, std::string* result) {
Andreas Gampedf878922015-08-13 16:44:54 -0700202 File file(file_name, O_RDONLY, false);
203 if (!file.IsOpened()) {
Elliott Hughesd92bec42011-09-02 17:04:36 -0700204 return false;
205 }
buzbeec143c552011-08-20 17:38:58 -0700206
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700207 std::vector<char> buf(8 * KB);
buzbeec143c552011-08-20 17:38:58 -0700208 while (true) {
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800209 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
Elliott Hughesd92bec42011-09-02 17:04:36 -0700210 if (n == -1) {
211 return false;
buzbeec143c552011-08-20 17:38:58 -0700212 }
Elliott Hughesd92bec42011-09-02 17:04:36 -0700213 if (n == 0) {
214 return true;
215 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700216 result->append(&buf[0], n);
buzbeec143c552011-08-20 17:38:58 -0700217 }
buzbeec143c552011-08-20 17:38:58 -0700218}
219
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800220bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
Andreas Gampedf878922015-08-13 16:44:54 -0700221 File file(file_name, O_RDONLY, false);
222 if (!file.IsOpened()) {
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800223 return false;
224 }
225
226 constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings.
227 char buf[kBufSize + 1]; // +1 for terminator.
228 size_t filled_to = 0;
229 while (true) {
230 DCHECK_LT(filled_to, kBufSize);
231 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
232 if (n <= 0) {
233 // Print the rest of the buffer, if it exists.
234 if (filled_to > 0) {
235 buf[filled_to] = 0;
236 LOG(level) << buf;
237 }
238 return n == 0;
239 }
240 // Scan for '\n'.
241 size_t i = filled_to;
242 bool found_newline = false;
243 for (; i < filled_to + n; ++i) {
244 if (buf[i] == '\n') {
245 // Found a line break, that's something to print now.
246 buf[i] = 0;
247 LOG(level) << buf;
248 // Copy the rest to the front.
249 if (i + 1 < filled_to + n) {
250 memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
251 filled_to = filled_to + n - i - 1;
252 } else {
253 filled_to = 0;
254 }
255 found_newline = true;
256 break;
257 }
258 }
259 if (found_newline) {
260 continue;
261 } else {
262 filled_to += n;
263 // Check if we must flush now.
264 if (filled_to == kBufSize) {
265 buf[kBufSize] = 0;
266 LOG(level) << buf;
267 filled_to = 0;
268 }
269 }
270 }
271}
272
Ian Rogersef7d42f2014-01-06 12:55:46 -0800273std::string PrettyDescriptor(mirror::String* java_descriptor) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700274 if (java_descriptor == nullptr) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700275 return "null";
276 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700277 return PrettyDescriptor(java_descriptor->ToModifiedUtf8().c_str());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700278}
Elliott Hughes5174fe62011-08-23 15:12:35 -0700279
Ian Rogersef7d42f2014-01-06 12:55:46 -0800280std::string PrettyDescriptor(mirror::Class* klass) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700281 if (klass == nullptr) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800282 return "null";
283 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700284 std::string temp;
285 return PrettyDescriptor(klass->GetDescriptor(&temp));
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800286}
287
Ian Rogers1ff3c982014-08-12 02:30:58 -0700288std::string PrettyDescriptor(const char* descriptor) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700289 // Count the number of '['s to get the dimensionality.
Ian Rogers1ff3c982014-08-12 02:30:58 -0700290 const char* c = descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700291 size_t dim = 0;
292 while (*c == '[') {
293 dim++;
294 c++;
295 }
296
297 // Reference or primitive?
298 if (*c == 'L') {
299 // "[[La/b/C;" -> "a.b.C[][]".
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700300 c++; // Skip the 'L'.
Elliott Hughes11e45072011-08-16 17:40:46 -0700301 } else {
302 // "[[B" -> "byte[][]".
303 // To make life easier, we make primitives look like unqualified
304 // reference types.
305 switch (*c) {
306 case 'B': c = "byte;"; break;
307 case 'C': c = "char;"; break;
308 case 'D': c = "double;"; break;
309 case 'F': c = "float;"; break;
310 case 'I': c = "int;"; break;
311 case 'J': c = "long;"; break;
312 case 'S': c = "short;"; break;
313 case 'Z': c = "boolean;"; break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700314 case 'V': c = "void;"; break; // Used when decoding return types.
Elliott Hughes5174fe62011-08-23 15:12:35 -0700315 default: return descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700316 }
317 }
318
319 // At this point, 'c' is a string of the form "fully/qualified/Type;"
320 // or "primitive;". Rewrite the type with '.' instead of '/':
321 std::string result;
322 const char* p = c;
323 while (*p != ';') {
324 char ch = *p++;
325 if (ch == '/') {
326 ch = '.';
327 }
328 result.push_back(ch);
329 }
330 // ...and replace the semicolon with 'dim' "[]" pairs:
Ian Rogers1ff3c982014-08-12 02:30:58 -0700331 for (size_t i = 0; i < dim; ++i) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700332 result += "[]";
333 }
334 return result;
335}
336
Mathieu Chartierc7853442015-03-27 14:35:38 -0700337std::string PrettyField(ArtField* f, bool with_type) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700338 if (f == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700339 return "null";
340 }
Elliott Hughes54e7df12011-09-16 11:47:04 -0700341 std::string result;
342 if (with_type) {
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700343 result += PrettyDescriptor(f->GetTypeDescriptor());
Elliott Hughes54e7df12011-09-16 11:47:04 -0700344 result += ' ';
345 }
Ian Rogers08f1f502014-12-02 15:04:37 -0800346 std::string temp;
347 result += PrettyDescriptor(f->GetDeclaringClass()->GetDescriptor(&temp));
Elliott Hughesa2501992011-08-26 19:39:54 -0700348 result += '.';
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700349 result += f->GetName();
Elliott Hughesa2501992011-08-26 19:39:54 -0700350 return result;
351}
352
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700353std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800354 if (field_idx >= dex_file.NumFieldIds()) {
355 return StringPrintf("<<invalid-field-idx-%d>>", field_idx);
356 }
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700357 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
358 std::string result;
359 if (with_type) {
360 result += dex_file.GetFieldTypeDescriptor(field_id);
361 result += ' ';
362 }
363 result += PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(field_id));
364 result += '.';
365 result += dex_file.GetFieldName(field_id);
366 return result;
367}
368
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700369std::string PrettyType(uint32_t type_idx, const DexFile& dex_file) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800370 if (type_idx >= dex_file.NumTypeIds()) {
371 return StringPrintf("<<invalid-type-idx-%d>>", type_idx);
372 }
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700373 const DexFile::TypeId& type_id = dex_file.GetTypeId(type_idx);
Mathieu Chartier4c70d772012-09-10 14:08:32 -0700374 return PrettyDescriptor(dex_file.GetTypeDescriptor(type_id));
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700375}
376
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700377std::string PrettyArguments(const char* signature) {
378 std::string result;
379 result += '(';
380 CHECK_EQ(*signature, '(');
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700381 ++signature; // Skip the '('.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700382 while (*signature != ')') {
383 size_t argument_length = 0;
384 while (signature[argument_length] == '[') {
385 ++argument_length;
386 }
387 if (signature[argument_length] == 'L') {
388 argument_length = (strchr(signature, ';') - signature + 1);
389 } else {
390 ++argument_length;
391 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700392 {
393 std::string argument_descriptor(signature, argument_length);
394 result += PrettyDescriptor(argument_descriptor.c_str());
395 }
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700396 if (signature[argument_length] != ')') {
397 result += ", ";
398 }
399 signature += argument_length;
400 }
401 CHECK_EQ(*signature, ')');
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700402 ++signature; // Skip the ')'.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700403 result += ')';
404 return result;
405}
406
407std::string PrettyReturnType(const char* signature) {
408 const char* return_type = strchr(signature, ')');
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700409 CHECK(return_type != nullptr);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700410 ++return_type; // Skip ')'.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700411 return PrettyDescriptor(return_type);
412}
413
Mathieu Chartiere401d142015-04-22 13:56:20 -0700414std::string PrettyMethod(ArtMethod* m, bool with_signature) {
Ian Rogers16ce0922014-01-10 14:59:36 -0800415 if (m == nullptr) {
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700416 return "null";
417 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700418 if (!m->IsRuntimeMethod()) {
419 m = m->GetInterfaceMethodIfProxy(Runtime::Current()->GetClassLinker()->GetImagePointerSize());
420 }
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700421 std::string result(PrettyDescriptor(m->GetDeclaringClassDescriptor()));
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700422 result += '.';
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700423 result += m->GetName();
Ian Rogers16ce0922014-01-10 14:59:36 -0800424 if (UNLIKELY(m->IsFastNative())) {
425 result += "!";
426 }
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700427 if (with_signature) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700428 const Signature signature = m->GetSignature();
Ian Rogersd91d6d62013-09-25 20:26:14 -0700429 std::string sig_as_string(signature.ToString());
430 if (signature == Signature::NoSignature()) {
431 return result + sig_as_string;
Elliott Hughesf8c11932012-03-23 19:53:59 -0700432 }
Ian Rogersd91d6d62013-09-25 20:26:14 -0700433 result = PrettyReturnType(sig_as_string.c_str()) + " " + result +
434 PrettyArguments(sig_as_string.c_str());
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700435 }
436 return result;
437}
438
Ian Rogers0571d352011-11-03 19:51:38 -0700439std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800440 if (method_idx >= dex_file.NumMethodIds()) {
441 return StringPrintf("<<invalid-method-idx-%d>>", method_idx);
442 }
Ian Rogers0571d352011-11-03 19:51:38 -0700443 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
444 std::string result(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(method_id)));
445 result += '.';
446 result += dex_file.GetMethodName(method_id);
447 if (with_signature) {
Ian Rogersd91d6d62013-09-25 20:26:14 -0700448 const Signature signature = dex_file.GetMethodSignature(method_id);
449 std::string sig_as_string(signature.ToString());
450 if (signature == Signature::NoSignature()) {
451 return result + sig_as_string;
Elliott Hughesf8c11932012-03-23 19:53:59 -0700452 }
Ian Rogersd91d6d62013-09-25 20:26:14 -0700453 result = PrettyReturnType(sig_as_string.c_str()) + " " + result +
454 PrettyArguments(sig_as_string.c_str());
Ian Rogers0571d352011-11-03 19:51:38 -0700455 }
456 return result;
457}
458
Ian Rogersef7d42f2014-01-06 12:55:46 -0800459std::string PrettyTypeOf(mirror::Object* obj) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700460 if (obj == nullptr) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700461 return "null";
462 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700463 if (obj->GetClass() == nullptr) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700464 return "(raw)";
465 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700466 std::string temp;
467 std::string result(PrettyDescriptor(obj->GetClass()->GetDescriptor(&temp)));
Elliott Hughes11e45072011-08-16 17:40:46 -0700468 if (obj->IsClass()) {
Ian Rogers1ff3c982014-08-12 02:30:58 -0700469 result += "<" + PrettyDescriptor(obj->AsClass()->GetDescriptor(&temp)) + ">";
Elliott Hughes11e45072011-08-16 17:40:46 -0700470 }
471 return result;
472}
473
Ian Rogersef7d42f2014-01-06 12:55:46 -0800474std::string PrettyClass(mirror::Class* c) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700475 if (c == nullptr) {
Elliott Hughes54e7df12011-09-16 11:47:04 -0700476 return "null";
477 }
478 std::string result;
479 result += "java.lang.Class<";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800480 result += PrettyDescriptor(c);
Elliott Hughes54e7df12011-09-16 11:47:04 -0700481 result += ">";
482 return result;
483}
484
Ian Rogersef7d42f2014-01-06 12:55:46 -0800485std::string PrettyClassAndClassLoader(mirror::Class* c) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700486 if (c == nullptr) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700487 return "null";
488 }
489 std::string result;
490 result += "java.lang.Class<";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800491 result += PrettyDescriptor(c);
Ian Rogersd81871c2011-10-03 13:57:23 -0700492 result += ",";
493 result += PrettyTypeOf(c->GetClassLoader());
494 // TODO: add an identifying hash value for the loader
495 result += ">";
496 return result;
497}
498
Andreas Gampec0d82292014-09-23 10:38:30 -0700499std::string PrettyJavaAccessFlags(uint32_t access_flags) {
500 std::string result;
501 if ((access_flags & kAccPublic) != 0) {
502 result += "public ";
503 }
504 if ((access_flags & kAccProtected) != 0) {
505 result += "protected ";
506 }
507 if ((access_flags & kAccPrivate) != 0) {
508 result += "private ";
509 }
510 if ((access_flags & kAccFinal) != 0) {
511 result += "final ";
512 }
513 if ((access_flags & kAccStatic) != 0) {
514 result += "static ";
515 }
David Brazdilca3c8c32016-09-06 14:04:48 +0100516 if ((access_flags & kAccAbstract) != 0) {
517 result += "abstract ";
518 }
519 if ((access_flags & kAccInterface) != 0) {
520 result += "interface ";
521 }
Andreas Gampec0d82292014-09-23 10:38:30 -0700522 if ((access_flags & kAccTransient) != 0) {
523 result += "transient ";
524 }
525 if ((access_flags & kAccVolatile) != 0) {
526 result += "volatile ";
527 }
528 if ((access_flags & kAccSynchronized) != 0) {
529 result += "synchronized ";
530 }
531 return result;
532}
533
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800534std::string PrettySize(int64_t byte_count) {
Elliott Hughesc967f782012-04-16 10:23:15 -0700535 // The byte thresholds at which we display amounts. A byte count is displayed
536 // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
Ian Rogersef7d42f2014-01-06 12:55:46 -0800537 static const int64_t kUnitThresholds[] = {
Elliott Hughesc967f782012-04-16 10:23:15 -0700538 0, // B up to...
539 3*1024, // KB up to...
540 2*1024*1024, // MB up to...
541 1024*1024*1024 // GB from here.
542 };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800543 static const int64_t kBytesPerUnit[] = { 1, KB, MB, GB };
Elliott Hughesc967f782012-04-16 10:23:15 -0700544 static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800545 const char* negative_str = "";
546 if (byte_count < 0) {
547 negative_str = "-";
548 byte_count = -byte_count;
549 }
Elliott Hughesc967f782012-04-16 10:23:15 -0700550 int i = arraysize(kUnitThresholds);
551 while (--i > 0) {
552 if (byte_count >= kUnitThresholds[i]) {
553 break;
554 }
Ian Rogers3bb17a62012-01-27 23:56:44 -0800555 }
Brian Carlstrom474cc792014-03-07 14:18:15 -0800556 return StringPrintf("%s%" PRId64 "%s",
557 negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
Ian Rogers3bb17a62012-01-27 23:56:44 -0800558}
559
Ian Rogers576ca0c2014-06-06 15:58:22 -0700560std::string PrintableChar(uint16_t ch) {
561 std::string result;
562 result += '\'';
563 if (NeedsEscaping(ch)) {
564 StringAppendF(&result, "\\u%04x", ch);
565 } else {
566 result += ch;
567 }
568 result += '\'';
569 return result;
570}
571
Ian Rogers68b56852014-08-29 20:19:11 -0700572std::string PrintableString(const char* utf) {
Elliott Hughes82914b62012-04-09 15:56:29 -0700573 std::string result;
574 result += '"';
Ian Rogers68b56852014-08-29 20:19:11 -0700575 const char* p = utf;
Elliott Hughes82914b62012-04-09 15:56:29 -0700576 size_t char_count = CountModifiedUtf8Chars(p);
577 for (size_t i = 0; i < char_count; ++i) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000578 uint32_t ch = GetUtf16FromUtf8(&p);
Elliott Hughes82914b62012-04-09 15:56:29 -0700579 if (ch == '\\') {
580 result += "\\\\";
581 } else if (ch == '\n') {
582 result += "\\n";
583 } else if (ch == '\r') {
584 result += "\\r";
585 } else if (ch == '\t') {
586 result += "\\t";
Elliott Hughes82914b62012-04-09 15:56:29 -0700587 } else {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000588 const uint16_t leading = GetLeadingUtf16Char(ch);
589
590 if (NeedsEscaping(leading)) {
591 StringAppendF(&result, "\\u%04x", leading);
592 } else {
593 result += leading;
594 }
595
596 const uint32_t trailing = GetTrailingUtf16Char(ch);
597 if (trailing != 0) {
598 // All high surrogates will need escaping.
599 StringAppendF(&result, "\\u%04x", trailing);
600 }
Elliott Hughes82914b62012-04-09 15:56:29 -0700601 }
602 }
603 result += '"';
604 return result;
605}
606
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800607// See http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/design.html#wp615 for the full rules.
Elliott Hughes79082e32011-08-25 12:07:32 -0700608std::string MangleForJni(const std::string& s) {
609 std::string result;
610 size_t char_count = CountModifiedUtf8Chars(s.c_str());
611 const char* cp = &s[0];
612 for (size_t i = 0; i < char_count; ++i) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000613 uint32_t ch = GetUtf16FromUtf8(&cp);
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800614 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
615 result.push_back(ch);
616 } else if (ch == '.' || ch == '/') {
617 result += "_";
618 } else if (ch == '_') {
619 result += "_1";
620 } else if (ch == ';') {
621 result += "_2";
622 } else if (ch == '[') {
623 result += "_3";
Elliott Hughes79082e32011-08-25 12:07:32 -0700624 } else {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000625 const uint16_t leading = GetLeadingUtf16Char(ch);
626 const uint32_t trailing = GetTrailingUtf16Char(ch);
627
628 StringAppendF(&result, "_0%04x", leading);
629 if (trailing != 0) {
630 StringAppendF(&result, "_0%04x", trailing);
631 }
Elliott Hughes79082e32011-08-25 12:07:32 -0700632 }
633 }
634 return result;
635}
636
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700637std::string DotToDescriptor(const char* class_name) {
638 std::string descriptor(class_name);
639 std::replace(descriptor.begin(), descriptor.end(), '.', '/');
640 if (descriptor.length() > 0 && descriptor[0] != '[') {
641 descriptor = "L" + descriptor + ";";
642 }
643 return descriptor;
644}
645
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800646std::string DescriptorToDot(const char* descriptor) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800647 size_t length = strlen(descriptor);
Ian Rogers1ff3c982014-08-12 02:30:58 -0700648 if (length > 1) {
649 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
650 // Descriptors have the leading 'L' and trailing ';' stripped.
651 std::string result(descriptor + 1, length - 2);
652 std::replace(result.begin(), result.end(), '/', '.');
653 return result;
654 } else {
655 // For arrays the 'L' and ';' remain intact.
656 std::string result(descriptor);
657 std::replace(result.begin(), result.end(), '/', '.');
658 return result;
659 }
Elliott Hughes2435a572012-02-17 16:07:41 -0800660 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700661 // Do nothing for non-class/array descriptors.
Elliott Hughes2435a572012-02-17 16:07:41 -0800662 return descriptor;
Elliott Hughes91bf6cd2012-02-14 17:27:48 -0800663}
664
665std::string DescriptorToName(const char* descriptor) {
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800666 size_t length = strlen(descriptor);
Elliott Hughes2435a572012-02-17 16:07:41 -0800667 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
668 std::string result(descriptor + 1, length - 2);
669 return result;
670 }
671 return descriptor;
Brian Carlstromaded5f72011-10-07 17:15:04 -0700672}
673
Mathieu Chartiere401d142015-04-22 13:56:20 -0700674std::string JniShortName(ArtMethod* m) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700675 std::string class_name(m->GetDeclaringClassDescriptor());
Elliott Hughes79082e32011-08-25 12:07:32 -0700676 // Remove the leading 'L' and trailing ';'...
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700677 CHECK_EQ(class_name[0], 'L') << class_name;
678 CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name;
Elliott Hughes79082e32011-08-25 12:07:32 -0700679 class_name.erase(0, 1);
680 class_name.erase(class_name.size() - 1, 1);
681
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700682 std::string method_name(m->GetName());
Elliott Hughes79082e32011-08-25 12:07:32 -0700683
684 std::string short_name;
685 short_name += "Java_";
686 short_name += MangleForJni(class_name);
687 short_name += "_";
688 short_name += MangleForJni(method_name);
689 return short_name;
690}
691
Mathieu Chartiere401d142015-04-22 13:56:20 -0700692std::string JniLongName(ArtMethod* m) {
Elliott Hughes79082e32011-08-25 12:07:32 -0700693 std::string long_name;
694 long_name += JniShortName(m);
695 long_name += "__";
696
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700697 std::string signature(m->GetSignature().ToString());
Elliott Hughes79082e32011-08-25 12:07:32 -0700698 signature.erase(0, 1);
699 signature.erase(signature.begin() + signature.find(')'), signature.end());
700
701 long_name += MangleForJni(signature);
702
703 return long_name;
704}
705
jeffhao10037c82012-01-23 15:06:23 -0800706// Helper for IsValidPartOfMemberNameUtf8(), a bit vector indicating valid low ascii.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700707uint32_t DEX_MEMBER_VALID_LOW_ASCII[4] = {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700708 0x00000000, // 00..1f low control characters; nothing valid
709 0x03ff2010, // 20..3f digits and symbols; valid: '0'..'9', '$', '-'
710 0x87fffffe, // 40..5f uppercase etc.; valid: 'A'..'Z', '_'
711 0x07fffffe // 60..7f lowercase etc.; valid: 'a'..'z'
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700712};
713
jeffhao10037c82012-01-23 15:06:23 -0800714// Helper for IsValidPartOfMemberNameUtf8(); do not call directly.
715bool IsValidPartOfMemberNameUtf8Slow(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700716 /*
717 * It's a multibyte encoded character. Decode it and analyze. We
718 * accept anything that isn't (a) an improperly encoded low value,
719 * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high
720 * control character, or (e) a high space, layout, or special
721 * character (U+00a0, U+2000..U+200f, U+2028..U+202f,
722 * U+fff0..U+ffff). This is all specified in the dex format
723 * document.
724 */
725
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000726 const uint32_t pair = GetUtf16FromUtf8(pUtf8Ptr);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000727 const uint16_t leading = GetLeadingUtf16Char(pair);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000728
Narayan Kamath8508e372015-05-06 14:55:43 +0100729 // We have a surrogate pair resulting from a valid 4 byte UTF sequence.
730 // No further checks are necessary because 4 byte sequences span code
731 // points [U+10000, U+1FFFFF], which are valid codepoints in a dex
732 // identifier. Furthermore, GetUtf16FromUtf8 guarantees that each of
733 // the surrogate halves are valid and well formed in this instance.
734 if (GetTrailingUtf16Char(pair) != 0) {
735 return true;
736 }
737
738
739 // We've encountered a one, two or three byte UTF-8 sequence. The
740 // three byte UTF-8 sequence could be one half of a surrogate pair.
741 switch (leading >> 8) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000742 case 0x00:
743 // It's only valid if it's above the ISO-8859-1 high space (0xa0).
744 return (leading > 0x00a0);
745 case 0xd8:
746 case 0xd9:
747 case 0xda:
748 case 0xdb:
Narayan Kamath8508e372015-05-06 14:55:43 +0100749 {
750 // We found a three byte sequence encoding one half of a surrogate.
751 // Look for the other half.
752 const uint32_t pair2 = GetUtf16FromUtf8(pUtf8Ptr);
753 const uint16_t trailing = GetLeadingUtf16Char(pair2);
754
755 return (GetTrailingUtf16Char(pair2) == 0) && (0xdc00 <= trailing && trailing <= 0xdfff);
756 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000757 case 0xdc:
758 case 0xdd:
759 case 0xde:
760 case 0xdf:
761 // It's a trailing surrogate, which is not valid at this point.
762 return false;
763 case 0x20:
764 case 0xff:
765 // It's in the range that has spaces, controls, and specials.
766 switch (leading & 0xfff8) {
Narayan Kamath8508e372015-05-06 14:55:43 +0100767 case 0x2000:
768 case 0x2008:
769 case 0x2028:
770 case 0xfff0:
771 case 0xfff8:
772 return false;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000773 }
Narayan Kamath8508e372015-05-06 14:55:43 +0100774 return true;
775 default:
776 return true;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700777 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000778
Narayan Kamath8508e372015-05-06 14:55:43 +0100779 UNREACHABLE();
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700780}
781
782/* Return whether the pointed-at modified-UTF-8 encoded character is
783 * valid as part of a member name, updating the pointer to point past
784 * the consumed character. This will consume two encoded UTF-16 code
785 * points if the character is encoded as a surrogate pair. Also, if
786 * this function returns false, then the given pointer may only have
787 * been partially advanced.
788 */
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700789static bool IsValidPartOfMemberNameUtf8(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700790 uint8_t c = (uint8_t) **pUtf8Ptr;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700791 if (LIKELY(c <= 0x7f)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700792 // It's low-ascii, so check the table.
793 uint32_t wordIdx = c >> 5;
794 uint32_t bitIdx = c & 0x1f;
795 (*pUtf8Ptr)++;
796 return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0;
797 }
798
799 // It's a multibyte encoded character. Call a non-inline function
800 // for the heavy lifting.
jeffhao10037c82012-01-23 15:06:23 -0800801 return IsValidPartOfMemberNameUtf8Slow(pUtf8Ptr);
802}
803
804bool IsValidMemberName(const char* s) {
805 bool angle_name = false;
806
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700807 switch (*s) {
jeffhao10037c82012-01-23 15:06:23 -0800808 case '\0':
809 // The empty string is not a valid name.
810 return false;
811 case '<':
812 angle_name = true;
813 s++;
814 break;
815 }
816
817 while (true) {
818 switch (*s) {
819 case '\0':
820 return !angle_name;
821 case '>':
822 return angle_name && s[1] == '\0';
823 }
824
825 if (!IsValidPartOfMemberNameUtf8(&s)) {
826 return false;
827 }
828 }
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700829}
830
Elliott Hughes906e6852011-10-28 14:52:10 -0700831enum ClassNameType { kName, kDescriptor };
Ian Rogers7b078e82014-09-10 14:44:24 -0700832template<ClassNameType kType, char kSeparator>
833static bool IsValidClassName(const char* s) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700834 int arrayCount = 0;
835 while (*s == '[') {
836 arrayCount++;
837 s++;
838 }
839
840 if (arrayCount > 255) {
841 // Arrays may have no more than 255 dimensions.
842 return false;
843 }
844
Ian Rogers7b078e82014-09-10 14:44:24 -0700845 ClassNameType type = kType;
846 if (type != kDescriptor && arrayCount != 0) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700847 /*
848 * If we're looking at an array of some sort, then it doesn't
849 * matter if what is being asked for is a class name; the
850 * format looks the same as a type descriptor in that case, so
851 * treat it as such.
852 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700853 type = kDescriptor;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700854 }
855
Elliott Hughes906e6852011-10-28 14:52:10 -0700856 if (type == kDescriptor) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700857 /*
858 * We are looking for a descriptor. Either validate it as a
859 * single-character primitive type, or continue on to check the
860 * embedded class name (bracketed by "L" and ";").
861 */
862 switch (*(s++)) {
863 case 'B':
864 case 'C':
865 case 'D':
866 case 'F':
867 case 'I':
868 case 'J':
869 case 'S':
870 case 'Z':
871 // These are all single-character descriptors for primitive types.
872 return (*s == '\0');
873 case 'V':
874 // Non-array void is valid, but you can't have an array of void.
875 return (arrayCount == 0) && (*s == '\0');
876 case 'L':
877 // Class name: Break out and continue below.
878 break;
879 default:
880 // Oddball descriptor character.
881 return false;
882 }
883 }
884
885 /*
886 * We just consumed the 'L' that introduces a class name as part
887 * of a type descriptor, or we are looking for an unadorned class
888 * name.
889 */
890
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700891 bool sepOrFirst = true; // first character or just encountered a separator.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700892 for (;;) {
893 uint8_t c = (uint8_t) *s;
894 switch (c) {
895 case '\0':
896 /*
897 * Premature end for a type descriptor, but valid for
898 * a class name as long as we haven't encountered an
899 * empty component (including the degenerate case of
900 * the empty string "").
901 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700902 return (type == kName) && !sepOrFirst;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700903 case ';':
904 /*
905 * Invalid character for a class name, but the
906 * legitimate end of a type descriptor. In the latter
907 * case, make sure that this is the end of the string
908 * and that it doesn't end with an empty component
909 * (including the degenerate case of "L;").
910 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700911 return (type == kDescriptor) && !sepOrFirst && (s[1] == '\0');
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700912 case '/':
913 case '.':
Ian Rogers7b078e82014-09-10 14:44:24 -0700914 if (c != kSeparator) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700915 // The wrong separator character.
916 return false;
917 }
918 if (sepOrFirst) {
919 // Separator at start or two separators in a row.
920 return false;
921 }
922 sepOrFirst = true;
923 s++;
924 break;
925 default:
jeffhao10037c82012-01-23 15:06:23 -0800926 if (!IsValidPartOfMemberNameUtf8(&s)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700927 return false;
928 }
929 sepOrFirst = false;
930 break;
931 }
932 }
933}
934
Elliott Hughes906e6852011-10-28 14:52:10 -0700935bool IsValidBinaryClassName(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700936 return IsValidClassName<kName, '.'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700937}
938
939bool IsValidJniClassName(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700940 return IsValidClassName<kName, '/'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700941}
942
943bool IsValidDescriptor(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700944 return IsValidClassName<kDescriptor, '/'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700945}
946
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700947void Split(const std::string& s, char separator, std::vector<std::string>* result) {
Elliott Hughes34023802011-08-30 12:06:17 -0700948 const char* p = s.data();
949 const char* end = p + s.size();
950 while (p != end) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800951 if (*p == separator) {
Elliott Hughes34023802011-08-30 12:06:17 -0700952 ++p;
953 } else {
954 const char* start = p;
Elliott Hughes48436bb2012-02-07 15:23:28 -0800955 while (++p != end && *p != separator) {
956 // Skip to the next occurrence of the separator.
Elliott Hughes34023802011-08-30 12:06:17 -0700957 }
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700958 result->push_back(std::string(start, p - start));
Elliott Hughes34023802011-08-30 12:06:17 -0700959 }
960 }
961}
962
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700963std::string Trim(const std::string& s) {
Dave Allison70202782013-10-22 17:52:19 -0700964 std::string result;
965 unsigned int start_index = 0;
966 unsigned int end_index = s.size() - 1;
967
968 // Skip initial whitespace.
969 while (start_index < s.size()) {
970 if (!isspace(s[start_index])) {
971 break;
972 }
973 start_index++;
974 }
975
976 // Skip terminating whitespace.
977 while (end_index >= start_index) {
978 if (!isspace(s[end_index])) {
979 break;
980 }
981 end_index--;
982 }
983
984 // All spaces, no beef.
985 if (end_index < start_index) {
986 return "";
987 }
988 // Start_index is the first non-space, end_index is the last one.
989 return s.substr(start_index, end_index - start_index + 1);
990}
991
Elliott Hughes48436bb2012-02-07 15:23:28 -0800992template <typename StringT>
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700993std::string Join(const std::vector<StringT>& strings, char separator) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800994 if (strings.empty()) {
995 return "";
996 }
997
998 std::string result(strings[0]);
999 for (size_t i = 1; i < strings.size(); ++i) {
1000 result += separator;
1001 result += strings[i];
1002 }
1003 return result;
1004}
1005
1006// Explicit instantiations.
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001007template std::string Join<std::string>(const std::vector<std::string>& strings, char separator);
1008template std::string Join<const char*>(const std::vector<const char*>& strings, char separator);
Elliott Hughes48436bb2012-02-07 15:23:28 -08001009
Elliott Hughesf1a5adc2012-02-10 18:09:35 -08001010bool StartsWith(const std::string& s, const char* prefix) {
1011 return s.compare(0, strlen(prefix), prefix) == 0;
1012}
1013
Brian Carlstrom7a967b32012-03-28 15:23:10 -07001014bool EndsWith(const std::string& s, const char* suffix) {
1015 size_t suffix_length = strlen(suffix);
1016 size_t string_length = s.size();
1017 if (suffix_length > string_length) {
1018 return false;
1019 }
1020 size_t offset = string_length - suffix_length;
1021 return s.compare(offset, suffix_length, suffix) == 0;
1022}
1023
Elliott Hughes22869a92012-03-27 14:08:24 -07001024void SetThreadName(const char* thread_name) {
Elliott Hughesdcc24742011-09-07 14:02:44 -07001025 int hasAt = 0;
1026 int hasDot = 0;
Elliott Hughes22869a92012-03-27 14:08:24 -07001027 const char* s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001028 while (*s) {
1029 if (*s == '.') {
1030 hasDot = 1;
1031 } else if (*s == '@') {
1032 hasAt = 1;
1033 }
1034 s++;
1035 }
Elliott Hughes22869a92012-03-27 14:08:24 -07001036 int len = s - thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001037 if (len < 15 || hasAt || !hasDot) {
Elliott Hughes22869a92012-03-27 14:08:24 -07001038 s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001039 } else {
Elliott Hughes22869a92012-03-27 14:08:24 -07001040 s = thread_name + len - 15;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001041 }
Elliott Hughes0a18df82015-01-09 15:16:16 -08001042#if defined(__linux__)
Elliott Hughes7c6a61e2012-03-12 18:01:41 -07001043 // pthread_setname_np fails rather than truncating long strings.
Elliott Hughes0a18df82015-01-09 15:16:16 -08001044 char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel.
Elliott Hughesdcc24742011-09-07 14:02:44 -07001045 strncpy(buf, s, sizeof(buf)-1);
1046 buf[sizeof(buf)-1] = '\0';
1047 errno = pthread_setname_np(pthread_self(), buf);
1048 if (errno != 0) {
1049 PLOG(WARNING) << "Unable to set the name of current thread to '" << buf << "'";
1050 }
Elliott Hughes0a18df82015-01-09 15:16:16 -08001051#else // __APPLE__
Elliott Hughes22869a92012-03-27 14:08:24 -07001052 pthread_setname_np(thread_name);
Elliott Hughesdcc24742011-09-07 14:02:44 -07001053#endif
1054}
1055
Brian Carlstrom29212012013-09-12 22:18:30 -07001056void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
1057 *utime = *stime = *task_cpu = 0;
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001058 std::string stats;
Elliott Hughes8a31b502012-04-30 19:36:11 -07001059 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001060 return;
1061 }
1062 // Skip the command, which may contain spaces.
1063 stats = stats.substr(stats.find(')') + 2);
1064 // Extract the three fields we care about.
1065 std::vector<std::string> fields;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001066 Split(stats, ' ', &fields);
Brian Carlstrom29212012013-09-12 22:18:30 -07001067 *state = fields[0][0];
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001068 *utime = strtoull(fields[11].c_str(), nullptr, 10);
1069 *stime = strtoull(fields[12].c_str(), nullptr, 10);
1070 *task_cpu = strtoull(fields[36].c_str(), nullptr, 10);
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001071}
1072
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001073std::string GetSchedulerGroupName(pid_t tid) {
1074 // /proc/<pid>/cgroup looks like this:
1075 // 2:devices:/
1076 // 1:cpuacct,cpu:/
1077 // We want the third field from the line whose second field contains the "cpu" token.
1078 std::string cgroup_file;
1079 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/cgroup", tid), &cgroup_file)) {
1080 return "";
1081 }
1082 std::vector<std::string> cgroup_lines;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001083 Split(cgroup_file, '\n', &cgroup_lines);
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001084 for (size_t i = 0; i < cgroup_lines.size(); ++i) {
1085 std::vector<std::string> cgroup_fields;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001086 Split(cgroup_lines[i], ':', &cgroup_fields);
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001087 std::vector<std::string> cgroups;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001088 Split(cgroup_fields[1], ',', &cgroups);
Andreas Gampe277ccbd2014-11-03 21:36:10 -08001089 for (size_t j = 0; j < cgroups.size(); ++j) {
1090 if (cgroups[j] == "cpu") {
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001091 return cgroup_fields[2].substr(1); // Skip the leading slash.
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001092 }
1093 }
1094 }
1095 return "";
1096}
1097
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001098const char* GetAndroidRoot() {
1099 const char* android_root = getenv("ANDROID_ROOT");
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001100 if (android_root == nullptr) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001101 if (OS::DirectoryExists("/system")) {
1102 android_root = "/system";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001103 } else {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001104 LOG(FATAL) << "ANDROID_ROOT not set and /system does not exist";
1105 return "";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001106 }
1107 }
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001108 if (!OS::DirectoryExists(android_root)) {
1109 LOG(FATAL) << "Failed to find ANDROID_ROOT directory " << android_root;
Brian Carlstroma9f19782011-10-13 00:14:47 -07001110 return "";
1111 }
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001112 return android_root;
1113}
Brian Carlstroma9f19782011-10-13 00:14:47 -07001114
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001115const char* GetAndroidData() {
Alex Lighta59dd802014-07-02 16:28:08 -07001116 std::string error_msg;
1117 const char* dir = GetAndroidDataSafe(&error_msg);
1118 if (dir != nullptr) {
1119 return dir;
1120 } else {
1121 LOG(FATAL) << error_msg;
1122 return "";
1123 }
1124}
1125
1126const char* GetAndroidDataSafe(std::string* error_msg) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001127 const char* android_data = getenv("ANDROID_DATA");
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001128 if (android_data == nullptr) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001129 if (OS::DirectoryExists("/data")) {
1130 android_data = "/data";
1131 } else {
Alex Lighta59dd802014-07-02 16:28:08 -07001132 *error_msg = "ANDROID_DATA not set and /data does not exist";
1133 return nullptr;
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001134 }
1135 }
1136 if (!OS::DirectoryExists(android_data)) {
Alex Lighta59dd802014-07-02 16:28:08 -07001137 *error_msg = StringPrintf("Failed to find ANDROID_DATA directory %s", android_data);
1138 return nullptr;
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001139 }
1140 return android_data;
1141}
1142
Alex Lighta59dd802014-07-02 16:28:08 -07001143void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
Andreas Gampe3c13a792014-09-18 20:56:04 -07001144 bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
Alex Lighta59dd802014-07-02 16:28:08 -07001145 CHECK(subdir != nullptr);
1146 std::string error_msg;
1147 const char* android_data = GetAndroidDataSafe(&error_msg);
1148 if (android_data == nullptr) {
1149 *have_android_data = false;
1150 *dalvik_cache_exists = false;
Andreas Gampe3c13a792014-09-18 20:56:04 -07001151 *is_global_cache = false;
Alex Lighta59dd802014-07-02 16:28:08 -07001152 return;
1153 } else {
1154 *have_android_data = true;
1155 }
1156 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
1157 *dalvik_cache = dalvik_cache_root + subdir;
1158 *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
Andreas Gampe3c13a792014-09-18 20:56:04 -07001159 *is_global_cache = strcmp(android_data, "/data") == 0;
1160 if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) {
Alex Lighta59dd802014-07-02 16:28:08 -07001161 // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
1162 *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
1163 (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
1164 }
1165}
1166
Richard Uhler55b58b62016-08-12 09:05:13 -07001167std::string GetDalvikCache(const char* subdir) {
Narayan Kamath11d9f062014-04-23 20:24:57 +01001168 CHECK(subdir != nullptr);
Brian Carlstrom41ccffd2014-05-06 10:37:30 -07001169 const char* android_data = GetAndroidData();
1170 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
Narayan Kamath11d9f062014-04-23 20:24:57 +01001171 const std::string dalvik_cache = dalvik_cache_root + subdir;
Andreas Gampe40da2862015-02-27 12:49:04 -08001172 if (!OS::DirectoryExists(dalvik_cache.c_str())) {
Richard Uhler55b58b62016-08-12 09:05:13 -07001173 // TODO: Check callers. Traditional behavior is to not abort.
1174 return "";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001175 }
Brian Carlstrom7675e162013-06-10 16:18:04 -07001176 return dalvik_cache;
Brian Carlstroma9f19782011-10-13 00:14:47 -07001177}
1178
Alex Lighta59dd802014-07-02 16:28:08 -07001179bool GetDalvikCacheFilename(const char* location, const char* cache_location,
1180 std::string* filename, std::string* error_msg) {
Ian Rogerse6060102013-05-16 12:01:04 -07001181 if (location[0] != '/') {
Alex Lighta59dd802014-07-02 16:28:08 -07001182 *error_msg = StringPrintf("Expected path in location to be absolute: %s", location);
1183 return false;
Ian Rogerse6060102013-05-16 12:01:04 -07001184 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001185 std::string cache_file(&location[1]); // skip leading slash
Alex Light6e183f22014-07-18 14:57:04 -07001186 if (!EndsWith(location, ".dex") && !EndsWith(location, ".art") && !EndsWith(location, ".oat")) {
Brian Carlstrom30e2ea42013-06-19 23:25:37 -07001187 cache_file += "/";
1188 cache_file += DexFile::kClassesDex;
1189 }
Brian Carlstromb7bbba42011-10-13 14:58:47 -07001190 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
Alex Lighta59dd802014-07-02 16:28:08 -07001191 *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
1192 return true;
1193}
1194
Brian Carlstrom2afe4942014-05-19 10:25:33 -07001195static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) {
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -07001196 // in = /foo/bar/baz
1197 // out = /foo/bar/<isa>/baz
1198 size_t pos = filename->rfind('/');
1199 CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
1200 filename->insert(pos, "/", 1);
1201 filename->insert(pos + 1, GetInstructionSetString(isa));
1202}
1203
1204std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
1205 // location = /system/framework/boot.art
1206 // filename = /system/framework/<isa>/boot.art
1207 std::string filename(location);
Brian Carlstrom2afe4942014-05-19 10:25:33 -07001208 InsertIsaDirectory(isa, &filename);
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -07001209 return filename;
1210}
1211
Calin Juravle2e2db782016-02-23 12:00:03 +00001212int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) {
Brian Carlstrom6449c622014-02-10 23:48:36 -08001213 const std::string command_line(Join(arg_vector, ' '));
Brian Carlstrom6449c622014-02-10 23:48:36 -08001214 CHECK_GE(arg_vector.size(), 1U) << command_line;
1215
1216 // Convert the args to char pointers.
1217 const char* program = arg_vector[0].c_str();
1218 std::vector<char*> args;
Brian Carlstrom35d8b8e2014-02-25 10:51:11 -08001219 for (size_t i = 0; i < arg_vector.size(); ++i) {
1220 const std::string& arg = arg_vector[i];
1221 char* arg_str = const_cast<char*>(arg.c_str());
1222 CHECK(arg_str != nullptr) << i;
1223 args.push_back(arg_str);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001224 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001225 args.push_back(nullptr);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001226
1227 // fork and exec
1228 pid_t pid = fork();
1229 if (pid == 0) {
1230 // no allocation allowed between fork and exec
1231
1232 // change process groups, so we don't get reaped by ProcessManager
1233 setpgid(0, 0);
1234
David Sehrd106d9f2016-08-16 19:22:57 -07001235 // (b/30160149): protect subprocesses from modifications to LD_LIBRARY_PATH, etc.
1236 // Use the snapshot of the environment from the time the runtime was created.
1237 char** envp = (Runtime::Current() == nullptr) ? nullptr : Runtime::Current()->GetEnvSnapshot();
1238 if (envp == nullptr) {
1239 execv(program, &args[0]);
1240 } else {
1241 execve(program, &args[0], envp);
1242 }
1243 PLOG(ERROR) << "Failed to execve(" << command_line << ")";
Tobias Lindskogae35c372015-11-04 19:41:21 +01001244 // _exit to avoid atexit handlers in child.
1245 _exit(1);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001246 } else {
1247 if (pid == -1) {
1248 *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
1249 command_line.c_str(), strerror(errno));
Calin Juravle2e2db782016-02-23 12:00:03 +00001250 return -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001251 }
1252
1253 // wait for subprocess to finish
Calin Juravle2e2db782016-02-23 12:00:03 +00001254 int status = -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001255 pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
1256 if (got_pid != pid) {
1257 *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
1258 "wanted %d, got %d: %s",
1259 command_line.c_str(), pid, got_pid, strerror(errno));
Calin Juravle2e2db782016-02-23 12:00:03 +00001260 return -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001261 }
Calin Juravle2e2db782016-02-23 12:00:03 +00001262 if (WIFEXITED(status)) {
1263 return WEXITSTATUS(status);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001264 }
Calin Juravle2e2db782016-02-23 12:00:03 +00001265 return -1;
1266 }
1267}
1268
1269bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
1270 int status = ExecAndReturnCode(arg_vector, error_msg);
1271 if (status != 0) {
1272 const std::string command_line(Join(arg_vector, ' '));
1273 *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
1274 command_line.c_str());
1275 return false;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001276 }
1277 return true;
1278}
1279
Calin Juravle5e2b9712015-12-18 14:10:00 +02001280bool FileExists(const std::string& filename) {
1281 struct stat buffer;
1282 return stat(filename.c_str(), &buffer) == 0;
1283}
1284
Calin Juravleb9c1b9b2016-03-17 17:07:52 +00001285bool FileExistsAndNotEmpty(const std::string& filename) {
1286 struct stat buffer;
1287 if (stat(filename.c_str(), &buffer) != 0) {
1288 return false;
1289 }
1290 return buffer.st_size > 0;
1291}
1292
David Brazdil7b49e6c2016-09-01 11:06:18 +01001293std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
1294 const size_t last_ext = filename.find_last_of('.');
1295 if (last_ext == std::string::npos) {
1296 return filename + "." + new_extension;
1297 } else {
1298 return filename.substr(0, last_ext + 1) + new_extension;
1299 }
1300}
1301
Mathieu Chartier76433272014-09-26 14:32:37 -07001302std::string PrettyDescriptor(Primitive::Type type) {
1303 return PrettyDescriptor(Primitive::Descriptor(type));
1304}
1305
Andreas Gampe5073fed2015-08-10 11:40:25 -07001306static void DumpMethodCFGImpl(const DexFile* dex_file,
1307 uint32_t dex_method_idx,
1308 const DexFile::CodeItem* code_item,
1309 std::ostream& os) {
1310 os << "digraph {\n";
1311 os << " # /* " << PrettyMethod(dex_method_idx, *dex_file, true) << " */\n";
1312
1313 std::set<uint32_t> dex_pc_is_branch_target;
1314 {
1315 // Go and populate.
1316 const Instruction* inst = Instruction::At(code_item->insns_);
1317 for (uint32_t dex_pc = 0;
1318 dex_pc < code_item->insns_size_in_code_units_;
1319 dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
1320 if (inst->IsBranch()) {
1321 dex_pc_is_branch_target.insert(dex_pc + inst->GetTargetOffset());
1322 } else if (inst->IsSwitch()) {
1323 const uint16_t* insns = code_item->insns_ + dex_pc;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001324 int32_t switch_offset = insns[1] | (static_cast<int32_t>(insns[2]) << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001325 const uint16_t* switch_insns = insns + switch_offset;
1326 uint32_t switch_count = switch_insns[1];
1327 int32_t targets_offset;
1328 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
1329 /* 0=sig, 1=count, 2/3=firstKey */
1330 targets_offset = 4;
1331 } else {
1332 /* 0=sig, 1=count, 2..count*2 = keys */
1333 targets_offset = 2 + 2 * switch_count;
1334 }
1335 for (uint32_t targ = 0; targ < switch_count; targ++) {
Andreas Gampe53de99c2015-08-17 13:43:55 -07001336 int32_t offset =
1337 static_cast<int32_t>(switch_insns[targets_offset + targ * 2]) |
1338 static_cast<int32_t>(switch_insns[targets_offset + targ * 2 + 1] << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001339 dex_pc_is_branch_target.insert(dex_pc + offset);
1340 }
1341 }
1342 }
1343 }
1344
1345 // Create nodes for "basic blocks."
1346 std::map<uint32_t, uint32_t> dex_pc_to_node_id; // This only has entries for block starts.
1347 std::map<uint32_t, uint32_t> dex_pc_to_incl_id; // This has entries for all dex pcs.
1348
1349 {
1350 const Instruction* inst = Instruction::At(code_item->insns_);
1351 bool first_in_block = true;
1352 bool force_new_block = false;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001353 for (uint32_t dex_pc = 0;
1354 dex_pc < code_item->insns_size_in_code_units_;
1355 dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
Andreas Gampe5073fed2015-08-10 11:40:25 -07001356 if (dex_pc == 0 ||
1357 (dex_pc_is_branch_target.find(dex_pc) != dex_pc_is_branch_target.end()) ||
1358 force_new_block) {
1359 uint32_t id = dex_pc_to_node_id.size();
1360 if (id > 0) {
1361 // End last node.
1362 os << "}\"];\n";
1363 }
1364 // Start next node.
1365 os << " node" << id << " [shape=record,label=\"{";
1366 dex_pc_to_node_id.insert(std::make_pair(dex_pc, id));
1367 first_in_block = true;
1368 force_new_block = false;
1369 }
1370
1371 // Register instruction.
1372 dex_pc_to_incl_id.insert(std::make_pair(dex_pc, dex_pc_to_node_id.size() - 1));
1373
1374 // Print instruction.
1375 if (!first_in_block) {
1376 os << " | ";
1377 } else {
1378 first_in_block = false;
1379 }
1380
1381 // Dump the instruction. Need to escape '"', '<', '>', '{' and '}'.
1382 os << "<" << "p" << dex_pc << ">";
1383 os << " 0x" << std::hex << dex_pc << std::dec << ": ";
1384 std::string inst_str = inst->DumpString(dex_file);
1385 size_t cur_start = 0; // It's OK to start at zero, instruction dumps don't start with chars
Andreas Gampe53de99c2015-08-17 13:43:55 -07001386 // we need to escape.
Andreas Gampe5073fed2015-08-10 11:40:25 -07001387 while (cur_start != std::string::npos) {
1388 size_t next_escape = inst_str.find_first_of("\"{}<>", cur_start + 1);
1389 if (next_escape == std::string::npos) {
1390 os << inst_str.substr(cur_start, inst_str.size() - cur_start);
1391 break;
1392 } else {
1393 os << inst_str.substr(cur_start, next_escape - cur_start);
1394 // Escape all necessary characters.
1395 while (next_escape < inst_str.size()) {
1396 char c = inst_str.at(next_escape);
1397 if (c == '"' || c == '{' || c == '}' || c == '<' || c == '>') {
1398 os << '\\' << c;
1399 } else {
1400 break;
1401 }
1402 next_escape++;
1403 }
1404 if (next_escape >= inst_str.size()) {
1405 next_escape = std::string::npos;
1406 }
1407 cur_start = next_escape;
1408 }
1409 }
1410
1411 // Force a new block for some fall-throughs and some instructions that terminate the "local"
1412 // control flow.
1413 force_new_block = inst->IsSwitch() || inst->IsBasicBlockEnd();
1414 }
1415 // Close last node.
1416 if (dex_pc_to_node_id.size() > 0) {
1417 os << "}\"];\n";
1418 }
1419 }
1420
1421 // Create edges between them.
1422 {
1423 std::ostringstream regular_edges;
1424 std::ostringstream taken_edges;
1425 std::ostringstream exception_edges;
1426
1427 // Common set of exception edges.
1428 std::set<uint32_t> exception_targets;
1429
1430 // These blocks (given by the first dex pc) need exception per dex-pc handling in a second
1431 // pass. In the first pass we try and see whether we can use a common set of edges.
1432 std::set<uint32_t> blocks_with_detailed_exceptions;
1433
1434 {
1435 uint32_t last_node_id = std::numeric_limits<uint32_t>::max();
1436 uint32_t old_dex_pc = 0;
1437 uint32_t block_start_dex_pc = std::numeric_limits<uint32_t>::max();
1438 const Instruction* inst = Instruction::At(code_item->insns_);
1439 for (uint32_t dex_pc = 0;
1440 dex_pc < code_item->insns_size_in_code_units_;
1441 old_dex_pc = dex_pc, dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
1442 {
1443 auto it = dex_pc_to_node_id.find(dex_pc);
1444 if (it != dex_pc_to_node_id.end()) {
1445 if (!exception_targets.empty()) {
1446 // It seems the last block had common exception handlers. Add the exception edges now.
1447 uint32_t node_id = dex_pc_to_node_id.find(block_start_dex_pc)->second;
1448 for (uint32_t handler_pc : exception_targets) {
1449 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1450 if (node_id_it != dex_pc_to_incl_id.end()) {
1451 exception_edges << " node" << node_id
1452 << " -> node" << node_id_it->second << ":p" << handler_pc
1453 << ";\n";
1454 }
1455 }
1456 exception_targets.clear();
1457 }
1458
1459 block_start_dex_pc = dex_pc;
1460
1461 // Seems to be a fall-through, connect to last_node_id. May be spurious edges for things
1462 // like switch data.
1463 uint32_t old_last = last_node_id;
1464 last_node_id = it->second;
1465 if (old_last != std::numeric_limits<uint32_t>::max()) {
1466 regular_edges << " node" << old_last << ":p" << old_dex_pc
1467 << " -> node" << last_node_id << ":p" << dex_pc
1468 << ";\n";
1469 }
1470 }
1471
1472 // Look at the exceptions of the first entry.
1473 CatchHandlerIterator catch_it(*code_item, dex_pc);
1474 for (; catch_it.HasNext(); catch_it.Next()) {
1475 exception_targets.insert(catch_it.GetHandlerAddress());
1476 }
1477 }
1478
1479 // Handle instruction.
1480
1481 // Branch: something with at most two targets.
1482 if (inst->IsBranch()) {
1483 const int32_t offset = inst->GetTargetOffset();
1484 const bool conditional = !inst->IsUnconditional();
1485
1486 auto target_it = dex_pc_to_node_id.find(dex_pc + offset);
1487 if (target_it != dex_pc_to_node_id.end()) {
1488 taken_edges << " node" << last_node_id << ":p" << dex_pc
1489 << " -> node" << target_it->second << ":p" << (dex_pc + offset)
1490 << ";\n";
1491 }
1492 if (!conditional) {
1493 // No fall-through.
1494 last_node_id = std::numeric_limits<uint32_t>::max();
1495 }
1496 } else if (inst->IsSwitch()) {
1497 // TODO: Iterate through all switch targets.
1498 const uint16_t* insns = code_item->insns_ + dex_pc;
1499 /* make sure the start of the switch is in range */
Andreas Gampe53de99c2015-08-17 13:43:55 -07001500 int32_t switch_offset = insns[1] | (static_cast<int32_t>(insns[2]) << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001501 /* offset to switch table is a relative branch-style offset */
1502 const uint16_t* switch_insns = insns + switch_offset;
1503 uint32_t switch_count = switch_insns[1];
1504 int32_t targets_offset;
1505 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
1506 /* 0=sig, 1=count, 2/3=firstKey */
1507 targets_offset = 4;
1508 } else {
1509 /* 0=sig, 1=count, 2..count*2 = keys */
1510 targets_offset = 2 + 2 * switch_count;
1511 }
1512 /* make sure the end of the switch is in range */
1513 /* verify each switch target */
1514 for (uint32_t targ = 0; targ < switch_count; targ++) {
Andreas Gampe53de99c2015-08-17 13:43:55 -07001515 int32_t offset =
1516 static_cast<int32_t>(switch_insns[targets_offset + targ * 2]) |
1517 static_cast<int32_t>(switch_insns[targets_offset + targ * 2 + 1] << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001518 int32_t abs_offset = dex_pc + offset;
1519 auto target_it = dex_pc_to_node_id.find(abs_offset);
1520 if (target_it != dex_pc_to_node_id.end()) {
1521 // TODO: value label.
1522 taken_edges << " node" << last_node_id << ":p" << dex_pc
1523 << " -> node" << target_it->second << ":p" << (abs_offset)
1524 << ";\n";
1525 }
1526 }
1527 }
1528
1529 // Exception edges. If this is not the first instruction in the block
1530 if (block_start_dex_pc != dex_pc) {
1531 std::set<uint32_t> current_handler_pcs;
1532 CatchHandlerIterator catch_it(*code_item, dex_pc);
1533 for (; catch_it.HasNext(); catch_it.Next()) {
1534 current_handler_pcs.insert(catch_it.GetHandlerAddress());
1535 }
1536 if (current_handler_pcs != exception_targets) {
1537 exception_targets.clear(); // Clear so we don't do something at the end.
1538 blocks_with_detailed_exceptions.insert(block_start_dex_pc);
1539 }
1540 }
1541
1542 if (inst->IsReturn() ||
1543 (inst->Opcode() == Instruction::THROW) ||
1544 (inst->IsBranch() && inst->IsUnconditional())) {
1545 // No fall-through.
1546 last_node_id = std::numeric_limits<uint32_t>::max();
1547 }
1548 }
1549 // Finish up the last block, if it had common exceptions.
1550 if (!exception_targets.empty()) {
1551 // It seems the last block had common exception handlers. Add the exception edges now.
1552 uint32_t node_id = dex_pc_to_node_id.find(block_start_dex_pc)->second;
1553 for (uint32_t handler_pc : exception_targets) {
1554 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1555 if (node_id_it != dex_pc_to_incl_id.end()) {
1556 exception_edges << " node" << node_id
1557 << " -> node" << node_id_it->second << ":p" << handler_pc
1558 << ";\n";
1559 }
1560 }
1561 exception_targets.clear();
1562 }
1563 }
1564
1565 // Second pass for detailed exception blocks.
1566 // TODO
1567 // Exception edges. If this is not the first instruction in the block
1568 for (uint32_t dex_pc : blocks_with_detailed_exceptions) {
1569 const Instruction* inst = Instruction::At(&code_item->insns_[dex_pc]);
1570 uint32_t this_node_id = dex_pc_to_incl_id.find(dex_pc)->second;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001571 while (true) {
Andreas Gampe5073fed2015-08-10 11:40:25 -07001572 CatchHandlerIterator catch_it(*code_item, dex_pc);
1573 if (catch_it.HasNext()) {
1574 std::set<uint32_t> handled_targets;
1575 for (; catch_it.HasNext(); catch_it.Next()) {
1576 uint32_t handler_pc = catch_it.GetHandlerAddress();
1577 auto it = handled_targets.find(handler_pc);
1578 if (it == handled_targets.end()) {
1579 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1580 if (node_id_it != dex_pc_to_incl_id.end()) {
1581 exception_edges << " node" << this_node_id << ":p" << dex_pc
1582 << " -> node" << node_id_it->second << ":p" << handler_pc
1583 << ";\n";
1584 }
1585
1586 // Mark as done.
1587 handled_targets.insert(handler_pc);
1588 }
1589 }
1590 }
1591 if (inst->IsBasicBlockEnd()) {
1592 break;
1593 }
1594
Andreas Gampe53de99c2015-08-17 13:43:55 -07001595 // Loop update. Have a break-out if the next instruction is a branch target and thus in
1596 // another block.
Andreas Gampe5073fed2015-08-10 11:40:25 -07001597 dex_pc += inst->SizeInCodeUnits();
1598 if (dex_pc >= code_item->insns_size_in_code_units_) {
1599 break;
1600 }
1601 if (dex_pc_to_node_id.find(dex_pc) != dex_pc_to_node_id.end()) {
1602 break;
1603 }
1604 inst = inst->Next();
1605 }
1606 }
1607
1608 // Write out the sub-graphs to make edges styled.
1609 os << "\n";
1610 os << " subgraph regular_edges {\n";
1611 os << " edge [color=\"#000000\",weight=.3,len=3];\n\n";
1612 os << " " << regular_edges.str() << "\n";
1613 os << " }\n\n";
1614
1615 os << " subgraph taken_edges {\n";
1616 os << " edge [color=\"#00FF00\",weight=.3,len=3];\n\n";
1617 os << " " << taken_edges.str() << "\n";
1618 os << " }\n\n";
1619
1620 os << " subgraph exception_edges {\n";
1621 os << " edge [color=\"#FF0000\",weight=.3,len=3];\n\n";
1622 os << " " << exception_edges.str() << "\n";
1623 os << " }\n\n";
1624 }
1625
1626 os << "}\n";
1627}
1628
1629void DumpMethodCFG(ArtMethod* method, std::ostream& os) {
1630 const DexFile* dex_file = method->GetDexFile();
1631 const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
1632
1633 DumpMethodCFGImpl(dex_file, method->GetDexMethodIndex(), code_item, os);
1634}
1635
1636void DumpMethodCFG(const DexFile* dex_file, uint32_t dex_method_idx, std::ostream& os) {
1637 // This is painful, we need to find the code item. That means finding the class, and then
1638 // iterating the table.
1639 if (dex_method_idx >= dex_file->NumMethodIds()) {
1640 os << "Could not find method-idx.";
1641 return;
1642 }
1643 const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
1644
1645 const DexFile::ClassDef* class_def = dex_file->FindClassDef(method_id.class_idx_);
1646 if (class_def == nullptr) {
1647 os << "Could not find class-def.";
1648 return;
1649 }
1650
1651 const uint8_t* class_data = dex_file->GetClassData(*class_def);
1652 if (class_data == nullptr) {
1653 os << "No class data.";
1654 return;
1655 }
1656
1657 ClassDataItemIterator it(*dex_file, class_data);
1658 // Skip fields
1659 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
1660 it.Next();
1661 }
1662
1663 // Find method, and dump it.
1664 while (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
1665 uint32_t method_idx = it.GetMemberIndex();
1666 if (method_idx == dex_method_idx) {
1667 DumpMethodCFGImpl(dex_file, dex_method_idx, it.GetMethodCodeItem(), os);
1668 return;
1669 }
1670 it.Next();
1671 }
1672
1673 // Otherwise complain.
1674 os << "Something went wrong, didn't find the method in the class data.";
1675}
1676
Nicolas Geoffrayabbb0f72015-10-29 18:55:58 +00001677static void ParseStringAfterChar(const std::string& s,
1678 char c,
1679 std::string* parsed_value,
1680 UsageFn Usage) {
1681 std::string::size_type colon = s.find(c);
1682 if (colon == std::string::npos) {
1683 Usage("Missing char %c in option %s\n", c, s.c_str());
1684 }
1685 // Add one to remove the char we were trimming until.
1686 *parsed_value = s.substr(colon + 1);
1687}
1688
1689void ParseDouble(const std::string& option,
1690 char after_char,
1691 double min,
1692 double max,
1693 double* parsed_value,
1694 UsageFn Usage) {
1695 std::string substring;
1696 ParseStringAfterChar(option, after_char, &substring, Usage);
1697 bool sane_val = true;
1698 double value;
1699 if ((false)) {
1700 // TODO: this doesn't seem to work on the emulator. b/15114595
1701 std::stringstream iss(substring);
1702 iss >> value;
1703 // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
1704 sane_val = iss.eof() && (value >= min) && (value <= max);
1705 } else {
1706 char* end = nullptr;
1707 value = strtod(substring.c_str(), &end);
1708 sane_val = *end == '\0' && value >= min && value <= max;
1709 }
1710 if (!sane_val) {
1711 Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str());
1712 }
1713 *parsed_value = value;
1714}
1715
Calin Juravle4d77b6a2015-12-01 18:38:09 +00001716int64_t GetFileSizeBytes(const std::string& filename) {
1717 struct stat stat_buf;
1718 int rc = stat(filename.c_str(), &stat_buf);
1719 return rc == 0 ? stat_buf.st_size : -1;
1720}
1721
Mathieu Chartier4d87df62016-01-07 15:14:19 -08001722void SleepForever() {
1723 while (true) {
1724 usleep(1000000);
1725 }
1726}
1727
Elliott Hughes42ee1422011-09-06 12:33:32 -07001728} // namespace art