1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
162867f0b3f48d3dcbdba9b4ba7db27f6107313663Andy McFadden
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Miscellaneous utility functions.
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stddef.h>
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
2510b0b7a8a1b91556b13c9156140f6ff7061b9f8cCarl Shapiro#include <strings.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <ctype.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <fcntl.h>
306e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes#include <cutils/ashmem.h>
316e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes#include <sys/mman.h>
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print a hex dump in this format:
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project01234567: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff  0123456789abcdef\n
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "mode" is kHexDumpLocal, we start at offset zero, and show a full
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 16 bytes on the first line.  If it's kHexDumpMem, we make this look
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * like a memory dump, using the actual address, outputting a partial line
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if "vaddr" isn't aligned on a 16-byte boundary.
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "priority" and "tag" determine the values passed to the log calls.
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Does not use printf() or other string-formatting calls.
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmPrintHexDumpEx(int priority, const char* tag, const void* vaddr,
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t length, HexDumpMode mode)
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const char gHexDigit[] = "0123456789abcdef";
51fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    const unsigned char* addr = (const unsigned char*)vaddr;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char out[77];           /* exact fit */
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int offset;    /* offset to show while printing */
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* hex;
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* asc;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int gap;
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //int trickle = 0;
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mode == kHexDumpLocal)
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        offset = 0;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        offset = (int) addr;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(out, ' ', sizeof(out)-1);
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    out[8] = ':';
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    out[sizeof(out)-2] = '\n';
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    out[sizeof(out)-1] = '\0';
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gap = (int) offset & 0x0f;
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (length) {
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int lineOffset = offset & ~0x0f;
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int i, count;
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hex = out;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        asc = out + 59;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < 8; i++) {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *hex++ = gHexDigit[lineOffset >> 28];
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineOffset <<= 4;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hex++;
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hex++;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        count = ((int)length > 16-gap) ? 16-gap : (int)length; /* cap length */
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(count != 0);
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(count+gap <= 16);
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gap) {
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* only on first line */
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hex += gap * 3;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            asc += gap;
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = gap ; i < count+gap; i++) {
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *hex++ = gHexDigit[*addr >> 4];
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *hex++ = gHexDigit[*addr & 0x0f];
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hex++;
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (*addr >= 0x20 && *addr < 0x7f /*isprint(*addr)*/)
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *asc++ = *addr;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *asc++ = '.';
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            addr++;
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for ( ; i < 16; i++) {
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* erase extra stuff; only happens on last line */
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *hex++ = ' ';
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *hex++ = ' ';
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hex++;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *asc++ = ' ';
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_PRI(priority, tag, "%s", out);
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 //def HAVE_ANDROID_OS
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We can overrun logcat easily by writing at full speed.  On the
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * other hand, we can make Eclipse time out if we're showing
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * packet dumps while debugging JDWP.
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (trickle++ == 8) {
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                trickle = 0;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                usleep(20000);
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gap = 0;
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        length -= count;
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        offset += count;
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Fill out a DebugOutputTarget, suitable for printing to the log.
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCreateLogOutputTarget(DebugOutputTarget* target, int priority,
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* tag)
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(target != NULL);
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(tag != NULL);
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    target->which = kDebugTargetLog;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    target->data.log.priority = priority;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    target->data.log.tag = tag;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Fill out a DebugOutputTarget suitable for printing to a file pointer.
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCreateFileOutputTarget(DebugOutputTarget* target, FILE* fp)
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(target != NULL);
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(fp != NULL);
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    target->which = kDebugTargetFile;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    target->data.file.fp = fp;
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free "target" and any associated data.
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeOutputTarget(DebugOutputTarget* target)
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(target);
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print a debug message, to either a file or the log.
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format,
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ...)
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_list args;
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_start(args, format);
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (target->which) {
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kDebugTargetLog:
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_PRI_VA(target->data.log.priority, target->data.log.tag,
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            format, args);
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kDebugTargetFile:
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vfprintf(target->data.file.fp, format, args);
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
187c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("unexpected 'which' %d", target->which);
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    va_end(args);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return a newly-allocated string in which all occurrences of '.' have
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * been changed to '/'.  If we find a '/' in the original string, NULL
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is returned to avoid ambiguity.
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dvmDotToSlash(const char* str)
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* newStr = strdup(str);
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp = newStr;
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
205f905853a8ae31d433032cf01fa3eeecafc8aa6c6Andy McFadden    if (newStr == NULL)
206f905853a8ae31d433032cf01fa3eeecafc8aa6c6Andy McFadden        return NULL;
207f905853a8ae31d433032cf01fa3eeecafc8aa6c6Andy McFadden
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*cp != '\0') {
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '/') {
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '.')
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *cp = '/';
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp++;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newStr;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstd::string dvmHumanReadableDescriptor(const char* descriptor) {
22298c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    // Count the number of '['s to get the dimensionality.
22398c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    const char* c = descriptor;
2245016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    size_t dim = 0;
2255016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    while (*c == '[') {
2265016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        dim++;
2275016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        c++;
2285016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    }
22998c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes
230b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    // Reference or primitive?
2315016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    if (*c == 'L') {
23298c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        // "[[La/b/C;" -> "a.b.C[][]".
23398c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        c++; // Skip the 'L'.
2345016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    } else {
23598c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        // "[[B" -> "byte[][]".
23698c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        // To make life easier, we make primitives look like unqualified
23798c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        // reference types.
2385016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        switch (*c) {
23998c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        case 'B': c = "byte;"; break;
24098c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        case 'C': c = "char;"; break;
24198c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        case 'D': c = "double;"; break;
24298c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        case 'F': c = "float;"; break;
24398c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        case 'I': c = "int;"; break;
24498c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        case 'J': c = "long;"; break;
24598c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        case 'S': c = "short;"; break;
24698c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        case 'Z': c = "boolean;"; break;
247b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        default: return descriptor;
2485016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        }
2495016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    }
2505016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes
25198c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    // At this point, 'c' is a string of the form "fully/qualified/Type;"
25298c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    // or "primitive;". Rewrite the type with '.' instead of '/':
253b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes    std::string result;
25498c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    const char* p = c;
25598c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    while (*p != ';') {
25698c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        char ch = *p++;
25798c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        if (ch == '/') {
25898c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes          ch = '.';
25998c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes        }
260b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result.push_back(ch);
26198c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    }
26298c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    // ...and replace the semicolon with 'dim' "[]" pairs:
2635016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    while (dim--) {
264b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes        result += "[]";
2655016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    }
26698c3592ce74e1a516e7a2b93b82525c92918b0e4Elliott Hughes    return result;
2675016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes}
2685016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes
269fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughesstd::string dvmHumanReadableType(const Object* obj)
270fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes{
271fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes    if (obj == NULL) {
2723ff838ee3920ef819d207cbf4148cc9c7939ef69Jesse Wilson        return "null";
273fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes    }
274fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes    if (obj->clazz == NULL) {
275fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes        /* should only be possible right after a plain dvmMalloc() */
276fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes        return "(raw)";
277fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes    }
278fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes    std::string result(dvmHumanReadableDescriptor(obj->clazz->descriptor));
279fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes    if (dvmIsClassObject(obj)) {
280fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes        const ClassObject* clazz = reinterpret_cast<const ClassObject*>(obj);
281fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes        result += "<" + dvmHumanReadableDescriptor(clazz->descriptor) + ">";
282fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes    }
283fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes    return result;
284fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes}
285fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes
2865719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughesstd::string dvmHumanReadableField(const Field* field)
2875719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes{
2885719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    if (field == NULL) {
2895719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes        return "(null)";
2905719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    }
2915719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    std::string result(dvmHumanReadableDescriptor(field->clazz->descriptor));
2925719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    result += '.';
2935719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    result += field->name;
2945719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    return result;
2955719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes}
2965719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes
2975719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughesstd::string dvmHumanReadableMethod(const Method* method, bool withSignature)
2985719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes{
2995719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    if (method == NULL) {
3005719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes        return "(null)";
3015719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    }
3025719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    std::string result(dvmHumanReadableDescriptor(method->clazz->descriptor));
3035719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    result += '.';
3045719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    result += method->name;
3055719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    if (withSignature) {
3065719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes        // TODO: the types in this aren't human readable!
3075719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes        char* signature = dexProtoCopyMethodDescriptor(&method->prototype);
3085719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes        result += signature;
3095719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes        free(signature);
3105719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    }
3115719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes    return result;
3125719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes}
3135719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return a newly-allocated string for the "dot version" of the class
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * name for the given type descriptor. That is, The initial "L" and
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * final ";" (if any) have been removed and all occurrences of '/'
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have been changed to '.'.
3195016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes *
3205016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes * "Dot version" names are used in the class loading machinery.
3215016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes * See also dvmHumanReadableDescriptor.
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dvmDescriptorToDot(const char* str)
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t at = strlen(str);
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* newStr;
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((at >= 2) && (str[0] == 'L') && (str[at - 1] == ';')) {
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        at -= 2; /* Two fewer chars to copy. */
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        str++; /* Skip the 'L'. */
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
333fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    newStr = (char*)malloc(at + 1); /* Add one for the '\0'. */
334f905853a8ae31d433032cf01fa3eeecafc8aa6c6Andy McFadden    if (newStr == NULL)
335f905853a8ae31d433032cf01fa3eeecafc8aa6c6Andy McFadden        return NULL;
336f905853a8ae31d433032cf01fa3eeecafc8aa6c6Andy McFadden
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newStr[at] = '\0';
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (at > 0) {
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        at--;
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newStr[at] = (str[at] == '/') ? '.' : str[at];
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newStr;
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return a newly-allocated string for the type descriptor
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * corresponding to the "dot version" of the given class name. That
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is, non-array names are surrounded by "L" and ";", and all
3515016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes * occurrences of '.' have been changed to '/'.
3525016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes *
3535016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes * "Dot version" names are used in the class loading machinery.
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dvmDotToDescriptor(const char* str)
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t length = strlen(str);
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int wrapElSemi = 0;
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* newStr;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* at;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (str[0] != '[') {
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        length += 2; /* for "L" and ";" */
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        wrapElSemi = 1;
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
367fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    newStr = at = (char*)malloc(length + 1); /* + 1 for the '\0' */
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (newStr == NULL) {
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wrapElSemi) {
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *(at++) = 'L';
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*str) {
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = *(str++);
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == '.') {
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            c = '/';
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *(at++) = c;
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wrapElSemi) {
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *(at++) = ';';
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *at = '\0';
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newStr;
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return a newly-allocated string for the internal-form class name for
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the given type descriptor. That is, the initial "L" and final ";" (if
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * any) have been removed.
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dvmDescriptorToName(const char* str)
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (str[0] == 'L') {
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        size_t length = strlen(str) - 1;
402fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        char* newStr = (char*)malloc(length);
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newStr == NULL) {
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        strlcpy(newStr, str + 1, length);
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return newStr;
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return strdup(str);
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return a newly-allocated string for the type descriptor for the given
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * internal-form class name. That is, a non-array class name will get
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * surrounded by "L" and ";", while array names are left as-is.
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dvmNameToDescriptor(const char* str)
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (str[0] != '[') {
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        size_t length = strlen(str);
424fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        char* descriptor = (char*)malloc(length + 3);
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (descriptor == NULL) {
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor[0] = 'L';
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        strcpy(descriptor + 1, str);
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor[length + 1] = ';';
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor[length + 2] = '\0';
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return descriptor;
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return strdup(str);
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a notion of the current time, in nanoseconds.  This is meant for
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * computing durations (e.g. "operation X took 52nsec"), so the result
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should not be used to get the current date/time.
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4461e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirou8 dvmGetRelativeTimeNsec()
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_CLOCKS
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timespec now;
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clock_gettime(CLOCK_MONOTONIC, &now);
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timeval now;
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gettimeofday(&now, NULL);
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (u8)now.tv_sec*1000000000LL + now.tv_usec * 1000LL;
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the per-thread CPU time, in nanoseconds.
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Only useful for time deltas.
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4641e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirou8 dvmGetThreadCpuTimeNsec()
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_POSIX_CLOCKS
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timespec now;
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (u8) -1;
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the per-thread CPU time, in nanoseconds, for the specified thread.
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectu8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread)
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 /*def HAVE_POSIX_CLOCKS*/
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int clockId;
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pthread_getcpuclockid(thread, &clockId) != 0)
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (u8) -1;
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timespec now;
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clock_gettime(clockId, &now);
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (u8) -1;
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Call this repeatedly, with successively higher values for "iteration",
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to sleep for a period of time not to exceed "maxTotalSleep".
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For example, when called with iteration==0 we will sleep for a very
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * brief time.  On the next call we will sleep for a longer time.  When
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the sum total of all sleeps reaches "maxTotalSleep", this returns false.
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The initial start time value for "relStartTime" MUST come from the
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmGetRelativeTimeUsec call.  On the device this must come from the
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monotonic clock source, not the wall clock.
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This should be used wherever you might be tempted to call sched_yield()
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in a loop.  The problem with sched_yield is that, for a high-priority
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thread, the kernel might not actually transfer control elsewhere.
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" if we were unable to sleep because our time was up.
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime)
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
51533c8ae5bb1bb8052680108d999c608df8c72a613Mathieu Chartier    /*
51633c8ae5bb1bb8052680108d999c608df8c72a613Mathieu Chartier     * Minimum sleep is one millisecond, it is important to keep this value
51733c8ae5bb1bb8052680108d999c608df8c72a613Mathieu Chartier     * low to ensure short GC pauses since dvmSuspendAllThreads() uses this
51833c8ae5bb1bb8052680108d999c608df8c72a613Mathieu Chartier     * function.
51933c8ae5bb1bb8052680108d999c608df8c72a613Mathieu Chartier     */
52033c8ae5bb1bb8052680108d999c608df8c72a613Mathieu Chartier    const int minSleep = 1000;
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u8 curTime;
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int curDelay;
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Get current time, and see if we've already exceeded the limit.
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    curTime = dvmGetRelativeTimeUsec();
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (curTime >= relStartTime + maxTotalSleep) {
52960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("exsl: sleep exceeded (start=%llu max=%d now=%llu)",
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            relStartTime, maxTotalSleep, curTime);
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute current delay.  We're bounded by "maxTotalSleep", so no
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * real risk of overflow assuming "usleep" isn't returning early.
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (Besides, 2^30 usec is about 18 minutes by itself.)
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For iteration==0 we just call sched_yield(), so the first sleep
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at iteration==1 is actually (minSleep * 2).
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    curDelay = minSleep;
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (iteration-- > 0)
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        curDelay *= 2;
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(curDelay > 0);
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (curTime + curDelay >= relStartTime + maxTotalSleep) {
54860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("exsl: reduced delay from %d to %d",
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            curDelay, (int) ((relStartTime + maxTotalSleep) - curTime));
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        curDelay = (int) ((relStartTime + maxTotalSleep) - curTime);
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (iteration == 0) {
55460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("exsl: yield");
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sched_yield();
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
55760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("exsl: sleep for %d", curDelay);
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        usleep(curDelay);
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set the "close on exec" flag so we don't expose our file descriptors
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to processes launched by us.
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmSetCloseOnExec(int fd)
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int flags;
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * There's presently only one flag defined, so getting the previous
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * value of the fd flags is probably unnecessary.
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    flags = fcntl(fd, F_GETFD);
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (flags < 0) {
578e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Unable to get fd flags for fd %d", fd);
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
582e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Unable to set close-on-exec for fd %d", fd);
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if (!HAVE_STRLCPY)
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Implementation of strlcpy() for platforms that don't already have it. */
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsize_t strlcpy(char *dst, const char *src, size_t size) {
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t srcLength = strlen(src);
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t copyLength = srcLength;
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (srcLength > (size - 1)) {
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyLength = size - 1;
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (size != 0) {
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        strncpy(dst, src, copyLength);
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dst[copyLength] = '\0';
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return srcLength;
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
6066e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes
6076e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes/*
6086e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes *  Allocates a memory region using ashmem and mmap, initialized to
6096e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes *  zero.  Actual allocation rounded up to page multiple.  Returns
6106e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes *  NULL on failure.
6116e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes */
6124a7db9c47500ded9d2509185a01e081bf03b64d4Brian Carlstromvoid *dvmAllocRegion(size_t byteCount, int prot, const char *name) {
6136e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    void *base;
6146e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    int fd, ret;
6156e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes
6164a7db9c47500ded9d2509185a01e081bf03b64d4Brian Carlstrom    byteCount = ALIGN_UP_TO_PAGE_SIZE(byteCount);
6174a7db9c47500ded9d2509185a01e081bf03b64d4Brian Carlstrom    fd = ashmem_create_region(name, byteCount);
6186e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    if (fd == -1) {
6196e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes        return NULL;
6206e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    }
6214a7db9c47500ded9d2509185a01e081bf03b64d4Brian Carlstrom    base = mmap(NULL, byteCount, prot, MAP_PRIVATE, fd, 0);
6226e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    ret = close(fd);
6236e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    if (base == MAP_FAILED) {
6246e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes        return NULL;
6256e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    }
6266e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    if (ret == -1) {
627a5e0812ac14be9c74ae78a27ab03bb7aa5af7adfYou Kim        munmap(base, byteCount);
6286e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes        return NULL;
6296e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    }
6306e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes    return base;
6316e5cf6021b2f3e00e18ab402f23ab93b27c6061bBarry Hayes}
6320a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
6330a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden/*
6340a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden * Get some per-thread stats.
6350a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden *
6360a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden * This is currently generated by opening the appropriate "stat" file
6370a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden * in /proc and reading the pile of stuff that comes out.
6380a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden */
6390a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFaddenbool dvmGetThreadStats(ProcStatData* pData, pid_t tid)
6400a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden{
6410a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    /*
6420a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    int pid;
6430a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    char comm[128];
6440a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    char state;
6450a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    int ppid, pgrp, session, tty_nr, tpgid;
6460a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    unsigned long flags, minflt, cminflt, majflt, cmajflt, utime, stime;
6470a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    long cutime, cstime, priority, nice, zero, itrealvalue;
6480a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    unsigned long starttime, vsize;
6490a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    long rss;
6500a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    unsigned long rlim, startcode, endcode, startstack, kstkesp, kstkeip;
6510a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    unsigned long signal, blocked, sigignore, sigcatch, wchan, nswap, cnswap;
6520a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    int exit_signal, processor;
6530a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    unsigned long rt_priority, policy;
6540a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
6550a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    scanf("%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld "
6560a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden          "%ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
6570a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden          "%lu %lu %lu %d %d %lu %lu",
6580a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        &pid, comm, &state, &ppid, &pgrp, &session, &tty_nr, &tpgid,
6590a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        &flags, &minflt, &cminflt, &majflt, &cmajflt, &utime, &stime,
6600a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        &cutime, &cstime, &priority, &nice, &zero, &itrealvalue,
6610a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        &starttime, &vsize, &rss, &rlim, &startcode, &endcode,
6620a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        &startstack, &kstkesp, &kstkeip, &signal, &blocked, &sigignore,
6630a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        &sigcatch, &wchan, &nswap, &cnswap, &exit_signal, &processor,
6640a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        &rt_priority, &policy);
6650a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
6660a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        (new: delayacct_blkio_ticks %llu (since Linux 2.6.18))
6670a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    */
6680a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
6690a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    char nameBuf[64];
6700a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    int i, fd;
6710a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
6720a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    /*
6730a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * Open and read the appropriate file.  This is expected to work on
6740a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * Linux but will fail on other platforms (e.g. Mac sim).
6750a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     */
6760a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    sprintf(nameBuf, "/proc/self/task/%d/stat", (int) tid);
6770a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    fd = open(nameBuf, O_RDONLY);
6780a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    if (fd < 0) {
67992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Unable to open '%s': %s", nameBuf, strerror(errno));
6800a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        return false;
6810a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    }
6820a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
6830a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    char lineBuf[512];      /* > 2x typical */
6840a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    int cc = read(fd, lineBuf, sizeof(lineBuf)-1);
6850a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    if (cc <= 0) {
6860a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        const char* msg = (cc == 0) ? "unexpected EOF" : strerror(errno);
6874308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("Unable to read '%s': %s", nameBuf, msg);
6880a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        close(fd);
6890a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        return false;
6900a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    }
6910a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    close(fd);
6920a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    lineBuf[cc] = '\0';
6930a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
6940a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    /*
6950a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * Skip whitespace-separated tokens.  For the most part we can assume
6960a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * that tokens do not contain spaces, and are separated by exactly one
6970a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * space character.  The only exception is the second field ("comm")
6980a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * which may contain spaces but is surrounded by parenthesis.
6990a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     */
7000a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    char* cp = strchr(lineBuf, ')');
7010a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    if (cp == NULL)
7020a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        goto parse_fail;
703b3667a19f5c573b7785876979af4781292d27327Andy McFadden    cp += 2;
704b3667a19f5c573b7785876979af4781292d27327Andy McFadden    pData->state = *cp++;
705b3667a19f5c573b7785876979af4781292d27327Andy McFadden
706b3667a19f5c573b7785876979af4781292d27327Andy McFadden    for (i = 3; i < 13; i++) {
7070a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        cp = strchr(cp+1, ' ');
7080a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        if (cp == NULL)
7090a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden            goto parse_fail;
7100a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    }
7110a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
7120a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    /*
7130a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * Grab utime/stime.
7140a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     */
7150a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    char* endp;
7160a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    pData->utime = strtoul(cp+1, &endp, 10);
7170a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    if (endp == cp+1)
7184308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("Warning: strtoul failed on utime ('%.30s...')", cp);
7190a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
7200a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    cp = strchr(cp+1, ' ');
7210a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    if (cp == NULL)
7220a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        goto parse_fail;
7230a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
7240a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    pData->stime = strtoul(cp+1, &endp, 10);
7250a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    if (endp == cp+1)
7264308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("Warning: strtoul failed on stime ('%.30s...')", cp);
7270a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
7280a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    /*
7290a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * Skip more stuff we don't care about.
7300a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     */
7310a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    for (i = 14; i < 38; i++) {
7320a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        cp = strchr(cp+1, ' ');
7330a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden        if (cp == NULL)
7340a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden            goto parse_fail;
7350a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    }
7360a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
7370a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    /*
7380a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     * Grab processor number.
7390a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden     */
7400a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    pData->processor = strtol(cp+1, &endp, 10);
7410a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    if (endp == cp+1)
7424308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("Warning: strtoul failed on processor ('%.30s...')", cp);
7430a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
7440a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    return true;
7450a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden
7460a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFaddenparse_fail:
7474308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("stat parse failed (%s)", lineBuf);
7480a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden    return false;
7490a3f698117bd6438d0b668dfbb72828d25a23a3bAndy McFadden}
750bbf9d73a5677de73eaa3b4e1f6de94a24697aad1Dan Bornstein
75132bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein/* documented in header file */
75232bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornsteinconst char* dvmPathToAbsolutePortion(const char* path) {
75332bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein    if (path == NULL) {
75432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein        return NULL;
75532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein    }
75632bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein
75732bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein    if (path[0] == '/') {
75832bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein        /* It's a regular absolute path. Return it. */
75932bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein        return path;
76032bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein    }
76132bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein
76232bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein    const char* sentinel = strstr(path, "/./");
76332bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein
76432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein    if (sentinel != NULL) {
76532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein        /* It's got the sentinel. Return a pointer to the second slash. */
76632bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein        return sentinel + 2;
76732bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein    }
76832bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein
76932bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein    return NULL;
77032bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein}
771708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
772708f143f318bb2167c810f9506102f4ad656545cElliott Hughes// From RE2.
7735719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughesvoid StringAppendV(std::string* dst, const char* format, va_list ap) {
774708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    // First try with a small fixed size buffer
775708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    char space[1024];
776708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
777708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    // It's possible for methods that use a va_list to invalidate
778708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    // the data in it upon use.  The fix is to make a copy
779708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    // of the structure before using it and use that copy instead.
780708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    va_list backup_ap;
781708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    va_copy(backup_ap, ap);
782708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    int result = vsnprintf(space, sizeof(space), format, backup_ap);
783708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    va_end(backup_ap);
784708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
785708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    if ((result >= 0) && ((size_t) result < sizeof(space))) {
786708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        // It fit
787708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        dst->append(space, result);
788708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        return;
789708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    }
790708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
791708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    // Repeatedly increase buffer size until it fits
792708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    int length = sizeof(space);
793708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    while (true) {
794708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        if (result < 0) {
795708f143f318bb2167c810f9506102f4ad656545cElliott Hughes            // Older behavior: just try doubling the buffer size
796708f143f318bb2167c810f9506102f4ad656545cElliott Hughes            length *= 2;
797708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        } else {
798708f143f318bb2167c810f9506102f4ad656545cElliott Hughes            // We need exactly "result+1" characters
799708f143f318bb2167c810f9506102f4ad656545cElliott Hughes            length = result+1;
800708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        }
801708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        char* buf = new char[length];
802708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
803708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        // Restore the va_list before we use it again
804708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        va_copy(backup_ap, ap);
805708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        result = vsnprintf(buf, length, format, backup_ap);
806708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        va_end(backup_ap);
807708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
808708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        if ((result >= 0) && (result < length)) {
809708f143f318bb2167c810f9506102f4ad656545cElliott Hughes            // It fit
810708f143f318bb2167c810f9506102f4ad656545cElliott Hughes            dst->append(buf, result);
811708f143f318bb2167c810f9506102f4ad656545cElliott Hughes            delete[] buf;
812708f143f318bb2167c810f9506102f4ad656545cElliott Hughes            return;
813708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        }
814708f143f318bb2167c810f9506102f4ad656545cElliott Hughes        delete[] buf;
815708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    }
816708f143f318bb2167c810f9506102f4ad656545cElliott Hughes}
817708f143f318bb2167c810f9506102f4ad656545cElliott Hughes
818837eabb829417c1542037423c55536649de404b8Elliott Hughesstd::string StringPrintf(const char* fmt, ...) {
819708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    va_list ap;
820708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    va_start(ap, fmt);
821708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    std::string result;
822708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    StringAppendV(&result, fmt, ap);
823708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    va_end(ap);
824708f143f318bb2167c810f9506102f4ad656545cElliott Hughes    return result;
825708f143f318bb2167c810f9506102f4ad656545cElliott Hughes}
826837eabb829417c1542037423c55536649de404b8Elliott Hughes
827837eabb829417c1542037423c55536649de404b8Elliott Hughesvoid StringAppendF(std::string* dst, const char* format, ...) {
828837eabb829417c1542037423c55536649de404b8Elliott Hughes    va_list ap;
829837eabb829417c1542037423c55536649de404b8Elliott Hughes    va_start(ap, format);
830837eabb829417c1542037423c55536649de404b8Elliott Hughes    StringAppendV(dst, format, ap);
831837eabb829417c1542037423c55536649de404b8Elliott Hughes    va_end(ap);
832837eabb829417c1542037423c55536649de404b8Elliott Hughes}
833