private void parseMaps(ClientData cd, byte[] maps) { using (var reader = new StreamReader(new MemoryStream(maps))) { string line; try { // most libraries are defined on several lines, so we need to make sure we parse // all the library lines and only add the library at the end long startAddr = 0; long endAddr = 0; string library = null; while ((line = reader.ReadLine()) != null) { Log.d("ddms", "line: " + line); if (line.Length < 16) { continue; } try { long tmpStart = Convert.ToInt64(line.Substring(0, 8), 16); long tmpEnd = Convert.ToInt64(line.Substring(9, 8), 16); int index = line.IndexOf('/'); if (index == -1) { continue; } string tmpLib = line.Substring(index); if (library == null || (library != null && tmpLib.Equals(library) == false)) { if (library != null) { cd.addNativeLibraryMapInfo(startAddr, endAddr, library); Log.d("ddms", library + "(" + startAddr.toHexString() + " - " + endAddr.toHexString() + ")"); } // now init the new library library = tmpLib; startAddr = tmpStart; endAddr = tmpEnd; } else { // add the new end endAddr = tmpEnd; } } catch (SystemException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } if (library != null) { cd.addNativeLibraryMapInfo(startAddr, endAddr, library); Log.d("ddms", library + "(" + startAddr.toHexString() + " - " + endAddr.toHexString() + ")"); } } catch (IOException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } }
/* * Handle our native heap data. */ private void handleNHGT(Client client, ByteBuffer data) { ClientData cd = client.clientData; Log.d("ddm-nativeheap", "NHGT: " + data.limit + " bytes"); // TODO - process incoming data and save in "cd" var copy = new byte[data.limit]; data.get(copy); // clear the previous run cd.clearNativeAllocationInfo(); ByteBuffer buffer = ByteBuffer.wrap(copy); buffer.order = ByteOrder.LITTLE_ENDIAN; // read the header // typedef struct Header { // uint32_t mapSize; // uint32_t allocSize; // uint32_t allocInfoSize; // uint32_t totalMemory; // uint32_t backtraceSize; // }; int mapSize = buffer.getInt(); int allocSize = buffer.getInt(); int allocInfoSize = buffer.getInt(); int totalMemory = buffer.getInt(); int backtraceSize = buffer.getInt(); Log.d("ddms", "mapSize: " + mapSize); Log.d("ddms", "allocSize: " + allocSize); Log.d("ddms", "allocInfoSize: " + allocInfoSize); Log.d("ddms", "totalMemory: " + totalMemory); cd.totalNativeMemory = totalMemory; // this means that updates aren't turned on. if (allocInfoSize == 0) { return; } if (mapSize > 0) { var maps = new byte[mapSize]; buffer.get(maps, 0, mapSize); parseMaps(cd, maps); } int iterations = allocSize / allocInfoSize; for (int i = 0; i < iterations; i++) { NativeAllocationInfo info = new NativeAllocationInfo(buffer.getInt(), buffer.getInt()); // allocations - size for (int j = 0; j < backtraceSize; j++) { long addr = (buffer.getInt()) & 0x00000000ffffffffL; if (addr == 0x0) { // skip past null addresses continue; } info.addStackCallAddress(addr); } cd.addNativeAllocation(info); } }
/// <summary> /// Create an object for a new client connection. /// </summary> /// <param name="device"> the device this client belongs to </param> /// <param name="chan"> the connected <seealso cref="SocketChannel"/>. </param> /// <param name="pid"> the client pid. </param> internal Client(Device device, SocketChannel chan, int pid) { mDevice = device; mChan = chan; mReadBuffer = ByteBuffer.allocate(INITIAL_BUF_SIZE); mWriteBuffer = ByteBuffer.allocate(WRITE_BUF_SIZE); mOutstandingReqs = new Dictionary<int?, ChunkHandler>(); mConnState = ST_INIT; mClientData = new ClientData(pid); mThreadUpdateEnabled = DdmPreferences.initialThreadUpdate; mHeapUpdateEnabled = DdmPreferences.initialHeapUpdate; }