diff --git a/Ghidra/Features/Base/ghidra_scripts/CallotherCensusScript.java b/Ghidra/Features/Base/ghidra_scripts/CallotherCensusScript.java new file mode 100644 index 0000000000..1e13fc7431 --- /dev/null +++ b/Ghidra/Features/Base/ghidra_scripts/CallotherCensusScript.java @@ -0,0 +1,89 @@ +/* ### + * IP: GHIDRA + * + * 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. + */ +// Produces a list of instructions whose pcode contains a CALLOTHER pcode op. The list is +// sorted by number of occurrences of an instruction. When run headlessly, the list is displayed +// each time a program is processed and the counts are cumulative. +// @category sleigh + +import java.util.HashMap; +import java.util.Map; + +import ghidra.app.script.GhidraScript; +import ghidra.program.model.listing.Instruction; +import ghidra.program.model.listing.InstructionIterator; +import ghidra.program.model.pcode.PcodeOp; + +public class CallotherCensusScript extends GhidraScript { + + public static Map instCountMap = new HashMap<>(); + + @Override + protected void run() throws Exception { + if (currentProgram == null) { + popup("This script requires an active current program."); + return; + } + if (!isRunningHeadless()) { + instCountMap.clear(); + } + + InstructionIterator instIter = currentProgram.getListing().getInstructions(true); + while (instIter.hasNext()) { + monitor.checkCanceled(); + Instruction inst = instIter.next(); + for (PcodeOp op : inst.getPcode()) { + if (op.getOpcode() == PcodeOp.CALLOTHER) { + String mnemonic = inst.getMnemonicString(); + CountAndLocationInfo countInfo = instCountMap.computeIfAbsent(mnemonic, + s -> new CountAndLocationInfo(s, + currentProgram.getDomainFile().getPathname() + " " + + inst.getAddress())); + countInfo.incrementCount(); + } + } + } + instCountMap.values().stream().sorted().forEach(x -> printf("%s\n", x.toString())); + + } + + class CountAndLocationInfo implements Comparable { + private String mnemonic; + private String firstOccurrence; + private Integer count; + + public CountAndLocationInfo(String mnemonic, String firstOccurrence) { + this.mnemonic = mnemonic; + this.firstOccurrence = firstOccurrence; + count = 0; + } + + public void incrementCount() { + count += 1; + } + + @Override + public String toString() { + return mnemonic + " " + count.toString() + " " + firstOccurrence; + } + + @Override + public int compareTo(CountAndLocationInfo o) { + return -Integer.compare(count, o.count); + } + + } + +} diff --git a/Ghidra/Features/Base/ghidra_scripts/MarkCallOtherPcode.java b/Ghidra/Features/Base/ghidra_scripts/MarkCallOtherPcode.java index 21a63da2af..be22fb4e60 100644 --- a/Ghidra/Features/Base/ghidra_scripts/MarkCallOtherPcode.java +++ b/Ghidra/Features/Base/ghidra_scripts/MarkCallOtherPcode.java @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// Generate WARNING Bookmarks CallOther PcodeOp's within an instructions Pcode. -// This is useful to find PsuedoOps that need to be implemented to yield better +// Generate WARNING Bookmarks at instructions whose pcode contains a CALLOTHER op. +// This is useful to find PseudoOps that need to be implemented to yield better // emulation or decompilation. // @category sleigh @@ -63,8 +63,9 @@ public class MarkCallOtherPcode extends GhidraScript { } private void markCallOtherPcode(Instruction instr, PcodeOp op) { - currentProgram.getBookmarkManager().setBookmark(instr.getAddress(), BookmarkType.WARNING, - "CallOther PcodeOp", - currentProgram.getLanguage().getUserDefinedOpName((int) op.getInput(0).getOffset())); + currentProgram.getBookmarkManager() + .setBookmark(instr.getAddress(), BookmarkType.WARNING, "CallOther PcodeOp", + currentProgram.getLanguage() + .getUserDefinedOpName((int) op.getInput(0).getOffset())); } }