/* ### * 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. */ // Fix any unknown switch instructions with the decompiler. // // Your mileage may vary! This should only be run after existing code has been found. // The results should be checked for validity. // // @category Analysis import java.util.*; import ghidra.app.cmd.function.DecompilerSwitchAnalysisCmd; import ghidra.app.decompiler.DecompileResults; import ghidra.app.decompiler.parallel.DecompilerCallback; import ghidra.app.decompiler.parallel.ParallelDecompiler; import ghidra.app.plugin.core.analysis.SwitchAnalysisDecompileConfigurer; import ghidra.app.plugin.core.bookmark.BookmarkEditCmd; import ghidra.app.script.GhidraScript; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.FlowType; import ghidra.program.model.symbol.Reference; import ghidra.util.task.TaskMonitor; public class FixSwitchStatementsWithDecompiler extends GhidraScript { @Override public void run() throws Exception { Map instructionsByFunction = filterFunctions(); DecompilerCallback callback = new DecompilerCallback(currentProgram, new SwitchAnalysisDecompileConfigurer(currentProgram)) { @Override public Void process(DecompileResults results, TaskMonitor m) throws Exception { Function func = results.getFunction(); DecompilerSwitchAnalysisCmd cmd = new DecompilerSwitchAnalysisCmd(results); cmd.applyTo(currentProgram); Instruction instr = instructionsByFunction.get(func); BookmarkEditCmd bmcmd = new BookmarkEditCmd(instr.getMinAddress(), BookmarkType.INFO, "FixSwitchStatementsWithDecompiler", "Fixed switch stmt"); bmcmd.applyTo(currentProgram); return null; } }; Set functions = instructionsByFunction.keySet(); try { ParallelDecompiler.decompileFunctions(callback, functions, monitor); } finally { callback.dispose(); } } private Map filterFunctions() { // search for all dynamic jump locations that have no target Map results = new HashMap<>(); Listing list = currentProgram.getListing(); FunctionManager functionManager = currentProgram.getFunctionManager(); InstructionIterator it = list.getInstructions(true); while (it.hasNext()) { if (monitor.isCancelled()) { return Collections.emptyMap(); } Instruction instr = it.next(); FlowType flowType = instr.getFlowType(); if (!flowType.isJump() || !flowType.isComputed()) { continue; } Reference[] refsFrom = instr.getReferencesFrom(); if (refsFrom.length == 0 || refsFrom.length > 2) { continue; } Function func = functionManager.getFunctionContaining(instr.getMinAddress()); if (func == null) { println("No function at " + instr.getMinAddress()); continue; } results.put(func, instr); } return results; } }