//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int ReadAt(IDebugMemoryContext2 pStartContext, uint dwCount, byte [] rgbMemory, out uint pdwRead, ref uint pdwUnreadable) { // // Reads a sequence of bytes, starting at a given location. // LoggingUtils.PrintFunction(); try { CONTEXT_INFO [] contextInfoArray = new CONTEXT_INFO [1]; LoggingUtils.RequireOk(pStartContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE, contextInfoArray)); string command = string.Format("-data-read-memory-bytes {0} {1}", contextInfoArray [0].bstrAddressAbsolute, dwCount); MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand(command); MiResultRecord.RequireOk(resultRecord, command); MiResultValueList memoryStreamList = (MiResultValueList)resultRecord ["memory"] [0]; for (int s = 0; s < memoryStreamList.Values.Count; ++s) { if (!memoryStreamList [s].HasField("contents")) { throw new InvalidOperationException("-data-read-memory-bytes result missing 'contents' field"); } string hexValue = memoryStreamList [s] ["contents"] [0].GetString(); if ((hexValue.Length / 2) != dwCount) { throw new InvalidOperationException(); } for (int i = 0; i < dwCount; ++i) { rgbMemory [i] = byte.Parse(hexValue.Substring(i * 2, 2), NumberStyles.HexNumber); } } pdwRead = dwCount; pdwUnreadable = 0; return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); pdwRead = 0; pdwUnreadable = dwCount; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public void RefreshThread(uint tid) { LoggingUtils.PrintFunction(); try { m_debugger.RunInterruptOperation(delegate(CLangDebugger debugger) { string command = string.Format("-thread-info {0}", (tid == 0) ? "" : tid.ToString()); MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand(command); MiResultRecord.RequireOk(resultRecord, command); if (!resultRecord.HasField("threads")) { throw new InvalidOperationException("-thread-info result missing 'threads' field"); } MiResultValueList threadsValueList = (MiResultValueList)resultRecord ["threads"] [0]; List <MiResultValue> threadsData = threadsValueList.List; bool refreshedProcesses = false; for (int i = threadsData.Count - 1; i >= 0; --i) // reported threads are in descending order. { uint id = threadsData [i] ["id"] [0].GetUnsignedInt(); CLangDebuggeeThread thread = GetThread(id) ?? AddThread(id); if (thread.RequiresRefresh) { MiResultValue threadData = threadsData [i]; if (!refreshedProcesses) { AndroidDevice hostDevice = DebugProgram.DebugProcess.NativeProcess.HostDevice; hostDevice.RefreshProcesses(DebugProgram.DebugProcess.NativeProcess.Pid); refreshedProcesses = true; } thread.Refresh(ref threadData); } } if (resultRecord.HasField("current-thread-id")) { CurrentThreadId = resultRecord ["current-thread-id"] [0].GetUnsignedInt(); } }); } catch (Exception e) { LoggingUtils.HandleException(e); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData [] prgDisassembly) { // // Reads instructions starting from the current position in the disassembly stream. // LoggingUtils.PrintFunction(); try { ulong startAddress = m_codeContext.Address.MemoryAddress; ulong endAddress = startAddress + ((ulong)(dwInstructions) * 4); // TODO: 4 for a 32-bit instruction set? string disassemblyCommand = string.Format("-data-disassemble -s 0x{0:X8} -e 0x{1:X8} -- 1", startAddress, endAddress); MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand(disassemblyCommand); MiResultRecord.RequireOk(resultRecord, disassemblyCommand); if (!resultRecord.HasField("asm_insns")) { throw new InvalidOperationException("-data-disassemble result missing 'asm_insns' field"); } MiResultValueList assemblyRecords = (MiResultValueList)resultRecord ["asm_insns"] [0]; long maxInstructions = Math.Min(assemblyRecords.Values.Count, dwInstructions); if (maxInstructions == 0) { throw new InvalidOperationException(); } int currentInstruction = 0; for (int i = 0; i < assemblyRecords.Values.Count; ++i) { MiResultValue recordValue = assemblyRecords [i]; if (recordValue.Variable.Equals("src_and_asm_line")) { // // Parse mixed-mode disassembly reports. // uint line = recordValue ["line"] [0].GetUnsignedInt(); string file = recordValue ["file"] [0].GetString(); MiResultValueList lineAsmInstructionValues = (MiResultValueList)recordValue ["line_asm_insn"] [0]; foreach (MiResultValue instructionValue in lineAsmInstructionValues.Values) { string address = instructionValue ["address"] [0].GetString(); if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0) { prgDisassembly [currentInstruction].bstrAddress = address; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET) != 0) { string offset = instructionValue ["offset"] [0].GetString(); prgDisassembly [currentInstruction].bstrAddressOffset = offset; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET; } if (((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) || ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS) != 0) || ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0)) { string inst = instructionValue ["inst"] [0].GetString(); string [] operations = inst.Split(new string [] { "\\t" }, StringSplitOptions.None); if (operations.Length > 0) { prgDisassembly [currentInstruction].bstrOpcode = operations [0]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE; } if (operations.Length > 1) { prgDisassembly [currentInstruction].bstrOperands = operations [1]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS; } if (operations.Length > 2) { prgDisassembly [currentInstruction].bstrOperands += " " + operations [2]; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS; } } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0) { string functionName = instructionValue ["func-name"] [0].GetString(); prgDisassembly [currentInstruction].bstrSymbol = functionName; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0) { DebuggeeAddress instructionAddress = new DebuggeeAddress(address); prgDisassembly [currentInstruction].uCodeLocationId = instructionAddress.MemoryAddress; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0) { prgDisassembly [currentInstruction].posBeg.dwLine = line; prgDisassembly [currentInstruction].posBeg.dwColumn = 0; prgDisassembly [currentInstruction].posEnd.dwLine = line; prgDisassembly [currentInstruction].posEnd.dwColumn = uint.MaxValue; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0) { prgDisassembly [currentInstruction].bstrDocumentUrl = "file://" + file; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0) { uint offset = instructionValue ["offset"] [0].GetUnsignedInt(); prgDisassembly [currentInstruction].dwByteOffset = offset; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET; } if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS) != 0) { prgDisassembly [currentInstruction].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_HASSOURCE; prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS; } if (++currentInstruction >= maxInstructions) { break; } } } } pdwInstructionsRead = (uint)currentInstruction; return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); pdwInstructionsRead = 0; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override List <DebuggeeStackFrame> StackTrace(uint depth) { // // Each thread maintains an internal cache of the last reported stack-trace. This is only cleared when threads are resumed via 'SetRunning(true)'. // LoggingUtils.PrintFunction(); try { if (m_threadStackFrames.Count < depth) { LoggingUtils.RequireOk(GetThreadId(out uint threadId)); m_debugProgram.AttachedEngine.NativeDebugger.RunInterruptOperation(delegate(CLangDebugger debugger) { // // Determine the maximum available stack depth. // string command; MiResultRecord resultRecord; if (depth == uint.MaxValue) { command = string.Format("-stack-info-depth --thread {0}", threadId); resultRecord = debugger.GdbClient.SendSyncCommand(command); MiResultRecord.RequireOk(resultRecord, command); depth = resultRecord ["depth"] [0].GetUnsignedInt(); } // // Acquire stack frame information for any levels which we're missing. // if (m_threadStackFrames.Count < depth) { command = string.Format("-stack-list-frames --thread {0} {1} {2}", threadId, m_threadStackFrames.Count, depth - 1); resultRecord = debugger.GdbClient.SendSyncCommand(command); MiResultRecord.RequireOk(resultRecord, command); if (resultRecord.HasField("stack")) { MiResultValueList stackRecord = resultRecord ["stack"] [0] as MiResultValueList; for (int i = 0; i < stackRecord.Values.Count; ++i) { MiResultValueTuple frameTuple = stackRecord [i] as MiResultValueTuple; uint stackLevel = frameTuple ["level"] [0].GetUnsignedInt(); string stackFrameId = m_threadName + "#" + stackLevel; CLangDebuggeeStackFrame stackFrame = new CLangDebuggeeStackFrame(debugger, this, frameTuple, stackFrameId); lock (m_threadStackFrames) { m_threadStackFrames.Add(stackFrame); } } } } }); } return(m_threadStackFrames); } catch (Exception e) { LoggingUtils.HandleException(e); throw; } }