// TODO: Is anybody crazy enough to programmatically consume the disassembly // objects? If so, I could stick a flag on them saying if we ran into flow // analysis errors. //private bool m_flowAnalysisWarning; public WholeFunctionDisasmParser(IPipelineCallback pipeline, bool hasCodeBytes) { if (null == pipeline) { throw new ArgumentNullException("pipeline"); } m_pipeline = pipeline; m_hasCodeBytes = hasCodeBytes; m_state = WfdState.DontKnow; } // end constructor
} // 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()