1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2009 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 */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Strip Android-specific records out of hprof data, back-converting from
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1.0.3 to 1.0.2.  This removes some useful information, but allows
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Android hprof data to be handled by widely-available tools (like "jhat").
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h>
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdint.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <assert.h>
283db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey#include <unistd.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//#define VERBOSE_DEBUG
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef VERBOSE_DEBUG
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define DBUG(...) fprintf(stderr, __VA_ARGS__)
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define DBUG(...)
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef FALSE
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define FALSE 0
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define TRUE (!FALSE)
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef enum HprofBasicType {
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_OBJECT = 2,
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_BOOLEAN = 4,
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_CHAR = 5,
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_FLOAT = 6,
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_DOUBLE = 7,
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_BYTE = 8,
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_SHORT = 9,
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_INT = 10,
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_BASIC_LONG = 11,
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} HprofBasicType;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef enum HprofTag {
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* tags we must handle specially */
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_TAG_HEAP_DUMP                 = 0x0c,
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_TAG_HEAP_DUMP_SEGMENT         = 0x1c,
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} HprofTag;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef enum HprofHeapTag {
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* 1.0.2 tags */
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_UNKNOWN                  = 0xff,
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_JNI_GLOBAL               = 0x01,
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_JNI_LOCAL                = 0x02,
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_JAVA_FRAME               = 0x03,
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_NATIVE_STACK             = 0x04,
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_STICKY_CLASS             = 0x05,
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_THREAD_BLOCK             = 0x06,
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_MONITOR_USED             = 0x07,
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_THREAD_OBJECT            = 0x08,
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_CLASS_DUMP                    = 0x20,
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_INSTANCE_DUMP                 = 0x21,
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_OBJECT_ARRAY_DUMP             = 0x22,
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_PRIMITIVE_ARRAY_DUMP          = 0x23,
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Android 1.0.3 tags */
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_HEAP_DUMP_INFO                = 0xfe,
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_INTERNED_STRING          = 0x89,
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_FINALIZING               = 0x8a,
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_DEBUGGER                 = 0x8b,
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_REFERENCE_CLEANUP        = 0x8c,
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_VM_INTERNAL              = 0x8d,
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_ROOT_JNI_MONITOR              = 0x8e,
8498740d6436340f17f5427d5923184fcace0e38ccCarl Shapiro    HPROF_UNREACHABLE                   = 0x90,  /* deprecated */
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPROF_PRIMITIVE_ARRAY_NODATA_DUMP   = 0xc3,
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} HprofHeapTag;
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
883db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkeytypedef enum HprofHeapId {
893db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    HPROF_HEAP_DEFAULT = 0,
903db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    HPROF_HEAP_ZYGOTE = 'Z',
913db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    HPROF_HEAP_APP = 'A',
923db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    HPROF_HEAP_IMAGE = 'I',
933db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey} HprofHeapId;
943db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kIdentSize  4
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kRecHdrLen  9
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
983db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey#define kFlagAppOnly 1
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Expanding buffer
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* simple struct */
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct {
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned char* storage;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t curLen;
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t maxLen;
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ExpandBuf;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create an ExpandBuf.
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ExpandBuf* ebAlloc(void)
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const int kInitialSize = 64;
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandBuf* newBuf = (ExpandBuf*) malloc(sizeof(ExpandBuf));
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (newBuf == NULL)
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newBuf->storage = (unsigned char*) malloc(kInitialSize);
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newBuf->curLen = 0;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newBuf->maxLen = kInitialSize;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newBuf;
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release the storage associated with an ExpandBuf.
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void ebFree(ExpandBuf* pBuf)
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pBuf != NULL) {
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pBuf->storage);
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(pBuf);
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return a pointer to the data buffer.
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The pointer may change as data is added to the buffer, so this value
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should not be cached.
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline unsigned char* ebGetBuffer(ExpandBuf* pBuf)
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pBuf->storage;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the amount of data currently in the buffer.
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline size_t ebGetLength(ExpandBuf* pBuf)
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pBuf->curLen;
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Empty the buffer.
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void ebClear(ExpandBuf* pBuf)
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pBuf->curLen = 0;
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Ensure that the buffer can hold at least "size" additional bytes.
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int ebEnsureCapacity(ExpandBuf* pBuf, int size)
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(size > 0);
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pBuf->curLen + size > pBuf->maxLen) {
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int newSize = pBuf->curLen + size + 128;    /* oversize slightly */
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned char* newStorage = realloc(pBuf->storage, newSize);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newStorage == NULL) {
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: realloc failed on size=%d\n", newSize);
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pBuf->storage = newStorage;
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pBuf->maxLen = newSize;
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pBuf->curLen + size <= pBuf->maxLen);
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add data to the buffer after ensuring it can hold it.
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int ebAddData(ExpandBuf* pBuf, const void* data, size_t count)
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ebEnsureCapacity(pBuf, count);
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(pBuf->storage + pBuf->curLen, data, count);
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pBuf->curLen += count;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Read a NULL-terminated string from the input.
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int ebReadString(ExpandBuf* pBuf, FILE* in)
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ic;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do {
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ebEnsureCapacity(pBuf, 1);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ic = getc(in);
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (feof(in) || ferror(in)) {
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: failed reading input\n");
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pBuf->storage[pBuf->curLen++] = (unsigned char) ic;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (ic != 0);
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Read some data, adding it to the expanding buffer.
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This will ensure that the buffer has enough space to hold the new data
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (plus the previous contents).
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int ebReadData(ExpandBuf* pBuf, FILE* in, size_t count, int eofExpected)
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t actual;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(count > 0);
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ebEnsureCapacity(pBuf, count);
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actual = fread(pBuf->storage + pBuf->curLen, 1, count, in);
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (actual != count) {
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (eofExpected && feof(in) && !ferror(in)) {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* return without reporting an error */
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: read %d of %d bytes\n", actual, count);
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pBuf->curLen += count;
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pBuf->curLen <= pBuf->maxLen);
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Write the data from the buffer.  Resets the data count to zero.
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int ebWriteData(ExpandBuf* pBuf, FILE* out)
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t actual;
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pBuf->curLen > 0);
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pBuf->curLen <= pBuf->maxLen);
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actual = fwrite(pBuf->storage, 1, pBuf->curLen, out);
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (actual != pBuf->curLen) {
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "ERROR: write %d of %d bytes\n", actual, pBuf->curLen);
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pBuf->curLen = 0;
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Hprof stuff
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a 2-byte value, in big-endian order, from memory.
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic uint16_t get2BE(const unsigned char* buf)
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint16_t val;
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val = (buf[0] << 8) | buf[1];
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get a 4-byte value, in big-endian order, from memory.
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic uint32_t get4BE(const unsigned char* buf)
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uint32_t val;
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    val = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set a 4-byte value, in big-endian order.
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void set4BE(unsigned char* buf, uint32_t val)
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf[0] = val >> 24;
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf[1] = val >> 16;
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf[2] = val >> 8;
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf[3] = val;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the size, in bytes, of one of the "basic types".
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeBasicLen(HprofBasicType basicType)
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const int sizes[] = { -1, -1, 4, -1, 1, 2, 4, 8, 1, 2, 4, 8  };
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const size_t maxSize = sizeof(sizes) / sizeof(sizes[0]);
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(basicType >= 0);
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (basicType >= maxSize)
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return sizes[basicType];
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the length of a HPROF_CLASS_DUMP block.
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeClassDumpLen(const unsigned char* origBuf, int len)
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const unsigned char* buf = origBuf;
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int blockLen = 0;
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, count;
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    blockLen += kIdentSize * 7 + 8;
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf += blockLen;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    len -= blockLen;
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (len < 0)
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = get2BE(buf);
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf += 2;
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    len -= 2;
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DBUG("CDL: 1st count is %d\n", count);
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < count; i++) {
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        HprofBasicType basicType;
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int basicLen;
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        basicType = buf[2];
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        basicLen = computeBasicLen(basicType);
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (basicLen < 0) {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DBUG("ERROR: invalid basicType %d\n", basicType);
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buf += 2 + 1 + basicLen;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len -= 2 + 1 + basicLen;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (len < 0)
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = get2BE(buf);
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf += 2;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    len -= 2;
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DBUG("CDL: 2nd count is %d\n", count);
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < count; i++) {
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        HprofBasicType basicType;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int basicLen;
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        basicType = buf[kIdentSize];
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        basicLen = computeBasicLen(basicType);
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (basicLen < 0) {
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: invalid basicType %d\n", basicType);
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buf += kIdentSize + 1 + basicLen;
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len -= kIdentSize + 1 + basicLen;
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (len < 0)
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = get2BE(buf);
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf += 2;
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    len -= 2;
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DBUG("CDL: 3rd count is %d\n", count);
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < count; i++) {
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buf += kIdentSize + 1;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len -= kIdentSize + 1;
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (len < 0)
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DBUG("Total class dump len: %d\n", buf - origBuf);
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return buf - origBuf;
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the length of a HPROF_INSTANCE_DUMP block.
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeInstanceDumpLen(const unsigned char* origBuf, int len)
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int extraCount = get4BE(origBuf + kIdentSize * 2 + 4);
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return kIdentSize * 2 + 8 + extraCount;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the length of a HPROF_OBJECT_ARRAY_DUMP block.
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeObjectArrayDumpLen(const unsigned char* origBuf, int len)
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int arrayCount = get4BE(origBuf + kIdentSize + 4);
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return kIdentSize * 2 + 8 + arrayCount * kIdentSize;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the length of a HPROF_PRIMITIVE_ARRAY_DUMP block.
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computePrimitiveArrayDumpLen(const unsigned char* origBuf, int len)
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int arrayCount = get4BE(origBuf + kIdentSize + 4);
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HprofBasicType basicType = origBuf[kIdentSize + 8];
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int basicLen = computeBasicLen(basicType);
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return kIdentSize + 9 + arrayCount * basicLen;
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Crunch through a heap dump record, writing the original or converted
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data to "out".
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4353db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkeystatic int processHeapDump(ExpandBuf* pBuf, FILE* out, int flags)
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandBuf* pOutBuf = ebAlloc();
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned char* origBuf = ebGetBuffer(pBuf);
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned char* buf = origBuf;
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int len = ebGetLength(pBuf);
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = -1;
4423db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    int heapType = HPROF_HEAP_DEFAULT;
4433db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    int heapIgnore = FALSE;
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pBuf = NULL;        /* we just use the raw pointer from here forward */
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* copy the original header to the output buffer */
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ebAddData(pOutBuf, buf, kRecHdrLen) != 0)
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf += kRecHdrLen;      /* skip past record header */
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    len -= kRecHdrLen;
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (len > 0) {
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned char subType = buf[0];
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int justCopy = TRUE;
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int subLen;
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DBUG("--- 0x%02x  ", subType);
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (subType) {
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* 1.0.2 types */
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_UNKNOWN:
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_JNI_GLOBAL:
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize * 2;
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_JNI_LOCAL:
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize + 8;
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_JAVA_FRAME:
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize + 8;
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_NATIVE_STACK:
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize + 4;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_STICKY_CLASS:
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_THREAD_BLOCK:
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize + 4;
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_MONITOR_USED:
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_THREAD_OBJECT:
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize + 8;
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_CLASS_DUMP:
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = computeClassDumpLen(buf+1, len-1);
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_INSTANCE_DUMP:
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = computeInstanceDumpLen(buf+1, len-1);
4943db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            if (heapIgnore) {
4953db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                justCopy = FALSE;
4963db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            }
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_OBJECT_ARRAY_DUMP:
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = computeObjectArrayDumpLen(buf+1, len-1);
5003db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            if (heapIgnore) {
5013db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                justCopy = FALSE;
5023db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            }
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_PRIMITIVE_ARRAY_DUMP:
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = computePrimitiveArrayDumpLen(buf+1, len-1);
5063db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            if (heapIgnore) {
5073db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                justCopy = FALSE;
5083db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            }
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* these were added for Android in 1.0.3 */
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_HEAP_DUMP_INFO:
5123db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            heapType = get4BE(buf+1);
5133db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            if ((flags & kFlagAppOnly) != 0
5143db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                    && (heapType == HPROF_HEAP_ZYGOTE || heapType == HPROF_HEAP_IMAGE)) {
5153db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                heapIgnore = TRUE;
5163db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            } else {
5173db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                heapIgnore = FALSE;
5183db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            }
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            justCopy = FALSE;
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize + 4;
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // no 1.0.2 equivalent for this
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_INTERNED_STRING:
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[0] = HPROF_ROOT_UNKNOWN;
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_FINALIZING:
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[0] = HPROF_ROOT_UNKNOWN;
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_DEBUGGER:
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[0] = HPROF_ROOT_UNKNOWN;
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_REFERENCE_CLEANUP:
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[0] = HPROF_ROOT_UNKNOWN;
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_VM_INTERNAL:
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[0] = HPROF_ROOT_UNKNOWN;
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_ROOT_JNI_MONITOR:
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* keep the ident, drop the next 8 bytes */
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[0] = HPROF_ROOT_UNKNOWN;
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            justCopy = FALSE;
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ebAddData(pOutBuf, buf, 1 + kIdentSize);
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize + 8;
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_UNREACHABLE:
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[0] = HPROF_ROOT_UNKNOWN;
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize;
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_PRIMITIVE_ARRAY_NODATA_DUMP:
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[0] = HPROF_PRIMITIVE_ARRAY_DUMP;
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buf[5] = buf[6] = buf[7] = buf[8] = 0;  /* set array len to 0 */
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            subLen = kIdentSize + 9;
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* shouldn't get here */
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fprintf(stderr, "ERROR: unexpected subtype 0x%02x at offset %d\n",
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                subType, buf - origBuf);
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (justCopy) {
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* copy source data */
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DBUG("(%d)\n", 1 + subLen);
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ebAddData(pOutBuf, buf, 1 + subLen);
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* other data has been written, or the sub-record omitted */
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DBUG("(adv %d)\n", 1 + subLen);
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* advance to next entry */
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buf += 1 + subLen;
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len -= 1 + subLen;
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Update the record length.
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    set4BE(ebGetBuffer(pOutBuf) + 5, ebGetLength(pOutBuf) - kRecHdrLen);
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ebWriteData(pOutBuf, out) != 0)
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = 0;
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ebFree(pOutBuf);
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Filter an hprof data file.
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
5993db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkeystatic int filterData(FILE* in, FILE* out, int flags)
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
6014e1205528c6047cd000b6c5617f8ea8ae3ede82aSiva Velusamy    const char *magicString;
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ExpandBuf* pBuf;
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = -1;
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pBuf = ebAlloc();
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pBuf == NULL)
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Start with the header.
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ebReadString(pBuf, in) != 0)
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6154e1205528c6047cd000b6c5617f8ea8ae3ede82aSiva Velusamy    magicString = (const char*)ebGetBuffer(pBuf);
6164e1205528c6047cd000b6c5617f8ea8ae3ede82aSiva Velusamy    if (strcmp(magicString, "JAVA PROFILE 1.0.3") != 0) {
6174e1205528c6047cd000b6c5617f8ea8ae3ede82aSiva Velusamy        if (strcmp(magicString, "JAVA PROFILE 1.0.2") == 0) {
6184e1205528c6047cd000b6c5617f8ea8ae3ede82aSiva Velusamy            fprintf(stderr, "ERROR: HPROF file already in 1.0.2 format.\n");
6194e1205528c6047cd000b6c5617f8ea8ae3ede82aSiva Velusamy        } else {
6204e1205528c6047cd000b6c5617f8ea8ae3ede82aSiva Velusamy            fprintf(stderr, "ERROR: expecting HPROF file format 1.0.3\n");
6214e1205528c6047cd000b6c5617f8ea8ae3ede82aSiva Velusamy        }
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* downgrade to 1.0.2 */
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    (ebGetBuffer(pBuf))[17] = '2';
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ebWriteData(pBuf, out) != 0)
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Copy:
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (4b) identifier size, always 4
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (8b) file creation date
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ebReadData(pBuf, in, 12, FALSE) != 0)
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ebWriteData(pBuf, out) != 0)
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Read records until we hit EOF.  Each record begins with:
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (1b) type
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (4b) timestamp
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (4b) length of data that follows
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(ebGetLength(pBuf) == 0);
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* read type char */
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ebReadData(pBuf, in, 1, TRUE) != 0)
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (feof(in))
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* read the rest of the header */
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ebReadData(pBuf, in, kRecHdrLen-1, FALSE) != 0)
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned char* buf = ebGetBuffer(pBuf);
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned char type;
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int timestamp, length;
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = buf[0];
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        timestamp = get4BE(buf + 1);
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        length = get4BE(buf + 5);
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buf = NULL;     /* ptr invalid after next read op */
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* read the record data */
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (length != 0) {
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (ebReadData(pBuf, in, length, FALSE) != 0)
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6743db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        if (type == HPROF_TAG_HEAP_DUMP
6753db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                || type == HPROF_TAG_HEAP_DUMP_SEGMENT) {
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DBUG("Processing heap dump 0x%02x (%d bytes)\n",
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                type, length);
6783db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            if (processHeapDump(pBuf, out, flags) != 0)
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ebClear(pBuf);
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* keep */
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DBUG("Keeping 0x%02x (%d bytes)\n", type, length);
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (ebWriteData(pBuf, out) != 0)
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = 0;
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ebFree(pBuf);
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6963db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkeystatic FILE* fopen_or_default(const char* path, const char* mode, FILE* def) {
6973db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    if (!strcmp(path, "-")) {
6983db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        return def;
6993db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    } else {
7003db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        return fopen(path, mode);
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
7023db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey}
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7043db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkeyint main(int argc, char** argv)
7053db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey{
7063db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    FILE* in = NULL;
7073db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    FILE* out = NULL;
7083db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    int flags = 0;
7093db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    int res = 1;
7103db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey
7113db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    int opt;
7123db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    while ((opt = getopt(argc, argv, "z")) != -1) {
7133db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        switch (opt) {
7143db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            case 'z':
7153db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                flags |= kFlagAppOnly;
7163db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                break;
7173db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            case '?':
7183db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            default:
7193db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey                goto usage;
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
7223db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey
7233db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    int i;
7243db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    for (i = optind; i < argc; i++) {
7253db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        char* arg = argv[i];
7263db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        if (!in) {
7273db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            in = fopen_or_default(arg, "rb", stdin);
7283db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        } else if (!out) {
7293db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            out = fopen_or_default(arg, "wb", stdout);
7303db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        } else {
7313db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey            goto usage;
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7353db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    if (in == NULL || out == NULL) {
7363db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        goto usage;
7373db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    }
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7393db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    res = filterData(in, out, flags);
7403db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    goto finish;
7413db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey
7423db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkeyusage:
7433db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    fprintf(stderr, "Usage: hprof-conf [-z] infile outfile\n");
7443db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    fprintf(stderr, "\n");
7453db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    fprintf(stderr, "  -z: exclude non-app heaps, such as Zygote\n");
7463db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    fprintf(stderr, "\n");
7473db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    fprintf(stderr, "Specify '-' for either or both files to use stdin/stdout.\n");
7483db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    fprintf(stderr, "\n");
7493db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey
7503db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    fprintf(stderr,
7513db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        "Copyright (C) 2009 The Android Open Source Project\n\n"
7523db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        "This software is built from source code licensed under the "
7533db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        "Apache License,\n"
7543db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        "Version 2.0 (the \"License\"). You may obtain a copy of the "
7553db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        "License at\n\n"
7563db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        "     http://www.apache.org/licenses/LICENSE-2.0\n\n"
7573db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        "See the associated NOTICE file for this software for further "
7583db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey        "details.\n");
7593db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    res = 2;
7603db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey
7613db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkeyfinish:
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (in != stdin)
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fclose(in);
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (out != stdout)
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fclose(out);
7663db80b5708eeae9194ff5dc44005efc8b2a726f1Jeff Sharkey    return res;
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
768