} // end ProcessRecord() private void _UnassembleInstructions(ulong addr, Func <ulong, bool> keepGoing) { ColorString csBlockId; try { ulong disp; var addrName = Debugger.GetNameByOffset(addr, out disp); csBlockId = DbgProvider.ColorizeSymbol(addrName); if (0 != disp) { csBlockId.Append(Util.Sprintf("+{0:x}", disp)); } } catch (DbgEngException) { // Ignore. We'll just use the address as the block id. If we really can't // get the memory there, we'll fail with a good error message later. csBlockId = new ColorString().Append(DbgProvider.FormatAddress(addr, Debugger.TargetIs32Bit, true)); } csBlockId.Append(":").MakeReadOnly(); bool hasCodeBytes = !Debugger.AssemblyOptions.HasFlag(DbgAssemblyOptions.NoCodeBytes); while (keepGoing(addr)) { ulong tmpAddr = addr; string disasm = Debugger.Disassemble(tmpAddr, out addr).Trim(); WriteObject(_ParseDisassembly(tmpAddr, disasm, csBlockId, hasCodeBytes)); } DbgProvider.SetAutoRepeatCommand(Util.Sprintf("{0} -Address 0x{1} -InstructionCount {2}", MyInvocation.InvocationName, addr.ToString("x"), InstructionCount)); NextAddrToDisassemble = addr; } // end _UnassembleInstructions()
} // end constructor public void AddLine(string s) { switch (m_state) { case WfdState.ExpectingBlockId: if ((s.Length > 0) && (s[s.Length - 1] != ':')) { // It's not a block ID... this can happen when "Flow // analysis was incomplete". m_currentBlockId = new ColorString(ConsoleColor.DarkGray, "<unknown>").MakeReadOnly(); m_pipeline.WriteObject(_ParseDisassembly(0, // will get parsed out of s s, m_currentBlockId, m_hasCodeBytes)); } else { m_currentBlockId = DbgProvider.ColorizeSymbol(s).MakeReadOnly(); } m_state = WfdState.ExpectingInstructionOrBlankLine; break; case WfdState.ExpectingInstructionOrBlankLine: if (String.IsNullOrEmpty(s)) { m_state = WfdState.ExpectingBlockId; m_currentBlockId = null; } else { m_pipeline.WriteObject(_ParseDisassembly(0, // will get parsed out of s s, m_currentBlockId, m_hasCodeBytes)); } break; // This is a horrible state. But sometimes we see it, like // sometimes after a flow analysis error. case WfdState.DontKnow: if (s.StartsWith("Flow analysis", StringComparison.OrdinalIgnoreCase)) { //m_flowAnalysisWarning = true; m_pipeline.WriteWarning(s); m_state = WfdState.DontKnow; break; } else if (s.StartsWith("*** WARNING: ", StringComparison.OrdinalIgnoreCase)) { m_pipeline.WriteWarning(s.Substring(13)); // trim off what will become redundant "WARNING" label. m_state = WfdState.DontKnow; break; } else if (s.StartsWith("*** ERROR: ", StringComparison.OrdinalIgnoreCase)) { s = s.Substring(11); // trim off what will become redundant "ERROR" label. var dpe = new DbgProviderException(s, "ErrorDuringUnassemble", ErrorCategory.ReadError); try { throw dpe; } catch (Exception) { } // give it a stack. m_pipeline.WriteError(dpe); m_state = WfdState.DontKnow; break; } else if (s.StartsWith("No code found, aborting", StringComparison.OrdinalIgnoreCase)) { var dpe = new DbgProviderException(s, "NoCodeFound", ErrorCategory.ReadError); try { throw dpe; } catch (Exception) { } // give it a stack. m_pipeline.WriteError(dpe); m_state = WfdState.DontKnow; // actually, we should be done now. break; } else if ((s.Length > 0) && (s[s.Length - 1] == ':')) { // Looks like a block ID... m_state = WfdState.ExpectingBlockId; AddLine(s); } else if (String.IsNullOrEmpty(s)) { m_state = WfdState.ExpectingBlockId; m_currentBlockId = null; } else { m_state = WfdState.ExpectingInstructionOrBlankLine; AddLine(s); } break; default: Util.Fail("Invalid parse state."); throw new Exception("Invalid parse state."); } } // end AddLine()