• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ddmlib;
18 
19 import java.io.BufferedReader;
20 import java.io.ByteArrayInputStream;
21 import java.io.IOException;
22 import java.io.InputStreamReader;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 
26 /**
27  * Handle thread status updates.
28  */
29 final class HandleNativeHeap extends ChunkHandler {
30 
31     public static final int CHUNK_NHGT = type("NHGT"); //$NON-NLS-1$
32     public static final int CHUNK_NHSG = type("NHSG"); //$NON-NLS-1$
33     public static final int CHUNK_NHST = type("NHST"); //$NON-NLS-1$
34     public static final int CHUNK_NHEN = type("NHEN"); //$NON-NLS-1$
35 
36     private static final HandleNativeHeap mInst = new HandleNativeHeap();
37 
HandleNativeHeap()38     private HandleNativeHeap() {
39     }
40 
41 
42     /**
43      * Register for the packets we expect to get from the client.
44      */
register(MonitorThread mt)45     public static void register(MonitorThread mt) {
46         mt.registerChunkHandler(CHUNK_NHGT, mInst);
47         mt.registerChunkHandler(CHUNK_NHSG, mInst);
48         mt.registerChunkHandler(CHUNK_NHST, mInst);
49         mt.registerChunkHandler(CHUNK_NHEN, mInst);
50     }
51 
52     /**
53      * Client is ready.
54      */
55     @Override
clientReady(Client client)56     public void clientReady(Client client) throws IOException {}
57 
58     /**
59      * Client went away.
60      */
61     @Override
clientDisconnected(Client client)62     public void clientDisconnected(Client client) {}
63 
64     /**
65      * Chunk handler entry point.
66      */
67     @Override
handleChunk(Client client, int type, ByteBuffer data, boolean isReply, int msgId)68     public void handleChunk(Client client, int type, ByteBuffer data, boolean isReply, int msgId) {
69 
70         Log.d("ddm-nativeheap", "handling " + ChunkHandler.name(type));
71 
72         if (type == CHUNK_NHGT) {
73             handleNHGT(client, data);
74         } else if (type == CHUNK_NHST) {
75             // start chunk before any NHSG chunk(s)
76             client.getClientData().getNativeHeapData().clearHeapData();
77         } else if (type == CHUNK_NHEN) {
78             // end chunk after NHSG chunk(s)
79             client.getClientData().getNativeHeapData().sealHeapData();
80         } else if (type == CHUNK_NHSG) {
81             handleNHSG(client, data);
82         } else {
83             handleUnknownChunk(client, type, data, isReply, msgId);
84         }
85 
86         client.update(Client.CHANGE_NATIVE_HEAP_DATA);
87     }
88 
89     /**
90      * Send an NHGT (Native Thread GeT) request to the client.
91      */
sendNHGT(Client client)92     public static void sendNHGT(Client client) throws IOException {
93 
94         ByteBuffer rawBuf = allocBuffer(0);
95         JdwpPacket packet = new JdwpPacket(rawBuf);
96         ByteBuffer buf = getChunkDataBuf(rawBuf);
97 
98         // no data in request message
99 
100         finishChunkPacket(packet, CHUNK_NHGT, buf.position());
101         Log.d("ddm-nativeheap", "Sending " + name(CHUNK_NHGT));
102         client.sendAndConsume(packet, mInst);
103 
104         rawBuf = allocBuffer(2);
105         packet = new JdwpPacket(rawBuf);
106         buf = getChunkDataBuf(rawBuf);
107 
108         buf.put((byte)HandleHeap.WHEN_DISABLE);
109         buf.put((byte)HandleHeap.WHAT_OBJ);
110 
111         finishChunkPacket(packet, CHUNK_NHSG, buf.position());
112         Log.d("ddm-nativeheap", "Sending " + name(CHUNK_NHSG));
113         client.sendAndConsume(packet, mInst);
114     }
115 
116     /*
117      * Handle our native heap data.
118      */
handleNHGT(Client client, ByteBuffer data)119     private void handleNHGT(Client client, ByteBuffer data) {
120         ClientData cd = client.getClientData();
121 
122         Log.d("ddm-nativeheap", "NHGT: " + data.limit() + " bytes");
123 
124         // TODO - process incoming data and save in "cd"
125         byte[] copy = new byte[data.limit()];
126         data.get(copy);
127 
128         // clear the previous run
129         cd.clearNativeAllocationInfo();
130 
131         ByteBuffer buffer = ByteBuffer.wrap(copy);
132         buffer.order(ByteOrder.LITTLE_ENDIAN);
133 
134 //        read the header
135 //        typedef struct Header {
136 //            uint32_t mapSize;
137 //            uint32_t allocSize;
138 //            uint32_t allocInfoSize;
139 //            uint32_t totalMemory;
140 //              uint32_t backtraceSize;
141 //        };
142 
143         int mapSize = buffer.getInt();
144         int allocSize = buffer.getInt();
145         int allocInfoSize = buffer.getInt();
146         int totalMemory = buffer.getInt();
147         int backtraceSize = buffer.getInt();
148 
149         Log.d("ddms", "mapSize: " + mapSize);
150         Log.d("ddms", "allocSize: " + allocSize);
151         Log.d("ddms", "allocInfoSize: " + allocInfoSize);
152         Log.d("ddms", "totalMemory: " + totalMemory);
153 
154         cd.setTotalNativeMemory(totalMemory);
155 
156         // this means that updates aren't turned on.
157         if (allocInfoSize == 0)
158           return;
159 
160         if (mapSize > 0) {
161             byte[] maps = new byte[mapSize];
162             buffer.get(maps, 0, mapSize);
163             parseMaps(cd, maps);
164         }
165 
166         int iterations = allocSize / allocInfoSize;
167 
168         for (int i = 0 ; i < iterations ; i++) {
169             NativeAllocationInfo info = new NativeAllocationInfo(
170                     buffer.getInt() /* size */,
171                     buffer.getInt() /* allocations */);
172 
173             for (int j = 0 ; j < backtraceSize ; j++) {
174                 long addr = (buffer.getInt()) & 0x00000000ffffffffL;
175 
176                 if (addr == 0x0) {
177                     // skip past null addresses
178                     continue;
179                 }
180 
181                 info.addStackCallAddress(addr);;
182             }
183 
184             cd.addNativeAllocation(info);
185         }
186     }
187 
handleNHSG(Client client, ByteBuffer data)188     private void handleNHSG(Client client, ByteBuffer data) {
189         byte dataCopy[] = new byte[data.limit()];
190         data.rewind();
191         data.get(dataCopy);
192         data = ByteBuffer.wrap(dataCopy);
193         client.getClientData().getNativeHeapData().addHeapData(data);
194 
195         if (true) {
196             return;
197         }
198 
199         // WORK IN PROGRESS
200 
201 //        Log.e("ddm-nativeheap", "NHSG: ----------------------------------");
202 //        Log.e("ddm-nativeheap", "NHSG: " + data.limit() + " bytes");
203 
204         byte[] copy = new byte[data.limit()];
205         data.get(copy);
206 
207         ByteBuffer buffer = ByteBuffer.wrap(copy);
208         buffer.order(ByteOrder.BIG_ENDIAN);
209 
210         int id = buffer.getInt();
211         int unitsize = buffer.get();
212         long startAddress = buffer.getInt() & 0x00000000ffffffffL;
213         int offset = buffer.getInt();
214         int allocationUnitCount = buffer.getInt();
215 
216 //        Log.e("ddm-nativeheap", "id: " + id);
217 //        Log.e("ddm-nativeheap", "unitsize: " + unitsize);
218 //        Log.e("ddm-nativeheap", "startAddress: 0x" + Long.toHexString(startAddress));
219 //        Log.e("ddm-nativeheap", "offset: " + offset);
220 //        Log.e("ddm-nativeheap", "allocationUnitCount: " + allocationUnitCount);
221 //        Log.e("ddm-nativeheap", "end: 0x" +
222 //                Long.toHexString(startAddress + unitsize * allocationUnitCount));
223 
224         // read the usage
225         while (buffer.position() < buffer.limit()) {
226             int eState = buffer.get() & 0x000000ff;
227             int eLen = (buffer.get() & 0x000000ff) + 1;
228             //Log.e("ddm-nativeheap", "solidity: " + (eState & 0x7) + " - kind: "
229             //        + ((eState >> 3) & 0x7) + " - len: " + eLen);
230         }
231 
232 
233 //        count += unitsize * allocationUnitCount;
234 //        Log.e("ddm-nativeheap", "count = " + count);
235 
236     }
237 
parseMaps(ClientData cd, byte[] maps)238     private void parseMaps(ClientData cd, byte[] maps) {
239         InputStreamReader input = new InputStreamReader(new ByteArrayInputStream(maps));
240         BufferedReader reader = new BufferedReader(input);
241 
242         String line;
243 
244         try {
245 
246             // most libraries are defined on several lines, so we need to make sure we parse
247             // all the library lines and only add the library at the end
248             long startAddr = 0;
249             long endAddr = 0;
250             String library = null;
251 
252             while ((line = reader.readLine()) != null) {
253                 Log.d("ddms", "line: " + line);
254                 if (line.length() < 16) {
255                     continue;
256                 }
257 
258                 try {
259                     long tmpStart = Long.parseLong(line.substring(0, 8), 16);
260                     long tmpEnd = Long.parseLong(line.substring(9, 17), 16);
261 
262                     int index = line.indexOf('/');
263 
264                     if (index == -1)
265                         continue;
266 
267                     String tmpLib = line.substring(index);
268 
269                     if (library == null ||
270                             (library != null && tmpLib.equals(library) == false)) {
271 
272                         if (library != null) {
273                             cd.addNativeLibraryMapInfo(startAddr, endAddr, library);
274                             Log.d("ddms", library + "(" + Long.toHexString(startAddr) +
275                                     " - " + Long.toHexString(endAddr) + ")");
276                         }
277 
278                         // now init the new library
279                         library = tmpLib;
280                         startAddr = tmpStart;
281                         endAddr = tmpEnd;
282                     } else {
283                         // add the new end
284                         endAddr = tmpEnd;
285                     }
286                 } catch (NumberFormatException e) {
287                     e.printStackTrace();
288                 }
289             }
290 
291             if (library != null) {
292                 cd.addNativeLibraryMapInfo(startAddr, endAddr, library);
293                 Log.d("ddms", library + "(" + Long.toHexString(startAddr) +
294                         " - " + Long.toHexString(endAddr) + ")");
295             }
296         } catch (IOException e) {
297             e.printStackTrace();
298         }
299     }
300 
301 
302 }
303 
304