/* Copyright 2014 Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.google.security.zynamics.binnavi.Debug.Debugger; import com.google.security.zynamics.binnavi.Debug.Connection.MockDebugConnection; import com.google.security.zynamics.binnavi.debug.connection.packets.parsers.MessageParserException; import com.google.security.zynamics.binnavi.debug.connection.packets.parsers.TargetInformationParser; import com.google.security.zynamics.binnavi.debug.debugger.AbstractDebugger; import com.google.security.zynamics.binnavi.debug.debugger.DebugExceptionWrapper; import com.google.security.zynamics.binnavi.debug.debugger.DebugTargetSettings; import com.google.security.zynamics.binnavi.debug.models.breakpoints.BreakpointAddress; import com.google.security.zynamics.binnavi.debug.models.breakpoints.enums.BreakpointType; import com.google.security.zynamics.binnavi.disassembly.INaviModule; import com.google.security.zynamics.zylib.disassembly.IAddress; import java.math.BigInteger; import java.util.Set; public final class MockDebugger extends AbstractDebugger { private int counter = Integer.MAX_VALUE; public final MockDebugConnection connection; public String requests = ""; private DebugTargetSettings m_debugSettings; public MockDebugger(final byte[][] data) { connection = new MockDebugConnection(this, data); } public MockDebugger(final DebugTargetSettings debugSettings) { m_debugSettings = debugSettings; connection = new MockDebugConnection(this); } private void processCounter() throws DebugExceptionWrapper { --counter; if (counter == 0) { throw new DebugExceptionWrapper(new Exception("No")); } } @Override public void cancelTargetSelection() { throw new IllegalStateException("Not yet implemented"); } @Override public boolean canDebug(final INaviModule module) { return true; } @Override public void close() { super.setTerminated(); } @Override public void connect() throws DebugExceptionWrapper { super.connect(connection); requests += "CONNECT;"; } public void connectNoTarget() throws DebugExceptionWrapper { super.connect(connection); } @Override public void detach() throws DebugExceptionWrapper { super.detach(); requests += "DETACH;"; } public MockDebugConnection getConnection() { return connection; } @Override public DebugTargetSettings getDebugTargetSettings() { return m_debugSettings; } @Override public int getId() { return 23; } @Override public void getMemoryMap() throws DebugExceptionWrapper { processCounter(); requests += "MEMMAP;"; } public MockDebugConnection getMockConnection() { return connection; } @Override public String getPrintableString() { return "Mock"; } @Override public void halt() { } @Override public int readMemory(final IAddress address, final int size) throws DebugExceptionWrapper { super.readMemory(address, size); processCounter(); requests += "READMEM/" + address.toString() + "/" + size + ";"; return 0; } @Override public void readRegisters() throws DebugExceptionWrapper { super.readRegisters(); processCounter(); requests += "READREGS;"; } public void receiveTargetInformation() { try { final String targetInformation = new String("<info>" + "<options>" + "</options>" + "<registers>" + "<register name=\"EAX\" size=\"4\" editable=\"0\"/>" + "<register name=\"EBX\" size=\"4\" editable=\"0\"/>" + "<register name=\"ECX\" size=\"4\" editable=\"0\"/>" + "<register name=\"EDX\" size=\"4\" editable=\"0\"/>" + "<register name=\"ESI\" size=\"4\" editable=\"0\"/>" + "<register name=\"EDI\" size=\"4\" editable=\"0\"/>" + "<register name=\"ESP\" size=\"4\" editable=\"0\"/>" + "<register name=\"EBP\" size=\"4\" editable=\"0\"/>" + "<register name=\"EIP\" size=\"4\" editable=\"0\"/>" + "<register name=\"EFLAGS\" size=\"4\" editable=\"0\"/>" + "</registers>" + "<size>" + "</size>" + "</info>"); getProcessManager().setTargetInformation( TargetInformationParser.parse(targetInformation.getBytes())); } catch (final MessageParserException e) { e.printStackTrace(); } } @Override public void removeBreakpoints(final Set<BreakpointAddress> breakpoints, final BreakpointType type) throws DebugExceptionWrapper { requests += "REMOVE_BREAKPOINTS/"; for (final BreakpointAddress breakpointAddress : breakpoints) { requests += breakpointAddress.getAddress().getAddress().toHexString(); requests += "/"; requests += type; } requests += ";"; processCounter(); } @Override public int requestProcessList() { throw new IllegalStateException("Not yet implemented"); } @Override public void resume() throws DebugExceptionWrapper { super.resume(); requests += "RESUME;"; processCounter(); } @Override public int search(final IAddress start, final int size, final byte[] data) throws DebugExceptionWrapper { processCounter(); return 0; } @Override public void selectProcess(final int pid) { throw new IllegalStateException("Not yet implemented"); } @Override public void setBreakPoints(final Set<BreakpointAddress> breakpoints, final BreakpointType type) throws DebugExceptionWrapper { requests += "SET_BREAKPOINTS/"; for (final BreakpointAddress breakpointAddress : breakpoints) { requests += breakpointAddress.getAddress().getAddress().toHexString(); requests += "/"; requests += type; } requests += ";"; processCounter(); } public void setCounter(final int counter) { this.counter = counter; } @Override public int setRegister(final long tid, final int index, final BigInteger value) throws DebugExceptionWrapper { processCounter(); return 0; } @Override public void singleStep() throws DebugExceptionWrapper { super.singleStep(); requests += "STEP;"; processCounter(); } @Override public void terminate() throws DebugExceptionWrapper { super.terminate(); requests += "TERMINATE;"; processCounter(); } }