private boolean isNativeCodeSequence( NativeCodeSequence nativeCodeSequence, CodeInstruction codeInstruction, CodeBlock codeBlock) { int address = codeInstruction.getAddress(); int numOpcodes = nativeCodeSequence.getNumOpcodes(); // Can this NativeCodeSequence only match a whole CodeBlock? if (nativeCodeSequence.isWholeCodeBlock()) { // Match only a whole CodeBlock: same StartAddress, same Length if (codeBlock.getStartAddress() != address) { return false; } if (codeBlock.getLength() != numOpcodes) { return false; } } IMemoryReader codeBlockReader = MemoryReader.getMemoryReader(address, 4); for (int i = 0; i < numOpcodes; i++) { int opcode = codeBlockReader.readNext(); if (!nativeCodeSequence.isMatching(i, opcode)) { return false; } } return true; }
private void addNativeCodeSequence(NativeCodeSequence nativeCodeSequence) { if (nativeCodeSequence.getNumOpcodes() > 0) { int firstOpcodeMask = nativeCodeSequence.getFirstOpcodeMask(); if (firstOpcodeMask == defaultOpcodeMask) { // First opcode has not mask: fast lookup allowed int firstOpcode = nativeCodeSequence.getFirstOpcode(); if (!nativeCodeSequencesByFirstOpcode.containsKey(firstOpcode)) { nativeCodeSequencesByFirstOpcode.put(firstOpcode, new LinkedList<NativeCodeSequence>()); } nativeCodeSequencesByFirstOpcode.get(firstOpcode).add(nativeCodeSequence); } else { // First opcode has not mask: only slow lookup possible nativeCodeSequenceWithMaskInFirstOpcode.add(nativeCodeSequence); } } }
private void loadNativeCodeOpcodes( NativeCodeSequence nativeCodeSequence, String codeInstructions) { BufferedReader reader = new BufferedReader(new StringReader(codeInstructions)); if (reader == null) { return; } Pattern codeInstructionPattern = Pattern.compile("\\s*((\\w+)\\s*:?\\s*)?\\[(\\p{XDigit}+)(/(\\p{XDigit}+))?\\].*"); final int labelGroup = 2; final int opcodeGroup = 3; final int opcodeMaskGroup = 5; try { while (true) { String line = reader.readLine(); if (line == null) { break; } line = line.trim(); if (line.length() > 0) { try { Matcher codeInstructionMatcher = codeInstructionPattern.matcher(line); int opcode = 0; int mask = defaultOpcodeMask; String label = null; if (codeInstructionMatcher.matches()) { opcode = Utilities.parseAddress(codeInstructionMatcher.group(opcodeGroup)); String opcodeMaskString = codeInstructionMatcher.group(opcodeMaskGroup); if (opcodeMaskString != null) { mask = Utilities.parseAddress(opcodeMaskString); } label = codeInstructionMatcher.group(labelGroup); } else { opcode = Utilities.parseAddress(line.trim()); } nativeCodeSequence.addOpcode(opcode, mask, label); } catch (NumberFormatException e) { Compiler.log.error(e); } } } } catch (IOException e) { Compiler.log.error(e); } }
private void loadBeforeCodeInstructions( NativeCodeSequence nativeCodeSequence, String codeInstructions) { BufferedReader reader = new BufferedReader(new StringReader(codeInstructions)); if (reader == null) { return; } Pattern codeInstructionPattern = Pattern.compile("\\s*(\\w+\\s*:?\\s*)?\\[(\\p{XDigit}+)\\].*"); final int opcodeGroup = 2; final int address = 0; try { while (true) { String line = reader.readLine(); if (line == null) { break; } line = line.trim(); if (line.length() > 0) { try { Matcher codeInstructionMatcher = codeInstructionPattern.matcher(line); int opcode = 0; if (codeInstructionMatcher.matches()) { opcode = Utilities.parseAddress(codeInstructionMatcher.group(opcodeGroup)); } else { opcode = Utilities.parseAddress(line.trim()); } Common.Instruction insn = Decoder.instruction(opcode); CodeInstruction codeInstruction = new CodeInstruction(address, opcode, insn, false, false, 0); nativeCodeSequence.addBeforeCodeInstruction(codeInstruction); } catch (NumberFormatException e) { Compiler.log.error(e); } } } } catch (IOException e) { Compiler.log.error(e); } }
private void setParameter( NativeCodeSequence nativeCodeSequence, int parameter, String valueString) { if (valueString == null || valueString.length() <= 0) { nativeCodeSequence.setParameter(parameter, 0, false); return; } for (int i = 0; i < Common.gprNames.length; i++) { if (Common.gprNames[i].equals(valueString)) { nativeCodeSequence.setParameter(parameter, i, false); return; } } for (int i = 0; i < Common.fprNames.length; i++) { if (Common.fprNames[i].equals(valueString)) { nativeCodeSequence.setParameter(parameter, i, false); return; } } if (valueString.startsWith("@")) { String label = valueString.substring(1); int labelIndex = nativeCodeSequence.getLabelIndex(label); if (labelIndex >= 0) { nativeCodeSequence.setParameter(parameter, labelIndex, true); return; } } try { int value; if (valueString.startsWith("0x")) { value = Integer.parseInt(valueString.substring(2), 16); } else { value = Integer.parseInt(valueString); } nativeCodeSequence.setParameter(parameter, value, false); } catch (NumberFormatException e) { Compiler.log.error(e); } }
private void loadNativeCodeSequence(Element element) { String name = element.getAttribute("name"); String className = getContent(element.getElementsByTagName("Class")); Class<INativeCodeSequence> nativeCodeSequenceClass = getNativeCodeSequenceClass(className); if (nativeCodeSequenceClass == null) { return; } NativeCodeSequence nativeCodeSequence = new NativeCodeSequence(name, nativeCodeSequenceClass); String isReturningString = getContent(element.getElementsByTagName("IsReturning")); if (isReturningString != null) { nativeCodeSequence.setReturning(Boolean.parseBoolean(isReturningString)); } String wholeCodeBlockString = getContent(element.getElementsByTagName("WholeCodeBlock")); if (wholeCodeBlockString != null) { nativeCodeSequence.setWholeCodeBlock(Boolean.parseBoolean(wholeCodeBlockString)); } String methodName = getContent(element.getElementsByTagName("Method")); if (methodName != null) { nativeCodeSequence.setMethodName(methodName); } String isHookString = getContent(element.getElementsByTagName("IsHook")); if (isHookString != null) { nativeCodeSequence.setHook(Boolean.parseBoolean(isHookString)); } String isMethodRetuningString = getContent(element.getElementsByTagName("IsMethodReturning")); if (isMethodRetuningString != null) { nativeCodeSequence.setMethodReturning(Boolean.parseBoolean(isMethodRetuningString)); } String codeInstructions = getContent(element.getElementsByTagName("CodeInstructions")); loadNativeCodeOpcodes(nativeCodeSequence, codeInstructions); // The "Parameters" and "BranchInstruction" have to be parsed after "CodeInstructions" // because they are using them (e.g. instruction labels) String parametersList = getContent(element.getElementsByTagName("Parameters")); if (parametersList != null) { String[] parameters = parametersList.split(" *, *"); for (int parameter = 0; parameters != null && parameter < parameters.length; parameter++) { setParameter(nativeCodeSequence, parameter, parameters[parameter].trim()); } } String branchInstructionLabel = getContent(element.getElementsByTagName("BranchInstruction")); if (branchInstructionLabel != null) { if (branchInstructionLabel.startsWith("@")) { branchInstructionLabel = branchInstructionLabel.substring(1); } int branchInstructionOffset = nativeCodeSequence.getLabelIndex(branchInstructionLabel.trim()); if (branchInstructionOffset >= 0) { nativeCodeSequence.setBranchInstruction(branchInstructionOffset); } else { Compiler.log.error( String.format("BranchInstruction: label '%s' not found", branchInstructionLabel)); } } String beforeCodeInstructions = getContent(element.getElementsByTagName("BeforeCodeInstructions")); if (beforeCodeInstructions != null) { loadBeforeCodeInstructions(nativeCodeSequence, beforeCodeInstructions); } addNativeCodeSequence(nativeCodeSequence); }