blob: 9a12b93d1835df400590a6b42fbb33e06c4fc162 [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
Elliott Hughes06e3ad42012-02-07 14:51:57 -080019#include <dynamic_annotations.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>
24#include <unistd.h>
25
Elliott Hughes90a33692011-08-30 13:27:07 -070026#include "UniquePtr.h"
Ian Rogersd81871c2011-10-03 13:57:23 -070027#include "class_loader.h"
buzbeec143c552011-08-20 17:38:58 -070028#include "file.h"
Elliott Hughes11e45072011-08-16 17:40:46 -070029#include "object.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080030#include "object_utils.h"
buzbeec143c552011-08-20 17:38:58 -070031#include "os.h"
Elliott Hughes11e45072011-08-16 17:40:46 -070032
Elliott Hughesad6c9c32012-01-19 17:39:12 -080033#if !defined(HAVE_POSIX_CLOCKS)
34#include <sys/time.h>
35#endif
36
Elliott Hughesdcc24742011-09-07 14:02:44 -070037#if defined(HAVE_PRCTL)
38#include <sys/prctl.h>
39#endif
40
Elliott Hughes4ae722a2012-03-13 11:08:51 -070041#if defined(__APPLE__)
42#include "AvailabilityMacros.h"
Elliott Hughesf1498432012-03-28 19:34:27 -070043#include <sys/syscall.h>
Elliott Hughes4ae722a2012-03-13 11:08:51 -070044#endif
45
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080046#if defined(__linux__)
Elliott Hughese1aee692012-01-17 16:40:10 -080047#include <linux/unistd.h>
Elliott Hughese1aee692012-01-17 16:40:10 -080048#endif
49
Elliott Hughes11e45072011-08-16 17:40:46 -070050namespace art {
51
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080052pid_t GetTid() {
Elliott Hughes5d6d5dc2012-03-29 11:59:27 -070053#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
54 // Darwin has a gettid(2), but it does something completely unrelated to tids.
55 // There is a thread_selfid(2) that does what we want though, and it seems to be what their
Elliott Hughesf1498432012-03-28 19:34:27 -070056 // pthreads implementation uses.
57 return syscall(SYS_thread_selfid);
Elliott Hughes5d6d5dc2012-03-29 11:59:27 -070058#elif defined(__APPLE__)
59 // On Mac OS 10.5 (which the build servers are still running) there was nothing usable.
60 return getpid();
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080061#else
62 // Neither bionic nor glibc exposes gettid(2).
63 return syscall(__NR_gettid);
64#endif
65}
66
Elliott Hughesd92bec42011-09-02 17:04:36 -070067bool ReadFileToString(const std::string& file_name, std::string* result) {
68 UniquePtr<File> file(OS::OpenFile(file_name.c_str(), false));
69 if (file.get() == NULL) {
70 return false;
71 }
buzbeec143c552011-08-20 17:38:58 -070072
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070073 std::vector<char> buf(8 * KB);
buzbeec143c552011-08-20 17:38:58 -070074 while (true) {
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070075 int64_t n = file->Read(&buf[0], buf.size());
Elliott Hughesd92bec42011-09-02 17:04:36 -070076 if (n == -1) {
77 return false;
buzbeec143c552011-08-20 17:38:58 -070078 }
Elliott Hughesd92bec42011-09-02 17:04:36 -070079 if (n == 0) {
80 return true;
81 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070082 result->append(&buf[0], n);
buzbeec143c552011-08-20 17:38:58 -070083 }
buzbeec143c552011-08-20 17:38:58 -070084}
85
Elliott Hughese27955c2011-08-26 15:21:24 -070086std::string GetIsoDate() {
87 time_t now = time(NULL);
88 struct tm tmbuf;
89 struct tm* ptm = localtime_r(&now, &tmbuf);
90 return StringPrintf("%04d-%02d-%02d %02d:%02d:%02d",
91 ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday,
92 ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
93}
94
Elliott Hughes7162ad92011-10-27 14:08:42 -070095uint64_t MilliTime() {
Elliott Hughesad6c9c32012-01-19 17:39:12 -080096#if defined(HAVE_POSIX_CLOCKS)
Elliott Hughes7162ad92011-10-27 14:08:42 -070097 struct timespec now;
98 clock_gettime(CLOCK_MONOTONIC, &now);
99 return static_cast<uint64_t>(now.tv_sec) * 1000LL + now.tv_nsec / 1000000LL;
Elliott Hughesad6c9c32012-01-19 17:39:12 -0800100#else
101 struct timeval now;
102 gettimeofday(&now, NULL);
103 return static_cast<uint64_t>(now.tv_sec) * 1000LL + now.tv_usec / 1000LL;
104#endif
Elliott Hughes7162ad92011-10-27 14:08:42 -0700105}
106
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800107uint64_t MicroTime() {
Elliott Hughesad6c9c32012-01-19 17:39:12 -0800108#if defined(HAVE_POSIX_CLOCKS)
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800109 struct timespec now;
110 clock_gettime(CLOCK_MONOTONIC, &now);
111 return static_cast<uint64_t>(now.tv_sec) * 1000000LL + now.tv_nsec / 1000LL;
Elliott Hughesad6c9c32012-01-19 17:39:12 -0800112#else
113 struct timeval now;
114 gettimeofday(&now, NULL);
115 return static_cast<uint64_t>(now.tv_sec) * 1000000LL + now.tv_usec * 1000LL;
116#endif
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800117}
118
Elliott Hughes83df2ac2011-10-11 16:37:54 -0700119uint64_t NanoTime() {
Elliott Hughesad6c9c32012-01-19 17:39:12 -0800120#if defined(HAVE_POSIX_CLOCKS)
Elliott Hughes83df2ac2011-10-11 16:37:54 -0700121 struct timespec now;
122 clock_gettime(CLOCK_MONOTONIC, &now);
123 return static_cast<uint64_t>(now.tv_sec) * 1000000000LL + now.tv_nsec;
Elliott Hughesad6c9c32012-01-19 17:39:12 -0800124#else
125 struct timeval now;
126 gettimeofday(&now, NULL);
127 return static_cast<uint64_t>(now.tv_sec) * 1000000000LL + now.tv_usec * 1000LL;
128#endif
Elliott Hughes83df2ac2011-10-11 16:37:54 -0700129}
130
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800131uint64_t ThreadCpuMicroTime() {
Elliott Hughesad6c9c32012-01-19 17:39:12 -0800132#if defined(HAVE_POSIX_CLOCKS)
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800133 struct timespec now;
134 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
135 return static_cast<uint64_t>(now.tv_sec) * 1000000LL + now.tv_nsec / 1000LL;
Elliott Hughesad6c9c32012-01-19 17:39:12 -0800136#else
137 UNIMPLEMENTED(WARNING);
138 return -1;
139#endif
jeffhaoa9ef3fd2011-12-13 18:33:43 -0800140}
141
Elliott Hughes0512f022012-03-15 22:10:52 -0700142uint64_t ThreadCpuNanoTime() {
143#if defined(HAVE_POSIX_CLOCKS)
144 struct timespec now;
145 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
146 return static_cast<uint64_t>(now.tv_sec) * 1000000000LL + now.tv_nsec;
147#else
148 UNIMPLEMENTED(WARNING);
149 return -1;
150#endif
151}
152
Elliott Hughes5174fe62011-08-23 15:12:35 -0700153std::string PrettyDescriptor(const String* java_descriptor) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700154 if (java_descriptor == NULL) {
155 return "null";
156 }
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700157 return PrettyDescriptor(java_descriptor->ToModifiedUtf8());
158}
Elliott Hughes5174fe62011-08-23 15:12:35 -0700159
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800160std::string PrettyDescriptor(const Class* klass) {
161 if (klass == NULL) {
162 return "null";
163 }
164 return PrettyDescriptor(ClassHelper(klass).GetDescriptor());
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800165}
166
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700167std::string PrettyDescriptor(const std::string& descriptor) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700168 // Count the number of '['s to get the dimensionality.
Elliott Hughes5174fe62011-08-23 15:12:35 -0700169 const char* c = descriptor.c_str();
Elliott Hughes11e45072011-08-16 17:40:46 -0700170 size_t dim = 0;
171 while (*c == '[') {
172 dim++;
173 c++;
174 }
175
176 // Reference or primitive?
177 if (*c == 'L') {
178 // "[[La/b/C;" -> "a.b.C[][]".
179 c++; // Skip the 'L'.
180 } else {
181 // "[[B" -> "byte[][]".
182 // To make life easier, we make primitives look like unqualified
183 // reference types.
184 switch (*c) {
185 case 'B': c = "byte;"; break;
186 case 'C': c = "char;"; break;
187 case 'D': c = "double;"; break;
188 case 'F': c = "float;"; break;
189 case 'I': c = "int;"; break;
190 case 'J': c = "long;"; break;
191 case 'S': c = "short;"; break;
192 case 'Z': c = "boolean;"; break;
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700193 case 'V': c = "void;"; break; // Used when decoding return types.
Elliott Hughes5174fe62011-08-23 15:12:35 -0700194 default: return descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700195 }
196 }
197
198 // At this point, 'c' is a string of the form "fully/qualified/Type;"
199 // or "primitive;". Rewrite the type with '.' instead of '/':
200 std::string result;
201 const char* p = c;
202 while (*p != ';') {
203 char ch = *p++;
204 if (ch == '/') {
205 ch = '.';
206 }
207 result.push_back(ch);
208 }
209 // ...and replace the semicolon with 'dim' "[]" pairs:
210 while (dim--) {
211 result += "[]";
212 }
213 return result;
214}
215
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700216std::string PrettyDescriptor(Primitive::Type type) {
Elliott Hughes91250e02011-12-13 22:30:35 -0800217 std::string descriptor_string(Primitive::Descriptor(type));
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700218 return PrettyDescriptor(descriptor_string);
219}
220
Elliott Hughes54e7df12011-09-16 11:47:04 -0700221std::string PrettyField(const Field* f, bool with_type) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700222 if (f == NULL) {
223 return "null";
224 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800225 FieldHelper fh(f);
Elliott Hughes54e7df12011-09-16 11:47:04 -0700226 std::string result;
227 if (with_type) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800228 result += PrettyDescriptor(fh.GetTypeDescriptor());
Elliott Hughes54e7df12011-09-16 11:47:04 -0700229 result += ' ';
230 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800231 result += PrettyDescriptor(fh.GetDeclaringClassDescriptor());
Elliott Hughesa2501992011-08-26 19:39:54 -0700232 result += '.';
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800233 result += fh.GetName();
Elliott Hughesa2501992011-08-26 19:39:54 -0700234 return result;
235}
236
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700237std::string PrettyArguments(const char* signature) {
238 std::string result;
239 result += '(';
240 CHECK_EQ(*signature, '(');
241 ++signature; // Skip the '('.
242 while (*signature != ')') {
243 size_t argument_length = 0;
244 while (signature[argument_length] == '[') {
245 ++argument_length;
246 }
247 if (signature[argument_length] == 'L') {
248 argument_length = (strchr(signature, ';') - signature + 1);
249 } else {
250 ++argument_length;
251 }
252 std::string argument_descriptor(signature, argument_length);
253 result += PrettyDescriptor(argument_descriptor);
254 if (signature[argument_length] != ')') {
255 result += ", ";
256 }
257 signature += argument_length;
258 }
259 CHECK_EQ(*signature, ')');
260 ++signature; // Skip the ')'.
261 result += ')';
262 return result;
263}
264
265std::string PrettyReturnType(const char* signature) {
266 const char* return_type = strchr(signature, ')');
267 CHECK(return_type != NULL);
268 ++return_type; // Skip ')'.
269 return PrettyDescriptor(return_type);
270}
271
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700272std::string PrettyMethod(const Method* m, bool with_signature) {
273 if (m == NULL) {
274 return "null";
275 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800276 MethodHelper mh(m);
277 std::string result(PrettyDescriptor(mh.GetDeclaringClassDescriptor()));
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700278 result += '.';
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800279 result += mh.GetName();
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700280 if (with_signature) {
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700281 std::string signature(mh.GetSignature());
Elliott Hughesf8c11932012-03-23 19:53:59 -0700282 if (signature == "<no signature>") {
283 return result + signature;
284 }
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700285 result = PrettyReturnType(signature.c_str()) + " " + result + PrettyArguments(signature.c_str());
Elliott Hughesa0b8feb2011-08-20 09:50:55 -0700286 }
287 return result;
288}
289
Ian Rogers0571d352011-11-03 19:51:38 -0700290std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature) {
291 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
292 std::string result(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(method_id)));
293 result += '.';
294 result += dex_file.GetMethodName(method_id);
295 if (with_signature) {
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700296 std::string signature(dex_file.GetMethodSignature(method_id));
Elliott Hughesf8c11932012-03-23 19:53:59 -0700297 if (signature == "<no signature>") {
298 return result + signature;
299 }
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700300 result = PrettyReturnType(signature.c_str()) + " " + result + PrettyArguments(signature.c_str());
Ian Rogers0571d352011-11-03 19:51:38 -0700301 }
302 return result;
303}
304
Elliott Hughes54e7df12011-09-16 11:47:04 -0700305std::string PrettyTypeOf(const Object* obj) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700306 if (obj == NULL) {
307 return "null";
308 }
309 if (obj->GetClass() == NULL) {
310 return "(raw)";
311 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800312 ClassHelper kh(obj->GetClass());
313 std::string result(PrettyDescriptor(kh.GetDescriptor()));
Elliott Hughes11e45072011-08-16 17:40:46 -0700314 if (obj->IsClass()) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800315 kh.ChangeClass(obj->AsClass());
316 result += "<" + PrettyDescriptor(kh.GetDescriptor()) + ">";
Elliott Hughes11e45072011-08-16 17:40:46 -0700317 }
318 return result;
319}
320
Elliott Hughes54e7df12011-09-16 11:47:04 -0700321std::string PrettyClass(const Class* c) {
322 if (c == NULL) {
323 return "null";
324 }
325 std::string result;
326 result += "java.lang.Class<";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800327 result += PrettyDescriptor(c);
Elliott Hughes54e7df12011-09-16 11:47:04 -0700328 result += ">";
329 return result;
330}
331
Ian Rogersd81871c2011-10-03 13:57:23 -0700332std::string PrettyClassAndClassLoader(const Class* c) {
333 if (c == NULL) {
334 return "null";
335 }
336 std::string result;
337 result += "java.lang.Class<";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800338 result += PrettyDescriptor(c);
Ian Rogersd81871c2011-10-03 13:57:23 -0700339 result += ",";
340 result += PrettyTypeOf(c->GetClassLoader());
341 // TODO: add an identifying hash value for the loader
342 result += ">";
343 return result;
344}
345
Ian Rogers3bb17a62012-01-27 23:56:44 -0800346std::string PrettySize(size_t size_in_bytes) {
347 if ((size_in_bytes / GB) * GB == size_in_bytes) {
348 return StringPrintf("%zdGB", size_in_bytes / GB);
349 } else if ((size_in_bytes / MB) * MB == size_in_bytes) {
350 return StringPrintf("%zdMB", size_in_bytes / MB);
351 } else if ((size_in_bytes / KB) * KB == size_in_bytes) {
352 return StringPrintf("%zdKiB", size_in_bytes / KB);
353 } else {
354 return StringPrintf("%zdB", size_in_bytes);
355 }
356}
357
358std::string PrettyDuration(uint64_t nano_duration) {
359 if (nano_duration == 0) {
360 return "0";
361 } else {
362 const uint64_t one_sec = 1000 * 1000 * 1000;
363 const uint64_t one_ms = 1000 * 1000;
364 const uint64_t one_us = 1000;
365 const char* unit;
366 uint64_t divisor;
367 uint32_t zero_fill;
368 if (nano_duration >= one_sec) {
369 unit = "s";
370 divisor = one_sec;
371 zero_fill = 9;
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700372 } else if (nano_duration >= one_ms) {
Ian Rogers3bb17a62012-01-27 23:56:44 -0800373 unit = "ms";
374 divisor = one_ms;
375 zero_fill = 6;
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700376 } else if (nano_duration >= one_us) {
Ian Rogers3bb17a62012-01-27 23:56:44 -0800377 unit = "us";
378 divisor = one_us;
379 zero_fill = 3;
380 } else {
381 unit = "ns";
382 divisor = 1;
383 zero_fill = 0;
384 }
385 uint64_t whole_part = nano_duration / divisor;
386 uint64_t fractional_part = nano_duration % divisor;
387 if (fractional_part == 0) {
388 return StringPrintf("%llu%s", whole_part, unit);
389 } else {
390 while ((fractional_part % 1000) == 0) {
391 zero_fill -= 3;
392 fractional_part /= 1000;
393 }
394 if (zero_fill == 3) {
395 return StringPrintf("%llu.%03llu%s", whole_part, fractional_part, unit);
396 } else if (zero_fill == 6) {
397 return StringPrintf("%llu.%06llu%s", whole_part, fractional_part, unit);
398 } else {
399 return StringPrintf("%llu.%09llu%s", whole_part, fractional_part, unit);
400 }
401 }
402 }
403}
404
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800405// 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 -0700406std::string MangleForJni(const std::string& s) {
407 std::string result;
408 size_t char_count = CountModifiedUtf8Chars(s.c_str());
409 const char* cp = &s[0];
410 for (size_t i = 0; i < char_count; ++i) {
411 uint16_t ch = GetUtf16FromUtf8(&cp);
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800412 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
413 result.push_back(ch);
414 } else if (ch == '.' || ch == '/') {
415 result += "_";
416 } else if (ch == '_') {
417 result += "_1";
418 } else if (ch == ';') {
419 result += "_2";
420 } else if (ch == '[') {
421 result += "_3";
Elliott Hughes79082e32011-08-25 12:07:32 -0700422 } else {
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800423 StringAppendF(&result, "_0%04x", ch);
Elliott Hughes79082e32011-08-25 12:07:32 -0700424 }
425 }
426 return result;
427}
428
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700429std::string DotToDescriptor(const char* class_name) {
430 std::string descriptor(class_name);
431 std::replace(descriptor.begin(), descriptor.end(), '.', '/');
432 if (descriptor.length() > 0 && descriptor[0] != '[') {
433 descriptor = "L" + descriptor + ";";
434 }
435 return descriptor;
436}
437
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800438std::string DescriptorToDot(const char* descriptor) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800439 size_t length = strlen(descriptor);
440 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
441 std::string result(descriptor + 1, length - 2);
442 std::replace(result.begin(), result.end(), '/', '.');
443 return result;
444 }
445 return descriptor;
Elliott Hughes91bf6cd2012-02-14 17:27:48 -0800446}
447
448std::string DescriptorToName(const char* descriptor) {
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800449 size_t length = strlen(descriptor);
Elliott Hughes2435a572012-02-17 16:07:41 -0800450 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
451 std::string result(descriptor + 1, length - 2);
452 return result;
453 }
454 return descriptor;
Brian Carlstromaded5f72011-10-07 17:15:04 -0700455}
456
Elliott Hughes79082e32011-08-25 12:07:32 -0700457std::string JniShortName(const Method* m) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800458 MethodHelper mh(m);
459 std::string class_name(mh.GetDeclaringClassDescriptor());
Elliott Hughes79082e32011-08-25 12:07:32 -0700460 // Remove the leading 'L' and trailing ';'...
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700461 CHECK_EQ(class_name[0], 'L') << class_name;
462 CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name;
Elliott Hughes79082e32011-08-25 12:07:32 -0700463 class_name.erase(0, 1);
464 class_name.erase(class_name.size() - 1, 1);
465
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800466 std::string method_name(mh.GetName());
Elliott Hughes79082e32011-08-25 12:07:32 -0700467
468 std::string short_name;
469 short_name += "Java_";
470 short_name += MangleForJni(class_name);
471 short_name += "_";
472 short_name += MangleForJni(method_name);
473 return short_name;
474}
475
476std::string JniLongName(const Method* m) {
477 std::string long_name;
478 long_name += JniShortName(m);
479 long_name += "__";
480
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800481 std::string signature(MethodHelper(m).GetSignature());
Elliott Hughes79082e32011-08-25 12:07:32 -0700482 signature.erase(0, 1);
483 signature.erase(signature.begin() + signature.find(')'), signature.end());
484
485 long_name += MangleForJni(signature);
486
487 return long_name;
488}
489
jeffhao10037c82012-01-23 15:06:23 -0800490// Helper for IsValidPartOfMemberNameUtf8(), a bit vector indicating valid low ascii.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700491uint32_t DEX_MEMBER_VALID_LOW_ASCII[4] = {
492 0x00000000, // 00..1f low control characters; nothing valid
493 0x03ff2010, // 20..3f digits and symbols; valid: '0'..'9', '$', '-'
494 0x87fffffe, // 40..5f uppercase etc.; valid: 'A'..'Z', '_'
495 0x07fffffe // 60..7f lowercase etc.; valid: 'a'..'z'
496};
497
jeffhao10037c82012-01-23 15:06:23 -0800498// Helper for IsValidPartOfMemberNameUtf8(); do not call directly.
499bool IsValidPartOfMemberNameUtf8Slow(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700500 /*
501 * It's a multibyte encoded character. Decode it and analyze. We
502 * accept anything that isn't (a) an improperly encoded low value,
503 * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high
504 * control character, or (e) a high space, layout, or special
505 * character (U+00a0, U+2000..U+200f, U+2028..U+202f,
506 * U+fff0..U+ffff). This is all specified in the dex format
507 * document.
508 */
509
510 uint16_t utf16 = GetUtf16FromUtf8(pUtf8Ptr);
511
512 // Perform follow-up tests based on the high 8 bits.
513 switch (utf16 >> 8) {
514 case 0x00:
515 // It's only valid if it's above the ISO-8859-1 high space (0xa0).
516 return (utf16 > 0x00a0);
517 case 0xd8:
518 case 0xd9:
519 case 0xda:
520 case 0xdb:
521 // It's a leading surrogate. Check to see that a trailing
522 // surrogate follows.
523 utf16 = GetUtf16FromUtf8(pUtf8Ptr);
524 return (utf16 >= 0xdc00) && (utf16 <= 0xdfff);
525 case 0xdc:
526 case 0xdd:
527 case 0xde:
528 case 0xdf:
529 // It's a trailing surrogate, which is not valid at this point.
530 return false;
531 case 0x20:
532 case 0xff:
533 // It's in the range that has spaces, controls, and specials.
534 switch (utf16 & 0xfff8) {
535 case 0x2000:
536 case 0x2008:
537 case 0x2028:
538 case 0xfff0:
539 case 0xfff8:
540 return false;
541 }
542 break;
543 }
544 return true;
545}
546
547/* Return whether the pointed-at modified-UTF-8 encoded character is
548 * valid as part of a member name, updating the pointer to point past
549 * the consumed character. This will consume two encoded UTF-16 code
550 * points if the character is encoded as a surrogate pair. Also, if
551 * this function returns false, then the given pointer may only have
552 * been partially advanced.
553 */
jeffhao10037c82012-01-23 15:06:23 -0800554bool IsValidPartOfMemberNameUtf8(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700555 uint8_t c = (uint8_t) **pUtf8Ptr;
556 if (c <= 0x7f) {
557 // It's low-ascii, so check the table.
558 uint32_t wordIdx = c >> 5;
559 uint32_t bitIdx = c & 0x1f;
560 (*pUtf8Ptr)++;
561 return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0;
562 }
563
564 // It's a multibyte encoded character. Call a non-inline function
565 // for the heavy lifting.
jeffhao10037c82012-01-23 15:06:23 -0800566 return IsValidPartOfMemberNameUtf8Slow(pUtf8Ptr);
567}
568
569bool IsValidMemberName(const char* s) {
570 bool angle_name = false;
571
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700572 switch (*s) {
jeffhao10037c82012-01-23 15:06:23 -0800573 case '\0':
574 // The empty string is not a valid name.
575 return false;
576 case '<':
577 angle_name = true;
578 s++;
579 break;
580 }
581
582 while (true) {
583 switch (*s) {
584 case '\0':
585 return !angle_name;
586 case '>':
587 return angle_name && s[1] == '\0';
588 }
589
590 if (!IsValidPartOfMemberNameUtf8(&s)) {
591 return false;
592 }
593 }
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700594}
595
Elliott Hughes906e6852011-10-28 14:52:10 -0700596enum ClassNameType { kName, kDescriptor };
597bool IsValidClassName(const char* s, ClassNameType type, char separator) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700598 int arrayCount = 0;
599 while (*s == '[') {
600 arrayCount++;
601 s++;
602 }
603
604 if (arrayCount > 255) {
605 // Arrays may have no more than 255 dimensions.
606 return false;
607 }
608
609 if (arrayCount != 0) {
610 /*
611 * If we're looking at an array of some sort, then it doesn't
612 * matter if what is being asked for is a class name; the
613 * format looks the same as a type descriptor in that case, so
614 * treat it as such.
615 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700616 type = kDescriptor;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700617 }
618
Elliott Hughes906e6852011-10-28 14:52:10 -0700619 if (type == kDescriptor) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700620 /*
621 * We are looking for a descriptor. Either validate it as a
622 * single-character primitive type, or continue on to check the
623 * embedded class name (bracketed by "L" and ";").
624 */
625 switch (*(s++)) {
626 case 'B':
627 case 'C':
628 case 'D':
629 case 'F':
630 case 'I':
631 case 'J':
632 case 'S':
633 case 'Z':
634 // These are all single-character descriptors for primitive types.
635 return (*s == '\0');
636 case 'V':
637 // Non-array void is valid, but you can't have an array of void.
638 return (arrayCount == 0) && (*s == '\0');
639 case 'L':
640 // Class name: Break out and continue below.
641 break;
642 default:
643 // Oddball descriptor character.
644 return false;
645 }
646 }
647
648 /*
649 * We just consumed the 'L' that introduces a class name as part
650 * of a type descriptor, or we are looking for an unadorned class
651 * name.
652 */
653
654 bool sepOrFirst = true; // first character or just encountered a separator.
655 for (;;) {
656 uint8_t c = (uint8_t) *s;
657 switch (c) {
658 case '\0':
659 /*
660 * Premature end for a type descriptor, but valid for
661 * a class name as long as we haven't encountered an
662 * empty component (including the degenerate case of
663 * the empty string "").
664 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700665 return (type == kName) && !sepOrFirst;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700666 case ';':
667 /*
668 * Invalid character for a class name, but the
669 * legitimate end of a type descriptor. In the latter
670 * case, make sure that this is the end of the string
671 * and that it doesn't end with an empty component
672 * (including the degenerate case of "L;").
673 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700674 return (type == kDescriptor) && !sepOrFirst && (s[1] == '\0');
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700675 case '/':
676 case '.':
677 if (c != separator) {
678 // The wrong separator character.
679 return false;
680 }
681 if (sepOrFirst) {
682 // Separator at start or two separators in a row.
683 return false;
684 }
685 sepOrFirst = true;
686 s++;
687 break;
688 default:
jeffhao10037c82012-01-23 15:06:23 -0800689 if (!IsValidPartOfMemberNameUtf8(&s)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700690 return false;
691 }
692 sepOrFirst = false;
693 break;
694 }
695 }
696}
697
Elliott Hughes906e6852011-10-28 14:52:10 -0700698bool IsValidBinaryClassName(const char* s) {
699 return IsValidClassName(s, kName, '.');
700}
701
702bool IsValidJniClassName(const char* s) {
703 return IsValidClassName(s, kName, '/');
704}
705
706bool IsValidDescriptor(const char* s) {
707 return IsValidClassName(s, kDescriptor, '/');
708}
709
Elliott Hughes48436bb2012-02-07 15:23:28 -0800710void Split(const std::string& s, char separator, std::vector<std::string>& result) {
Elliott Hughes34023802011-08-30 12:06:17 -0700711 const char* p = s.data();
712 const char* end = p + s.size();
713 while (p != end) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800714 if (*p == separator) {
Elliott Hughes34023802011-08-30 12:06:17 -0700715 ++p;
716 } else {
717 const char* start = p;
Elliott Hughes48436bb2012-02-07 15:23:28 -0800718 while (++p != end && *p != separator) {
719 // Skip to the next occurrence of the separator.
Elliott Hughes34023802011-08-30 12:06:17 -0700720 }
721 result.push_back(std::string(start, p - start));
722 }
723 }
724}
725
Elliott Hughes48436bb2012-02-07 15:23:28 -0800726template <typename StringT>
727std::string Join(std::vector<StringT>& strings, char separator) {
728 if (strings.empty()) {
729 return "";
730 }
731
732 std::string result(strings[0]);
733 for (size_t i = 1; i < strings.size(); ++i) {
734 result += separator;
735 result += strings[i];
736 }
737 return result;
738}
739
740// Explicit instantiations.
741template std::string Join<std::string>(std::vector<std::string>& strings, char separator);
742template std::string Join<const char*>(std::vector<const char*>& strings, char separator);
743template std::string Join<char*>(std::vector<char*>& strings, char separator);
744
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800745bool StartsWith(const std::string& s, const char* prefix) {
746 return s.compare(0, strlen(prefix), prefix) == 0;
747}
748
Brian Carlstrom7a967b32012-03-28 15:23:10 -0700749bool EndsWith(const std::string& s, const char* suffix) {
750 size_t suffix_length = strlen(suffix);
751 size_t string_length = s.size();
752 if (suffix_length > string_length) {
753 return false;
754 }
755 size_t offset = string_length - suffix_length;
756 return s.compare(offset, suffix_length, suffix) == 0;
757}
758
Elliott Hughes22869a92012-03-27 14:08:24 -0700759void SetThreadName(const char* thread_name) {
760 ANNOTATE_THREAD_NAME(thread_name); // For tsan.
Elliott Hughes06e3ad42012-02-07 14:51:57 -0800761
Elliott Hughesdcc24742011-09-07 14:02:44 -0700762 int hasAt = 0;
763 int hasDot = 0;
Elliott Hughes22869a92012-03-27 14:08:24 -0700764 const char* s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700765 while (*s) {
766 if (*s == '.') {
767 hasDot = 1;
768 } else if (*s == '@') {
769 hasAt = 1;
770 }
771 s++;
772 }
Elliott Hughes22869a92012-03-27 14:08:24 -0700773 int len = s - thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700774 if (len < 15 || hasAt || !hasDot) {
Elliott Hughes22869a92012-03-27 14:08:24 -0700775 s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700776 } else {
Elliott Hughes22869a92012-03-27 14:08:24 -0700777 s = thread_name + len - 15;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700778 }
779#if defined(HAVE_ANDROID_PTHREAD_SETNAME_NP)
Elliott Hughes7c6a61e2012-03-12 18:01:41 -0700780 // pthread_setname_np fails rather than truncating long strings.
Elliott Hughesdcc24742011-09-07 14:02:44 -0700781 char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded into bionic
782 strncpy(buf, s, sizeof(buf)-1);
783 buf[sizeof(buf)-1] = '\0';
784 errno = pthread_setname_np(pthread_self(), buf);
785 if (errno != 0) {
786 PLOG(WARNING) << "Unable to set the name of current thread to '" << buf << "'";
787 }
Elliott Hughes4ae722a2012-03-13 11:08:51 -0700788#elif defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
Elliott Hughes22869a92012-03-27 14:08:24 -0700789 pthread_setname_np(thread_name);
Elliott Hughesdcc24742011-09-07 14:02:44 -0700790#elif defined(HAVE_PRCTL)
Elliott Hughes398f64b2012-03-26 18:05:48 -0700791 prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0); // NOLINT (unsigned long)
Elliott Hughesdcc24742011-09-07 14:02:44 -0700792#else
Elliott Hughes22869a92012-03-27 14:08:24 -0700793 UNIMPLEMENTED(WARNING) << thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700794#endif
795}
796
Elliott Hughesbfe487b2011-10-26 15:48:55 -0700797void GetTaskStats(pid_t tid, int& utime, int& stime, int& task_cpu) {
798 utime = stime = task_cpu = 0;
799 std::string stats;
Elliott Hughes1bac54f2012-03-16 12:48:31 -0700800 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid).c_str(), &stats)) {
Elliott Hughesbfe487b2011-10-26 15:48:55 -0700801 return;
802 }
803 // Skip the command, which may contain spaces.
804 stats = stats.substr(stats.find(')') + 2);
805 // Extract the three fields we care about.
806 std::vector<std::string> fields;
807 Split(stats, ' ', fields);
808 utime = strtoull(fields[11].c_str(), NULL, 10);
809 stime = strtoull(fields[12].c_str(), NULL, 10);
810 task_cpu = strtoull(fields[36].c_str(), NULL, 10);
811}
812
Elliott Hughes1bac54f2012-03-16 12:48:31 -0700813std::string GetSchedulerGroupName(pid_t tid) {
814 // /proc/<pid>/cgroup looks like this:
815 // 2:devices:/
816 // 1:cpuacct,cpu:/
817 // We want the third field from the line whose second field contains the "cpu" token.
818 std::string cgroup_file;
819 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/cgroup", tid), &cgroup_file)) {
820 return "";
821 }
822 std::vector<std::string> cgroup_lines;
823 Split(cgroup_file, '\n', cgroup_lines);
824 for (size_t i = 0; i < cgroup_lines.size(); ++i) {
825 std::vector<std::string> cgroup_fields;
826 Split(cgroup_lines[i], ':', cgroup_fields);
827 std::vector<std::string> cgroups;
828 Split(cgroup_fields[1], ',', cgroups);
829 for (size_t i = 0; i < cgroups.size(); ++i) {
830 if (cgroups[i] == "cpu") {
831 return cgroup_fields[2].substr(1); // Skip the leading slash.
832 }
833 }
834 }
835 return "";
836}
837
Brian Carlstroma56fcd62012-02-04 21:23:01 -0800838const char* GetAndroidRoot() {
839 const char* android_root = getenv("ANDROID_ROOT");
840 if (android_root == NULL) {
841 if (OS::DirectoryExists("/system")) {
842 android_root = "/system";
Brian Carlstroma9f19782011-10-13 00:14:47 -0700843 } else {
Brian Carlstroma56fcd62012-02-04 21:23:01 -0800844 LOG(FATAL) << "ANDROID_ROOT not set and /system does not exist";
845 return "";
Brian Carlstroma9f19782011-10-13 00:14:47 -0700846 }
847 }
Brian Carlstroma56fcd62012-02-04 21:23:01 -0800848 if (!OS::DirectoryExists(android_root)) {
849 LOG(FATAL) << "Failed to find ANDROID_ROOT directory " << android_root;
Brian Carlstroma9f19782011-10-13 00:14:47 -0700850 return "";
851 }
Brian Carlstroma56fcd62012-02-04 21:23:01 -0800852 return android_root;
853}
Brian Carlstroma9f19782011-10-13 00:14:47 -0700854
Brian Carlstroma56fcd62012-02-04 21:23:01 -0800855const char* GetAndroidData() {
856 const char* android_data = getenv("ANDROID_DATA");
857 if (android_data == NULL) {
858 if (OS::DirectoryExists("/data")) {
859 android_data = "/data";
860 } else {
861 LOG(FATAL) << "ANDROID_DATA not set and /data does not exist";
862 return "";
863 }
864 }
865 if (!OS::DirectoryExists(android_data)) {
866 LOG(FATAL) << "Failed to find ANDROID_DATA directory " << android_data;
867 return "";
868 }
869 return android_data;
870}
871
872std::string GetArtCacheOrDie() {
873 std::string art_cache(StringPrintf("%s/art-cache", GetAndroidData()));
Brian Carlstroma9f19782011-10-13 00:14:47 -0700874
875 if (!OS::DirectoryExists(art_cache.c_str())) {
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800876 if (StartsWith(art_cache, "/tmp/")) {
Brian Carlstroma9f19782011-10-13 00:14:47 -0700877 int result = mkdir(art_cache.c_str(), 0700);
878 if (result != 0) {
879 LOG(FATAL) << "Failed to create art-cache directory " << art_cache;
880 return "";
881 }
882 } else {
883 LOG(FATAL) << "Failed to find art-cache directory " << art_cache;
884 return "";
885 }
886 }
887 return art_cache;
888}
889
jeffhao262bf462011-10-20 18:36:32 -0700890std::string GetArtCacheFilenameOrDie(const std::string& location) {
Elliott Hughes95572412011-12-13 18:14:20 -0800891 std::string art_cache(GetArtCacheOrDie());
Elliott Hughesc308a5d2012-02-16 17:12:06 -0800892 CHECK_EQ(location[0], '/') << location;
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700893 std::string cache_file(location, 1); // skip leading slash
894 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
895 return art_cache + "/" + cache_file;
896}
897
jeffhao262bf462011-10-20 18:36:32 -0700898bool IsValidZipFilename(const std::string& filename) {
899 if (filename.size() < 4) {
900 return false;
901 }
902 std::string suffix(filename.substr(filename.size() - 4));
903 return (suffix == ".zip" || suffix == ".jar" || suffix == ".apk");
904}
905
906bool IsValidDexFilename(const std::string& filename) {
Brian Carlstrom7a967b32012-03-28 15:23:10 -0700907 return EndsWith(filename, ".dex");
908}
909
910bool IsValidOatFilename(const std::string& filename) {
911 return EndsWith(filename, ".oat");
jeffhao262bf462011-10-20 18:36:32 -0700912}
913
Elliott Hughes42ee1422011-09-06 12:33:32 -0700914} // namespace art