• 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_GC);
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 = ((long)buffer.getInt()) & 0x00000000ffffffffL;
175 
176                 info.addStackCallAddress(addr);;
177             }
178 
179             cd.addNativeAllocation(info);
180         }
181     }
182 
handleNHSG(Client client, ByteBuffer data)183     private void handleNHSG(Client client, ByteBuffer data) {
184         byte dataCopy[] = new byte[data.limit()];
185         data.rewind();
186         data.get(dataCopy);
187         data = ByteBuffer.wrap(dataCopy);
188         client.getClientData().getNativeHeapData().addHeapData(data);
189 
190         if (true) {
191             return;
192         }
193 
194         // WORK IN PROGRESS
195 
196 //        Log.e("ddm-nativeheap", "NHSG: ----------------------------------");
197 //        Log.e("ddm-nativeheap", "NHSG: " + data.limit() + " bytes");
198 
199         byte[] copy = new byte[data.limit()];
200         data.get(copy);
201 
202         ByteBuffer buffer = ByteBuffer.wrap(copy);
203         buffer.order(ByteOrder.BIG_ENDIAN);
204 
205         int id = buffer.getInt();
206         int unitsize = (int) buffer.get();
207         long startAddress = (long) buffer.getInt() & 0x00000000ffffffffL;
208         int offset = buffer.getInt();
209         int allocationUnitCount = buffer.getInt();
210 
211 //        Log.e("ddm-nativeheap", "id: " + id);
212 //        Log.e("ddm-nativeheap", "unitsize: " + unitsize);
213 //        Log.e("ddm-nativeheap", "startAddress: 0x" + Long.toHexString(startAddress));
214 //        Log.e("ddm-nativeheap", "offset: " + offset);
215 //        Log.e("ddm-nativeheap", "allocationUnitCount: " + allocationUnitCount);
216 //        Log.e("ddm-nativeheap", "end: 0x" +
217 //                Long.toHexString(startAddress + unitsize * allocationUnitCount));
218 
219         // read the usage
220         while (buffer.position() < buffer.limit()) {
221             int eState = (int)buffer.get() & 0x000000ff;
222             int eLen = ((int)buffer.get() & 0x000000ff) + 1;
223             //Log.e("ddm-nativeheap", "solidity: " + (eState & 0x7) + " - kind: "
224             //        + ((eState >> 3) & 0x7) + " - len: " + eLen);
225         }
226 
227 
228 //        count += unitsize * allocationUnitCount;
229 //        Log.e("ddm-nativeheap", "count = " + count);
230 
231     }
232 
parseMaps(ClientData cd, byte[] maps)233     private void parseMaps(ClientData cd, byte[] maps) {
234         InputStreamReader input = new InputStreamReader(new ByteArrayInputStream(maps));
235         BufferedReader reader = new BufferedReader(input);
236 
237         String line;
238 
239         try {
240 
241             // most libraries are defined on several lines, so we need to make sure we parse
242             // all the library lines and only add the library at the end
243             long startAddr = 0;
244             long endAddr = 0;
245             String library = null;
246 
247             while ((line = reader.readLine()) != null) {
248                 Log.d("ddms", "line: " + line);
249                 if (line.length() < 16) {
250                     continue;
251                 }
252 
253                 try {
254                     long tmpStart = Long.parseLong(line.substring(0, 8), 16);
255                     long tmpEnd = Long.parseLong(line.substring(9, 17), 16);
256 
257                      /*
258                       * only check for library addresses as defined in
259                       * //device/config/prelink-linux-arm.map
260                       */
261                     if (tmpStart >= 0x0000000080000000L && tmpStart <= 0x00000000BFFFFFFFL) {
262 
263                         int index = line.indexOf('/');
264 
265                         if (index == -1)
266                             continue;
267 
268                         String tmpLib = line.substring(index);
269 
270                         if (library == null ||
271                                 (library != null && tmpLib.equals(library) == false)) {
272 
273                             if (library != null) {
274                                 cd.addNativeLibraryMapInfo(startAddr, endAddr, library);
275                                 Log.d("ddms", library + "(" + Long.toHexString(startAddr) +
276                                         " - " + Long.toHexString(endAddr) + ")");
277                             }
278 
279                             // now init the new library
280                             library = tmpLib;
281                             startAddr = tmpStart;
282                             endAddr = tmpEnd;
283                         } else {
284                             // add the new end
285                             endAddr = tmpEnd;
286                         }
287                     }
288                 } catch (NumberFormatException e) {
289                     e.printStackTrace();
290                 }
291             }
292 
293             if (library != null) {
294                 cd.addNativeLibraryMapInfo(startAddr, endAddr, library);
295                 Log.d("ddms", library + "(" + Long.toHexString(startAddr) +
296                         " - " + Long.toHexString(endAddr) + ")");
297             }
298         } catch (IOException e) {
299             e.printStackTrace();
300         }
301     }
302 
303 
304 }
305 
306