blob: a40e3131180fe6dbfb0d6db2f0b94c9ef9774c3c [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>
Elliott Hughes4ae722a2012-03-13 11:08:51 -070048#endif
49
Elliott Hughes058a6de2012-05-24 19:13:02 -070050#if defined(__linux__)
Elliott Hughese1aee692012-01-17 16:40:10 -080051#include <linux/unistd.h>
Elliott Hughese1aee692012-01-17 16:40:10 -080052#endif
53
Elliott Hughes11e45072011-08-16 17:40:46 -070054namespace art {
55
Alex Light9c20a142016-08-23 15:05:12 -070056static const uint8_t kBase64Map[256] = {
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, 255, 255, 255, 255, 255,
60 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
61 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
62 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
63 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT
64 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT
65 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
66 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT
67 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT
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, 255, 255, 255, 255, 255, 255, 255, 255,
78 255, 255, 255, 255
79};
80
81uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
82 std::vector<uint8_t> tmp;
83 uint32_t t = 0, y = 0;
84 int g = 3;
85 for (size_t i = 0; src[i] != '\0'; ++i) {
86 uint8_t c = kBase64Map[src[i] & 0xFF];
87 if (c == 255) continue;
88 // the final = symbols are read and used to trim the remaining bytes
89 if (c == 254) {
90 c = 0;
91 // prevent g < 0 which would potentially allow an overflow later
92 if (--g < 0) {
93 *dst_size = 0;
94 return nullptr;
95 }
96 } else if (g != 3) {
97 // we only allow = to be at the end
98 *dst_size = 0;
99 return nullptr;
100 }
101 t = (t << 6) | c;
102 if (++y == 4) {
103 tmp.push_back((t >> 16) & 255);
104 if (g > 1) {
105 tmp.push_back((t >> 8) & 255);
106 }
107 if (g > 2) {
108 tmp.push_back(t & 255);
109 }
110 y = t = 0;
111 }
112 }
113 if (y != 0) {
114 *dst_size = 0;
115 return nullptr;
116 }
117 std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
118 if (dst_size != nullptr) {
119 *dst_size = tmp.size();
120 } else {
121 *dst_size = 0;
122 }
123 std::copy(tmp.begin(), tmp.end(), dst.get());
124 return dst.release();
125}
126
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800127pid_t GetTid() {
Brian Carlstromf3a26412012-08-24 11:06:02 -0700128#if defined(__APPLE__)
129 uint64_t owner;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700130 CHECK_PTHREAD_CALL(pthread_threadid_np, (nullptr, &owner), __FUNCTION__); // Requires Mac OS 10.6
Brian Carlstromf3a26412012-08-24 11:06:02 -0700131 return owner;
Elliott Hughes323aa862014-08-20 15:00:04 -0700132#elif defined(__BIONIC__)
133 return gettid();
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800134#else
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800135 return syscall(__NR_gettid);
136#endif
137}
138
Elliott Hughes289be852012-06-12 13:57:20 -0700139std::string GetThreadName(pid_t tid) {
140 std::string result;
141 if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700142 result.resize(result.size() - 1); // Lose the trailing '\n'.
Elliott Hughes289be852012-06-12 13:57:20 -0700143 } else {
144 result = "<unknown>";
145 }
146 return result;
147}
148
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700149void GetThreadStack(pthread_t thread, void** stack_base, size_t* stack_size, size_t* guard_size) {
Elliott Hughese1884192012-04-23 12:38:15 -0700150#if defined(__APPLE__)
Brian Carlstrom29212012013-09-12 22:18:30 -0700151 *stack_size = pthread_get_stacksize_np(thread);
Ian Rogers120f1c72012-09-28 17:17:10 -0700152 void* stack_addr = pthread_get_stackaddr_np(thread);
Elliott Hughese1884192012-04-23 12:38:15 -0700153
154 // Check whether stack_addr is the base or end of the stack.
155 // (On Mac OS 10.7, it's the end.)
156 int stack_variable;
157 if (stack_addr > &stack_variable) {
Ian Rogers13735952014-10-08 12:43:28 -0700158 *stack_base = reinterpret_cast<uint8_t*>(stack_addr) - *stack_size;
Elliott Hughese1884192012-04-23 12:38:15 -0700159 } else {
Brian Carlstrom29212012013-09-12 22:18:30 -0700160 *stack_base = stack_addr;
Elliott Hughese1884192012-04-23 12:38:15 -0700161 }
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700162
163 // This is wrong, but there doesn't seem to be a way to get the actual value on the Mac.
164 pthread_attr_t attributes;
165 CHECK_PTHREAD_CALL(pthread_attr_init, (&attributes), __FUNCTION__);
166 CHECK_PTHREAD_CALL(pthread_attr_getguardsize, (&attributes, guard_size), __FUNCTION__);
167 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
Elliott Hughese1884192012-04-23 12:38:15 -0700168#else
169 pthread_attr_t attributes;
Ian Rogers120f1c72012-09-28 17:17:10 -0700170 CHECK_PTHREAD_CALL(pthread_getattr_np, (thread, &attributes), __FUNCTION__);
Brian Carlstrom29212012013-09-12 22:18:30 -0700171 CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, stack_base, stack_size), __FUNCTION__);
Elliott Hughes6d3fc562014-08-27 11:47:01 -0700172 CHECK_PTHREAD_CALL(pthread_attr_getguardsize, (&attributes, guard_size), __FUNCTION__);
Elliott Hughese1884192012-04-23 12:38:15 -0700173 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
Elliott Hughes839cc302014-08-28 10:24:44 -0700174
175#if defined(__GLIBC__)
176 // If we're the main thread, check whether we were run with an unlimited stack. In that case,
177 // glibc will have reported a 2GB stack for our 32-bit process, and our stack overflow detection
178 // will be broken because we'll die long before we get close to 2GB.
179 bool is_main_thread = (::art::GetTid() == getpid());
180 if (is_main_thread) {
181 rlimit stack_limit;
182 if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) {
183 PLOG(FATAL) << "getrlimit(RLIMIT_STACK) failed";
184 }
185 if (stack_limit.rlim_cur == RLIM_INFINITY) {
186 size_t old_stack_size = *stack_size;
187
188 // Use the kernel default limit as our size, and adjust the base to match.
189 *stack_size = 8 * MB;
190 *stack_base = reinterpret_cast<uint8_t*>(*stack_base) + (old_stack_size - *stack_size);
191
192 VLOG(threads) << "Limiting unlimited stack (reported as " << PrettySize(old_stack_size) << ")"
193 << " to " << PrettySize(*stack_size)
194 << " with base " << *stack_base;
195 }
196 }
197#endif
198
Elliott Hughese1884192012-04-23 12:38:15 -0700199#endif
200}
201
Elliott Hughesd92bec42011-09-02 17:04:36 -0700202bool ReadFileToString(const std::string& file_name, std::string* result) {
Andreas Gampedf878922015-08-13 16:44:54 -0700203 File file(file_name, O_RDONLY, false);
204 if (!file.IsOpened()) {
Elliott Hughesd92bec42011-09-02 17:04:36 -0700205 return false;
206 }
buzbeec143c552011-08-20 17:38:58 -0700207
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700208 std::vector<char> buf(8 * KB);
buzbeec143c552011-08-20 17:38:58 -0700209 while (true) {
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800210 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
Elliott Hughesd92bec42011-09-02 17:04:36 -0700211 if (n == -1) {
212 return false;
buzbeec143c552011-08-20 17:38:58 -0700213 }
Elliott Hughesd92bec42011-09-02 17:04:36 -0700214 if (n == 0) {
215 return true;
216 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700217 result->append(&buf[0], n);
buzbeec143c552011-08-20 17:38:58 -0700218 }
buzbeec143c552011-08-20 17:38:58 -0700219}
220
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800221bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
Andreas Gampedf878922015-08-13 16:44:54 -0700222 File file(file_name, O_RDONLY, false);
223 if (!file.IsOpened()) {
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800224 return false;
225 }
226
227 constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings.
228 char buf[kBufSize + 1]; // +1 for terminator.
229 size_t filled_to = 0;
230 while (true) {
231 DCHECK_LT(filled_to, kBufSize);
232 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
233 if (n <= 0) {
234 // Print the rest of the buffer, if it exists.
235 if (filled_to > 0) {
236 buf[filled_to] = 0;
237 LOG(level) << buf;
238 }
239 return n == 0;
240 }
241 // Scan for '\n'.
242 size_t i = filled_to;
243 bool found_newline = false;
244 for (; i < filled_to + n; ++i) {
245 if (buf[i] == '\n') {
246 // Found a line break, that's something to print now.
247 buf[i] = 0;
248 LOG(level) << buf;
249 // Copy the rest to the front.
250 if (i + 1 < filled_to + n) {
251 memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
252 filled_to = filled_to + n - i - 1;
253 } else {
254 filled_to = 0;
255 }
256 found_newline = true;
257 break;
258 }
259 }
260 if (found_newline) {
261 continue;
262 } else {
263 filled_to += n;
264 // Check if we must flush now.
265 if (filled_to == kBufSize) {
266 buf[kBufSize] = 0;
267 LOG(level) << buf;
268 filled_to = 0;
269 }
270 }
271 }
272}
273
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700274std::string PrettyStringDescriptor(ObjPtr<mirror::String> java_descriptor) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700275 if (java_descriptor == nullptr) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700276 return "null";
277 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700278 return PrettyDescriptor(java_descriptor->ToModifiedUtf8().c_str());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700279}
Elliott Hughes5174fe62011-08-23 15:12:35 -0700280
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700281std::string PrettyDescriptor(ObjPtr<mirror::Class> klass) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700282 if (klass == nullptr) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800283 return "null";
284 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700285 std::string temp;
286 return PrettyDescriptor(klass->GetDescriptor(&temp));
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800287}
288
Ian Rogers1ff3c982014-08-12 02:30:58 -0700289std::string PrettyDescriptor(const char* descriptor) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700290 // Count the number of '['s to get the dimensionality.
Ian Rogers1ff3c982014-08-12 02:30:58 -0700291 const char* c = descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700292 size_t dim = 0;
293 while (*c == '[') {
294 dim++;
295 c++;
296 }
297
298 // Reference or primitive?
299 if (*c == 'L') {
300 // "[[La/b/C;" -> "a.b.C[][]".
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700301 c++; // Skip the 'L'.
Elliott Hughes11e45072011-08-16 17:40:46 -0700302 } else {
303 // "[[B" -> "byte[][]".
304 // To make life easier, we make primitives look like unqualified
305 // reference types.
306 switch (*c) {
307 case 'B': c = "byte;"; break;
308 case 'C': c = "char;"; break;
309 case 'D': c = "double;"; break;
310 case 'F': c = "float;"; break;
311 case 'I': c = "int;"; break;
312 case 'J': c = "long;"; break;
313 case 'S': c = "short;"; break;
314 case 'Z': c = "boolean;"; break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700315 case 'V': c = "void;"; break; // Used when decoding return types.
Elliott Hughes5174fe62011-08-23 15:12:35 -0700316 default: return descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700317 }
318 }
319
320 // At this point, 'c' is a string of the form "fully/qualified/Type;"
321 // or "primitive;". Rewrite the type with '.' instead of '/':
322 std::string result;
323 const char* p = c;
324 while (*p != ';') {
325 char ch = *p++;
326 if (ch == '/') {
327 ch = '.';
328 }
329 result.push_back(ch);
330 }
331 // ...and replace the semicolon with 'dim' "[]" pairs:
Ian Rogers1ff3c982014-08-12 02:30:58 -0700332 for (size_t i = 0; i < dim; ++i) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700333 result += "[]";
334 }
335 return result;
336}
337
Mathieu Chartierc7853442015-03-27 14:35:38 -0700338std::string PrettyField(ArtField* f, bool with_type) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700339 if (f == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700340 return "null";
341 }
Elliott Hughes54e7df12011-09-16 11:47:04 -0700342 std::string result;
343 if (with_type) {
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700344 result += PrettyDescriptor(f->GetTypeDescriptor());
Elliott Hughes54e7df12011-09-16 11:47:04 -0700345 result += ' ';
346 }
Ian Rogers08f1f502014-12-02 15:04:37 -0800347 std::string temp;
348 result += PrettyDescriptor(f->GetDeclaringClass()->GetDescriptor(&temp));
Elliott Hughesa2501992011-08-26 19:39:54 -0700349 result += '.';
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700350 result += f->GetName();
Elliott Hughesa2501992011-08-26 19:39:54 -0700351 return result;
352}
353
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700354std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800355 if (field_idx >= dex_file.NumFieldIds()) {
356 return StringPrintf("<<invalid-field-idx-%d>>", field_idx);
357 }
Brian Carlstrom6f29d0e2012-05-11 15:50:29 -0700358 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
359 std::string result;
360 if (with_type) {
361 result += dex_file.GetFieldTypeDescriptor(field_id);
362 result += ' ';
363 }
364 result += PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(field_id));
365 result += '.';
366 result += dex_file.GetFieldName(field_id);
367 return result;
368}
369
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700370std::string PrettyType(uint32_t type_idx, const DexFile& dex_file) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800371 if (type_idx >= dex_file.NumTypeIds()) {
372 return StringPrintf("<<invalid-type-idx-%d>>", type_idx);
373 }
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700374 const DexFile::TypeId& type_id = dex_file.GetTypeId(type_idx);
Mathieu Chartier4c70d772012-09-10 14:08:32 -0700375 return PrettyDescriptor(dex_file.GetTypeDescriptor(type_id));
Mathieu Chartier18c24b62012-09-10 08:54:25 -0700376}
377
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700378std::string PrettyArguments(const char* signature) {
379 std::string result;
380 result += '(';
381 CHECK_EQ(*signature, '(');
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700382 ++signature; // Skip the '('.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700383 while (*signature != ')') {
384 size_t argument_length = 0;
385 while (signature[argument_length] == '[') {
386 ++argument_length;
387 }
388 if (signature[argument_length] == 'L') {
389 argument_length = (strchr(signature, ';') - signature + 1);
390 } else {
391 ++argument_length;
392 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700393 {
394 std::string argument_descriptor(signature, argument_length);
395 result += PrettyDescriptor(argument_descriptor.c_str());
396 }
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700397 if (signature[argument_length] != ')') {
398 result += ", ";
399 }
400 signature += argument_length;
401 }
402 CHECK_EQ(*signature, ')');
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700403 ++signature; // Skip the ')'.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700404 result += ')';
405 return result;
406}
407
408std::string PrettyReturnType(const char* signature) {
409 const char* return_type = strchr(signature, ')');
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700410 CHECK(return_type != nullptr);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700411 ++return_type; // Skip ')'.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700412 return PrettyDescriptor(return_type);
413}
414
Mathieu Chartiere401d142015-04-22 13:56:20 -0700415std::string PrettyMethod(ArtMethod* m, bool with_signature) {
Ian Rogers16ce0922014-01-10 14:59:36 -0800416 if (m == nullptr) {
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700417 return "null";
418 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700419 if (!m->IsRuntimeMethod()) {
420 m = m->GetInterfaceMethodIfProxy(Runtime::Current()->GetClassLinker()->GetImagePointerSize());
421 }
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700422 std::string result(PrettyDescriptor(m->GetDeclaringClassDescriptor()));
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700423 result += '.';
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700424 result += m->GetName();
Ian Rogers16ce0922014-01-10 14:59:36 -0800425 if (UNLIKELY(m->IsFastNative())) {
426 result += "!";
427 }
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700428 if (with_signature) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700429 const Signature signature = m->GetSignature();
Ian Rogersd91d6d62013-09-25 20:26:14 -0700430 std::string sig_as_string(signature.ToString());
431 if (signature == Signature::NoSignature()) {
432 return result + sig_as_string;
Elliott Hughesf8c11932012-03-23 19:53:59 -0700433 }
Ian Rogersd91d6d62013-09-25 20:26:14 -0700434 result = PrettyReturnType(sig_as_string.c_str()) + " " + result +
435 PrettyArguments(sig_as_string.c_str());
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700436 }
437 return result;
438}
439
Ian Rogers0571d352011-11-03 19:51:38 -0700440std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature) {
Elliott Hughes60641a72013-02-27 14:36:16 -0800441 if (method_idx >= dex_file.NumMethodIds()) {
442 return StringPrintf("<<invalid-method-idx-%d>>", method_idx);
443 }
Ian Rogers0571d352011-11-03 19:51:38 -0700444 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
445 std::string result(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(method_id)));
446 result += '.';
447 result += dex_file.GetMethodName(method_id);
448 if (with_signature) {
Ian Rogersd91d6d62013-09-25 20:26:14 -0700449 const Signature signature = dex_file.GetMethodSignature(method_id);
450 std::string sig_as_string(signature.ToString());
451 if (signature == Signature::NoSignature()) {
452 return result + sig_as_string;
Elliott Hughesf8c11932012-03-23 19:53:59 -0700453 }
Ian Rogersd91d6d62013-09-25 20:26:14 -0700454 result = PrettyReturnType(sig_as_string.c_str()) + " " + result +
455 PrettyArguments(sig_as_string.c_str());
Ian Rogers0571d352011-11-03 19:51:38 -0700456 }
457 return result;
458}
459
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700460std::string PrettyTypeOf(ObjPtr<mirror::Object> obj) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700461 if (obj == nullptr) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700462 return "null";
463 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700464 if (obj->GetClass() == nullptr) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700465 return "(raw)";
466 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700467 std::string temp;
468 std::string result(PrettyDescriptor(obj->GetClass()->GetDescriptor(&temp)));
Elliott Hughes11e45072011-08-16 17:40:46 -0700469 if (obj->IsClass()) {
Ian Rogers1ff3c982014-08-12 02:30:58 -0700470 result += "<" + PrettyDescriptor(obj->AsClass()->GetDescriptor(&temp)) + ">";
Elliott Hughes11e45072011-08-16 17:40:46 -0700471 }
472 return result;
473}
474
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700475std::string PrettyClass(ObjPtr<mirror::Class> c) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700476 if (c == nullptr) {
Elliott Hughes54e7df12011-09-16 11:47:04 -0700477 return "null";
478 }
479 std::string result;
480 result += "java.lang.Class<";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800481 result += PrettyDescriptor(c);
Elliott Hughes54e7df12011-09-16 11:47:04 -0700482 result += ">";
483 return result;
484}
485
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700486std::string PrettyClassAndClassLoader(ObjPtr<mirror::Class> c) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700487 if (c == nullptr) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700488 return "null";
489 }
490 std::string result;
491 result += "java.lang.Class<";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800492 result += PrettyDescriptor(c);
Ian Rogersd81871c2011-10-03 13:57:23 -0700493 result += ",";
494 result += PrettyTypeOf(c->GetClassLoader());
495 // TODO: add an identifying hash value for the loader
496 result += ">";
497 return result;
498}
499
Andreas Gampec0d82292014-09-23 10:38:30 -0700500std::string PrettyJavaAccessFlags(uint32_t access_flags) {
501 std::string result;
502 if ((access_flags & kAccPublic) != 0) {
503 result += "public ";
504 }
505 if ((access_flags & kAccProtected) != 0) {
506 result += "protected ";
507 }
508 if ((access_flags & kAccPrivate) != 0) {
509 result += "private ";
510 }
511 if ((access_flags & kAccFinal) != 0) {
512 result += "final ";
513 }
514 if ((access_flags & kAccStatic) != 0) {
515 result += "static ";
516 }
David Brazdilca3c8c32016-09-06 14:04:48 +0100517 if ((access_flags & kAccAbstract) != 0) {
518 result += "abstract ";
519 }
520 if ((access_flags & kAccInterface) != 0) {
521 result += "interface ";
522 }
Andreas Gampec0d82292014-09-23 10:38:30 -0700523 if ((access_flags & kAccTransient) != 0) {
524 result += "transient ";
525 }
526 if ((access_flags & kAccVolatile) != 0) {
527 result += "volatile ";
528 }
529 if ((access_flags & kAccSynchronized) != 0) {
530 result += "synchronized ";
531 }
532 return result;
533}
534
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800535std::string PrettySize(int64_t byte_count) {
Elliott Hughesc967f782012-04-16 10:23:15 -0700536 // The byte thresholds at which we display amounts. A byte count is displayed
537 // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
Ian Rogersef7d42f2014-01-06 12:55:46 -0800538 static const int64_t kUnitThresholds[] = {
Elliott Hughesc967f782012-04-16 10:23:15 -0700539 0, // B up to...
540 3*1024, // KB up to...
541 2*1024*1024, // MB up to...
542 1024*1024*1024 // GB from here.
543 };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800544 static const int64_t kBytesPerUnit[] = { 1, KB, MB, GB };
Elliott Hughesc967f782012-04-16 10:23:15 -0700545 static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800546 const char* negative_str = "";
547 if (byte_count < 0) {
548 negative_str = "-";
549 byte_count = -byte_count;
550 }
Elliott Hughesc967f782012-04-16 10:23:15 -0700551 int i = arraysize(kUnitThresholds);
552 while (--i > 0) {
553 if (byte_count >= kUnitThresholds[i]) {
554 break;
555 }
Ian Rogers3bb17a62012-01-27 23:56:44 -0800556 }
Brian Carlstrom474cc792014-03-07 14:18:15 -0800557 return StringPrintf("%s%" PRId64 "%s",
558 negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
Ian Rogers3bb17a62012-01-27 23:56:44 -0800559}
560
Ian Rogers576ca0c2014-06-06 15:58:22 -0700561std::string PrintableChar(uint16_t ch) {
562 std::string result;
563 result += '\'';
564 if (NeedsEscaping(ch)) {
565 StringAppendF(&result, "\\u%04x", ch);
566 } else {
567 result += ch;
568 }
569 result += '\'';
570 return result;
571}
572
Ian Rogers68b56852014-08-29 20:19:11 -0700573std::string PrintableString(const char* utf) {
Elliott Hughes82914b62012-04-09 15:56:29 -0700574 std::string result;
575 result += '"';
Ian Rogers68b56852014-08-29 20:19:11 -0700576 const char* p = utf;
Elliott Hughes82914b62012-04-09 15:56:29 -0700577 size_t char_count = CountModifiedUtf8Chars(p);
578 for (size_t i = 0; i < char_count; ++i) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000579 uint32_t ch = GetUtf16FromUtf8(&p);
Elliott Hughes82914b62012-04-09 15:56:29 -0700580 if (ch == '\\') {
581 result += "\\\\";
582 } else if (ch == '\n') {
583 result += "\\n";
584 } else if (ch == '\r') {
585 result += "\\r";
586 } else if (ch == '\t') {
587 result += "\\t";
Elliott Hughes82914b62012-04-09 15:56:29 -0700588 } else {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000589 const uint16_t leading = GetLeadingUtf16Char(ch);
590
591 if (NeedsEscaping(leading)) {
592 StringAppendF(&result, "\\u%04x", leading);
593 } else {
594 result += leading;
595 }
596
597 const uint32_t trailing = GetTrailingUtf16Char(ch);
598 if (trailing != 0) {
599 // All high surrogates will need escaping.
600 StringAppendF(&result, "\\u%04x", trailing);
601 }
Elliott Hughes82914b62012-04-09 15:56:29 -0700602 }
603 }
604 result += '"';
605 return result;
606}
607
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800608// 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 -0700609std::string MangleForJni(const std::string& s) {
610 std::string result;
611 size_t char_count = CountModifiedUtf8Chars(s.c_str());
612 const char* cp = &s[0];
613 for (size_t i = 0; i < char_count; ++i) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000614 uint32_t ch = GetUtf16FromUtf8(&cp);
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800615 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
616 result.push_back(ch);
617 } else if (ch == '.' || ch == '/') {
618 result += "_";
619 } else if (ch == '_') {
620 result += "_1";
621 } else if (ch == ';') {
622 result += "_2";
623 } else if (ch == '[') {
624 result += "_3";
Elliott Hughes79082e32011-08-25 12:07:32 -0700625 } else {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000626 const uint16_t leading = GetLeadingUtf16Char(ch);
627 const uint32_t trailing = GetTrailingUtf16Char(ch);
628
629 StringAppendF(&result, "_0%04x", leading);
630 if (trailing != 0) {
631 StringAppendF(&result, "_0%04x", trailing);
632 }
Elliott Hughes79082e32011-08-25 12:07:32 -0700633 }
634 }
635 return result;
636}
637
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700638std::string DotToDescriptor(const char* class_name) {
639 std::string descriptor(class_name);
640 std::replace(descriptor.begin(), descriptor.end(), '.', '/');
641 if (descriptor.length() > 0 && descriptor[0] != '[') {
642 descriptor = "L" + descriptor + ";";
643 }
644 return descriptor;
645}
646
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800647std::string DescriptorToDot(const char* descriptor) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800648 size_t length = strlen(descriptor);
Ian Rogers1ff3c982014-08-12 02:30:58 -0700649 if (length > 1) {
650 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
651 // Descriptors have the leading 'L' and trailing ';' stripped.
652 std::string result(descriptor + 1, length - 2);
653 std::replace(result.begin(), result.end(), '/', '.');
654 return result;
655 } else {
656 // For arrays the 'L' and ';' remain intact.
657 std::string result(descriptor);
658 std::replace(result.begin(), result.end(), '/', '.');
659 return result;
660 }
Elliott Hughes2435a572012-02-17 16:07:41 -0800661 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700662 // Do nothing for non-class/array descriptors.
Elliott Hughes2435a572012-02-17 16:07:41 -0800663 return descriptor;
Elliott Hughes91bf6cd2012-02-14 17:27:48 -0800664}
665
666std::string DescriptorToName(const char* descriptor) {
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800667 size_t length = strlen(descriptor);
Elliott Hughes2435a572012-02-17 16:07:41 -0800668 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
669 std::string result(descriptor + 1, length - 2);
670 return result;
671 }
672 return descriptor;
Brian Carlstromaded5f72011-10-07 17:15:04 -0700673}
674
Mathieu Chartiere401d142015-04-22 13:56:20 -0700675std::string JniShortName(ArtMethod* m) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700676 std::string class_name(m->GetDeclaringClassDescriptor());
Elliott Hughes79082e32011-08-25 12:07:32 -0700677 // Remove the leading 'L' and trailing ';'...
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700678 CHECK_EQ(class_name[0], 'L') << class_name;
679 CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name;
Elliott Hughes79082e32011-08-25 12:07:32 -0700680 class_name.erase(0, 1);
681 class_name.erase(class_name.size() - 1, 1);
682
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700683 std::string method_name(m->GetName());
Elliott Hughes79082e32011-08-25 12:07:32 -0700684
685 std::string short_name;
686 short_name += "Java_";
687 short_name += MangleForJni(class_name);
688 short_name += "_";
689 short_name += MangleForJni(method_name);
690 return short_name;
691}
692
Mathieu Chartiere401d142015-04-22 13:56:20 -0700693std::string JniLongName(ArtMethod* m) {
Elliott Hughes79082e32011-08-25 12:07:32 -0700694 std::string long_name;
695 long_name += JniShortName(m);
696 long_name += "__";
697
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700698 std::string signature(m->GetSignature().ToString());
Elliott Hughes79082e32011-08-25 12:07:32 -0700699 signature.erase(0, 1);
700 signature.erase(signature.begin() + signature.find(')'), signature.end());
701
702 long_name += MangleForJni(signature);
703
704 return long_name;
705}
706
jeffhao10037c82012-01-23 15:06:23 -0800707// Helper for IsValidPartOfMemberNameUtf8(), a bit vector indicating valid low ascii.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700708uint32_t DEX_MEMBER_VALID_LOW_ASCII[4] = {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700709 0x00000000, // 00..1f low control characters; nothing valid
710 0x03ff2010, // 20..3f digits and symbols; valid: '0'..'9', '$', '-'
711 0x87fffffe, // 40..5f uppercase etc.; valid: 'A'..'Z', '_'
712 0x07fffffe // 60..7f lowercase etc.; valid: 'a'..'z'
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700713};
714
jeffhao10037c82012-01-23 15:06:23 -0800715// Helper for IsValidPartOfMemberNameUtf8(); do not call directly.
716bool IsValidPartOfMemberNameUtf8Slow(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700717 /*
718 * It's a multibyte encoded character. Decode it and analyze. We
719 * accept anything that isn't (a) an improperly encoded low value,
720 * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high
721 * control character, or (e) a high space, layout, or special
722 * character (U+00a0, U+2000..U+200f, U+2028..U+202f,
723 * U+fff0..U+ffff). This is all specified in the dex format
724 * document.
725 */
726
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000727 const uint32_t pair = GetUtf16FromUtf8(pUtf8Ptr);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000728 const uint16_t leading = GetLeadingUtf16Char(pair);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000729
Narayan Kamath8508e372015-05-06 14:55:43 +0100730 // We have a surrogate pair resulting from a valid 4 byte UTF sequence.
731 // No further checks are necessary because 4 byte sequences span code
732 // points [U+10000, U+1FFFFF], which are valid codepoints in a dex
733 // identifier. Furthermore, GetUtf16FromUtf8 guarantees that each of
734 // the surrogate halves are valid and well formed in this instance.
735 if (GetTrailingUtf16Char(pair) != 0) {
736 return true;
737 }
738
739
740 // We've encountered a one, two or three byte UTF-8 sequence. The
741 // three byte UTF-8 sequence could be one half of a surrogate pair.
742 switch (leading >> 8) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000743 case 0x00:
744 // It's only valid if it's above the ISO-8859-1 high space (0xa0).
745 return (leading > 0x00a0);
746 case 0xd8:
747 case 0xd9:
748 case 0xda:
749 case 0xdb:
Narayan Kamath8508e372015-05-06 14:55:43 +0100750 {
751 // We found a three byte sequence encoding one half of a surrogate.
752 // Look for the other half.
753 const uint32_t pair2 = GetUtf16FromUtf8(pUtf8Ptr);
754 const uint16_t trailing = GetLeadingUtf16Char(pair2);
755
756 return (GetTrailingUtf16Char(pair2) == 0) && (0xdc00 <= trailing && trailing <= 0xdfff);
757 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000758 case 0xdc:
759 case 0xdd:
760 case 0xde:
761 case 0xdf:
762 // It's a trailing surrogate, which is not valid at this point.
763 return false;
764 case 0x20:
765 case 0xff:
766 // It's in the range that has spaces, controls, and specials.
767 switch (leading & 0xfff8) {
Narayan Kamath8508e372015-05-06 14:55:43 +0100768 case 0x2000:
769 case 0x2008:
770 case 0x2028:
771 case 0xfff0:
772 case 0xfff8:
773 return false;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000774 }
Narayan Kamath8508e372015-05-06 14:55:43 +0100775 return true;
776 default:
777 return true;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700778 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000779
Narayan Kamath8508e372015-05-06 14:55:43 +0100780 UNREACHABLE();
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700781}
782
783/* Return whether the pointed-at modified-UTF-8 encoded character is
784 * valid as part of a member name, updating the pointer to point past
785 * the consumed character. This will consume two encoded UTF-16 code
786 * points if the character is encoded as a surrogate pair. Also, if
787 * this function returns false, then the given pointer may only have
788 * been partially advanced.
789 */
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700790static bool IsValidPartOfMemberNameUtf8(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700791 uint8_t c = (uint8_t) **pUtf8Ptr;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700792 if (LIKELY(c <= 0x7f)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700793 // It's low-ascii, so check the table.
794 uint32_t wordIdx = c >> 5;
795 uint32_t bitIdx = c & 0x1f;
796 (*pUtf8Ptr)++;
797 return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0;
798 }
799
800 // It's a multibyte encoded character. Call a non-inline function
801 // for the heavy lifting.
jeffhao10037c82012-01-23 15:06:23 -0800802 return IsValidPartOfMemberNameUtf8Slow(pUtf8Ptr);
803}
804
805bool IsValidMemberName(const char* s) {
806 bool angle_name = false;
807
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700808 switch (*s) {
jeffhao10037c82012-01-23 15:06:23 -0800809 case '\0':
810 // The empty string is not a valid name.
811 return false;
812 case '<':
813 angle_name = true;
814 s++;
815 break;
816 }
817
818 while (true) {
819 switch (*s) {
820 case '\0':
821 return !angle_name;
822 case '>':
823 return angle_name && s[1] == '\0';
824 }
825
826 if (!IsValidPartOfMemberNameUtf8(&s)) {
827 return false;
828 }
829 }
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700830}
831
Elliott Hughes906e6852011-10-28 14:52:10 -0700832enum ClassNameType { kName, kDescriptor };
Ian Rogers7b078e82014-09-10 14:44:24 -0700833template<ClassNameType kType, char kSeparator>
834static bool IsValidClassName(const char* s) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700835 int arrayCount = 0;
836 while (*s == '[') {
837 arrayCount++;
838 s++;
839 }
840
841 if (arrayCount > 255) {
842 // Arrays may have no more than 255 dimensions.
843 return false;
844 }
845
Ian Rogers7b078e82014-09-10 14:44:24 -0700846 ClassNameType type = kType;
847 if (type != kDescriptor && arrayCount != 0) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700848 /*
849 * If we're looking at an array of some sort, then it doesn't
850 * matter if what is being asked for is a class name; the
851 * format looks the same as a type descriptor in that case, so
852 * treat it as such.
853 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700854 type = kDescriptor;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700855 }
856
Elliott Hughes906e6852011-10-28 14:52:10 -0700857 if (type == kDescriptor) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700858 /*
859 * We are looking for a descriptor. Either validate it as a
860 * single-character primitive type, or continue on to check the
861 * embedded class name (bracketed by "L" and ";").
862 */
863 switch (*(s++)) {
864 case 'B':
865 case 'C':
866 case 'D':
867 case 'F':
868 case 'I':
869 case 'J':
870 case 'S':
871 case 'Z':
872 // These are all single-character descriptors for primitive types.
873 return (*s == '\0');
874 case 'V':
875 // Non-array void is valid, but you can't have an array of void.
876 return (arrayCount == 0) && (*s == '\0');
877 case 'L':
878 // Class name: Break out and continue below.
879 break;
880 default:
881 // Oddball descriptor character.
882 return false;
883 }
884 }
885
886 /*
887 * We just consumed the 'L' that introduces a class name as part
888 * of a type descriptor, or we are looking for an unadorned class
889 * name.
890 */
891
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700892 bool sepOrFirst = true; // first character or just encountered a separator.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700893 for (;;) {
894 uint8_t c = (uint8_t) *s;
895 switch (c) {
896 case '\0':
897 /*
898 * Premature end for a type descriptor, but valid for
899 * a class name as long as we haven't encountered an
900 * empty component (including the degenerate case of
901 * the empty string "").
902 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700903 return (type == kName) && !sepOrFirst;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700904 case ';':
905 /*
906 * Invalid character for a class name, but the
907 * legitimate end of a type descriptor. In the latter
908 * case, make sure that this is the end of the string
909 * and that it doesn't end with an empty component
910 * (including the degenerate case of "L;").
911 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700912 return (type == kDescriptor) && !sepOrFirst && (s[1] == '\0');
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700913 case '/':
914 case '.':
Ian Rogers7b078e82014-09-10 14:44:24 -0700915 if (c != kSeparator) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700916 // The wrong separator character.
917 return false;
918 }
919 if (sepOrFirst) {
920 // Separator at start or two separators in a row.
921 return false;
922 }
923 sepOrFirst = true;
924 s++;
925 break;
926 default:
jeffhao10037c82012-01-23 15:06:23 -0800927 if (!IsValidPartOfMemberNameUtf8(&s)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700928 return false;
929 }
930 sepOrFirst = false;
931 break;
932 }
933 }
934}
935
Elliott Hughes906e6852011-10-28 14:52:10 -0700936bool IsValidBinaryClassName(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700937 return IsValidClassName<kName, '.'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700938}
939
940bool IsValidJniClassName(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700941 return IsValidClassName<kName, '/'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700942}
943
944bool IsValidDescriptor(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700945 return IsValidClassName<kDescriptor, '/'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700946}
947
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700948void Split(const std::string& s, char separator, std::vector<std::string>* result) {
Elliott Hughes34023802011-08-30 12:06:17 -0700949 const char* p = s.data();
950 const char* end = p + s.size();
951 while (p != end) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800952 if (*p == separator) {
Elliott Hughes34023802011-08-30 12:06:17 -0700953 ++p;
954 } else {
955 const char* start = p;
Elliott Hughes48436bb2012-02-07 15:23:28 -0800956 while (++p != end && *p != separator) {
957 // Skip to the next occurrence of the separator.
Elliott Hughes34023802011-08-30 12:06:17 -0700958 }
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700959 result->push_back(std::string(start, p - start));
Elliott Hughes34023802011-08-30 12:06:17 -0700960 }
961 }
962}
963
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700964std::string Trim(const std::string& s) {
Dave Allison70202782013-10-22 17:52:19 -0700965 std::string result;
966 unsigned int start_index = 0;
967 unsigned int end_index = s.size() - 1;
968
969 // Skip initial whitespace.
970 while (start_index < s.size()) {
971 if (!isspace(s[start_index])) {
972 break;
973 }
974 start_index++;
975 }
976
977 // Skip terminating whitespace.
978 while (end_index >= start_index) {
979 if (!isspace(s[end_index])) {
980 break;
981 }
982 end_index--;
983 }
984
985 // All spaces, no beef.
986 if (end_index < start_index) {
987 return "";
988 }
989 // Start_index is the first non-space, end_index is the last one.
990 return s.substr(start_index, end_index - start_index + 1);
991}
992
Elliott Hughes48436bb2012-02-07 15:23:28 -0800993template <typename StringT>
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700994std::string Join(const std::vector<StringT>& strings, char separator) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800995 if (strings.empty()) {
996 return "";
997 }
998
999 std::string result(strings[0]);
1000 for (size_t i = 1; i < strings.size(); ++i) {
1001 result += separator;
1002 result += strings[i];
1003 }
1004 return result;
1005}
1006
1007// Explicit instantiations.
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001008template std::string Join<std::string>(const std::vector<std::string>& strings, char separator);
1009template std::string Join<const char*>(const std::vector<const char*>& strings, char separator);
Elliott Hughes48436bb2012-02-07 15:23:28 -08001010
Elliott Hughesf1a5adc2012-02-10 18:09:35 -08001011bool StartsWith(const std::string& s, const char* prefix) {
1012 return s.compare(0, strlen(prefix), prefix) == 0;
1013}
1014
Brian Carlstrom7a967b32012-03-28 15:23:10 -07001015bool EndsWith(const std::string& s, const char* suffix) {
1016 size_t suffix_length = strlen(suffix);
1017 size_t string_length = s.size();
1018 if (suffix_length > string_length) {
1019 return false;
1020 }
1021 size_t offset = string_length - suffix_length;
1022 return s.compare(offset, suffix_length, suffix) == 0;
1023}
1024
Elliott Hughes22869a92012-03-27 14:08:24 -07001025void SetThreadName(const char* thread_name) {
Elliott Hughesdcc24742011-09-07 14:02:44 -07001026 int hasAt = 0;
1027 int hasDot = 0;
Elliott Hughes22869a92012-03-27 14:08:24 -07001028 const char* s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001029 while (*s) {
1030 if (*s == '.') {
1031 hasDot = 1;
1032 } else if (*s == '@') {
1033 hasAt = 1;
1034 }
1035 s++;
1036 }
Elliott Hughes22869a92012-03-27 14:08:24 -07001037 int len = s - thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001038 if (len < 15 || hasAt || !hasDot) {
Elliott Hughes22869a92012-03-27 14:08:24 -07001039 s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001040 } else {
Elliott Hughes22869a92012-03-27 14:08:24 -07001041 s = thread_name + len - 15;
Elliott Hughesdcc24742011-09-07 14:02:44 -07001042 }
Elliott Hughes0a18df82015-01-09 15:16:16 -08001043#if defined(__linux__)
Elliott Hughes7c6a61e2012-03-12 18:01:41 -07001044 // pthread_setname_np fails rather than truncating long strings.
Elliott Hughes0a18df82015-01-09 15:16:16 -08001045 char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel.
Elliott Hughesdcc24742011-09-07 14:02:44 -07001046 strncpy(buf, s, sizeof(buf)-1);
1047 buf[sizeof(buf)-1] = '\0';
1048 errno = pthread_setname_np(pthread_self(), buf);
1049 if (errno != 0) {
1050 PLOG(WARNING) << "Unable to set the name of current thread to '" << buf << "'";
1051 }
Elliott Hughes0a18df82015-01-09 15:16:16 -08001052#else // __APPLE__
Elliott Hughes22869a92012-03-27 14:08:24 -07001053 pthread_setname_np(thread_name);
Elliott Hughesdcc24742011-09-07 14:02:44 -07001054#endif
1055}
1056
Brian Carlstrom29212012013-09-12 22:18:30 -07001057void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
1058 *utime = *stime = *task_cpu = 0;
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001059 std::string stats;
Elliott Hughes8a31b502012-04-30 19:36:11 -07001060 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001061 return;
1062 }
1063 // Skip the command, which may contain spaces.
1064 stats = stats.substr(stats.find(')') + 2);
1065 // Extract the three fields we care about.
1066 std::vector<std::string> fields;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001067 Split(stats, ' ', &fields);
Brian Carlstrom29212012013-09-12 22:18:30 -07001068 *state = fields[0][0];
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001069 *utime = strtoull(fields[11].c_str(), nullptr, 10);
1070 *stime = strtoull(fields[12].c_str(), nullptr, 10);
1071 *task_cpu = strtoull(fields[36].c_str(), nullptr, 10);
Elliott Hughesbfe487b2011-10-26 15:48:55 -07001072}
1073
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001074std::string GetSchedulerGroupName(pid_t tid) {
1075 // /proc/<pid>/cgroup looks like this:
1076 // 2:devices:/
1077 // 1:cpuacct,cpu:/
1078 // We want the third field from the line whose second field contains the "cpu" token.
1079 std::string cgroup_file;
1080 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/cgroup", tid), &cgroup_file)) {
1081 return "";
1082 }
1083 std::vector<std::string> cgroup_lines;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001084 Split(cgroup_file, '\n', &cgroup_lines);
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001085 for (size_t i = 0; i < cgroup_lines.size(); ++i) {
1086 std::vector<std::string> cgroup_fields;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001087 Split(cgroup_lines[i], ':', &cgroup_fields);
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001088 std::vector<std::string> cgroups;
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001089 Split(cgroup_fields[1], ',', &cgroups);
Andreas Gampe277ccbd2014-11-03 21:36:10 -08001090 for (size_t j = 0; j < cgroups.size(); ++j) {
1091 if (cgroups[j] == "cpu") {
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001092 return cgroup_fields[2].substr(1); // Skip the leading slash.
Elliott Hughes1bac54f2012-03-16 12:48:31 -07001093 }
1094 }
1095 }
1096 return "";
1097}
1098
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001099const char* GetAndroidRoot() {
1100 const char* android_root = getenv("ANDROID_ROOT");
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001101 if (android_root == nullptr) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001102 if (OS::DirectoryExists("/system")) {
1103 android_root = "/system";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001104 } else {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001105 LOG(FATAL) << "ANDROID_ROOT not set and /system does not exist";
1106 return "";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001107 }
1108 }
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001109 if (!OS::DirectoryExists(android_root)) {
1110 LOG(FATAL) << "Failed to find ANDROID_ROOT directory " << android_root;
Brian Carlstroma9f19782011-10-13 00:14:47 -07001111 return "";
1112 }
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001113 return android_root;
1114}
Brian Carlstroma9f19782011-10-13 00:14:47 -07001115
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001116const char* GetAndroidData() {
Alex Lighta59dd802014-07-02 16:28:08 -07001117 std::string error_msg;
1118 const char* dir = GetAndroidDataSafe(&error_msg);
1119 if (dir != nullptr) {
1120 return dir;
1121 } else {
1122 LOG(FATAL) << error_msg;
1123 return "";
1124 }
1125}
1126
1127const char* GetAndroidDataSafe(std::string* error_msg) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001128 const char* android_data = getenv("ANDROID_DATA");
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001129 if (android_data == nullptr) {
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001130 if (OS::DirectoryExists("/data")) {
1131 android_data = "/data";
1132 } else {
Alex Lighta59dd802014-07-02 16:28:08 -07001133 *error_msg = "ANDROID_DATA not set and /data does not exist";
1134 return nullptr;
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001135 }
1136 }
1137 if (!OS::DirectoryExists(android_data)) {
Alex Lighta59dd802014-07-02 16:28:08 -07001138 *error_msg = StringPrintf("Failed to find ANDROID_DATA directory %s", android_data);
1139 return nullptr;
Brian Carlstroma56fcd62012-02-04 21:23:01 -08001140 }
1141 return android_data;
1142}
1143
Alex Lighta59dd802014-07-02 16:28:08 -07001144void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
Andreas Gampe3c13a792014-09-18 20:56:04 -07001145 bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
Alex Lighta59dd802014-07-02 16:28:08 -07001146 CHECK(subdir != nullptr);
1147 std::string error_msg;
1148 const char* android_data = GetAndroidDataSafe(&error_msg);
1149 if (android_data == nullptr) {
1150 *have_android_data = false;
1151 *dalvik_cache_exists = false;
Andreas Gampe3c13a792014-09-18 20:56:04 -07001152 *is_global_cache = false;
Alex Lighta59dd802014-07-02 16:28:08 -07001153 return;
1154 } else {
1155 *have_android_data = true;
1156 }
1157 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
1158 *dalvik_cache = dalvik_cache_root + subdir;
1159 *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
Andreas Gampe3c13a792014-09-18 20:56:04 -07001160 *is_global_cache = strcmp(android_data, "/data") == 0;
1161 if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) {
Alex Lighta59dd802014-07-02 16:28:08 -07001162 // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
1163 *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
1164 (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
1165 }
1166}
1167
Richard Uhler55b58b62016-08-12 09:05:13 -07001168std::string GetDalvikCache(const char* subdir) {
Narayan Kamath11d9f062014-04-23 20:24:57 +01001169 CHECK(subdir != nullptr);
Brian Carlstrom41ccffd2014-05-06 10:37:30 -07001170 const char* android_data = GetAndroidData();
1171 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
Narayan Kamath11d9f062014-04-23 20:24:57 +01001172 const std::string dalvik_cache = dalvik_cache_root + subdir;
Andreas Gampe40da2862015-02-27 12:49:04 -08001173 if (!OS::DirectoryExists(dalvik_cache.c_str())) {
Richard Uhler55b58b62016-08-12 09:05:13 -07001174 // TODO: Check callers. Traditional behavior is to not abort.
1175 return "";
Brian Carlstroma9f19782011-10-13 00:14:47 -07001176 }
Brian Carlstrom7675e162013-06-10 16:18:04 -07001177 return dalvik_cache;
Brian Carlstroma9f19782011-10-13 00:14:47 -07001178}
1179
Alex Lighta59dd802014-07-02 16:28:08 -07001180bool GetDalvikCacheFilename(const char* location, const char* cache_location,
1181 std::string* filename, std::string* error_msg) {
Ian Rogerse6060102013-05-16 12:01:04 -07001182 if (location[0] != '/') {
Alex Lighta59dd802014-07-02 16:28:08 -07001183 *error_msg = StringPrintf("Expected path in location to be absolute: %s", location);
1184 return false;
Ian Rogerse6060102013-05-16 12:01:04 -07001185 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001186 std::string cache_file(&location[1]); // skip leading slash
Alex Light6e183f22014-07-18 14:57:04 -07001187 if (!EndsWith(location, ".dex") && !EndsWith(location, ".art") && !EndsWith(location, ".oat")) {
Brian Carlstrom30e2ea42013-06-19 23:25:37 -07001188 cache_file += "/";
1189 cache_file += DexFile::kClassesDex;
1190 }
Brian Carlstromb7bbba42011-10-13 14:58:47 -07001191 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
Alex Lighta59dd802014-07-02 16:28:08 -07001192 *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
1193 return true;
1194}
1195
Brian Carlstrom2afe4942014-05-19 10:25:33 -07001196static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) {
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -07001197 // in = /foo/bar/baz
1198 // out = /foo/bar/<isa>/baz
1199 size_t pos = filename->rfind('/');
1200 CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
1201 filename->insert(pos, "/", 1);
1202 filename->insert(pos + 1, GetInstructionSetString(isa));
1203}
1204
1205std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
1206 // location = /system/framework/boot.art
1207 // filename = /system/framework/<isa>/boot.art
1208 std::string filename(location);
Brian Carlstrom2afe4942014-05-19 10:25:33 -07001209 InsertIsaDirectory(isa, &filename);
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -07001210 return filename;
1211}
1212
Calin Juravle2e2db782016-02-23 12:00:03 +00001213int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) {
Brian Carlstrom6449c622014-02-10 23:48:36 -08001214 const std::string command_line(Join(arg_vector, ' '));
Brian Carlstrom6449c622014-02-10 23:48:36 -08001215 CHECK_GE(arg_vector.size(), 1U) << command_line;
1216
1217 // Convert the args to char pointers.
1218 const char* program = arg_vector[0].c_str();
1219 std::vector<char*> args;
Brian Carlstrom35d8b8e2014-02-25 10:51:11 -08001220 for (size_t i = 0; i < arg_vector.size(); ++i) {
1221 const std::string& arg = arg_vector[i];
1222 char* arg_str = const_cast<char*>(arg.c_str());
1223 CHECK(arg_str != nullptr) << i;
1224 args.push_back(arg_str);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001225 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001226 args.push_back(nullptr);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001227
1228 // fork and exec
1229 pid_t pid = fork();
1230 if (pid == 0) {
1231 // no allocation allowed between fork and exec
1232
1233 // change process groups, so we don't get reaped by ProcessManager
1234 setpgid(0, 0);
1235
David Sehrd106d9f2016-08-16 19:22:57 -07001236 // (b/30160149): protect subprocesses from modifications to LD_LIBRARY_PATH, etc.
1237 // Use the snapshot of the environment from the time the runtime was created.
1238 char** envp = (Runtime::Current() == nullptr) ? nullptr : Runtime::Current()->GetEnvSnapshot();
1239 if (envp == nullptr) {
1240 execv(program, &args[0]);
1241 } else {
1242 execve(program, &args[0], envp);
1243 }
1244 PLOG(ERROR) << "Failed to execve(" << command_line << ")";
Tobias Lindskogae35c372015-11-04 19:41:21 +01001245 // _exit to avoid atexit handlers in child.
1246 _exit(1);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001247 } else {
1248 if (pid == -1) {
1249 *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
1250 command_line.c_str(), strerror(errno));
Calin Juravle2e2db782016-02-23 12:00:03 +00001251 return -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001252 }
1253
1254 // wait for subprocess to finish
Calin Juravle2e2db782016-02-23 12:00:03 +00001255 int status = -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001256 pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
1257 if (got_pid != pid) {
1258 *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
1259 "wanted %d, got %d: %s",
1260 command_line.c_str(), pid, got_pid, strerror(errno));
Calin Juravle2e2db782016-02-23 12:00:03 +00001261 return -1;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001262 }
Calin Juravle2e2db782016-02-23 12:00:03 +00001263 if (WIFEXITED(status)) {
1264 return WEXITSTATUS(status);
Brian Carlstrom6449c622014-02-10 23:48:36 -08001265 }
Calin Juravle2e2db782016-02-23 12:00:03 +00001266 return -1;
1267 }
1268}
1269
1270bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
1271 int status = ExecAndReturnCode(arg_vector, error_msg);
1272 if (status != 0) {
1273 const std::string command_line(Join(arg_vector, ' '));
1274 *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
1275 command_line.c_str());
1276 return false;
Brian Carlstrom6449c622014-02-10 23:48:36 -08001277 }
1278 return true;
1279}
1280
Calin Juravle5e2b9712015-12-18 14:10:00 +02001281bool FileExists(const std::string& filename) {
1282 struct stat buffer;
1283 return stat(filename.c_str(), &buffer) == 0;
1284}
1285
Calin Juravleb9c1b9b2016-03-17 17:07:52 +00001286bool FileExistsAndNotEmpty(const std::string& filename) {
1287 struct stat buffer;
1288 if (stat(filename.c_str(), &buffer) != 0) {
1289 return false;
1290 }
1291 return buffer.st_size > 0;
1292}
1293
David Brazdil7b49e6c2016-09-01 11:06:18 +01001294std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
1295 const size_t last_ext = filename.find_last_of('.');
1296 if (last_ext == std::string::npos) {
1297 return filename + "." + new_extension;
1298 } else {
1299 return filename.substr(0, last_ext + 1) + new_extension;
1300 }
1301}
1302
Mathieu Chartier76433272014-09-26 14:32:37 -07001303std::string PrettyDescriptor(Primitive::Type type) {
1304 return PrettyDescriptor(Primitive::Descriptor(type));
1305}
1306
Andreas Gampe5073fed2015-08-10 11:40:25 -07001307static void DumpMethodCFGImpl(const DexFile* dex_file,
1308 uint32_t dex_method_idx,
1309 const DexFile::CodeItem* code_item,
1310 std::ostream& os) {
1311 os << "digraph {\n";
1312 os << " # /* " << PrettyMethod(dex_method_idx, *dex_file, true) << " */\n";
1313
1314 std::set<uint32_t> dex_pc_is_branch_target;
1315 {
1316 // Go and populate.
1317 const Instruction* inst = Instruction::At(code_item->insns_);
1318 for (uint32_t dex_pc = 0;
1319 dex_pc < code_item->insns_size_in_code_units_;
1320 dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
1321 if (inst->IsBranch()) {
1322 dex_pc_is_branch_target.insert(dex_pc + inst->GetTargetOffset());
1323 } else if (inst->IsSwitch()) {
1324 const uint16_t* insns = code_item->insns_ + dex_pc;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001325 int32_t switch_offset = insns[1] | (static_cast<int32_t>(insns[2]) << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001326 const uint16_t* switch_insns = insns + switch_offset;
1327 uint32_t switch_count = switch_insns[1];
1328 int32_t targets_offset;
1329 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
1330 /* 0=sig, 1=count, 2/3=firstKey */
1331 targets_offset = 4;
1332 } else {
1333 /* 0=sig, 1=count, 2..count*2 = keys */
1334 targets_offset = 2 + 2 * switch_count;
1335 }
1336 for (uint32_t targ = 0; targ < switch_count; targ++) {
Andreas Gampe53de99c2015-08-17 13:43:55 -07001337 int32_t offset =
1338 static_cast<int32_t>(switch_insns[targets_offset + targ * 2]) |
1339 static_cast<int32_t>(switch_insns[targets_offset + targ * 2 + 1] << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001340 dex_pc_is_branch_target.insert(dex_pc + offset);
1341 }
1342 }
1343 }
1344 }
1345
1346 // Create nodes for "basic blocks."
1347 std::map<uint32_t, uint32_t> dex_pc_to_node_id; // This only has entries for block starts.
1348 std::map<uint32_t, uint32_t> dex_pc_to_incl_id; // This has entries for all dex pcs.
1349
1350 {
1351 const Instruction* inst = Instruction::At(code_item->insns_);
1352 bool first_in_block = true;
1353 bool force_new_block = false;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001354 for (uint32_t dex_pc = 0;
1355 dex_pc < code_item->insns_size_in_code_units_;
1356 dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
Andreas Gampe5073fed2015-08-10 11:40:25 -07001357 if (dex_pc == 0 ||
1358 (dex_pc_is_branch_target.find(dex_pc) != dex_pc_is_branch_target.end()) ||
1359 force_new_block) {
1360 uint32_t id = dex_pc_to_node_id.size();
1361 if (id > 0) {
1362 // End last node.
1363 os << "}\"];\n";
1364 }
1365 // Start next node.
1366 os << " node" << id << " [shape=record,label=\"{";
1367 dex_pc_to_node_id.insert(std::make_pair(dex_pc, id));
1368 first_in_block = true;
1369 force_new_block = false;
1370 }
1371
1372 // Register instruction.
1373 dex_pc_to_incl_id.insert(std::make_pair(dex_pc, dex_pc_to_node_id.size() - 1));
1374
1375 // Print instruction.
1376 if (!first_in_block) {
1377 os << " | ";
1378 } else {
1379 first_in_block = false;
1380 }
1381
1382 // Dump the instruction. Need to escape '"', '<', '>', '{' and '}'.
1383 os << "<" << "p" << dex_pc << ">";
1384 os << " 0x" << std::hex << dex_pc << std::dec << ": ";
1385 std::string inst_str = inst->DumpString(dex_file);
1386 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 -07001387 // we need to escape.
Andreas Gampe5073fed2015-08-10 11:40:25 -07001388 while (cur_start != std::string::npos) {
1389 size_t next_escape = inst_str.find_first_of("\"{}<>", cur_start + 1);
1390 if (next_escape == std::string::npos) {
1391 os << inst_str.substr(cur_start, inst_str.size() - cur_start);
1392 break;
1393 } else {
1394 os << inst_str.substr(cur_start, next_escape - cur_start);
1395 // Escape all necessary characters.
1396 while (next_escape < inst_str.size()) {
1397 char c = inst_str.at(next_escape);
1398 if (c == '"' || c == '{' || c == '}' || c == '<' || c == '>') {
1399 os << '\\' << c;
1400 } else {
1401 break;
1402 }
1403 next_escape++;
1404 }
1405 if (next_escape >= inst_str.size()) {
1406 next_escape = std::string::npos;
1407 }
1408 cur_start = next_escape;
1409 }
1410 }
1411
1412 // Force a new block for some fall-throughs and some instructions that terminate the "local"
1413 // control flow.
1414 force_new_block = inst->IsSwitch() || inst->IsBasicBlockEnd();
1415 }
1416 // Close last node.
1417 if (dex_pc_to_node_id.size() > 0) {
1418 os << "}\"];\n";
1419 }
1420 }
1421
1422 // Create edges between them.
1423 {
1424 std::ostringstream regular_edges;
1425 std::ostringstream taken_edges;
1426 std::ostringstream exception_edges;
1427
1428 // Common set of exception edges.
1429 std::set<uint32_t> exception_targets;
1430
1431 // These blocks (given by the first dex pc) need exception per dex-pc handling in a second
1432 // pass. In the first pass we try and see whether we can use a common set of edges.
1433 std::set<uint32_t> blocks_with_detailed_exceptions;
1434
1435 {
1436 uint32_t last_node_id = std::numeric_limits<uint32_t>::max();
1437 uint32_t old_dex_pc = 0;
1438 uint32_t block_start_dex_pc = std::numeric_limits<uint32_t>::max();
1439 const Instruction* inst = Instruction::At(code_item->insns_);
1440 for (uint32_t dex_pc = 0;
1441 dex_pc < code_item->insns_size_in_code_units_;
1442 old_dex_pc = dex_pc, dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
1443 {
1444 auto it = dex_pc_to_node_id.find(dex_pc);
1445 if (it != dex_pc_to_node_id.end()) {
1446 if (!exception_targets.empty()) {
1447 // It seems the last block had common exception handlers. Add the exception edges now.
1448 uint32_t node_id = dex_pc_to_node_id.find(block_start_dex_pc)->second;
1449 for (uint32_t handler_pc : exception_targets) {
1450 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1451 if (node_id_it != dex_pc_to_incl_id.end()) {
1452 exception_edges << " node" << node_id
1453 << " -> node" << node_id_it->second << ":p" << handler_pc
1454 << ";\n";
1455 }
1456 }
1457 exception_targets.clear();
1458 }
1459
1460 block_start_dex_pc = dex_pc;
1461
1462 // Seems to be a fall-through, connect to last_node_id. May be spurious edges for things
1463 // like switch data.
1464 uint32_t old_last = last_node_id;
1465 last_node_id = it->second;
1466 if (old_last != std::numeric_limits<uint32_t>::max()) {
1467 regular_edges << " node" << old_last << ":p" << old_dex_pc
1468 << " -> node" << last_node_id << ":p" << dex_pc
1469 << ";\n";
1470 }
1471 }
1472
1473 // Look at the exceptions of the first entry.
1474 CatchHandlerIterator catch_it(*code_item, dex_pc);
1475 for (; catch_it.HasNext(); catch_it.Next()) {
1476 exception_targets.insert(catch_it.GetHandlerAddress());
1477 }
1478 }
1479
1480 // Handle instruction.
1481
1482 // Branch: something with at most two targets.
1483 if (inst->IsBranch()) {
1484 const int32_t offset = inst->GetTargetOffset();
1485 const bool conditional = !inst->IsUnconditional();
1486
1487 auto target_it = dex_pc_to_node_id.find(dex_pc + offset);
1488 if (target_it != dex_pc_to_node_id.end()) {
1489 taken_edges << " node" << last_node_id << ":p" << dex_pc
1490 << " -> node" << target_it->second << ":p" << (dex_pc + offset)
1491 << ";\n";
1492 }
1493 if (!conditional) {
1494 // No fall-through.
1495 last_node_id = std::numeric_limits<uint32_t>::max();
1496 }
1497 } else if (inst->IsSwitch()) {
1498 // TODO: Iterate through all switch targets.
1499 const uint16_t* insns = code_item->insns_ + dex_pc;
1500 /* make sure the start of the switch is in range */
Andreas Gampe53de99c2015-08-17 13:43:55 -07001501 int32_t switch_offset = insns[1] | (static_cast<int32_t>(insns[2]) << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001502 /* offset to switch table is a relative branch-style offset */
1503 const uint16_t* switch_insns = insns + switch_offset;
1504 uint32_t switch_count = switch_insns[1];
1505 int32_t targets_offset;
1506 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
1507 /* 0=sig, 1=count, 2/3=firstKey */
1508 targets_offset = 4;
1509 } else {
1510 /* 0=sig, 1=count, 2..count*2 = keys */
1511 targets_offset = 2 + 2 * switch_count;
1512 }
1513 /* make sure the end of the switch is in range */
1514 /* verify each switch target */
1515 for (uint32_t targ = 0; targ < switch_count; targ++) {
Andreas Gampe53de99c2015-08-17 13:43:55 -07001516 int32_t offset =
1517 static_cast<int32_t>(switch_insns[targets_offset + targ * 2]) |
1518 static_cast<int32_t>(switch_insns[targets_offset + targ * 2 + 1] << 16);
Andreas Gampe5073fed2015-08-10 11:40:25 -07001519 int32_t abs_offset = dex_pc + offset;
1520 auto target_it = dex_pc_to_node_id.find(abs_offset);
1521 if (target_it != dex_pc_to_node_id.end()) {
1522 // TODO: value label.
1523 taken_edges << " node" << last_node_id << ":p" << dex_pc
1524 << " -> node" << target_it->second << ":p" << (abs_offset)
1525 << ";\n";
1526 }
1527 }
1528 }
1529
1530 // Exception edges. If this is not the first instruction in the block
1531 if (block_start_dex_pc != dex_pc) {
1532 std::set<uint32_t> current_handler_pcs;
1533 CatchHandlerIterator catch_it(*code_item, dex_pc);
1534 for (; catch_it.HasNext(); catch_it.Next()) {
1535 current_handler_pcs.insert(catch_it.GetHandlerAddress());
1536 }
1537 if (current_handler_pcs != exception_targets) {
1538 exception_targets.clear(); // Clear so we don't do something at the end.
1539 blocks_with_detailed_exceptions.insert(block_start_dex_pc);
1540 }
1541 }
1542
1543 if (inst->IsReturn() ||
1544 (inst->Opcode() == Instruction::THROW) ||
1545 (inst->IsBranch() && inst->IsUnconditional())) {
1546 // No fall-through.
1547 last_node_id = std::numeric_limits<uint32_t>::max();
1548 }
1549 }
1550 // Finish up the last block, if it had common exceptions.
1551 if (!exception_targets.empty()) {
1552 // It seems the last block had common exception handlers. Add the exception edges now.
1553 uint32_t node_id = dex_pc_to_node_id.find(block_start_dex_pc)->second;
1554 for (uint32_t handler_pc : exception_targets) {
1555 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1556 if (node_id_it != dex_pc_to_incl_id.end()) {
1557 exception_edges << " node" << node_id
1558 << " -> node" << node_id_it->second << ":p" << handler_pc
1559 << ";\n";
1560 }
1561 }
1562 exception_targets.clear();
1563 }
1564 }
1565
1566 // Second pass for detailed exception blocks.
1567 // TODO
1568 // Exception edges. If this is not the first instruction in the block
1569 for (uint32_t dex_pc : blocks_with_detailed_exceptions) {
1570 const Instruction* inst = Instruction::At(&code_item->insns_[dex_pc]);
1571 uint32_t this_node_id = dex_pc_to_incl_id.find(dex_pc)->second;
Andreas Gampe53de99c2015-08-17 13:43:55 -07001572 while (true) {
Andreas Gampe5073fed2015-08-10 11:40:25 -07001573 CatchHandlerIterator catch_it(*code_item, dex_pc);
1574 if (catch_it.HasNext()) {
1575 std::set<uint32_t> handled_targets;
1576 for (; catch_it.HasNext(); catch_it.Next()) {
1577 uint32_t handler_pc = catch_it.GetHandlerAddress();
1578 auto it = handled_targets.find(handler_pc);
1579 if (it == handled_targets.end()) {
1580 auto node_id_it = dex_pc_to_incl_id.find(handler_pc);
1581 if (node_id_it != dex_pc_to_incl_id.end()) {
1582 exception_edges << " node" << this_node_id << ":p" << dex_pc
1583 << " -> node" << node_id_it->second << ":p" << handler_pc
1584 << ";\n";
1585 }
1586
1587 // Mark as done.
1588 handled_targets.insert(handler_pc);
1589 }
1590 }
1591 }
1592 if (inst->IsBasicBlockEnd()) {
1593 break;
1594 }
1595
Andreas Gampe53de99c2015-08-17 13:43:55 -07001596 // Loop update. Have a break-out if the next instruction is a branch target and thus in
1597 // another block.
Andreas Gampe5073fed2015-08-10 11:40:25 -07001598 dex_pc += inst->SizeInCodeUnits();
1599 if (dex_pc >= code_item->insns_size_in_code_units_) {
1600 break;
1601 }
1602 if (dex_pc_to_node_id.find(dex_pc) != dex_pc_to_node_id.end()) {
1603 break;
1604 }
1605 inst = inst->Next();
1606 }
1607 }
1608
1609 // Write out the sub-graphs to make edges styled.
1610 os << "\n";
1611 os << " subgraph regular_edges {\n";
1612 os << " edge [color=\"#000000\",weight=.3,len=3];\n\n";
1613 os << " " << regular_edges.str() << "\n";
1614 os << " }\n\n";
1615
1616 os << " subgraph taken_edges {\n";
1617 os << " edge [color=\"#00FF00\",weight=.3,len=3];\n\n";
1618 os << " " << taken_edges.str() << "\n";
1619 os << " }\n\n";
1620
1621 os << " subgraph exception_edges {\n";
1622 os << " edge [color=\"#FF0000\",weight=.3,len=3];\n\n";
1623 os << " " << exception_edges.str() << "\n";
1624 os << " }\n\n";
1625 }
1626
1627 os << "}\n";
1628}
1629
1630void DumpMethodCFG(ArtMethod* method, std::ostream& os) {
1631 const DexFile* dex_file = method->GetDexFile();
1632 const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
1633
1634 DumpMethodCFGImpl(dex_file, method->GetDexMethodIndex(), code_item, os);
1635}
1636
1637void DumpMethodCFG(const DexFile* dex_file, uint32_t dex_method_idx, std::ostream& os) {
1638 // This is painful, we need to find the code item. That means finding the class, and then
1639 // iterating the table.
1640 if (dex_method_idx >= dex_file->NumMethodIds()) {
1641 os << "Could not find method-idx.";
1642 return;
1643 }
1644 const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
1645
1646 const DexFile::ClassDef* class_def = dex_file->FindClassDef(method_id.class_idx_);
1647 if (class_def == nullptr) {
1648 os << "Could not find class-def.";
1649 return;
1650 }
1651
1652 const uint8_t* class_data = dex_file->GetClassData(*class_def);
1653 if (class_data == nullptr) {
1654 os << "No class data.";
1655 return;
1656 }
1657
1658 ClassDataItemIterator it(*dex_file, class_data);
1659 // Skip fields
1660 while (it.HasNextStaticField() || it.HasNextInstanceField()) {
1661 it.Next();
1662 }
1663
1664 // Find method, and dump it.
1665 while (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
1666 uint32_t method_idx = it.GetMemberIndex();
1667 if (method_idx == dex_method_idx) {
1668 DumpMethodCFGImpl(dex_file, dex_method_idx, it.GetMethodCodeItem(), os);
1669 return;
1670 }
1671 it.Next();
1672 }
1673
1674 // Otherwise complain.
1675 os << "Something went wrong, didn't find the method in the class data.";
1676}
1677
Nicolas Geoffrayabbb0f72015-10-29 18:55:58 +00001678static void ParseStringAfterChar(const std::string& s,
1679 char c,
1680 std::string* parsed_value,
1681 UsageFn Usage) {
1682 std::string::size_type colon = s.find(c);
1683 if (colon == std::string::npos) {
1684 Usage("Missing char %c in option %s\n", c, s.c_str());
1685 }
1686 // Add one to remove the char we were trimming until.
1687 *parsed_value = s.substr(colon + 1);
1688}
1689
1690void ParseDouble(const std::string& option,
1691 char after_char,
1692 double min,
1693 double max,
1694 double* parsed_value,
1695 UsageFn Usage) {
1696 std::string substring;
1697 ParseStringAfterChar(option, after_char, &substring, Usage);
1698 bool sane_val = true;
1699 double value;
1700 if ((false)) {
1701 // TODO: this doesn't seem to work on the emulator. b/15114595
1702 std::stringstream iss(substring);
1703 iss >> value;
1704 // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
1705 sane_val = iss.eof() && (value >= min) && (value <= max);
1706 } else {
1707 char* end = nullptr;
1708 value = strtod(substring.c_str(), &end);
1709 sane_val = *end == '\0' && value >= min && value <= max;
1710 }
1711 if (!sane_val) {
1712 Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str());
1713 }
1714 *parsed_value = value;
1715}
1716
Calin Juravle4d77b6a2015-12-01 18:38:09 +00001717int64_t GetFileSizeBytes(const std::string& filename) {
1718 struct stat stat_buf;
1719 int rc = stat(filename.c_str(), &stat_buf);
1720 return rc == 0 ? stat_buf.st_size : -1;
1721}
1722
Mathieu Chartier4d87df62016-01-07 15:14:19 -08001723void SleepForever() {
1724 while (true) {
1725 usleep(1000000);
1726 }
1727}
1728
Elliott Hughes42ee1422011-09-06 12:33:32 -07001729} // namespace art