blob: 6a20eaf9e0033498426026b8649a196fbc0707b3 [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
Andreas Gampe46ee31b2016-12-14 10:11:49 -080028#include "android-base/stringprintf.h"
Andreas Gampe9186ced2016-12-12 14:28:21 -080029#include "android-base/strings.h"
30
Brian Carlstrom6449c622014-02-10 23:48:36 -080031#include "base/stl_util.h"
Elliott Hughes76160052012-12-12 16:31:20 -080032#include "base/unix_file/fd_file.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070033#include "dex_file-inl.h"
Andreas Gampe5073fed2015-08-10 11:40:25 -070034#include "dex_instruction.h"
Nicolas Geoffray524e7ea2015-10-16 17:13:34 +010035#include "oat_quick_method_header.h"
buzbeec143c552011-08-20 17:38:58 -070036#include "os.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070037#include "scoped_thread_state_change-inl.h"
Ian Rogersa6724902013-09-23 09:23:37 -070038#include "utf-inl.h"
Elliott Hughes11e45072011-08-16 17:40:46 -070039
Elliott Hughes4ae722a2012-03-13 11:08:51 -070040#if defined(__APPLE__)
Brian Carlstrom7934ac22013-07-26 10:54:15 -070041#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
Elliott Hughesf1498432012-03-28 19:34:27 -070042#include <sys/syscall.h>
David Sehrfa442002016-08-22 18:42:08 -070043#include <crt_externs.h>
Elliott Hughes4ae722a2012-03-13 11:08:51 -070044#endif
45
Elliott Hughes058a6de2012-05-24 19:13:02 -070046#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
Andreas Gampe46ee31b2016-12-14 10:11:49 -080052using android::base::StringAppendF;
53using android::base::StringPrintf;
54
Alex Light9c20a142016-08-23 15:05:12 -070055static const uint8_t kBase64Map[256] = {
56 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
57 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
58 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
59 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
60 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
61 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
62 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT
63 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT
64 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
65 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT
66 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT
67 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
70 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
71 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
72 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
73 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
75 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
76 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
77 255, 255, 255, 255
78};
79
80uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
81 std::vector<uint8_t> tmp;
82 uint32_t t = 0, y = 0;
83 int g = 3;
84 for (size_t i = 0; src[i] != '\0'; ++i) {
85 uint8_t c = kBase64Map[src[i] & 0xFF];
86 if (c == 255) continue;
87 // the final = symbols are read and used to trim the remaining bytes
88 if (c == 254) {
89 c = 0;
90 // prevent g < 0 which would potentially allow an overflow later
91 if (--g < 0) {
92 *dst_size = 0;
93 return nullptr;
94 }
95 } else if (g != 3) {
96 // we only allow = to be at the end
97 *dst_size = 0;
98 return nullptr;
99 }
100 t = (t << 6) | c;
101 if (++y == 4) {
102 tmp.push_back((t >> 16) & 255);
103 if (g > 1) {
104 tmp.push_back((t >> 8) & 255);
105 }
106 if (g > 2) {
107 tmp.push_back(t & 255);
108 }
109 y = t = 0;
110 }
111 }
112 if (y != 0) {
113 *dst_size = 0;
114 return nullptr;
115 }
116 std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
117 if (dst_size != nullptr) {
118 *dst_size = tmp.size();
119 } else {
120 *dst_size = 0;
121 }
122 std::copy(tmp.begin(), tmp.end(), dst.get());
123 return dst.release();
124}
125
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800126pid_t GetTid() {
Brian Carlstromf3a26412012-08-24 11:06:02 -0700127#if defined(__APPLE__)
128 uint64_t owner;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700129 CHECK_PTHREAD_CALL(pthread_threadid_np, (nullptr, &owner), __FUNCTION__); // Requires Mac OS 10.6
Brian Carlstromf3a26412012-08-24 11:06:02 -0700130 return owner;
Elliott Hughes323aa862014-08-20 15:00:04 -0700131#elif defined(__BIONIC__)
132 return gettid();
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800133#else
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800134 return syscall(__NR_gettid);
135#endif
136}
137
Elliott Hughes289be852012-06-12 13:57:20 -0700138std::string GetThreadName(pid_t tid) {
139 std::string result;
140 if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700141 result.resize(result.size() - 1); // Lose the trailing '\n'.
Elliott Hughes289be852012-06-12 13:57:20 -0700142 } else {
143 result = "<unknown>";
144 }
145 return result;
146}
147
Elliott Hughesd92bec42011-09-02 17:04:36 -0700148bool ReadFileToString(const std::string& file_name, std::string* result) {
Andreas Gampedf878922015-08-13 16:44:54 -0700149 File file(file_name, O_RDONLY, false);
150 if (!file.IsOpened()) {
Elliott Hughesd92bec42011-09-02 17:04:36 -0700151 return false;
152 }
buzbeec143c552011-08-20 17:38:58 -0700153
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700154 std::vector<char> buf(8 * KB);
buzbeec143c552011-08-20 17:38:58 -0700155 while (true) {
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800156 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
Elliott Hughesd92bec42011-09-02 17:04:36 -0700157 if (n == -1) {
158 return false;
buzbeec143c552011-08-20 17:38:58 -0700159 }
Elliott Hughesd92bec42011-09-02 17:04:36 -0700160 if (n == 0) {
161 return true;
162 }
Elliott Hughes3b6baaa2011-10-14 19:13:56 -0700163 result->append(&buf[0], n);
buzbeec143c552011-08-20 17:38:58 -0700164 }
buzbeec143c552011-08-20 17:38:58 -0700165}
166
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800167bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
Andreas Gampedf878922015-08-13 16:44:54 -0700168 File file(file_name, O_RDONLY, false);
169 if (!file.IsOpened()) {
Andreas Gampea6dfdae2015-02-24 15:50:19 -0800170 return false;
171 }
172
173 constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings.
174 char buf[kBufSize + 1]; // +1 for terminator.
175 size_t filled_to = 0;
176 while (true) {
177 DCHECK_LT(filled_to, kBufSize);
178 int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
179 if (n <= 0) {
180 // Print the rest of the buffer, if it exists.
181 if (filled_to > 0) {
182 buf[filled_to] = 0;
183 LOG(level) << buf;
184 }
185 return n == 0;
186 }
187 // Scan for '\n'.
188 size_t i = filled_to;
189 bool found_newline = false;
190 for (; i < filled_to + n; ++i) {
191 if (buf[i] == '\n') {
192 // Found a line break, that's something to print now.
193 buf[i] = 0;
194 LOG(level) << buf;
195 // Copy the rest to the front.
196 if (i + 1 < filled_to + n) {
197 memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
198 filled_to = filled_to + n - i - 1;
199 } else {
200 filled_to = 0;
201 }
202 found_newline = true;
203 break;
204 }
205 }
206 if (found_newline) {
207 continue;
208 } else {
209 filled_to += n;
210 // Check if we must flush now.
211 if (filled_to == kBufSize) {
212 buf[kBufSize] = 0;
213 LOG(level) << buf;
214 filled_to = 0;
215 }
216 }
217 }
218}
219
Ian Rogers1ff3c982014-08-12 02:30:58 -0700220std::string PrettyDescriptor(const char* descriptor) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700221 // Count the number of '['s to get the dimensionality.
Ian Rogers1ff3c982014-08-12 02:30:58 -0700222 const char* c = descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700223 size_t dim = 0;
224 while (*c == '[') {
225 dim++;
226 c++;
227 }
228
229 // Reference or primitive?
230 if (*c == 'L') {
231 // "[[La/b/C;" -> "a.b.C[][]".
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700232 c++; // Skip the 'L'.
Elliott Hughes11e45072011-08-16 17:40:46 -0700233 } else {
234 // "[[B" -> "byte[][]".
235 // To make life easier, we make primitives look like unqualified
236 // reference types.
237 switch (*c) {
238 case 'B': c = "byte;"; break;
239 case 'C': c = "char;"; break;
240 case 'D': c = "double;"; break;
241 case 'F': c = "float;"; break;
242 case 'I': c = "int;"; break;
243 case 'J': c = "long;"; break;
244 case 'S': c = "short;"; break;
245 case 'Z': c = "boolean;"; break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700246 case 'V': c = "void;"; break; // Used when decoding return types.
Elliott Hughes5174fe62011-08-23 15:12:35 -0700247 default: return descriptor;
Elliott Hughes11e45072011-08-16 17:40:46 -0700248 }
249 }
250
251 // At this point, 'c' is a string of the form "fully/qualified/Type;"
252 // or "primitive;". Rewrite the type with '.' instead of '/':
253 std::string result;
254 const char* p = c;
255 while (*p != ';') {
256 char ch = *p++;
257 if (ch == '/') {
258 ch = '.';
259 }
260 result.push_back(ch);
261 }
262 // ...and replace the semicolon with 'dim' "[]" pairs:
Ian Rogers1ff3c982014-08-12 02:30:58 -0700263 for (size_t i = 0; i < dim; ++i) {
Elliott Hughes11e45072011-08-16 17:40:46 -0700264 result += "[]";
265 }
266 return result;
267}
268
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700269std::string PrettyArguments(const char* signature) {
270 std::string result;
271 result += '(';
272 CHECK_EQ(*signature, '(');
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700273 ++signature; // Skip the '('.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700274 while (*signature != ')') {
275 size_t argument_length = 0;
276 while (signature[argument_length] == '[') {
277 ++argument_length;
278 }
279 if (signature[argument_length] == 'L') {
280 argument_length = (strchr(signature, ';') - signature + 1);
281 } else {
282 ++argument_length;
283 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700284 {
285 std::string argument_descriptor(signature, argument_length);
286 result += PrettyDescriptor(argument_descriptor.c_str());
287 }
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700288 if (signature[argument_length] != ')') {
289 result += ", ";
290 }
291 signature += argument_length;
292 }
293 CHECK_EQ(*signature, ')');
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700294 ++signature; // Skip the ')'.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700295 result += ')';
296 return result;
297}
298
299std::string PrettyReturnType(const char* signature) {
300 const char* return_type = strchr(signature, ')');
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700301 CHECK(return_type != nullptr);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700302 ++return_type; // Skip ')'.
Elliott Hughes9058f2b2012-03-22 18:06:48 -0700303 return PrettyDescriptor(return_type);
304}
305
Andreas Gampec0d82292014-09-23 10:38:30 -0700306std::string PrettyJavaAccessFlags(uint32_t access_flags) {
307 std::string result;
308 if ((access_flags & kAccPublic) != 0) {
309 result += "public ";
310 }
311 if ((access_flags & kAccProtected) != 0) {
312 result += "protected ";
313 }
314 if ((access_flags & kAccPrivate) != 0) {
315 result += "private ";
316 }
317 if ((access_flags & kAccFinal) != 0) {
318 result += "final ";
319 }
320 if ((access_flags & kAccStatic) != 0) {
321 result += "static ";
322 }
David Brazdilca3c8c32016-09-06 14:04:48 +0100323 if ((access_flags & kAccAbstract) != 0) {
324 result += "abstract ";
325 }
326 if ((access_flags & kAccInterface) != 0) {
327 result += "interface ";
328 }
Andreas Gampec0d82292014-09-23 10:38:30 -0700329 if ((access_flags & kAccTransient) != 0) {
330 result += "transient ";
331 }
332 if ((access_flags & kAccVolatile) != 0) {
333 result += "volatile ";
334 }
335 if ((access_flags & kAccSynchronized) != 0) {
336 result += "synchronized ";
337 }
338 return result;
339}
340
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800341std::string PrettySize(int64_t byte_count) {
Elliott Hughesc967f782012-04-16 10:23:15 -0700342 // The byte thresholds at which we display amounts. A byte count is displayed
343 // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
Ian Rogersef7d42f2014-01-06 12:55:46 -0800344 static const int64_t kUnitThresholds[] = {
Elliott Hughesc967f782012-04-16 10:23:15 -0700345 0, // B up to...
346 3*1024, // KB up to...
347 2*1024*1024, // MB up to...
348 1024*1024*1024 // GB from here.
349 };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800350 static const int64_t kBytesPerUnit[] = { 1, KB, MB, GB };
Elliott Hughesc967f782012-04-16 10:23:15 -0700351 static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800352 const char* negative_str = "";
353 if (byte_count < 0) {
354 negative_str = "-";
355 byte_count = -byte_count;
356 }
Elliott Hughesc967f782012-04-16 10:23:15 -0700357 int i = arraysize(kUnitThresholds);
358 while (--i > 0) {
359 if (byte_count >= kUnitThresholds[i]) {
360 break;
361 }
Ian Rogers3bb17a62012-01-27 23:56:44 -0800362 }
Brian Carlstrom474cc792014-03-07 14:18:15 -0800363 return StringPrintf("%s%" PRId64 "%s",
364 negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
Ian Rogers3bb17a62012-01-27 23:56:44 -0800365}
366
Andreas Gampe9186ced2016-12-12 14:28:21 -0800367static inline constexpr bool NeedsEscaping(uint16_t ch) {
368 return (ch < ' ' || ch > '~');
369}
370
Ian Rogers576ca0c2014-06-06 15:58:22 -0700371std::string PrintableChar(uint16_t ch) {
372 std::string result;
373 result += '\'';
374 if (NeedsEscaping(ch)) {
375 StringAppendF(&result, "\\u%04x", ch);
376 } else {
377 result += ch;
378 }
379 result += '\'';
380 return result;
381}
382
Ian Rogers68b56852014-08-29 20:19:11 -0700383std::string PrintableString(const char* utf) {
Elliott Hughes82914b62012-04-09 15:56:29 -0700384 std::string result;
385 result += '"';
Ian Rogers68b56852014-08-29 20:19:11 -0700386 const char* p = utf;
Elliott Hughes82914b62012-04-09 15:56:29 -0700387 size_t char_count = CountModifiedUtf8Chars(p);
388 for (size_t i = 0; i < char_count; ++i) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000389 uint32_t ch = GetUtf16FromUtf8(&p);
Elliott Hughes82914b62012-04-09 15:56:29 -0700390 if (ch == '\\') {
391 result += "\\\\";
392 } else if (ch == '\n') {
393 result += "\\n";
394 } else if (ch == '\r') {
395 result += "\\r";
396 } else if (ch == '\t') {
397 result += "\\t";
Elliott Hughes82914b62012-04-09 15:56:29 -0700398 } else {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000399 const uint16_t leading = GetLeadingUtf16Char(ch);
400
401 if (NeedsEscaping(leading)) {
402 StringAppendF(&result, "\\u%04x", leading);
403 } else {
404 result += leading;
405 }
406
407 const uint32_t trailing = GetTrailingUtf16Char(ch);
408 if (trailing != 0) {
409 // All high surrogates will need escaping.
410 StringAppendF(&result, "\\u%04x", trailing);
411 }
Elliott Hughes82914b62012-04-09 15:56:29 -0700412 }
413 }
414 result += '"';
415 return result;
416}
417
Alex Light888a59e2017-01-25 11:41:41 -0800418std::string GetJniShortName(const std::string& class_descriptor, const std::string& method) {
419 // Remove the leading 'L' and trailing ';'...
420 std::string class_name(class_descriptor);
421 CHECK_EQ(class_name[0], 'L') << class_name;
422 CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name;
423 class_name.erase(0, 1);
424 class_name.erase(class_name.size() - 1, 1);
425
426 std::string short_name;
427 short_name += "Java_";
428 short_name += MangleForJni(class_name);
429 short_name += "_";
430 short_name += MangleForJni(method);
431 return short_name;
432}
433
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800434// 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 -0700435std::string MangleForJni(const std::string& s) {
436 std::string result;
437 size_t char_count = CountModifiedUtf8Chars(s.c_str());
438 const char* cp = &s[0];
439 for (size_t i = 0; i < char_count; ++i) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000440 uint32_t ch = GetUtf16FromUtf8(&cp);
Elliott Hughesd8c00d02012-01-30 14:08:31 -0800441 if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
442 result.push_back(ch);
443 } else if (ch == '.' || ch == '/') {
444 result += "_";
445 } else if (ch == '_') {
446 result += "_1";
447 } else if (ch == ';') {
448 result += "_2";
449 } else if (ch == '[') {
450 result += "_3";
Elliott Hughes79082e32011-08-25 12:07:32 -0700451 } else {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000452 const uint16_t leading = GetLeadingUtf16Char(ch);
453 const uint32_t trailing = GetTrailingUtf16Char(ch);
454
455 StringAppendF(&result, "_0%04x", leading);
456 if (trailing != 0) {
457 StringAppendF(&result, "_0%04x", trailing);
458 }
Elliott Hughes79082e32011-08-25 12:07:32 -0700459 }
460 }
461 return result;
462}
463
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700464std::string DotToDescriptor(const char* class_name) {
465 std::string descriptor(class_name);
466 std::replace(descriptor.begin(), descriptor.end(), '.', '/');
467 if (descriptor.length() > 0 && descriptor[0] != '[') {
468 descriptor = "L" + descriptor + ";";
469 }
470 return descriptor;
471}
472
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800473std::string DescriptorToDot(const char* descriptor) {
Elliott Hughes2435a572012-02-17 16:07:41 -0800474 size_t length = strlen(descriptor);
Ian Rogers1ff3c982014-08-12 02:30:58 -0700475 if (length > 1) {
476 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
477 // Descriptors have the leading 'L' and trailing ';' stripped.
478 std::string result(descriptor + 1, length - 2);
479 std::replace(result.begin(), result.end(), '/', '.');
480 return result;
481 } else {
482 // For arrays the 'L' and ';' remain intact.
483 std::string result(descriptor);
484 std::replace(result.begin(), result.end(), '/', '.');
485 return result;
486 }
Elliott Hughes2435a572012-02-17 16:07:41 -0800487 }
Ian Rogers1ff3c982014-08-12 02:30:58 -0700488 // Do nothing for non-class/array descriptors.
Elliott Hughes2435a572012-02-17 16:07:41 -0800489 return descriptor;
Elliott Hughes91bf6cd2012-02-14 17:27:48 -0800490}
491
492std::string DescriptorToName(const char* descriptor) {
Elliott Hughesf1a5adc2012-02-10 18:09:35 -0800493 size_t length = strlen(descriptor);
Elliott Hughes2435a572012-02-17 16:07:41 -0800494 if (descriptor[0] == 'L' && descriptor[length - 1] == ';') {
495 std::string result(descriptor + 1, length - 2);
496 return result;
497 }
498 return descriptor;
Brian Carlstromaded5f72011-10-07 17:15:04 -0700499}
500
jeffhao10037c82012-01-23 15:06:23 -0800501// Helper for IsValidPartOfMemberNameUtf8(), a bit vector indicating valid low ascii.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700502uint32_t DEX_MEMBER_VALID_LOW_ASCII[4] = {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700503 0x00000000, // 00..1f low control characters; nothing valid
504 0x03ff2010, // 20..3f digits and symbols; valid: '0'..'9', '$', '-'
505 0x87fffffe, // 40..5f uppercase etc.; valid: 'A'..'Z', '_'
506 0x07fffffe // 60..7f lowercase etc.; valid: 'a'..'z'
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700507};
508
jeffhao10037c82012-01-23 15:06:23 -0800509// Helper for IsValidPartOfMemberNameUtf8(); do not call directly.
510bool IsValidPartOfMemberNameUtf8Slow(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700511 /*
512 * It's a multibyte encoded character. Decode it and analyze. We
513 * accept anything that isn't (a) an improperly encoded low value,
514 * (b) an improper surrogate pair, (c) an encoded '\0', (d) a high
515 * control character, or (e) a high space, layout, or special
516 * character (U+00a0, U+2000..U+200f, U+2028..U+202f,
517 * U+fff0..U+ffff). This is all specified in the dex format
518 * document.
519 */
520
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000521 const uint32_t pair = GetUtf16FromUtf8(pUtf8Ptr);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000522 const uint16_t leading = GetLeadingUtf16Char(pair);
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000523
Narayan Kamath8508e372015-05-06 14:55:43 +0100524 // We have a surrogate pair resulting from a valid 4 byte UTF sequence.
525 // No further checks are necessary because 4 byte sequences span code
526 // points [U+10000, U+1FFFFF], which are valid codepoints in a dex
527 // identifier. Furthermore, GetUtf16FromUtf8 guarantees that each of
528 // the surrogate halves are valid and well formed in this instance.
529 if (GetTrailingUtf16Char(pair) != 0) {
530 return true;
531 }
532
533
534 // We've encountered a one, two or three byte UTF-8 sequence. The
535 // three byte UTF-8 sequence could be one half of a surrogate pair.
536 switch (leading >> 8) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000537 case 0x00:
538 // It's only valid if it's above the ISO-8859-1 high space (0xa0).
539 return (leading > 0x00a0);
540 case 0xd8:
541 case 0xd9:
542 case 0xda:
543 case 0xdb:
Narayan Kamath8508e372015-05-06 14:55:43 +0100544 {
545 // We found a three byte sequence encoding one half of a surrogate.
546 // Look for the other half.
547 const uint32_t pair2 = GetUtf16FromUtf8(pUtf8Ptr);
548 const uint16_t trailing = GetLeadingUtf16Char(pair2);
549
550 return (GetTrailingUtf16Char(pair2) == 0) && (0xdc00 <= trailing && trailing <= 0xdfff);
551 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000552 case 0xdc:
553 case 0xdd:
554 case 0xde:
555 case 0xdf:
556 // It's a trailing surrogate, which is not valid at this point.
557 return false;
558 case 0x20:
559 case 0xff:
560 // It's in the range that has spaces, controls, and specials.
561 switch (leading & 0xfff8) {
Narayan Kamath8508e372015-05-06 14:55:43 +0100562 case 0x2000:
563 case 0x2008:
564 case 0x2028:
565 case 0xfff0:
566 case 0xfff8:
567 return false;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000568 }
Narayan Kamath8508e372015-05-06 14:55:43 +0100569 return true;
570 default:
571 return true;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700572 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +0000573
Narayan Kamath8508e372015-05-06 14:55:43 +0100574 UNREACHABLE();
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700575}
576
577/* Return whether the pointed-at modified-UTF-8 encoded character is
578 * valid as part of a member name, updating the pointer to point past
579 * the consumed character. This will consume two encoded UTF-16 code
580 * points if the character is encoded as a surrogate pair. Also, if
581 * this function returns false, then the given pointer may only have
582 * been partially advanced.
583 */
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700584static bool IsValidPartOfMemberNameUtf8(const char** pUtf8Ptr) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700585 uint8_t c = (uint8_t) **pUtf8Ptr;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700586 if (LIKELY(c <= 0x7f)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700587 // It's low-ascii, so check the table.
588 uint32_t wordIdx = c >> 5;
589 uint32_t bitIdx = c & 0x1f;
590 (*pUtf8Ptr)++;
591 return (DEX_MEMBER_VALID_LOW_ASCII[wordIdx] & (1 << bitIdx)) != 0;
592 }
593
594 // It's a multibyte encoded character. Call a non-inline function
595 // for the heavy lifting.
jeffhao10037c82012-01-23 15:06:23 -0800596 return IsValidPartOfMemberNameUtf8Slow(pUtf8Ptr);
597}
598
599bool IsValidMemberName(const char* s) {
600 bool angle_name = false;
601
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700602 switch (*s) {
jeffhao10037c82012-01-23 15:06:23 -0800603 case '\0':
604 // The empty string is not a valid name.
605 return false;
606 case '<':
607 angle_name = true;
608 s++;
609 break;
610 }
611
612 while (true) {
613 switch (*s) {
614 case '\0':
615 return !angle_name;
616 case '>':
617 return angle_name && s[1] == '\0';
618 }
619
620 if (!IsValidPartOfMemberNameUtf8(&s)) {
621 return false;
622 }
623 }
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700624}
625
Elliott Hughes906e6852011-10-28 14:52:10 -0700626enum ClassNameType { kName, kDescriptor };
Ian Rogers7b078e82014-09-10 14:44:24 -0700627template<ClassNameType kType, char kSeparator>
628static bool IsValidClassName(const char* s) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700629 int arrayCount = 0;
630 while (*s == '[') {
631 arrayCount++;
632 s++;
633 }
634
635 if (arrayCount > 255) {
636 // Arrays may have no more than 255 dimensions.
637 return false;
638 }
639
Ian Rogers7b078e82014-09-10 14:44:24 -0700640 ClassNameType type = kType;
641 if (type != kDescriptor && arrayCount != 0) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700642 /*
643 * If we're looking at an array of some sort, then it doesn't
644 * matter if what is being asked for is a class name; the
645 * format looks the same as a type descriptor in that case, so
646 * treat it as such.
647 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700648 type = kDescriptor;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700649 }
650
Elliott Hughes906e6852011-10-28 14:52:10 -0700651 if (type == kDescriptor) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700652 /*
653 * We are looking for a descriptor. Either validate it as a
654 * single-character primitive type, or continue on to check the
655 * embedded class name (bracketed by "L" and ";").
656 */
657 switch (*(s++)) {
658 case 'B':
659 case 'C':
660 case 'D':
661 case 'F':
662 case 'I':
663 case 'J':
664 case 'S':
665 case 'Z':
666 // These are all single-character descriptors for primitive types.
667 return (*s == '\0');
668 case 'V':
669 // Non-array void is valid, but you can't have an array of void.
670 return (arrayCount == 0) && (*s == '\0');
671 case 'L':
672 // Class name: Break out and continue below.
673 break;
674 default:
675 // Oddball descriptor character.
676 return false;
677 }
678 }
679
680 /*
681 * We just consumed the 'L' that introduces a class name as part
682 * of a type descriptor, or we are looking for an unadorned class
683 * name.
684 */
685
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700686 bool sepOrFirst = true; // first character or just encountered a separator.
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700687 for (;;) {
688 uint8_t c = (uint8_t) *s;
689 switch (c) {
690 case '\0':
691 /*
692 * Premature end for a type descriptor, but valid for
693 * a class name as long as we haven't encountered an
694 * empty component (including the degenerate case of
695 * the empty string "").
696 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700697 return (type == kName) && !sepOrFirst;
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700698 case ';':
699 /*
700 * Invalid character for a class name, but the
701 * legitimate end of a type descriptor. In the latter
702 * case, make sure that this is the end of the string
703 * and that it doesn't end with an empty component
704 * (including the degenerate case of "L;").
705 */
Elliott Hughes906e6852011-10-28 14:52:10 -0700706 return (type == kDescriptor) && !sepOrFirst && (s[1] == '\0');
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700707 case '/':
708 case '.':
Ian Rogers7b078e82014-09-10 14:44:24 -0700709 if (c != kSeparator) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700710 // The wrong separator character.
711 return false;
712 }
713 if (sepOrFirst) {
714 // Separator at start or two separators in a row.
715 return false;
716 }
717 sepOrFirst = true;
718 s++;
719 break;
720 default:
jeffhao10037c82012-01-23 15:06:23 -0800721 if (!IsValidPartOfMemberNameUtf8(&s)) {
Elliott Hughes64bf5a32011-09-20 14:43:12 -0700722 return false;
723 }
724 sepOrFirst = false;
725 break;
726 }
727 }
728}
729
Elliott Hughes906e6852011-10-28 14:52:10 -0700730bool IsValidBinaryClassName(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700731 return IsValidClassName<kName, '.'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700732}
733
734bool IsValidJniClassName(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700735 return IsValidClassName<kName, '/'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700736}
737
738bool IsValidDescriptor(const char* s) {
Ian Rogers7b078e82014-09-10 14:44:24 -0700739 return IsValidClassName<kDescriptor, '/'>(s);
Elliott Hughes906e6852011-10-28 14:52:10 -0700740}
741
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700742void Split(const std::string& s, char separator, std::vector<std::string>* result) {
Elliott Hughes34023802011-08-30 12:06:17 -0700743 const char* p = s.data();
744 const char* end = p + s.size();
745 while (p != end) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800746 if (*p == separator) {
Elliott Hughes34023802011-08-30 12:06:17 -0700747 ++p;
748 } else {
749 const char* start = p;
Elliott Hughes48436bb2012-02-07 15:23:28 -0800750 while (++p != end && *p != separator) {
751 // Skip to the next occurrence of the separator.
Elliott Hughes34023802011-08-30 12:06:17 -0700752 }
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700753 result->push_back(std::string(start, p - start));
Elliott Hughes34023802011-08-30 12:06:17 -0700754 }
755 }
756}
757
Elliott Hughes22869a92012-03-27 14:08:24 -0700758void SetThreadName(const char* thread_name) {
Elliott Hughesdcc24742011-09-07 14:02:44 -0700759 int hasAt = 0;
760 int hasDot = 0;
Elliott Hughes22869a92012-03-27 14:08:24 -0700761 const char* s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700762 while (*s) {
763 if (*s == '.') {
764 hasDot = 1;
765 } else if (*s == '@') {
766 hasAt = 1;
767 }
768 s++;
769 }
Elliott Hughes22869a92012-03-27 14:08:24 -0700770 int len = s - thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700771 if (len < 15 || hasAt || !hasDot) {
Elliott Hughes22869a92012-03-27 14:08:24 -0700772 s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700773 } else {
Elliott Hughes22869a92012-03-27 14:08:24 -0700774 s = thread_name + len - 15;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700775 }
Elliott Hughes0a18df82015-01-09 15:16:16 -0800776#if defined(__linux__)
Elliott Hughes7c6a61e2012-03-12 18:01:41 -0700777 // pthread_setname_np fails rather than truncating long strings.
Elliott Hughes0a18df82015-01-09 15:16:16 -0800778 char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel.
Elliott Hughesdcc24742011-09-07 14:02:44 -0700779 strncpy(buf, s, sizeof(buf)-1);
780 buf[sizeof(buf)-1] = '\0';
781 errno = pthread_setname_np(pthread_self(), buf);
782 if (errno != 0) {
783 PLOG(WARNING) << "Unable to set the name of current thread to '" << buf << "'";
784 }
Elliott Hughes0a18df82015-01-09 15:16:16 -0800785#else // __APPLE__
Elliott Hughes22869a92012-03-27 14:08:24 -0700786 pthread_setname_np(thread_name);
Elliott Hughesdcc24742011-09-07 14:02:44 -0700787#endif
788}
789
Brian Carlstrom29212012013-09-12 22:18:30 -0700790void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
791 *utime = *stime = *task_cpu = 0;
Elliott Hughesbfe487b2011-10-26 15:48:55 -0700792 std::string stats;
Elliott Hughes8a31b502012-04-30 19:36:11 -0700793 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
Elliott Hughesbfe487b2011-10-26 15:48:55 -0700794 return;
795 }
796 // Skip the command, which may contain spaces.
797 stats = stats.substr(stats.find(')') + 2);
798 // Extract the three fields we care about.
799 std::vector<std::string> fields;
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700800 Split(stats, ' ', &fields);
Brian Carlstrom29212012013-09-12 22:18:30 -0700801 *state = fields[0][0];
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700802 *utime = strtoull(fields[11].c_str(), nullptr, 10);
803 *stime = strtoull(fields[12].c_str(), nullptr, 10);
804 *task_cpu = strtoull(fields[36].c_str(), nullptr, 10);
Elliott Hughesbfe487b2011-10-26 15:48:55 -0700805}
806
Calin Juravle36eb3132017-01-13 16:32:38 -0800807static const char* GetAndroidDirSafe(const char* env_var,
808 const char* default_dir,
809 std::string* error_msg) {
810 const char* android_dir = getenv(env_var);
811 if (android_dir == nullptr) {
812 if (OS::DirectoryExists(default_dir)) {
813 android_dir = default_dir;
Brian Carlstroma9f19782011-10-13 00:14:47 -0700814 } else {
Calin Juravle36eb3132017-01-13 16:32:38 -0800815 *error_msg = StringPrintf("%s not set and %s does not exist", env_var, default_dir);
816 return nullptr;
Brian Carlstroma9f19782011-10-13 00:14:47 -0700817 }
818 }
Calin Juravle36eb3132017-01-13 16:32:38 -0800819 if (!OS::DirectoryExists(android_dir)) {
820 *error_msg = StringPrintf("Failed to find %s directory %s", env_var, android_dir);
821 return nullptr;
Brian Carlstroma9f19782011-10-13 00:14:47 -0700822 }
Calin Juravle36eb3132017-01-13 16:32:38 -0800823 return android_dir;
Brian Carlstroma56fcd62012-02-04 21:23:01 -0800824}
Brian Carlstroma9f19782011-10-13 00:14:47 -0700825
Calin Juravle36eb3132017-01-13 16:32:38 -0800826const char* GetAndroidDir(const char* env_var, const char* default_dir) {
Alex Lighta59dd802014-07-02 16:28:08 -0700827 std::string error_msg;
Calin Juravle36eb3132017-01-13 16:32:38 -0800828 const char* dir = GetAndroidDirSafe(env_var, default_dir, &error_msg);
Alex Lighta59dd802014-07-02 16:28:08 -0700829 if (dir != nullptr) {
830 return dir;
831 } else {
832 LOG(FATAL) << error_msg;
Calin Juravle36eb3132017-01-13 16:32:38 -0800833 return nullptr;
Alex Lighta59dd802014-07-02 16:28:08 -0700834 }
835}
836
Calin Juravle36eb3132017-01-13 16:32:38 -0800837const char* GetAndroidRoot() {
838 return GetAndroidDir("ANDROID_ROOT", "/system");
839}
840
841const char* GetAndroidRootSafe(std::string* error_msg) {
842 return GetAndroidDirSafe("ANDROID_ROOT", "/system", error_msg);
843}
844
845const char* GetAndroidData() {
846 return GetAndroidDir("ANDROID_DATA", "/data");
847}
848
Alex Lighta59dd802014-07-02 16:28:08 -0700849const char* GetAndroidDataSafe(std::string* error_msg) {
Calin Juravle36eb3132017-01-13 16:32:38 -0800850 return GetAndroidDirSafe("ANDROID_DATA", "/data", error_msg);
851}
852
853std::string GetDefaultBootImageLocation(std::string* error_msg) {
854 const char* android_root = GetAndroidRootSafe(error_msg);
855 if (android_root == nullptr) {
856 return "";
Brian Carlstroma56fcd62012-02-04 21:23:01 -0800857 }
Calin Juravle36eb3132017-01-13 16:32:38 -0800858 return StringPrintf("%s/framework/boot.art", android_root);
Brian Carlstroma56fcd62012-02-04 21:23:01 -0800859}
860
Alex Lighta59dd802014-07-02 16:28:08 -0700861void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
Andreas Gampe3c13a792014-09-18 20:56:04 -0700862 bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
Alex Lighta59dd802014-07-02 16:28:08 -0700863 CHECK(subdir != nullptr);
864 std::string error_msg;
865 const char* android_data = GetAndroidDataSafe(&error_msg);
866 if (android_data == nullptr) {
867 *have_android_data = false;
868 *dalvik_cache_exists = false;
Andreas Gampe3c13a792014-09-18 20:56:04 -0700869 *is_global_cache = false;
Alex Lighta59dd802014-07-02 16:28:08 -0700870 return;
871 } else {
872 *have_android_data = true;
873 }
874 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
875 *dalvik_cache = dalvik_cache_root + subdir;
876 *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
Andreas Gampe3c13a792014-09-18 20:56:04 -0700877 *is_global_cache = strcmp(android_data, "/data") == 0;
878 if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) {
Alex Lighta59dd802014-07-02 16:28:08 -0700879 // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
880 *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
881 (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
882 }
883}
884
Richard Uhler55b58b62016-08-12 09:05:13 -0700885std::string GetDalvikCache(const char* subdir) {
Narayan Kamath11d9f062014-04-23 20:24:57 +0100886 CHECK(subdir != nullptr);
Brian Carlstrom41ccffd2014-05-06 10:37:30 -0700887 const char* android_data = GetAndroidData();
888 const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
Narayan Kamath11d9f062014-04-23 20:24:57 +0100889 const std::string dalvik_cache = dalvik_cache_root + subdir;
Andreas Gampe40da2862015-02-27 12:49:04 -0800890 if (!OS::DirectoryExists(dalvik_cache.c_str())) {
Richard Uhler55b58b62016-08-12 09:05:13 -0700891 // TODO: Check callers. Traditional behavior is to not abort.
892 return "";
Brian Carlstroma9f19782011-10-13 00:14:47 -0700893 }
Brian Carlstrom7675e162013-06-10 16:18:04 -0700894 return dalvik_cache;
Brian Carlstroma9f19782011-10-13 00:14:47 -0700895}
896
Alex Lighta59dd802014-07-02 16:28:08 -0700897bool GetDalvikCacheFilename(const char* location, const char* cache_location,
898 std::string* filename, std::string* error_msg) {
Ian Rogerse6060102013-05-16 12:01:04 -0700899 if (location[0] != '/') {
Alex Lighta59dd802014-07-02 16:28:08 -0700900 *error_msg = StringPrintf("Expected path in location to be absolute: %s", location);
901 return false;
Ian Rogerse6060102013-05-16 12:01:04 -0700902 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700903 std::string cache_file(&location[1]); // skip leading slash
Andreas Gampe9186ced2016-12-12 14:28:21 -0800904 if (!android::base::EndsWith(location, ".dex") &&
905 !android::base::EndsWith(location, ".art") &&
906 !android::base::EndsWith(location, ".oat")) {
Brian Carlstrom30e2ea42013-06-19 23:25:37 -0700907 cache_file += "/";
908 cache_file += DexFile::kClassesDex;
909 }
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700910 std::replace(cache_file.begin(), cache_file.end(), '/', '@');
Alex Lighta59dd802014-07-02 16:28:08 -0700911 *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
912 return true;
913}
914
Brian Carlstrom2afe4942014-05-19 10:25:33 -0700915static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) {
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -0700916 // in = /foo/bar/baz
917 // out = /foo/bar/<isa>/baz
918 size_t pos = filename->rfind('/');
919 CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
920 filename->insert(pos, "/", 1);
921 filename->insert(pos + 1, GetInstructionSetString(isa));
922}
923
924std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
925 // location = /system/framework/boot.art
926 // filename = /system/framework/<isa>/boot.art
927 std::string filename(location);
Brian Carlstrom2afe4942014-05-19 10:25:33 -0700928 InsertIsaDirectory(isa, &filename);
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -0700929 return filename;
930}
931
Calin Juravle5e2b9712015-12-18 14:10:00 +0200932bool FileExists(const std::string& filename) {
933 struct stat buffer;
934 return stat(filename.c_str(), &buffer) == 0;
935}
936
Calin Juravleb9c1b9b2016-03-17 17:07:52 +0000937bool FileExistsAndNotEmpty(const std::string& filename) {
938 struct stat buffer;
939 if (stat(filename.c_str(), &buffer) != 0) {
940 return false;
941 }
942 return buffer.st_size > 0;
943}
944
David Brazdil7b49e6c2016-09-01 11:06:18 +0100945std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
946 const size_t last_ext = filename.find_last_of('.');
947 if (last_ext == std::string::npos) {
948 return filename + "." + new_extension;
949 } else {
950 return filename.substr(0, last_ext + 1) + new_extension;
951 }
952}
953
Mathieu Chartier76433272014-09-26 14:32:37 -0700954std::string PrettyDescriptor(Primitive::Type type) {
955 return PrettyDescriptor(Primitive::Descriptor(type));
956}
957
Nicolas Geoffrayabbb0f72015-10-29 18:55:58 +0000958static void ParseStringAfterChar(const std::string& s,
959 char c,
960 std::string* parsed_value,
961 UsageFn Usage) {
962 std::string::size_type colon = s.find(c);
963 if (colon == std::string::npos) {
964 Usage("Missing char %c in option %s\n", c, s.c_str());
965 }
966 // Add one to remove the char we were trimming until.
967 *parsed_value = s.substr(colon + 1);
968}
969
970void ParseDouble(const std::string& option,
971 char after_char,
972 double min,
973 double max,
974 double* parsed_value,
975 UsageFn Usage) {
976 std::string substring;
977 ParseStringAfterChar(option, after_char, &substring, Usage);
978 bool sane_val = true;
979 double value;
980 if ((false)) {
981 // TODO: this doesn't seem to work on the emulator. b/15114595
982 std::stringstream iss(substring);
983 iss >> value;
984 // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
985 sane_val = iss.eof() && (value >= min) && (value <= max);
986 } else {
987 char* end = nullptr;
988 value = strtod(substring.c_str(), &end);
989 sane_val = *end == '\0' && value >= min && value <= max;
990 }
991 if (!sane_val) {
992 Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str());
993 }
994 *parsed_value = value;
995}
996
Calin Juravle4d77b6a2015-12-01 18:38:09 +0000997int64_t GetFileSizeBytes(const std::string& filename) {
998 struct stat stat_buf;
999 int rc = stat(filename.c_str(), &stat_buf);
1000 return rc == 0 ? stat_buf.st_size : -1;
1001}
1002
Mathieu Chartier4d87df62016-01-07 15:14:19 -08001003void SleepForever() {
1004 while (true) {
1005 usleep(1000000);
1006 }
1007}
1008
Elliott Hughes42ee1422011-09-06 12:33:32 -07001009} // namespace art