blob: 6f3402f0c638f9c650b1888d6bc73ba1bf4070d7 [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"
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070040#include "obj_ptr-inl.h"
buzbeec143c552011-08-20 17:38:58 -070041#include "os.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070042#include "scoped_thread_state_change-inl.h"
Ian Rogersa6724902013-09-23 09:23:37 -070043#include "utf-inl.h"
Elliott Hughes11e45072011-08-16 17:40:46 -070044
Elliott Hughes4ae722a2012-03-13 11:08:51 -070045#if defined(__APPLE__)
Brian Carlstrom7934ac22013-07-26 10:54:15 -070046#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
Elliott Hughesf1498432012-03-28 19:34:27 -070047#include <sys/syscall.h>
David Sehrfa442002016-08-22 18:42:08 -070048#include <crt_externs.h>
Elliott Hughes4ae722a2012-03-13 11:08:51 -070049#endif
50
Elliott Hughes058a6de2012-05-24 19:13:02 -070051#if defined(__linux__)
Elliott Hughese1aee692012-01-17 16:40:10 -080052#include <linux/unistd.h>
Elliott Hughese1aee692012-01-17 16:40:10 -080053#endif
54
Elliott Hughes11e45072011-08-16 17:40:46 -070055namespace art {
56
Alex Light9c20a142016-08-23 15:05:12 -070057static const uint8_t kBase64Map[256] = {
58 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
59 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
60 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
61 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
62 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
63 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
64 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT
65 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT
66 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
67 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT
68 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT
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, 255, 255, 255, 255, 255, 255, 255, 255,
78 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
79 255, 255, 255, 255
80};
81
82uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
83 std::vector<uint8_t> tmp;
84 uint32_t t = 0, y = 0;
85 int g = 3;
86 for (size_t i = 0; src[i] != '\0'; ++i) {
87 uint8_t c = kBase64Map[src[i] & 0xFF];
88 if (c == 255) continue;
89 // the final = symbols are read and used to trim the remaining bytes
90 if (c == 254) {
91 c = 0;
92 // prevent g < 0 which would potentially allow an overflow later
93 if (--g < 0) {
94 *dst_size = 0;
95 return nullptr;
96 }
97 } else if (g != 3) {
98 // we only allow = to be at the end
99 *dst_size = 0;
100 return nullptr;
101 }
102 t = (t << 6) | c;
103 if (++y == 4) {
104 tmp.push_back((t >> 16) & 255);
105 if (g > 1) {
106 tmp.push_back((t >> 8) & 255);
107 }
108 if (g > 2) {
109 tmp.push_back(t & 255);
110 }
111 y = t = 0;
112 }
113 }
114 if (y != 0) {
115 *dst_size = 0;
116 return nullptr;
117 }
118 std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
119 if (dst_size != nullptr) {
120 *dst_size = tmp.size();
121 } else {
122 *dst_size = 0;
123 }
124 std::copy(tmp.begin(), tmp.end(), dst.get());
125 return dst.release();
126}
127
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800128pid_t GetTid() {
Brian Carlstromf3a26412012-08-24 11:06:02 -0700129#if defined(__APPLE__)
130 uint64_t owner;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700131 CHECK_PTHREAD_CALL(pthread_threadid_np, (nullptr, &owner), __FUNCTION__); // Requires Mac OS 10.6
Brian Carlstromf3a26412012-08-24 11:06:02 -0700132 return owner;
Elliott Hughes323aa862014-08-20 15:00:04 -0700133#elif defined(__BIONIC__)
134 return gettid();
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800135#else
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800136 return syscall(__NR_gettid);
137#endif
138}
139
Elliott Hughes289be852012-06-12 13:57:20 -0700140std::string GetThreadName(pid_t tid) {
141 std::string result;
142 if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700143 result.resize(result.size() - 1); // Lose the trailing '\n'.
Elliott Hughes289be852012-06-12 13:57:20 -0700144 } else {
145 result = "<unknown>";
146 }
147 return result;
148}
149
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700150void GetThreadStack(pthread_t thread, void** stack_base, size_t* stack_size, size_t* guard_size) {
Elliott Hughese1884192012-04-23 12:38:15 -0700151#if defined(__APPLE__)
Brian Carlstrom29212012013-09-12 22:18:30 -0700152 *stack_size = pthread_get_stacksize_np(thread);
Ian Rogers120f1c72012-09-28 17:17:10 -0700153 void* stack_addr = pthread_get_stackaddr_np(thread);
Elliott Hughese1884192012-04-23 12:38:15 -0700154
155 // Check whether stack_addr is the base or end of the stack.
156 // (On Mac OS 10.7, it's the end.)
157 int stack_variable;
158 if (stack_addr > &stack_variable) {
Ian Rogers13735952014-10-08 12:43:28 -0700159 *stack_base = reinterpret_cast<uint8_t*>(stack_addr) - *stack_size;
Elliott Hughese1884192012-04-23 12:38:15 -0700160 } else {
Brian Carlstrom29212012013-09-12 22:18:30 -0700161 *stack_base = stack_addr;
Elliott Hughese1884192012-04-23 12:38:15 -0700162 }
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700163
164 // This is wrong, but there doesn't seem to be a way to get the actual value on the Mac.
165 pthread_attr_t attributes;
166 CHECK_PTHREAD_CALL(pthread_attr_init, (&attributes), __FUNCTION__);
167 CHECK_PTHREAD_CALL(pthread_attr_getguardsize, (&attributes, guard_size), __FUNCTION__);
168 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
Elliott Hughese1884192012-04-23 12:38:15 -0700169#else
170 pthread_attr_t attributes;
Ian Rogers120f1c72012-09-28 17:17:10 -0700171 CHECK_PTHREAD_CALL(pthread_getattr_np, (thread, &attributes), __FUNCTION__);
Brian Carlstrom29212012013-09-12 22:18:30 -0700172 CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, stack_base, stack_size), __FUNCTION__);
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700173 CHECK_PTHREAD_CALL(pthread_attr_getguardsize, (&attributes, guard_size), __FUNCTION__);
Elliott Hughese1884192012-04-23 12:38:15 -0700174 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
Elliott Hughes839cc302014-08-28 10:24:44 -0700175
176#if defined(__GLIBC__)
177 // If we're the main thread, check whether we were run with an unlimited stack. In that case,
178 // glibc will have reported a 2GB stack for our 32-bit process, and our stack overflow detection
179 // will be broken because we'll die long before we get close to 2GB.
180 bool is_main_thread = (::art::GetTid() == getpid());
181 if (is_main_thread) {
182 rlimit stack_limit;
183 if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) {
184 PLOG(FATAL) << "getrlimit(RLIMIT_STACK) failed";
185 }
186 if (stack_limit.rlim_cur == RLIM_INFINITY) {
187 size_t old_stack_size = *stack_size;
188
189 // Use the kernel default limit as our size, and adjust the base to match.
190 *stack_size = 8 * MB;
191 *stack_base = reinterpret_cast<uint8_t*>(*stack_base) + (old_stack_size - *stack_size);
192
193 VLOG(threads) << "Limiting unlimited stack (reported as " << PrettySize(old_stack_size) << ")"
194 << " to " << PrettySize(*stack_size)
195 << " with base " << *stack_base;
196 }
197 }
198#endif
199
Elliott Hughese1884192012-04-23 12:38:15 -0700200#endif
201}
202
Elliott Hughesd92bec42011-09-02 17:04:36 -0700203bool ReadFileToString(const std::string& file_name, std::string* result) {
Andreas Gampedf878922015-08-13 16:44:54 -0700204 File file(file_name, O_RDONLY, false);
205 if (!file.IsOpened()) {
Elliott Hughesd92bec42011-09-02 17:04:36 -0700206 return false;
207 }
buzbeec143c552011-08-20 17:38:58 -0700208
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700209 std::vector<char> buf(8 * KB);
buzbeec143c552011-08-20 17:38:58 -0700210 while (true) {
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800211 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
Elliott Hughesd92bec42011-09-02 17:04:36 -0700212 if (n == -1) {
213 return false;
buzbeec143c552011-08-20 17:38:58 -0700214 }
Elliott Hughesd92bec42011-09-02 17:04:36 -0700215 if (n == 0) {
216 return true;
217 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700218 result->append(&buf[0], n);
buzbeec143c552011-08-20 17:38:58 -0700219 }
buzbeec143c552011-08-20 17:38:58 -0700220}
221
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800222bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
Andreas Gampedf878922015-08-13 16:44:54 -0700223 File file(file_name, O_RDONLY, false);
224 if (!file.IsOpened()) {
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800225 return false;
226 }
227
228 constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings.
229 char buf[kBufSize + 1]; // +1 for terminator.
230 size_t filled_to = 0;
231 while (true) {
232 DCHECK_LT(filled_to, kBufSize);
233 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
234 if (n <= 0) {
235 // Print the rest of the buffer, if it exists.
236 if (filled_to > 0) {
237 buf[filled_to] = 0;
238 LOG(level) << buf;
239 }
240 return n == 0;
241 }
242 // Scan for '\n'.
243 size_t i = filled_to;
244 bool found_newline = false;
245 for (; i < filled_to + n; ++i) {
246 if (buf[i] == '\n') {
247 // Found a line break, that's something to print now.
248 buf[i] = 0;
249 LOG(level) << buf;
250 // Copy the rest to the front.
251 if (i + 1 < filled_to + n) {
252 memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
253 filled_to = filled_to + n - i - 1;
254 } else {
255 filled_to = 0;
256 }
257 found_newline = true;
258 break;
259 }
260 }
261 if (found_newline) {
262 continue;
263 } else {
264 filled_to += n;
265 // Check if we must flush now.
266 if (filled_to == kBufSize) {
267 buf[kBufSize] = 0;
268 LOG(level) << buf;
269 filled_to = 0;
270 }
271 }
272 }
273}
274
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700275std::string PrettyStringDescriptor(ObjPtr<mirror::String> java_descriptor) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700276 if (java_descriptor == nullptr) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700277 return "null";
278 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700279 return PrettyDescriptor(java_descriptor->ToModifiedUtf8().c_str());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700280}
Elliott Hughes5174fe62011-08-23 15:12:35 -0700281
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700282std::string PrettyDescriptor(ObjPtr<mirror::Class> klass) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700283 if (klass == nullptr) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800284 return "null";
285 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700286 std::string temp;
287 return PrettyDescriptor(klass->GetDescriptor(&temp));
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800288}
289
Ian Rogers1ff3c982014-08-12 02:30:58 -0700290std::string PrettyDescriptor(const char* descriptor) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700291 // Count the number of '['s to get the dimensionality.
Ian Rogers1ff3c982014-08-12 02:30:58 -0700292 const char* c = descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700293 size_t dim = 0;
294 while (*c == '[') {
295 dim++;
296 c++;
297 }
298
299 // Reference or primitive?
300 if (*c == 'L') {
301 // "[[La/b/C;" -> "a.b.C[][]".
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700302 c++; // Skip the 'L'.
Elliott Hughes11e45072011-08-16 17:40:46 -0700303 } else {
304 // "[[B" -> "byte[][]".
305 // To make life easier, we make primitives look like unqualified
306 // reference types.
307 switch (*c) {
308 case 'B': c = "byte;"; break;
309 case 'C': c = "char;"; break;
310 case 'D': c = "double;"; break;
311 case 'F': c = "float;"; break;
312 case 'I': c = "int;"; break;
313 case 'J': c = "long;"; break;
314 case 'S': c = "short;"; break;
315 case 'Z': c = "boolean;"; break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700316 case 'V': c = "void;"; break; // Used when decoding return types.
Elliott Hughes5174fe62011-08-23 15:12:35 -0700317 default: return descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700318 }
319 }
320
321 // At this point, 'c' is a string of the form "fully/qualified/Type;"
322 // or "primitive;". Rewrite the type with '.' instead of '/':
323 std::string result;
324 const char* p = c;
325 while (*p != ';') {
326 char ch = *p++;
327 if (ch == '/') {
328 ch = '.';
329 }
330 result.push_back(ch);
331 }
332 // ...and replace the semicolon with 'dim' "[]" pairs:
Ian Rogers1ff3c982014-08-12 02:30:58 -0700333 for (size_t i = 0; i < dim; ++i) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700334 result += "[]";
335 }
336 return result;
337}
338
Mathieu Chartierc7853442015-03-27 14:35:38 -0700339std::string PrettyField(ArtField* f, bool with_type) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700340 if (f == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700341 return "null";
342 }
Elliott Hughes54e7df12011-09-16 11:47:04 -0700343 std::string result;
344 if (with_type) {
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700345 result += PrettyDescriptor(f->GetTypeDescriptor());
Elliott Hughes54e7df12011-09-16 11:47:04 -0700346 result += ' ';
347 }
Ian Rogers08f1f502014-12-02 15:04:37 -0800348 std::string temp;
349 result += PrettyDescriptor(f->GetDeclaringClass()->GetDescriptor(&temp));
Elliott Hughesa2501992011-08-26 19:39:54 -0700350 result += '.';
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700351 result += f->GetName();
Elliott Hughesa2501992011-08-26 19:39:54 -0700352 return result;
353}
354
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700355std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800356 if (field_idx >= dex_file.NumFieldIds()) {
357 return StringPrintf("<<invalid-field-idx-%d>>", field_idx);
358 }
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700359 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
360 std::string result;
361 if (with_type) {
362 result += dex_file.GetFieldTypeDescriptor(field_id);
363 result += ' ';
364 }
365 result += PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(field_id));
366 result += '.';
367 result += dex_file.GetFieldName(field_id);
368 return result;
369}
370
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700371std::string PrettyType(uint32_t type_idx, const DexFile& dex_file) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800372 if (type_idx >= dex_file.NumTypeIds()) {
373 return StringPrintf("<<invalid-type-idx-%d>>", type_idx);
374 }
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700375 const DexFile::TypeId& type_id = dex_file.GetTypeId(type_idx);
Mathieu Chartier4c70d772012-09-10 14:08:32 -0700376 return PrettyDescriptor(dex_file.GetTypeDescriptor(type_id));
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700377}
378
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700379std::string PrettyArguments(const char* signature) {
380 std::string result;
381 result += '(';
382 CHECK_EQ(*signature, '(');
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700383 ++signature; // Skip the '('.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700384 while (*signature != ')') {
385 size_t argument_length = 0;
386 while (signature[argument_length] == '[') {
387 ++argument_length;
388 }
389 if (signature[argument_length] == 'L') {
390 argument_length = (strchr(signature, ';') - signature + 1);
391 } else {
392 ++argument_length;
393 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700394 {
395 std::string argument_descriptor(signature, argument_length);
396 result += PrettyDescriptor(argument_descriptor.c_str());
397 }
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700398 if (signature[argument_length] != ')') {
399 result += ", ";
400 }
401 signature += argument_length;
402 }
403 CHECK_EQ(*signature, ')');
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700404 ++signature; // Skip the ')'.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700405 result += ')';
406 return result;
407}
408
409std::string PrettyReturnType(const char* signature) {
410 const char* return_type = strchr(signature, ')');
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700411 CHECK(return_type != nullptr);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700412 ++return_type; // Skip ')'.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700413 return PrettyDescriptor(return_type);
414}
415
Mathieu Chartiere401d142015-04-22 13:56:20 -0700416std::string PrettyMethod(ArtMethod* m, bool with_signature) {
Ian Rogers16ce0922014-01-10 14:59:36 -0800417 if (m == nullptr) {
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700418 return "null";
419 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700420 if (!m->IsRuntimeMethod()) {
421 m = m->GetInterfaceMethodIfProxy(Runtime::Current()->GetClassLinker()->GetImagePointerSize());
422 }
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700423 std::string result(PrettyDescriptor(m->GetDeclaringClassDescriptor()));
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700424 result += '.';
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700425 result += m->GetName();
Ian Rogers16ce0922014-01-10 14:59:36 -0800426 if (UNLIKELY(m->IsFastNative())) {
427 result += "!";
428 }
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700429 if (with_signature) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700430 const Signature signature = m->GetSignature();
Ian Rogersd91d6d62013-09-25 20:26:14 -0700431 std::string sig_as_string(signature.ToString());
432 if (signature == Signature::NoSignature()) {
433 return result + sig_as_string;
Elliott Hughesf8c11932012-03-23 19:53:59 -0700434 }
Ian Rogersd91d6d62013-09-25 20:26:14 -0700435 result = PrettyReturnType(sig_as_string.c_str()) + " " + result +
436 PrettyArguments(sig_as_string.c_str());
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700437 }
438 return result;
439}
440
Ian Rogers0571d352011-11-03 19:51:38 -0700441std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800442 if (method_idx >= dex_file.NumMethodIds()) {
443 return StringPrintf("<<invalid-method-idx-%d>>", method_idx);
444 }
Ian Rogers0571d352011-11-03 19:51:38 -0700445 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
446 std::string result(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(method_id)));
447 result += '.';
448 result += dex_file.GetMethodName(method_id);
449 if (with_signature) {
Ian Rogersd91d6d62013-09-25 20:26:14 -0700450 const Signature signature = dex_file.GetMethodSignature(method_id);
451 std::string sig_as_string(signature.ToString());
452 if (signature == Signature::NoSignature()) {
453 return result + sig_as_string;
Elliott Hughesf8c11932012-03-23 19:53:59 -0700454 }
Ian Rogersd91d6d62013-09-25 20:26:14 -0700455 result = PrettyReturnType(sig_as_string.c_str()) + " " + result +
456 PrettyArguments(sig_as_string.c_str());
Ian Rogers0571d352011-11-03 19:51:38 -0700457 }
458 return result;
459}
460
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700461std::string PrettyTypeOf(ObjPtr<mirror::Object> obj) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700462 if (obj == nullptr) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700463 return "null";
464 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700465 if (obj->GetClass() == nullptr) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700466 return "(raw)";
467 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700468 std::string temp;
469 std::string result(PrettyDescriptor(obj->GetClass()->GetDescriptor(&temp)));
Elliott Hughes11e45072011-08-16 17:40:46 -0700470 if (obj->IsClass()) {
Ian Rogers1ff3c982014-08-12 02:30:58 -0700471 result += "<" + PrettyDescriptor(obj->AsClass()->GetDescriptor(&temp)) + ">";
Elliott Hughes11e45072011-08-16 17:40:46 -0700472 }
473 return result;
474}
475
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700476std::string PrettyClass(ObjPtr<mirror::Class> c) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700477 if (c == nullptr) {
Elliott Hughes54e7df12011-09-16 11:47:04 -0700478 return "null";
479 }
480 std::string result;
481 result += "java.lang.Class<";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800482 result += PrettyDescriptor(c);
Elliott Hughes54e7df12011-09-16 11:47:04 -0700483 result += ">";
484 return result;
485}
486
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700487std::string PrettyClassAndClassLoader(ObjPtr<mirror::Class> c) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700488 if (c == nullptr) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700489 return "null";
490 }
491 std::string result;
492 result += "java.lang.Class<";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800493 result += PrettyDescriptor(c);
Ian Rogersd81871c2011-10-03 13:57:23 -0700494 result += ",";
495 result += PrettyTypeOf(c->GetClassLoader());
496 // TODO: add an identifying hash value for the loader
497 result += ">";
498 return result;
499}
500
Andreas Gampec0d82292014-09-23 10:38:30 -0700501std::string PrettyJavaAccessFlags(uint32_t access_flags) {
502 std::string result;
503 if ((access_flags & kAccPublic) != 0) {
504 result += "public ";
505 }
506 if ((access_flags & kAccProtected) != 0) {
507 result += "protected ";
508 }
509 if ((access_flags & kAccPrivate) != 0) {
510 result += "private ";
511 }
512 if ((access_flags & kAccFinal) != 0) {
513 result += "final ";
514 }
515 if ((access_flags & kAccStatic) != 0) {
516 result += "static ";
517 }
David Brazdilca3c8c32016-09-06 14:04:48 +0100518 if ((access_flags & kAccAbstract) != 0) {
519 result += "abstract ";
520 }
521 if ((access_flags & kAccInterface) != 0) {
522 result += "interface ";
523 }
Andreas Gampec0d82292014-09-23 10:38:30 -0700524 if ((access_flags & kAccTransient) != 0) {
525 result += "transient ";
526 }
527 if ((access_flags & kAccVolatile) != 0) {
528 result += "volatile ";
529 }
530 if ((access_flags & kAccSynchronized) != 0) {
531 result += "synchronized ";
532 }
533 return result;
534}
535
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800536std::string PrettySize(int64_t byte_count) {
Elliott Hughesc967f782012-04-16 10:23:15 -0700537 // The byte thresholds at which we display amounts. A byte count is displayed
538 // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
Ian Rogersef7d42f2014-01-06 12:55:46 -0800539 static const int64_t kUnitThresholds[] = {
Elliott Hughesc967f782012-04-16 10:23:15 -0700540 0, // B up to...
541 3*1024, // KB up to...
542 2*1024*1024, // MB up to...
543 1024*1024*1024 // GB from here.
544 };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800545 static const int64_t kBytesPerUnit[] = { 1, KB, MB, GB };
Elliott Hughesc967f782012-04-16 10:23:15 -0700546 static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800547 const char* negative_str = "";
548 if (byte_count < 0) {
549 negative_str = "-";
550 byte_count = -byte_count;
551 }
Elliott Hughesc967f782012-04-16 10:23:15 -0700552 int i = arraysize(kUnitThresholds);
553 while (--i > 0) {
554 if (byte_count >= kUnitThresholds[i]) {
555 break;
556 }
Ian Rogers3bb17a62012-01-27 23:56:44 -0800557 }
Brian Carlstrom474cc792014-03-07 14:18:15 -0800558 return StringPrintf("%s%" PRId64 "%s",
559 negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
Ian Rogers3bb17a62012-01-27 23:56:44 -0800560}
561
Ian Rogers576ca0c2014-06-06 15:58:22 -0700562std::string PrintableChar(uint16_t ch) {
563 std::string result;
564 result += '\'';
565 if (NeedsEscaping(ch)) {
566 StringAppendF(&result, "\\u%04x", ch);
567 } else {
568 result += ch;
569 }
570 result += '\'';
571 return result;
572}
573
Ian Rogers68b56852014-08-29 20:19:11 -0700574std::string PrintableString(const char* utf) {
Elliott Hughes82914b62012-04-09 15:56:29 -0700575 std::string result;
576 result += '"';
Ian Rogers68b56852014-08-29 20:19:11 -0700577 const char* p = utf;
Elliott Hughes82914b62012-04-09 15:56:29 -0700578 size_t char_count = CountModifiedUtf8Chars(p);
579 for (size_t i = 0; i < char_count; ++i) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000580 uint32_t ch = GetUtf16FromUtf8(&p);
Elliott Hughes82914b62012-04-09 15:56:29 -0700581 if (ch == '\\') {
582 result += "\\\\";
583 } else if (ch == '\n') {
584 result += "\\n";
585 } else if (ch == '\r') {
586 result += "\\r";
587 } else if (ch == '\t') {
588 result += "\\t";
Elliott Hughes82914b62012-04-09 15:56:29 -0700589 } else {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000590 const uint16_t leading = GetLeadingUtf16Char(ch);
591
592 if (NeedsEscaping(leading)) {
593 StringAppendF(&result, "\\u%04x", leading);
594 } else {
595 result += leading;
596 }
597
598 const uint32_t trailing = GetTrailingUtf16Char(ch);
599 if (trailing != 0) {
600 // All high surrogates will need escaping.
601 StringAppendF(&result, "\\u%04x", trailing);
602 }
Elliott Hughes82914b62012-04-09 15:56:29 -0700603 }
604 }
605 result += '"';
606 return result;
607}
608
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800609// 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 -0700610std::string MangleForJni(const std::string& s) {
611 std::string result;
612 size_t char_count = CountModifiedUtf8Chars(s.c_str());
613 const char* cp = &s[0];
614 for (size_t i = 0; i < char_count; ++i) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000615 uint32_t ch = GetUtf16FromUtf8(&cp);
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800616 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
617 result.push_back(ch);
618 } else if (ch == '.' || ch == '/') {
619 result += "_";
620 } else if (ch == '_') {
621 result += "_1";
622 } else if (ch == ';') {
623 result += "_2";
624 } else if (ch == '[') {
625 result += "_3";
Elliott Hughes79082e32011-08-25 12:07:32 -0700626 } else {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000627 const uint16_t leading = GetLeadingUtf16Char(ch);
628 const uint32_t trailing = GetTrailingUtf16Char(ch);
629
630 StringAppendF(&result, "_0%04x", leading);
631 if (trailing != 0) {
632 StringAppendF(&result, "_0%04x", trailing);
633 }
Elliott Hughes79082e32011-08-25 12:07:32 -0700634 }
635 }
636 return result;
637}
638
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700639std::string DotToDescriptor(const char* class_name) {
640 std::string descriptor(class_name);
641 std::replace(descriptor.begin(), descriptor.end(), '.', '/');
642 if (descriptor.length() > 0 && descriptor[0] != '[') {
643 descriptor = "L" + descriptor + ";";
644 }
645 return descriptor;
646}
647
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800648std::string DescriptorToDot(const char* descriptor) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800649 size_t length = strlen(descriptor);
Ian Rogers1ff3c982014-08-12 02:30:58 -0700650 if (length > 1) {
651 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
652 // Descriptors have the leading 'L' and trailing ';' stripped.
653 std::string result(descriptor + 1, length - 2);
654 std::replace(result.begin(), result.end(), '/', '.');
655 return result;
656 } else {
657 // For arrays the 'L' and ';' remain intact.
658 std::string result(descriptor);
659 std::replace(result.begin(), result.end(), '/', '.');
660 return result;
661 }
Elliott Hughes2435a572012-02-17 16:07:41 -0800662 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700663 // Do nothing for non-class/array descriptors.
Elliott Hughes2435a572012-02-17 16:07:41 -0800664 return descriptor;
Elliott Hughes91bf6cd2012-02-14 17:27:48 -0800665}
666
667std::string DescriptorToName(const char* descriptor) {
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800668 size_t length = strlen(descriptor);
Elliott Hughes2435a572012-02-17 16:07:41 -0800669 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
670 std::string result(descriptor + 1, length - 2);
671 return result;
672 }
673 return descriptor;
Brian Carlstromaded5f72011-10-07 17:15:04 -0700674}
675
Mathieu Chartiere401d142015-04-22 13:56:20 -0700676std::string JniShortName(ArtMethod* m) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700677 std::string class_name(m->GetDeclaringClassDescriptor());
Elliott Hughes79082e32011-08-25 12:07:32 -0700678 // Remove the leading 'L' and trailing ';'...
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700679 CHECK_EQ(class_name[0], 'L') << class_name;
680 CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name;
Elliott Hughes79082e32011-08-25 12:07:32 -0700681 class_name.erase(0, 1);
682 class_name.erase(class_name.size() - 1, 1);
683
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700684 std::string method_name(m->GetName());
Elliott Hughes79082e32011-08-25 12:07:32 -0700685
686 std::string short_name;
687 short_name += "Java_";
688 short_name += MangleForJni(class_name);
689 short_name += "_";
690 short_name += MangleForJni(method_name);
691 return short_name;
692}
693
Mathieu Chartiere401d142015-04-22 13:56:20 -0700694std::string JniLongName(ArtMethod* m) {
Elliott Hughes79082e32011-08-25 12:07:32 -0700695 std::string long_name;
696 long_name += JniShortName(m);
697 long_name += "__";
698
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700699 std::string signature(m->GetSignature().ToString());
Elliott Hughes79082e32011-08-25 12:07:32 -0700700 signature.erase(0, 1);
701 signature.erase(signature.begin() + signature.find(')'), signature.end());
702
703 long_name += MangleForJni(signature);
704
705 return long_name;
706}
707
jeffhao10037c82012-01-23 15:06:23 -0800708// Helper for IsValidPartOfMemberNameUtf8(), a bit vector indicating valid low ascii.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700709uint32_t DEX_MEMBER_VALID_LOW_ASCII[4] = {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700710 0x00000000, // 00..1f low control characters; nothing valid
711 0x03ff2010, // 20..3f digits and symbols; valid: '0'..'9', '$', '-'
712 0x87fffffe, // 40..5f uppercase etc.; valid: 'A'..'Z', '_'
713 0x07fffffe // 60..7f lowercase etc.; valid: 'a'..'z'
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700714};
715
jeffhao10037c82012-01-23 15:06:23 -0800716// Helper for IsValidPartOfMemberNameUtf8(); do not call directly.
717bool IsValidPartOfMemberNameUtf8Slow(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700718 /*
719 * It's a multibyte encoded character. Decode it and analyze. We
720 * accept anything that isn't (a) an improperly encoded low value,
721 * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high
722 * control character, or (e) a high space, layout, or special
723 * character (U+00a0, U+2000..U+200f, U+2028..U+202f,
724 * U+fff0..U+ffff). This is all specified in the dex format
725 * document.
726 */
727
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000728 const uint32_t pair = GetUtf16FromUtf8(pUtf8Ptr);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000729 const uint16_t leading = GetLeadingUtf16Char(pair);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000730
Narayan Kamath8508e372015-05-06 14:55:43 +0100731 // We have a surrogate pair resulting from a valid 4 byte UTF sequence.
732 // No further checks are necessary because 4 byte sequences span code
733 // points [U+10000, U+1FFFFF], which are valid codepoints in a dex
734 // identifier. Furthermore, GetUtf16FromUtf8 guarantees that each of
735 // the surrogate halves are valid and well formed in this instance.
736 if (GetTrailingUtf16Char(pair) != 0) {
737 return true;
738 }
739
740
741 // We've encountered a one, two or three byte UTF-8 sequence. The
742 // three byte UTF-8 sequence could be one half of a surrogate pair.
743 switch (leading >> 8) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000744 case 0x00:
745 // It's only valid if it's above the ISO-8859-1 high space (0xa0).
746 return (leading > 0x00a0);
747 case 0xd8:
748 case 0xd9:
749 case 0xda:
750 case 0xdb:
Narayan Kamath8508e372015-05-06 14:55:43 +0100751 {
752 // We found a three byte sequence encoding one half of a surrogate.
753 // Look for the other half.
754 const uint32_t pair2 = GetUtf16FromUtf8(pUtf8Ptr);
755 const uint16_t trailing = GetLeadingUtf16Char(pair2);
756
757 return (GetTrailingUtf16Char(pair2) == 0) && (0xdc00 <= trailing && trailing <= 0xdfff);
758 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000759 case 0xdc:
760 case 0xdd:
761 case 0xde:
762 case 0xdf:
763 // It's a trailing surrogate, which is not valid at this point.
764 return false;
765 case 0x20:
766 case 0xff:
767 // It's in the range that has spaces, controls, and specials.
768 switch (leading & 0xfff8) {
Narayan Kamath8508e372015-05-06 14:55:43 +0100769 case 0x2000:
770 case 0x2008:
771 case 0x2028:
772 case 0xfff0:
773 case 0xfff8:
774 return false;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000775 }
Narayan Kamath8508e372015-05-06 14:55:43 +0100776 return true;
777 default:
778 return true;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700779 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000780
Narayan Kamath8508e372015-05-06 14:55:43 +0100781 UNREACHABLE();
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700782}
783
784/* Return whether the pointed-at modified-UTF-8 encoded character is
785 * valid as part of a member name, updating the pointer to point past
786 * the consumed character. This will consume two encoded UTF-16 code
787 * points if the character is encoded as a surrogate pair. Also, if
788 * this function returns false, then the given pointer may only have
789 * been partially advanced.
790 */
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700791static bool IsValidPartOfMemberNameUtf8(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700792 uint8_t c = (uint8_t) **pUtf8Ptr;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700793 if (LIKELY(c <= 0x7f)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700794 // It's low-ascii, so check the table.
795 uint32_t wordIdx = c >> 5;
796 uint32_t bitIdx = c & 0x1f;
797 (*pUtf8Ptr)++;
798 return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0;
799 }
800
801 // It's a multibyte encoded character. Call a non-inline function
802 // for the heavy lifting.
jeffhao10037c82012-01-23 15:06:23 -0800803 return IsValidPartOfMemberNameUtf8Slow(pUtf8Ptr);
804}
805
806bool IsValidMemberName(const char* s) {
807 bool angle_name = false;
808
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700809 switch (*s) {
jeffhao10037c82012-01-23 15:06:23 -0800810 case '\0':
811 // The empty string is not a valid name.
812 return false;
813 case '<':
814 angle_name = true;
815 s++;
816 break;
817 }
818
819 while (true) {
820 switch (*s) {
821 case '\0':
822 return !angle_name;
823 case '>':
824 return angle_name && s[1] == '\0';
825 }
826
827 if (!IsValidPartOfMemberNameUtf8(&s)) {
828 return false;
829 }
830 }
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700831}
832
Elliott Hughes906e6852011-10-28 14:52:10 -0700833enum ClassNameType { kName, kDescriptor };
Ian Rogers7b078e82014-09-10 14:44:24 -0700834template<ClassNameType kType, char kSeparator>
835static bool IsValidClassName(const char* s) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700836 int arrayCount = 0;
837 while (*s == '[') {
838 arrayCount++;
839 s++;
840 }
841
842 if (arrayCount > 255) {
843 // Arrays may have no more than 255 dimensions.
844 return false;
845 }
846
Ian Rogers7b078e82014-09-10 14:44:24 -0700847 ClassNameType type = kType;
848 if (type != kDescriptor && arrayCount != 0) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700849 /*
850 * If we're looking at an array of some sort, then it doesn't
851 * matter if what is being asked for is a class name; the
852 * format looks the same as a type descriptor in that case, so
853 * treat it as such.
854 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700855 type = kDescriptor;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700856 }
857
Elliott Hughes906e6852011-10-28 14:52:10 -0700858 if (type == kDescriptor) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700859 /*
860 * We are looking for a descriptor. Either validate it as a
861 * single-character primitive type, or continue on to check the
862 * embedded class name (bracketed by "L" and ";").
863 */
864 switch (*(s++)) {
865 case 'B':
866 case 'C':
867 case 'D':
868 case 'F':
869 case 'I':
870 case 'J':
871 case 'S':
872 case 'Z':
873 // These are all single-character descriptors for primitive types.
874 return (*s == '\0');
875 case 'V':
876 // Non-array void is valid, but you can't have an array of void.
877 return (arrayCount == 0) && (*s == '\0');
878 case 'L':
879 // Class name: Break out and continue below.
880 break;
881 default:
882 // Oddball descriptor character.
883 return false;
884 }
885 }
886
887 /*
888 * We just consumed the 'L' that introduces a class name as part
889 * of a type descriptor, or we are looking for an unadorned class
890 * name.
891 */
892
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700893 bool sepOrFirst = true; // first character or just encountered a separator.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700894 for (;;) {
895 uint8_t c = (uint8_t) *s;
896 switch (c) {
897 case '\0':
898 /*
899 * Premature end for a type descriptor, but valid for
900 * a class name as long as we haven't encountered an
901 * empty component (including the degenerate case of
902 * the empty string "").
903 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700904 return (type == kName) && !sepOrFirst;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700905 case ';':
906 /*
907 * Invalid character for a class name, but the
908 * legitimate end of a type descriptor. In the latter
909 * case, make sure that this is the end of the string
910 * and that it doesn't end with an empty component
911 * (including the degenerate case of "L;").
912 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700913 return (type == kDescriptor) && !sepOrFirst && (s[1] == '\0');
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700914 case '/':
915 case '.':
Ian Rogers7b078e82014-09-10 14:44:24 -0700916 if (c != kSeparator) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700917 // The wrong separator character.
918 return false;
919 }
920 if (sepOrFirst) {
921 // Separator at start or two separators in a row.
922 return false;
923 }
924 sepOrFirst = true;
925 s++;
926 break;
927 default:
jeffhao10037c82012-01-23 15:06:23 -0800928 if (!IsValidPartOfMemberNameUtf8(&s)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700929 return false;
930 }
931 sepOrFirst = false;
932 break;
933 }
934 }
935}
936
Elliott Hughes906e6852011-10-28 14:52:10 -0700937bool IsValidBinaryClassName(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700938 return IsValidClassName<kName, '.'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700939}
940
941bool IsValidJniClassName(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700942 return IsValidClassName<kName, '/'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700943}
944
945bool IsValidDescriptor(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700946 return IsValidClassName<kDescriptor, '/'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700947}
948
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700949void Split(const std::string& s, char separator, std::vector<std::string>* result) {
Elliott Hughes34023802011-08-30 12:06:17 -0700950 const char* p = s.data();
951 const char* end = p + s.size();
952 while (p != end) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800953 if (*p == separator) {
Elliott Hughes34023802011-08-30 12:06:17 -0700954 ++p;
955 } else {
956 const char* start = p;
Elliott Hughes48436bb2012-02-07 15:23:28 -0800957 while (++p != end && *p != separator) {
958 // Skip to the next occurrence of the separator.
Elliott Hughes34023802011-08-30 12:06:17 -0700959 }
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700960 result->push_back(std::string(start, p - start));
Elliott Hughes34023802011-08-30 12:06:17 -0700961 }
962 }
963}
964
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700965std::string Trim(const std::string& s) {
Dave Allison70202782013-10-22 17:52:19 -0700966 std::string result;
967 unsigned int start_index = 0;
968 unsigned int end_index = s.size() - 1;
969
970 // Skip initial whitespace.
971 while (start_index < s.size()) {
972 if (!isspace(s[start_index])) {
973 break;
974 }
975 start_index++;
976 }
977
978 // Skip terminating whitespace.
979 while (end_index >= start_index) {
980 if (!isspace(s[end_index])) {
981 break;
982 }
983 end_index--;
984 }
985
986 // All spaces, no beef.
987 if (end_index < start_index) {
988 return "";
989 }
990 // Start_index is the first non-space, end_index is the last one.
991 return s.substr(start_index, end_index - start_index + 1);
992}
993
Elliott Hughes48436bb2012-02-07 15:23:28 -0800994template <typename StringT>
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700995std::string Join(const std::vector<StringT>& strings, char separator) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800996 if (strings.empty()) {
997 return "";
998 }
999
1000 std::string result(strings[0]);
1001 for (size_t i = 1; i < strings.size(); ++i) {
1002 result += separator;
1003 result += strings[i];
1004 }
1005 return result;
1006}
1007
1008// Explicit instantiations.
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001009template std::string Join<std::string>(const std::vector<std::string>& strings, char separator);
1010template std::string Join<const char*>(const std::vector<const char*>& strings, char separator);
Elliott Hughes48436bb2012-02-07 15:23:28 -08001011
Elliott Hughesf1a5adc2012-02-10 18:09:35 -08001012bool StartsWith(const std::string& s, const char* prefix) {
1013 return s.compare(0, strlen(prefix), prefix) == 0;
1014}
1015
Brian Carlstrom7a967b32012-03-28 15:23:10 -07001016bool EndsWith(const std::string& s, const char* suffix) {
1017 size_t suffix_length = strlen(suffix);
1018 size_t string_length = s.size();
1019 if (suffix_length > string_length) {
1020 return false;
1021 }
1022 size_t offset = string_length - suffix_length;
1023 return s.compare(offset, suffix_length, suffix) == 0;
1024}
1025
Elliott Hughes22869a92012-03-27 14:08:24 -07001026void SetThreadName(const char* thread_name) {
Elliott Hughesdcc24742011-09-07 14:02:44 -07001027 int hasAt = 0;
1028 int hasDot = 0;
Elliott Hughes22869a92012-03-27 14:08:24 -07001029 const char* s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001030 while (*s) {
1031 if (*s == '.') {
1032 hasDot = 1;
1033 } else if (*s == '@') {
1034 hasAt = 1;
1035 }
1036 s++;
1037 }
Elliott Hughes22869a92012-03-27 14:08:24 -07001038 int len = s - thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001039 if (len < 15 || hasAt || !hasDot) {
Elliott Hughes22869a92012-03-27 14:08:24 -07001040 s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001041 } else {
Elliott Hughes22869a92012-03-27 14:08:24 -07001042 s = thread_name + len - 15;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001043 }
Elliott Hughes0a18df82015-01-09 15:16:16 -08001044#if defined(__linux__)
Elliott Hughes7c6a61e2012-03-12 18:01:41 -07001045 // pthread_setname_np fails rather than truncating long strings.
Elliott Hughes0a18df82015-01-09 15:16:16 -08001046 char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel.
Elliott Hughesdcc24742011-09-07 14:02:44 -07001047 strncpy(buf, s, sizeof(buf)-1);
1048 buf[sizeof(buf)-1] = '\0';
1049 errno = pthread_setname_np(pthread_self(), buf);
1050 if (errno != 0) {
1051 PLOG(WARNING) << "Unable to set the name of current thread to '" << buf << "'";
1052 }
Elliott Hughes0a18df82015-01-09 15:16:16 -08001053#else // __APPLE__
Elliott Hughes22869a92012-03-27 14:08:24 -07001054 pthread_setname_np(thread_name);
Elliott Hughesdcc24742011-09-07 14:02:44 -07001055#endif
1056}
1057
Brian Carlstrom29212012013-09-12 22:18:30 -07001058void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
1059 *utime = *stime = *task_cpu = 0;
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001060 std::string stats;
Elliott Hughes8a31b502012-04-30 19:36:11 -07001061 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001062 return;
1063 }
1064 // Skip the command, which may contain spaces.
1065 stats = stats.substr(stats.find(')') + 2);
1066 // Extract the three fields we care about.
1067 std::vector<std::string> fields;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001068 Split(stats, ' ', &fields);
Brian Carlstrom29212012013-09-12 22:18:30 -07001069 *state = fields[0][0];
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001070 *utime = strtoull(fields[11].c_str(), nullptr, 10);
1071 *stime = strtoull(fields[12].c_str(), nullptr, 10);
1072 *task_cpu = strtoull(fields[36].c_str(), nullptr, 10);
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001073}
1074
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001075std::string GetSchedulerGroupName(pid_t tid) {
1076 // /proc/<pid>/cgroup looks like this:
1077 // 2:devices:/
1078 // 1:cpuacct,cpu:/
1079 // We want the third field from the line whose second field contains the "cpu" token.
1080 std::string cgroup_file;
1081 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/cgroup", tid), &cgroup_file)) {
1082 return "";
1083 }
1084 std::vector<std::string> cgroup_lines;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001085 Split(cgroup_file, '\n', &cgroup_lines);
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001086 for (size_t i = 0; i < cgroup_lines.size(); ++i) {
1087 std::vector<std::string> cgroup_fields;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001088 Split(cgroup_lines[i], ':', &cgroup_fields);
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001089 std::vector<std::string> cgroups;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001090 Split(cgroup_fields[1], ',', &cgroups);
Andreas Gampe277ccbd2014-11-03 21:36:10 -08001091 for (size_t j = 0; j < cgroups.size(); ++j) {
1092 if (cgroups[j] == "cpu") {
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001093 return cgroup_fields[2].substr(1); // Skip the leading slash.
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001094 }
1095 }
1096 }
1097 return "";
1098}
1099
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001100const char* GetAndroidRoot() {
1101 const char* android_root = getenv("ANDROID_ROOT");
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001102 if (android_root == nullptr) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001103 if (OS::DirectoryExists("/system")) {
1104 android_root = "/system";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001105 } else {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001106 LOG(FATAL) << "ANDROID_ROOT not set and /system does not exist";
1107 return "";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001108 }
1109 }
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001110 if (!OS::DirectoryExists(android_root)) {
1111 LOG(FATAL) << "Failed to find ANDROID_ROOT directory " << android_root;
Brian Carlstroma9f19782011-10-13 00:14:47 -07001112 return "";
1113 }
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001114 return android_root;
1115}
Brian Carlstroma9f19782011-10-13 00:14:47 -07001116
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001117const char* GetAndroidData() {
Alex Lighta59dd802014-07-02 16:28:08 -07001118 std::string error_msg;
1119 const char* dir = GetAndroidDataSafe(&error_msg);
1120 if (dir != nullptr) {
1121 return dir;
1122 } else {
1123 LOG(FATAL) << error_msg;
1124 return "";
1125 }
1126}
1127
1128const char* GetAndroidDataSafe(std::string* error_msg) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001129 const char* android_data = getenv("ANDROID_DATA");
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001130 if (android_data == nullptr) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001131 if (OS::DirectoryExists("/data")) {
1132 android_data = "/data";
1133 } else {
Alex Lighta59dd802014-07-02 16:28:08 -07001134 *error_msg = "ANDROID_DATA not set and /data does not exist";
1135 return nullptr;
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001136 }
1137 }
1138 if (!OS::DirectoryExists(android_data)) {
Alex Lighta59dd802014-07-02 16:28:08 -07001139 *error_msg = StringPrintf("Failed to find ANDROID_DATA directory %s", android_data);
1140 return nullptr;
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001141 }
1142 return android_data;
1143}
1144
Alex Lighta59dd802014-07-02 16:28:08 -07001145void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
Andreas Gampe3c13a792014-09-18 20:56:04 -07001146 bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
Alex Lighta59dd802014-07-02 16:28:08 -07001147 CHECK(subdir != nullptr);
1148 std::string error_msg;
1149 const char* android_data = GetAndroidDataSafe(&error_msg);
1150 if (android_data == nullptr) {
1151 *have_android_data = false;
1152 *dalvik_cache_exists = false;
Andreas Gampe3c13a792014-09-18 20:56:04 -07001153 *is_global_cache = false;
Alex Lighta59dd802014-07-02 16:28:08 -07001154 return;
1155 } else {
1156 *have_android_data = true;
1157 }
1158 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
1159 *dalvik_cache = dalvik_cache_root + subdir;
1160 *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
Andreas Gampe3c13a792014-09-18 20:56:04 -07001161 *is_global_cache = strcmp(android_data, "/data") == 0;
1162 if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) {
Alex Lighta59dd802014-07-02 16:28:08 -07001163 // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
1164 *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
1165 (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
1166 }
1167}
1168
Richard Uhler55b58b62016-08-12 09:05:13 -07001169std::string GetDalvikCache(const char* subdir) {
Narayan Kamath11d9f062014-04-23 20:24:57 +01001170 CHECK(subdir != nullptr);
Brian Carlstrom41ccffd2014-05-06 10:37:30 -07001171 const char* android_data = GetAndroidData();
1172 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
Narayan Kamath11d9f062014-04-23 20:24:57 +01001173 const std::string dalvik_cache = dalvik_cache_root + subdir;
Andreas Gampe40da2862015-02-27 12:49:04 -08001174 if (!OS::DirectoryExists(dalvik_cache.c_str())) {
Richard Uhler55b58b62016-08-12 09:05:13 -07001175 // TODO: Check callers. Traditional behavior is to not abort.
1176 return "";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001177 }
Brian Carlstrom7675e162013-06-10 16:18:04 -07001178 return dalvik_cache;
Brian Carlstroma9f19782011-10-13 00:14:47 -07001179}
1180
Alex Lighta59dd802014-07-02 16:28:08 -07001181bool GetDalvikCacheFilename(const char* location, const char* cache_location,
1182 std::string* filename, std::string* error_msg) {
Ian Rogerse6060102013-05-16 12:01:04 -07001183 if (location[0] != '/') {
Alex Lighta59dd802014-07-02 16:28:08 -07001184 *error_msg = StringPrintf("Expected path in location to be absolute: %s", location);
1185 return false;
Ian Rogerse6060102013-05-16 12:01:04 -07001186 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001187 std::string cache_file(&location[1]); // skip leading slash
Alex Light6e183f22014-07-18 14:57:04 -07001188 if (!EndsWith(location, ".dex") && !EndsWith(location, ".art") && !EndsWith(location, ".oat")) {
Brian Carlstrom30e2ea42013-06-19 23:25:37 -07001189 cache_file += "/";
1190 cache_file += DexFile::kClassesDex;
1191 }
Brian Carlstromb7bbba42011-10-13 14:58:47 -07001192 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
Alex Lighta59dd802014-07-02 16:28:08 -07001193 *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
1194 return true;
1195}
1196
Brian Carlstrom2afe4942014-05-19 10:25:33 -07001197static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) {
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -07001198 // in = /foo/bar/baz
1199 // out = /foo/bar/<isa>/baz
1200 size_t pos = filename->rfind('/');
1201 CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
1202 filename->insert(pos, "/", 1);
1203 filename->insert(pos + 1, GetInstructionSetString(isa));
1204}
1205
1206std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
1207 // location = /system/framework/boot.art
1208 // filename = /system/framework/<isa>/boot.art
1209 std::string filename(location);
Brian Carlstrom2afe4942014-05-19 10:25:33 -07001210 InsertIsaDirectory(isa, &filename);
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -07001211 return filename;
1212}
1213
Calin Juravle2e2db782016-02-23 12:00:03 +00001214int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) {
Brian Carlstrom6449c622014-02-10 23:48:36 -08001215 const std::string command_line(Join(arg_vector, ' '));
Brian Carlstrom6449c622014-02-10 23:48:36 -08001216 CHECK_GE(arg_vector.size(), 1U) << command_line;
1217
1218 // Convert the args to char pointers.
1219 const char* program = arg_vector[0].c_str();
1220 std::vector<char*> args;
Brian Carlstrom35d8b8e2014-02-25 10:51:11 -08001221 for (size_t i = 0; i < arg_vector.size(); ++i) {
1222 const std::string& arg = arg_vector[i];
1223 char* arg_str = const_cast<char*>(arg.c_str());
1224 CHECK(arg_str != nullptr) << i;
1225 args.push_back(arg_str);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001226 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001227 args.push_back(nullptr);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001228
1229 // fork and exec
1230 pid_t pid = fork();
1231 if (pid == 0) {
1232 // no allocation allowed between fork and exec
1233
1234 // change process groups, so we don't get reaped by ProcessManager
1235 setpgid(0, 0);
1236
David Sehrd106d9f2016-08-16 19:22:57 -07001237 // (b/30160149): protect subprocesses from modifications to LD_LIBRARY_PATH, etc.
1238 // Use the snapshot of the environment from the time the runtime was created.
1239 char** envp = (Runtime::Current() == nullptr) ? nullptr : Runtime::Current()->GetEnvSnapshot();
1240 if (envp == nullptr) {
1241 execv(program, &args[0]);
1242 } else {
1243 execve(program, &args[0], envp);
1244 }
1245 PLOG(ERROR) << "Failed to execve(" << command_line << ")";
Tobias Lindskogae35c372015-11-04 19:41:21 +01001246 // _exit to avoid atexit handlers in child.
1247 _exit(1);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001248 } else {
1249 if (pid == -1) {
1250 *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
1251 command_line.c_str(), strerror(errno));
Calin Juravle2e2db782016-02-23 12:00:03 +00001252 return -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001253 }
1254
1255 // wait for subprocess to finish
Calin Juravle2e2db782016-02-23 12:00:03 +00001256 int status = -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001257 pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
1258 if (got_pid != pid) {
1259 *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
1260 "wanted %d, got %d: %s",
1261 command_line.c_str(), pid, got_pid, strerror(errno));
Calin Juravle2e2db782016-02-23 12:00:03 +00001262 return -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001263 }
Calin Juravle2e2db782016-02-23 12:00:03 +00001264 if (WIFEXITED(status)) {
1265 return WEXITSTATUS(status);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001266 }
Calin Juravle2e2db782016-02-23 12:00:03 +00001267 return -1;
1268 }
1269}
1270
1271bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
1272 int status = ExecAndReturnCode(arg_vector, error_msg);
1273 if (status != 0) {
1274 const std::string command_line(Join(arg_vector, ' '));
1275 *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
1276 command_line.c_str());
1277 return false;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001278 }
1279 return true;
1280}
1281
Calin Juravle5e2b9712015-12-18 14:10:00 +02001282bool FileExists(const std::string& filename) {
1283 struct stat buffer;
1284 return stat(filename.c_str(), &buffer) == 0;
1285}
1286
Calin Juravleb9c1b9b2016-03-17 17:07:52 +00001287bool FileExistsAndNotEmpty(const std::string& filename) {
1288 struct stat buffer;
1289 if (stat(filename.c_str(), &buffer) != 0) {
1290 return false;
1291 }
1292 return buffer.st_size > 0;
1293}
1294
David Brazdil7b49e6c2016-09-01 11:06:18 +01001295std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
1296 const size_t last_ext = filename.find_last_of('.');
1297 if (last_ext == std::string::npos) {
1298 return filename + "." + new_extension;
1299 } else {
1300 return filename.substr(0, last_ext + 1) + new_extension;
1301 }
1302}
1303
Mathieu Chartier76433272014-09-26 14:32:37 -07001304std::string PrettyDescriptor(Primitive::Type type) {
1305 return PrettyDescriptor(Primitive::Descriptor(type));
1306}
1307
Andreas Gampe5073fed2015-08-10 11:40:25 -07001308static void DumpMethodCFGImpl(const DexFile* dex_file,
1309 uint32_t dex_method_idx,
1310 const DexFile::CodeItem* code_item,
1311 std::ostream& os) {
1312 os << "digraph {\n";
1313 os << " # /* " << PrettyMethod(dex_method_idx, *dex_file, true) << " */\n";
1314
1315 std::set<uint32_t> dex_pc_is_branch_target;
1316 {
1317 // Go and populate.
1318 const Instruction* inst = Instruction::At(code_item->insns_);
1319 for (uint32_t dex_pc = 0;
1320 dex_pc < code_item->insns_size_in_code_units_;
1321 dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
1322 if (inst->IsBranch()) {
1323 dex_pc_is_branch_target.insert(dex_pc + inst->GetTargetOffset());
1324 } else if (inst->IsSwitch()) {
1325 const uint16_t* insns = code_item->insns_ + dex_pc;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001326 int32_t switch_offset = insns[1] | (static_cast<int32_t>(insns[2]) << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001327 const uint16_t* switch_insns = insns + switch_offset;
1328 uint32_t switch_count = switch_insns[1];
1329 int32_t targets_offset;
1330 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
1331 /* 0=sig, 1=count, 2/3=firstKey */
1332 targets_offset = 4;
1333 } else {
1334 /* 0=sig, 1=count, 2..count*2 = keys */
1335 targets_offset = 2 + 2 * switch_count;
1336 }
1337 for (uint32_t targ = 0; targ < switch_count; targ++) {
Andreas Gampe53de99c2015-08-17 13:43:55 -07001338 int32_t offset =
1339 static_cast<int32_t>(switch_insns[targets_offset + targ * 2]) |
1340 static_cast<int32_t>(switch_insns[targets_offset + targ * 2 + 1] << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001341 dex_pc_is_branch_target.insert(dex_pc + offset);
1342 }
1343 }
1344 }
1345 }
1346
1347 // Create nodes for "basic blocks."
1348 std::map<uint32_t, uint32_t> dex_pc_to_node_id; // This only has entries for block starts.
1349 std::map<uint32_t, uint32_t> dex_pc_to_incl_id; // This has entries for all dex pcs.
1350
1351 {
1352 const Instruction* inst = Instruction::At(code_item->insns_);
1353 bool first_in_block = true;
1354 bool force_new_block = false;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001355 for (uint32_t dex_pc = 0;
1356 dex_pc < code_item->insns_size_in_code_units_;
1357 dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
Andreas Gampe5073fed2015-08-10 11:40:25 -07001358 if (dex_pc == 0 ||
1359 (dex_pc_is_branch_target.find(dex_pc) != dex_pc_is_branch_target.end()) ||
1360 force_new_block) {
1361 uint32_t id = dex_pc_to_node_id.size();
1362 if (id > 0) {
1363 // End last node.
1364 os << "}\"];\n";
1365 }
1366 // Start next node.
1367 os << " node" << id << " [shape=record,label=\"{";
1368 dex_pc_to_node_id.insert(std::make_pair(dex_pc, id));
1369 first_in_block = true;
1370 force_new_block = false;
1371 }
1372
1373 // Register instruction.
1374 dex_pc_to_incl_id.insert(std::make_pair(dex_pc, dex_pc_to_node_id.size() - 1));
1375
1376 // Print instruction.
1377 if (!first_in_block) {
1378 os << " | ";
1379 } else {
1380 first_in_block = false;
1381 }
1382
1383 // Dump the instruction. Need to escape '"', '<', '>', '{' and '}'.
1384 os << "<" << "p" << dex_pc << ">";
1385 os << " 0x" << std::hex << dex_pc << std::dec << ": ";
1386 std::string inst_str = inst->DumpString(dex_file);
1387 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 -07001388 // we need to escape.
Andreas Gampe5073fed2015-08-10 11:40:25 -07001389 while (cur_start != std::string::npos) {
1390 size_t next_escape = inst_str.find_first_of("\"{}<>", cur_start + 1);
1391 if (next_escape == std::string::npos) {
1392 os << inst_str.substr(cur_start, inst_str.size() - cur_start);
1393 break;
1394 } else {
1395 os << inst_str.substr(cur_start, next_escape - cur_start);
1396 // Escape all necessary characters.
1397 while (next_escape < inst_str.size()) {
1398 char c = inst_str.at(next_escape);
1399 if (c == '"' || c == '{' || c == '}' || c == '<' || c == '>') {
1400 os << '\\' << c;
1401 } else {
1402 break;
1403 }
1404 next_escape++;
1405 }
1406 if (next_escape >= inst_str.size()) {
1407 next_escape = std::string::npos;
1408 }
1409 cur_start = next_escape;
1410 }
1411 }
1412
1413 // Force a new block for some fall-throughs and some instructions that terminate the "local"
1414 // control flow.
1415 force_new_block = inst->IsSwitch() || inst->IsBasicBlockEnd();
1416 }
1417 // Close last node.
1418 if (dex_pc_to_node_id.size() > 0) {
1419 os << "}\"];\n";
1420 }
1421 }
1422
1423 // Create edges between them.
1424 {
1425 std::ostringstream regular_edges;
1426 std::ostringstream taken_edges;
1427 std::ostringstream exception_edges;
1428
1429 // Common set of exception edges.
1430 std::set<uint32_t> exception_targets;
1431
1432 // These blocks (given by the first dex pc) need exception per dex-pc handling in a second
1433 // pass. In the first pass we try and see whether we can use a common set of edges.
1434 std::set<uint32_t> blocks_with_detailed_exceptions;
1435
1436 {
1437 uint32_t last_node_id = std::numeric_limits<uint32_t>::max();
1438 uint32_t old_dex_pc = 0;
1439 uint32_t block_start_dex_pc = std::numeric_limits<uint32_t>::max();
1440 const Instruction* inst = Instruction::At(code_item->insns_);
1441 for (uint32_t dex_pc = 0;
1442 dex_pc < code_item->insns_size_in_code_units_;
1443 old_dex_pc = dex_pc, dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
1444 {
1445 auto it = dex_pc_to_node_id.find(dex_pc);
1446 if (it != dex_pc_to_node_id.end()) {
1447 if (!exception_targets.empty()) {
1448 // It seems the last block had common exception handlers. Add the exception edges now.
1449 uint32_t node_id = dex_pc_to_node_id.find(block_start_dex_pc)->second;
1450 for (uint32_t handler_pc : exception_targets) {
1451 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1452 if (node_id_it != dex_pc_to_incl_id.end()) {
1453 exception_edges << " node" << node_id
1454 << " -> node" << node_id_it->second << ":p" << handler_pc
1455 << ";\n";
1456 }
1457 }
1458 exception_targets.clear();
1459 }
1460
1461 block_start_dex_pc = dex_pc;
1462
1463 // Seems to be a fall-through, connect to last_node_id. May be spurious edges for things
1464 // like switch data.
1465 uint32_t old_last = last_node_id;
1466 last_node_id = it->second;
1467 if (old_last != std::numeric_limits<uint32_t>::max()) {
1468 regular_edges << " node" << old_last << ":p" << old_dex_pc
1469 << " -> node" << last_node_id << ":p" << dex_pc
1470 << ";\n";
1471 }
1472 }
1473
1474 // Look at the exceptions of the first entry.
1475 CatchHandlerIterator catch_it(*code_item, dex_pc);
1476 for (; catch_it.HasNext(); catch_it.Next()) {
1477 exception_targets.insert(catch_it.GetHandlerAddress());
1478 }
1479 }
1480
1481 // Handle instruction.
1482
1483 // Branch: something with at most two targets.
1484 if (inst->IsBranch()) {
1485 const int32_t offset = inst->GetTargetOffset();
1486 const bool conditional = !inst->IsUnconditional();
1487
1488 auto target_it = dex_pc_to_node_id.find(dex_pc + offset);
1489 if (target_it != dex_pc_to_node_id.end()) {
1490 taken_edges << " node" << last_node_id << ":p" << dex_pc
1491 << " -> node" << target_it->second << ":p" << (dex_pc + offset)
1492 << ";\n";
1493 }
1494 if (!conditional) {
1495 // No fall-through.
1496 last_node_id = std::numeric_limits<uint32_t>::max();
1497 }
1498 } else if (inst->IsSwitch()) {
1499 // TODO: Iterate through all switch targets.
1500 const uint16_t* insns = code_item->insns_ + dex_pc;
1501 /* make sure the start of the switch is in range */
Andreas Gampe53de99c2015-08-17 13:43:55 -07001502 int32_t switch_offset = insns[1] | (static_cast<int32_t>(insns[2]) << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001503 /* offset to switch table is a relative branch-style offset */
1504 const uint16_t* switch_insns = insns + switch_offset;
1505 uint32_t switch_count = switch_insns[1];
1506 int32_t targets_offset;
1507 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
1508 /* 0=sig, 1=count, 2/3=firstKey */
1509 targets_offset = 4;
1510 } else {
1511 /* 0=sig, 1=count, 2..count*2 = keys */
1512 targets_offset = 2 + 2 * switch_count;
1513 }
1514 /* make sure the end of the switch is in range */
1515 /* verify each switch target */
1516 for (uint32_t targ = 0; targ < switch_count; targ++) {
Andreas Gampe53de99c2015-08-17 13:43:55 -07001517 int32_t offset =
1518 static_cast<int32_t>(switch_insns[targets_offset + targ * 2]) |
1519 static_cast<int32_t>(switch_insns[targets_offset + targ * 2 + 1] << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001520 int32_t abs_offset = dex_pc + offset;
1521 auto target_it = dex_pc_to_node_id.find(abs_offset);
1522 if (target_it != dex_pc_to_node_id.end()) {
1523 // TODO: value label.
1524 taken_edges << " node" << last_node_id << ":p" << dex_pc
1525 << " -> node" << target_it->second << ":p" << (abs_offset)
1526 << ";\n";
1527 }
1528 }
1529 }
1530
1531 // Exception edges. If this is not the first instruction in the block
1532 if (block_start_dex_pc != dex_pc) {
1533 std::set<uint32_t> current_handler_pcs;
1534 CatchHandlerIterator catch_it(*code_item, dex_pc);
1535 for (; catch_it.HasNext(); catch_it.Next()) {
1536 current_handler_pcs.insert(catch_it.GetHandlerAddress());
1537 }
1538 if (current_handler_pcs != exception_targets) {
1539 exception_targets.clear(); // Clear so we don't do something at the end.
1540 blocks_with_detailed_exceptions.insert(block_start_dex_pc);
1541 }
1542 }
1543
1544 if (inst->IsReturn() ||
1545 (inst->Opcode() == Instruction::THROW) ||
1546 (inst->IsBranch() && inst->IsUnconditional())) {
1547 // No fall-through.
1548 last_node_id = std::numeric_limits<uint32_t>::max();
1549 }
1550 }
1551 // Finish up the last block, if it had common exceptions.
1552 if (!exception_targets.empty()) {
1553 // It seems the last block had common exception handlers. Add the exception edges now.
1554 uint32_t node_id = dex_pc_to_node_id.find(block_start_dex_pc)->second;
1555 for (uint32_t handler_pc : exception_targets) {
1556 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1557 if (node_id_it != dex_pc_to_incl_id.end()) {
1558 exception_edges << " node" << node_id
1559 << " -> node" << node_id_it->second << ":p" << handler_pc
1560 << ";\n";
1561 }
1562 }
1563 exception_targets.clear();
1564 }
1565 }
1566
1567 // Second pass for detailed exception blocks.
1568 // TODO
1569 // Exception edges. If this is not the first instruction in the block
1570 for (uint32_t dex_pc : blocks_with_detailed_exceptions) {
1571 const Instruction* inst = Instruction::At(&code_item->insns_[dex_pc]);
1572 uint32_t this_node_id = dex_pc_to_incl_id.find(dex_pc)->second;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001573 while (true) {
Andreas Gampe5073fed2015-08-10 11:40:25 -07001574 CatchHandlerIterator catch_it(*code_item, dex_pc);
1575 if (catch_it.HasNext()) {
1576 std::set<uint32_t> handled_targets;
1577 for (; catch_it.HasNext(); catch_it.Next()) {
1578 uint32_t handler_pc = catch_it.GetHandlerAddress();
1579 auto it = handled_targets.find(handler_pc);
1580 if (it == handled_targets.end()) {
1581 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1582 if (node_id_it != dex_pc_to_incl_id.end()) {
1583 exception_edges << " node" << this_node_id << ":p" << dex_pc
1584 << " -> node" << node_id_it->second << ":p" << handler_pc
1585 << ";\n";
1586 }
1587
1588 // Mark as done.
1589 handled_targets.insert(handler_pc);
1590 }
1591 }
1592 }
1593 if (inst->IsBasicBlockEnd()) {
1594 break;
1595 }
1596
Andreas Gampe53de99c2015-08-17 13:43:55 -07001597 // Loop update. Have a break-out if the next instruction is a branch target and thus in
1598 // another block.
Andreas Gampe5073fed2015-08-10 11:40:25 -07001599 dex_pc += inst->SizeInCodeUnits();
1600 if (dex_pc >= code_item->insns_size_in_code_units_) {
1601 break;
1602 }
1603 if (dex_pc_to_node_id.find(dex_pc) != dex_pc_to_node_id.end()) {
1604 break;
1605 }
1606 inst = inst->Next();
1607 }
1608 }
1609
1610 // Write out the sub-graphs to make edges styled.
1611 os << "\n";
1612 os << " subgraph regular_edges {\n";
1613 os << " edge [color=\"#000000\",weight=.3,len=3];\n\n";
1614 os << " " << regular_edges.str() << "\n";
1615 os << " }\n\n";
1616
1617 os << " subgraph taken_edges {\n";
1618 os << " edge [color=\"#00FF00\",weight=.3,len=3];\n\n";
1619 os << " " << taken_edges.str() << "\n";
1620 os << " }\n\n";
1621
1622 os << " subgraph exception_edges {\n";
1623 os << " edge [color=\"#FF0000\",weight=.3,len=3];\n\n";
1624 os << " " << exception_edges.str() << "\n";
1625 os << " }\n\n";
1626 }
1627
1628 os << "}\n";
1629}
1630
1631void DumpMethodCFG(ArtMethod* method, std::ostream& os) {
1632 const DexFile* dex_file = method->GetDexFile();
1633 const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
1634
1635 DumpMethodCFGImpl(dex_file, method->GetDexMethodIndex(), code_item, os);
1636}
1637
1638void DumpMethodCFG(const DexFile* dex_file, uint32_t dex_method_idx, std::ostream& os) {
1639 // This is painful, we need to find the code item. That means finding the class, and then
1640 // iterating the table.
1641 if (dex_method_idx >= dex_file->NumMethodIds()) {
1642 os << "Could not find method-idx.";
1643 return;
1644 }
1645 const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
1646
1647 const DexFile::ClassDef* class_def = dex_file->FindClassDef(method_id.class_idx_);
1648 if (class_def == nullptr) {
1649 os << "Could not find class-def.";
1650 return;
1651 }
1652
1653 const uint8_t* class_data = dex_file->GetClassData(*class_def);
1654 if (class_data == nullptr) {
1655 os << "No class data.";
1656 return;
1657 }
1658
1659 ClassDataItemIterator it(*dex_file, class_data);
1660 // Skip fields
1661 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
1662 it.Next();
1663 }
1664
1665 // Find method, and dump it.
1666 while (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
1667 uint32_t method_idx = it.GetMemberIndex();
1668 if (method_idx == dex_method_idx) {
1669 DumpMethodCFGImpl(dex_file, dex_method_idx, it.GetMethodCodeItem(), os);
1670 return;
1671 }
1672 it.Next();
1673 }
1674
1675 // Otherwise complain.
1676 os << "Something went wrong, didn't find the method in the class data.";
1677}
1678
Nicolas Geoffrayabbb0f72015-10-29 18:55:58 +00001679static void ParseStringAfterChar(const std::string& s,
1680 char c,
1681 std::string* parsed_value,
1682 UsageFn Usage) {
1683 std::string::size_type colon = s.find(c);
1684 if (colon == std::string::npos) {
1685 Usage("Missing char %c in option %s\n", c, s.c_str());
1686 }
1687 // Add one to remove the char we were trimming until.
1688 *parsed_value = s.substr(colon + 1);
1689}
1690
1691void ParseDouble(const std::string& option,
1692 char after_char,
1693 double min,
1694 double max,
1695 double* parsed_value,
1696 UsageFn Usage) {
1697 std::string substring;
1698 ParseStringAfterChar(option, after_char, &substring, Usage);
1699 bool sane_val = true;
1700 double value;
1701 if ((false)) {
1702 // TODO: this doesn't seem to work on the emulator. b/15114595
1703 std::stringstream iss(substring);
1704 iss >> value;
1705 // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
1706 sane_val = iss.eof() && (value >= min) && (value <= max);
1707 } else {
1708 char* end = nullptr;
1709 value = strtod(substring.c_str(), &end);
1710 sane_val = *end == '\0' && value >= min && value <= max;
1711 }
1712 if (!sane_val) {
1713 Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str());
1714 }
1715 *parsed_value = value;
1716}
1717
Calin Juravle4d77b6a2015-12-01 18:38:09 +00001718int64_t GetFileSizeBytes(const std::string& filename) {
1719 struct stat stat_buf;
1720 int rc = stat(filename.c_str(), &stat_buf);
1721 return rc == 0 ? stat_buf.st_size : -1;
1722}
1723
Mathieu Chartier4d87df62016-01-07 15:14:19 -08001724void SleepForever() {
1725 while (true) {
1726 usleep(1000000);
1727 }
1728}
1729
Elliott Hughes42ee1422011-09-06 12:33:32 -07001730} // namespace art