Example #1
0
		/*
		 * Handle a reply to our WAIT message.
		 */
		private static void handleWAIT(Client client, ByteBuffer data)
		{
		    var reason = data.get();

			Log.d("ddm-wait", "WAIT: reason=" + reason);


			ClientData cd = client.clientData;
			lock (cd)
			{
				cd.debuggerConnectionStatus = ClientData.DebuggerStatus.WAITING;
			}

			client.update(Client.CHANGE_DEBUGGER_STATUS);
		}
Example #2
0
		/*
		 * Handle HeaP Dump Streaming response.  "data" contains the full
		 * hprof dump.
		 */
		private void handleHPDS(Client client, ByteBuffer data)
		{
			ClientData.IHprofDumpHandler handler = ClientData.hprofDumpHandler;
			if (handler != null)
			{
				var stuff = new byte[data.capacity];
				data.get(stuff, 0, stuff.Length);

				Log.d("ddm-hprof", "got hprof file, size: " + data.capacity + " bytes");

				handler.onSuccess(stuff, client);
			}
		}
Example #3
0
		/*
		 * Handle notification of completion of a HeaP DUmp.
		 */
		private void handleHPDU(Client client, ByteBuffer data)
		{
		    // get the filename and make the client not have pending HPROF dump anymore.
			string filename = client.clientData.pendingHprofDump;
			client.clientData.pendingHprofDump = null;

			// get the dump result
			var result = data.get();

			// get the app-level handler for HPROF dump
			ClientData.IHprofDumpHandler handler = ClientData.hprofDumpHandler;
			if (handler != null)
			{
				if (result == 0)
				{
					handler.onSuccess(filename, client);

					Log.d("ddm-heap", "Heap dump request has finished");
				}
				else
				{
					handler.onEndFailure(client, null);
					Log.w("ddm-heap", "Heap dump request failed (check device log)");
				}
			}
		}
Example #4
0
		/*
		 * Handle a heap segment message.
		 */
		private void handleHPSG(Client client, ByteBuffer data)
		{
			var dataCopy = new byte[data.limit];
			data.rewind();
			data.get(dataCopy);
			data = ByteBuffer.wrap(dataCopy);
			client.clientData.vmHeapData.addHeapData(data);
	//xxx todo: add to the heap mentioned in <data>
		}
Example #5
0
		/*
		 * Handle a heap info message.
		 */
		private void handleHPIF(Client client, ByteBuffer data)
		{
			Log.d("ddm-heap", "HPIF!");
			try
			{
                int numHeaps = data.getInt();

				for (int i = 0; i < numHeaps; i++)
				{
                    int heapId = data.getInt();
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @SuppressWarnings("unused") long timeStamp = data.getLong();
                    long timeStamp = data.getLong();
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @SuppressWarnings("unused") byte reason = data.get();
					var reason = data.get();
					long maxHeapSize = (long)data.getInt() & 0x00ffffffff;
					long heapSize = (long)data.getInt() & 0x00ffffffff;
					long bytesAllocated = (long)data.getInt() & 0x00ffffffff;
                    long objectsAllocated = (long)data.getInt() & 0x00ffffffff;

					client.clientData.setHeapInfo(heapId, maxHeapSize, heapSize, bytesAllocated, objectsAllocated);
					client.update(Client.CHANGE_HEAP_DATA);
				}
			}
			catch (BufferUnderflowException)
			{
				Log.w("ddm-heap", "malformed HPIF chunk from client");
			}
		}
Example #6
0
		/*
		 * Handle a thread creation message.
		 */
		private void handleTEST(Client client, ByteBuffer data)
		{
			/*
			 * Can't call data.array() on a read-only ByteBuffer, so we make
			 * a copy.
			 */
			var copy = new byte[data.limit];
			data.get(copy);

			Log.d("ddm-test", "Received:");
			Log.hexDump("ddm-test", Log.LogLevel.DEBUG, copy, 0, copy.Length);
		}
Example #7
0
		/// <summary>
		/// Receive response to query.
		/// </summary>
		private void handleMPRQ(Client client, ByteBuffer data)
		{
		    var result = data.get();

			if (result == 0)
			{
				client.clientData.methodProfilingStatus = ClientData.MethodProfilingStatus.OFF;
				Log.d("ddm-prof", "Method profiling is not running");
			}
			else
			{
				client.clientData.methodProfilingStatus = ClientData.MethodProfilingStatus.ON;
				Log.d("ddm-prof", "Method profiling is running");
			}
			client.update(Client.CHANGE_METHOD_PROFILING_STATUS);
		}
Example #8
0
		/*
		 * 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);
			}
		}
Example #9
0
		/// <summary>
		/// Handle notification that method profiling has finished writing
		/// data to disk.
		/// </summary>
		private void handleMPRE(Client client, ByteBuffer data)
		{
		    // get the filename and make the client not have pending HPROF dump anymore.
			string filename = client.clientData.pendingMethodProfiling;
			client.clientData.pendingMethodProfiling = null;

			byte result = data.get();

			// get the app-level handler for method tracing dump
			ClientData.IMethodProfilingHandler handler = ClientData.methodProfilingHandler;
			if (handler != null)
			{
				if (result == 0)
				{
					handler.onSuccess(filename, client);

					Log.d("ddm-prof", "Method profiling has finished");
				}
				else
				{
					handler.onEndFailure(client, null); //message

					Log.w("ddm-prof", "Method profiling has failed (check device log)");
				}
			}

			client.clientData.methodProfilingStatus = ClientData.MethodProfilingStatus.OFF;
			client.update(Client.CHANGE_METHOD_PROFILING_STATUS);
		}
Example #10
0
		/// <summary>
		/// Handle incoming profiling data.  The MPSE packet includes the
		/// complete .trace file.
		/// </summary>
		private void handleMPSE(Client client, ByteBuffer data)
		{
			ClientData.IMethodProfilingHandler handler = ClientData.methodProfilingHandler;
			if (handler != null)
			{
				var stuff = new byte[data.capacity];
				data.get(stuff, 0, stuff.Length);

				Log.d("ddm-prof", "got trace file, size: " + stuff.Length + " bytes");

				handler.onSuccess(stuff, client);
			}

			client.clientData.methodProfilingStatus = ClientData.MethodProfilingStatus.OFF;
			client.update(Client.CHANGE_METHOD_PROFILING_STATUS);
		}
Example #11
0
        /// <summary>
        /// Find the JDWP packet at the start of "buf".  The start is known,
        /// but the length has to be parsed out.
        /// 
        /// On entry, the packet data in "buf" must start at offset 0 and end
        /// at "position".  "limit" should be set to the buffer capacity.  This
        /// method does not alter "buf"s attributes.
        /// 
        /// Returns a new JdwpPacket if a full one is found in the buffer.  If
        /// not, returns null.  Throws an exception if the data doesn't look like
        /// a valid JDWP packet.
        /// </summary>
        internal static JdwpPacket findPacket(ByteBuffer buf)
        {
            int count = buf.position;
            int length, id, flags, cmdSet, cmd;

            if (count < JDWP_HEADER_LEN)
            {
                return null;
            }

            ByteOrder oldOrder = buf.order;
            buf.order =(ChunkHandler.CHUNK_ORDER);

            length = buf.getInt(0x00);
            id = buf.getInt(0x04);
            flags = buf.get(0x08) & 0xff;
            cmdSet = buf.get(0x09) & 0xff;
            cmd = buf.get(0x0a) & 0xff;

            buf.order = oldOrder;

            if (length < JDWP_HEADER_LEN)
            {
                throw new BadPacketException();
            }
            if (count < length)
            {
                return null;
            }

            JdwpPacket pkt = new JdwpPacket(buf);
            //pkt.mBuffer = buf;
            pkt.mLength = length;
            pkt.mId = id;
            pkt.mFlags = flags;

            if ((flags & REPLY_PACKET) == 0)
            {
                pkt.mCmdSet = cmdSet;
                pkt.mCmd = cmd;
                pkt.mErrCode = -1;
            }
            else
            {
                pkt.mCmdSet = -1;
                pkt.mCmd = -1;
                pkt.mErrCode = cmdSet | (cmd << 8);
            }

            return pkt;
        }
Example #12
0
        /// <summary>
        /// Like findPacket(), but when we're expecting the JDWP handshake.
        /// 
        /// Returns one of:
        ///   HANDSHAKE_GOOD   - found handshake, looks good
        ///   HANDSHAKE_BAD    - found enough data, but it's wrong
        ///   HANDSHAKE_NOTYET - not enough data has been read yet
        /// </summary>
        internal static int findHandshake(ByteBuffer buf)
        {
            int count = buf.position;
            int i;

            if (count < mHandshake.Length)
            {
                return HANDSHAKE_NOTYET;
            }

            for (i = mHandshake.Length - 1; i >= 0; --i)
            {
                if (buf.get(i) != mHandshake[i])
                {
                    return HANDSHAKE_BAD;
                }
            }

            return HANDSHAKE_GOOD;
        }
Example #13
0
		private void handleNHSG(Client client, ByteBuffer data)
		{
			var dataCopy = new byte[data.limit];
			data.rewind();
			data.get(dataCopy);
			data = ByteBuffer.wrap(dataCopy);
			client.clientData.nativeHeapData.addHeapData(data);

			if (true)
			{
				return;
			}

			/* WORK IN PROGRESS

	//        Log.e("ddm-nativeheap", "NHSG: ----------------------------------");
	//        Log.e("ddm-nativeheap", "NHSG: " + data.limit() + " bytes");

			var copy = new byte[data.limit];
			data.get(copy);

			ByteBuffer buffer = ByteBuffer.wrap(copy);
			buffer.order = ByteOrder.BIG_ENDIAN;

			int id = buffer.getInt();
			int unitsize = buffer.get();
            long startAddress = buffer.getInt() & 0x00000000ffffffffL;
            int offset = buffer.getInt();
            int allocationUnitCount = buffer.getInt();

	//        Log.e("ddm-nativeheap", "id: " + id);
	//        Log.e("ddm-nativeheap", "unitsize: " + unitsize);
	//        Log.e("ddm-nativeheap", "startAddress: 0x" + Long.toHexString(startAddress));
	//        Log.e("ddm-nativeheap", "offset: " + offset);
	//        Log.e("ddm-nativeheap", "allocationUnitCount: " + allocationUnitCount);
	//        Log.e("ddm-nativeheap", "end: 0x" +
	//                Long.toHexString(startAddress + unitsize * allocationUnitCount));

			// read the usage
			while (buffer.position < buffer.limit)
			{
				int eState = buffer.get() & 0x000000ff;
				int eLen = (buffer.get() & 0x000000ff) + 1;
				//Log.e("ddm-nativeheap", "solidity: " + (eState & 0x7) + " - kind: "
				//        + ((eState >> 3) & 0x7) + " - len: " + eLen);
			}


	//        count += unitsize * allocationUnitCount;
	//        Log.e("ddm-nativeheap", "count = " + count);
             
            */

		}
Example #14
0
		/*
		 * Handle the response from our REcent Allocation Query message.
		 */
		private void handleREAQ(Client client, ByteBuffer data)
		{
			bool enabled;

			enabled = (data.get() != 0);
			Log.d("ddm-heap", "REAQ says: enabled=" + enabled);

			client.clientData.allocationStatus = enabled ? ClientData.AllocationTrackingStatus.ON : ClientData.AllocationTrackingStatus.OFF;
			client.update(Client.CHANGE_HEAP_ALLOCATION_STATUS);
		}
Example #15
0
		private void handleFAIL(Client client, ByteBuffer data)
		{
			/*int errorCode =*/	 data.getInt();
            int length = data.getInt() * 2;
			string message = null;
			if (length > 0)
			{
				var messageBuffer = new byte[length];
				data.get(messageBuffer, 0, length);
				message = Encoding.Default.GetString(messageBuffer);
			}

			// this can be sent if
			// - MPRS failed (like wrong permission)
			// - MPSE failed for whatever reason

			string filename = client.clientData.pendingMethodProfiling;
			if (filename != null)
			{
				// reset the pending file.
				client.clientData.pendingMethodProfiling = null;

				// and notify of failure
				ClientData.IMethodProfilingHandler handler = ClientData.methodProfilingHandler;
				if (handler != null)
				{
					handler.onStartFailure(client, message);
				}
			}
			else
			{
				// this is MPRE
				// notify of failure
				ClientData.IMethodProfilingHandler handler = ClientData.methodProfilingHandler;
				if (handler != null)
				{
					handler.onEndFailure(client, message);
				}
			}

			// send a query to know the current status
			try
			{
				sendMPRQ(client);
			}
			catch (IOException e)
			{
				Log.e("HandleProfiling", e);
			}
		}
Example #16
0
		/*
		 * Handle a REcent ALlocation response.
		 *
		 * Message header (all values big-endian):
		 *   (1b) message header len (to allow future expansion); includes itself
		 *   (1b) entry header len
		 *   (1b) stack frame len
		 *   (2b) number of entries
		 *   (4b) offset to string table from start of message
		 *   (2b) number of class name strings
		 *   (2b) number of method name strings
		 *   (2b) number of source file name strings
		 *   For each entry:
		 *     (4b) total allocation size
		 *     (2b) threadId
		 *     (2b) allocated object's class name index
		 *     (1b) stack depth
		 *     For each stack frame:
		 *       (2b) method's class name
		 *       (2b) method name
		 *       (2b) method source file
		 *       (2b) line number, clipped to 32767; -2 if native; -1 if no source
		 *   (xb) class name strings
		 *   (xb) method name strings
		 *   (xb) source file strings
		 *
		 *   As with other DDM traffic, strings are sent as a 4-byte length
		 *   followed by UTF-16 data.
		 */
		private void handleREAL(Client client, ByteBuffer data)
		{
			Log.e("ddm-heap", "*** Received " + name(CHUNK_REAL));
			int messageHdrLen, entryHdrLen, stackFrameLen;
			int numEntries, offsetToStrings;
			int numClassNames, numMethodNames, numFileNames;

			/*
			 * Read the header.
			 */
			messageHdrLen = (data.get() & 0xff);
			entryHdrLen = (data.get() & 0xff);
			stackFrameLen = (data.get() & 0xff);
			numEntries = (data.getShort() & 0xffff);
            offsetToStrings = data.getInt();
			numClassNames = (data.getShort() & 0xffff);
			numMethodNames = (data.getShort()& 0xffff);
			numFileNames = (data.getShort()& 0xffff);


			/*
			 * Skip forward to the strings and read them.
			 */
			data.position = offsetToStrings;

			string[] classNames = new string[numClassNames];
			string[] methodNames = new string[numMethodNames];
			string[] fileNames = new string[numFileNames];

			readStringTable(data, classNames);
			readStringTable(data, methodNames);
			//System.out.println("METHODS: "
			//    + java.util.Arrays.deepToString(methodNames));
			readStringTable(data, fileNames);

			/*
			 * Skip back to a point just past the header and start reading
			 * entries.
			 */
			data.position = messageHdrLen;

			List<AllocationInfo> list = new List<AllocationInfo>(numEntries);
			int allocNumber = numEntries; // order value for the entry. This is sent in reverse order.
			for (int i = 0; i < numEntries; i++)
			{
				int totalSize;
				int threadId, classNameIndex, stackDepth;

                totalSize = data.getInt();
				threadId = (data.getShort() & 0xffff);
				classNameIndex = (data.getShort() & 0xffff);
				stackDepth = (data.get() & 0xff);
				/* we've consumed 9 bytes; gobble up any extra */
				for (int skip = 9; skip < entryHdrLen; skip++)
				{
					data.get();
				}

				StackTraceElement[] steArray = new StackTraceElement[stackDepth];

				/*
				 * Pull out the stack trace.
				 */
				for (int sti = 0; sti < stackDepth; sti++)
				{
					int methodClassNameIndex, methodNameIndex;
					int methodSourceFileIndex;
					short lineNumber;
					string methodClassName, methodName, methodSourceFile;

					methodClassNameIndex = (data.getShort() & 0xffff);
					methodNameIndex = (data.getShort()& 0xffff);
					methodSourceFileIndex = (data.getShort()& 0xffff);
					lineNumber = data.getShort();

					methodClassName = classNames[methodClassNameIndex];
					methodName = methodNames[methodNameIndex];
					methodSourceFile = fileNames[methodSourceFileIndex];

					steArray[sti] = new StackTraceElement(methodClassName, methodName, methodSourceFile, lineNumber);

					/* we've consumed 8 bytes; gobble up any extra */
					for (int skip = 9; skip < stackFrameLen; skip++)
					{
						data.get();
					}
				}

				list.Add(new AllocationInfo(allocNumber--, classNames[classNameIndex], totalSize, (short) threadId, steArray));
			}

			client.clientData.allocations = list.ToArray();
			client.update(Client.CHANGE_HEAP_ALLOCATIONS);
		}
Example #17
0
		/*
		 * Handle a thread status update message.
		 *
		 * Response has:
		 *  (1b) header len
		 *  (1b) bytes per entry
		 *  (2b) thread count
		 * Then, for each thread:
		 *  (4b) threadId (matches value from THCR)
		 *  (1b) thread status
		 *  (4b) tid
		 *  (4b) utime
		 *  (4b) stime
		 */
		private void handleTHST(Client client, ByteBuffer data)
		{
			int headerLen, bytesPerEntry, extraPerEntry;
			int threadCount;

			headerLen = (data.get() & 0xff);
			bytesPerEntry = (data.get() & 0xff);
            threadCount = data.getShort();

			headerLen -= 4; // we've read 4 bytes
			while (headerLen-- > 0)
			{
				data.get();
			}

			extraPerEntry = bytesPerEntry - 18; // we want 18 bytes

			Log.v("ddm-thread", "THST: threadCount=" + threadCount);

			/*
			 * For each thread, extract the data, find the appropriate
			 * client, and add it to the ClientData.
			 */
			for (int i = 0; i < threadCount; i++)
			{
				int threadId, status, tid, utime, stime;
				bool isDaemon = false;

                threadId = data.getInt();
				status = data.get();
                tid = data.getInt();
                utime = data.getInt();
                stime = data.getInt();
				if (bytesPerEntry >= 18)
				{
					isDaemon = (data.get() != 0);
				}

				Log.v("ddm-thread", "  id=" + threadId + ", status=" + status + ", tid=" + tid + ", utime=" + utime + ", stime=" + stime);

				ClientData cd = client.clientData;
				ThreadInfo threadInfo = cd.getThread(threadId);
				if (threadInfo != null)
				{
					threadInfo.updateThread(status, tid, utime, stime, isDaemon);
				}
				else
				{
					Log.d("ddms", "Thread with id=" + threadId + " not found");
				}

				// slurp up any extra
				for (int slurp = extraPerEntry; slurp > 0; slurp--)
				{
					data.get();
				}
			}

			client.update(Client.CHANGE_THREAD_DATA);
		}