diff --git a/Ghidra/Processors/tricore/data/languages/tricore.cspec b/Ghidra/Processors/tricore/data/languages/tricore.cspec index a9c69243fe3..ec4038e5812 100644 --- a/Ghidra/Processors/tricore/data/languages/tricore.cspec +++ b/Ghidra/Processors/tricore/data/languages/tricore.cspec @@ -124,6 +124,85 @@ the correct return storage location when there are multiple return location types --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java b/Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java new file mode 100644 index 00000000000..99f9691e749 --- /dev/null +++ b/Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java @@ -0,0 +1,112 @@ +/* ### + * 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. + */ +package ghidra.app.plugin.core.analysis; + +import java.math.BigInteger; + +import ghidra.app.services.AbstractAnalyzer; +import ghidra.app.services.AnalysisPriority; +import ghidra.app.services.AnalyzerType; +import ghidra.app.util.importer.MessageLog; +import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.lang.Processor; +import ghidra.program.model.lang.Register; +import ghidra.program.model.lang.RegisterValue; +import ghidra.program.model.listing.Function; +import ghidra.program.model.listing.FunctionIterator; +import ghidra.program.model.listing.Instruction; +import ghidra.program.model.listing.InstructionIterator; +import ghidra.program.model.listing.Program; +import ghidra.program.model.symbol.SourceType; +import ghidra.util.Msg; +import ghidra.util.exception.CancelledException; +import ghidra.util.exception.InvalidInputException; +import ghidra.util.task.TaskMonitor; + +public class TricoreFCallAnalyzer extends AbstractAnalyzer { + + private static final String NAME = "Tricore FCall Analyzer"; + private static final String DESCRIPTION = "Analyzes Tricore programs to find routines called by FCALL opcode. This analyzer looks at the type of return used for the function to identify the calling convention."; + + public TricoreFCallAnalyzer() { + super(NAME, DESCRIPTION, AnalyzerType.FUNCTION_ANALYZER); + setPriority(AnalysisPriority.FUNCTION_ANALYSIS); + setDefaultEnablement(true); + } + + @Override + public boolean canAnalyze(Program program) { + // Only analyze Tricore Programs + Processor processor = program.getLanguage().getProcessor(); + + boolean canDo = processor.equals(Processor.findOrPossiblyCreateProcessor("tricore")); + return canDo; + } + + void checkReturn(Program program, Instruction instr) { + String mnemonic = instr.getMnemonicString().toLowerCase(); + + if (instr == null || !instr.getFlowType().isTerminal()) { + return; + } + if (mnemonic.equals("fret")) { + setPrototypeModel(program, instr, "__fastcall"); + return; + } + } + + private void setPrototypeModel(Program program, Instruction instr, String convention) { + if (convention == null) { + return; + } + + Function func = program.getFunctionManager().getFunctionContaining(instr.getMinAddress()); + if (func == null) { + return; + } + + if (func.getSignatureSource() != SourceType.DEFAULT) { + return; + } + + try { + func.setCallingConvention(convention); + } catch (InvalidInputException e) { + Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); + } + } + + @Override + public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) + throws CancelledException { + + // get all functions within the set + FunctionIterator functions = program.getFunctionManager().getFunctions(set, true); + for (Function function : functions) { + + // for each function body, search instructions + AddressSetView body = function.getBody(); + InstructionIterator instructions = program.getListing().getInstructions(body, true); + for (Instruction instr : instructions) { + if (instr.getFlowType().isTerminal()) { + checkReturn(program, instr); + } + } + } + return true; + } + +}