Skip to content

Conversation

arvi18
Copy link

@arvi18 arvi18 commented Apr 21, 2025

While working with tricore binary I found that some small routines can be called through FCALL (fast call) opcode, not by common CALL.
And even though it is already supported in sleigh, it produces a wrong decompiled code if caller function uses stack variables, because CALL and FCALL handle stack in a different manner.

So, here is two patches:

  • add a new calling convention to support these functions
  • copy of the HCS12 plugin to automatically detect such functions.

some notes:

  • I'm not sure that the FCALL can be used in the C++ code (to be honest, I have never seen C++ tricore binaries)
  • I'm not sure about parameters transferred through stack. For common functions it working good enough, but my sample use the only few fast calls with just a few arguments, there is no stack usage to transfer parameters.

@visz11
Copy link
Collaborator

visz11 commented Aug 7, 2025

/refacto-test

Copy link

refacto-test bot commented Aug 7, 2025

Refacto is reviewing this PR. Please wait for the review comments to be posted.

Comment on lines +59 to +69
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;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential for Incomplete Calling Convention Detection

The checkReturn method first checks if the instruction is null, then attempts to access the mnemonic string from it. This creates a potential null pointer exception risk if instr is null. While the current implementation checks for null after using the object, this could lead to unexpected behavior if the code is modified in the future.

Suggested change
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;
}
}
void checkReturn(Program program, Instruction instr) {
if (instr == null || !instr.getFlowType().isTerminal()) {
return;
}
String mnemonic = instr.getMnemonicString().toLowerCase();
if (mnemonic.equals("fret")) {
setPrototypeModel(program, instr, "__fastcall");
return;
}
}
Standards
  • CWE-476
  • Secure Coding Best Practices

Copy link

refacto-test bot commented Aug 7, 2025

Security Implications of Tricore FCALL Analyzer Implementation

👍 Well Done
Proper Processor-Specific Analyzer Implementation

The analyzer correctly checks if it's analyzing a Tricore processor before proceeding with the analysis.

Appropriate Error Handling

The code includes proper error handling for InvalidInputException when setting calling conventions.

Consistent Calling Convention Definition

The __fastcall calling convention is properly defined with appropriate register usage patterns and stack behavior.

📌 Files Processed
  • Ghidra/Processors/tricore/data/languages/tricore.cspec
  • Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java
📝 Additional Comments
Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java (1)
Redundant Flow Control in Terminal Instruction Check

The added method performs a redundant check for terminal instructions. The code in the 'added' method already checks for terminal instructions in lines 102-106, and then again in the checkReturn method at line 62. This duplication could lead to maintenance issues if one check is updated but not the other.

Standards:

  • Clean Code Principles
  • DRY (Don't Repeat Yourself) Principle

@coderabbit-test coderabbit-test deleted a comment from coderabbitai bot Aug 7, 2025
@coderabbit-test coderabbit-test deleted a comment from visz11 Aug 7, 2025
@coderabbit-test coderabbit-test deleted a comment from visz11 Aug 7, 2025
@coderabbit-test coderabbit-test deleted a comment from coderabbitai bot Aug 7, 2025
@coderabbit-test coderabbit-test deleted a comment from refacto-test bot Aug 7, 2025
Copy link

refacto-test bot commented Aug 7, 2025

Refacto is reviewing this PR. Please wait for the review comments to be posted.

@visz11
Copy link
Collaborator

visz11 commented Sep 15, 2025

/refacto-test-arvi

Copy link

Refacto is reviewing this PR. Please wait for the review comments to be posted.

Copy link

Code Review: Tricore FCALL/FRET Calling Convention Analysis

👍 Well Done
Consistent Calling Convention

Implementation follows processor-specific calling convention pattern with proper register assignments.

Clear Calling Convention

Well-defined register usage protects against unexpected register corruption.

📌 Files Processed
  • Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java
  • Ghidra/Processors/tricore/data/languages/tricore.cspec
📝 Additional Comments
Ghidra/Processors/tricore/data/languages/tricore.cspec (1)
Extrapop Value Validation

The extrapop and stackshift values are both set to 4, but there's no validation that this correctly matches the FCALL/FRET instruction behavior. Incorrect stack adjustment values could cause decompilation errors in function analysis.

Standards:

  • Business-Rule-Validation
  • Mathematical-Accuracy-Constraint-Checking
Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java (1)
Unvalidated Function Convention

Setting calling convention without validating if it exists could cause unexpected behavior. If convention is invalid, exception is caught but only logged. Could lead to incorrect analysis.

Standards:

  • CWE-754

Comment on lines +59 to +69
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;
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing FCALL Analysis

The analyzer only handles FRET instructions but not FCALL instructions despite the class name and description. This creates inconsistent calling convention detection since only function returns are analyzed without corresponding call sites.

Suggested change
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;
}
}
void checkInstruction(Program program, Instruction instr) {
String mnemonic = instr.getMnemonicString().toLowerCase();
if (instr.getFlowType().isTerminal()) {
if (mnemonic.equals("fret")) {
setPrototypeModel(program, instr, "__fastcall");
return;
}
} else if (mnemonic.equals("fcall")) {
Function calledFunction = program.getFunctionManager().getFunctionAt(instr.getFlows()[0]);
if (calledFunction != null) {
try {
calledFunction.setCallingConvention("__fastcall");
} catch (InvalidInputException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
}
}
}
Standards
  • Logic-Verification-Completeness
  • Algorithm-Correctness-Pattern-Matching

void checkReturn(Program program, Instruction instr) {
String mnemonic = instr.getMnemonicString().toLowerCase();

if (instr == null || !instr.getFlowType().isTerminal()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Null Check Redundancy

Null check on instr is redundant as the method already uses instr to call getMnemonicString() before this check. If instr were null, a NullPointerException would occur at line 60.

Suggested change
if (instr == null || !instr.getFlowType().isTerminal()) {
if (!instr.getFlowType().isTerminal()) {
Standards
  • Logic-Verification-Consistency
  • Algorithm-Correctness-Control-Flow

@visz11
Copy link
Collaborator

visz11 commented Sep 15, 2025

/refacto-test-arvi

Copy link

Refacto is reviewing this PR. Please wait for the review comments to be posted.

Copy link

Code Review: Calling Convention Implementation

👍 Well Done
Structured Analyzer Implementation

Properly follows Ghidra analyzer pattern with appropriate priority and processor validation.

Complete Prototype Definition

Thorough calling convention specification with proper input/output/unaffected register definitions.

📌 Files Processed
  • Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java
  • Ghidra/Processors/tricore/data/languages/tricore.cspec
📝 Additional Comments
Ghidra/Processors/tricore/src/main/java/ghidra/app/plugin/core/analysis/TricoreFCallAnalyzer.java (2)
Redundant Null Check

The instr parameter is checked for null, but the method is only called with a non-null instruction from the added() method. This redundant check adds unnecessary complexity without improving reliability.

Standards:

  • ISO-IEC-25010-Functional-Correctness-Appropriateness
Missing Progress Reporting

No progress reporting is implemented for the function iteration. For large programs with many functions, users won't receive feedback on analysis progress. Should use monitor.setProgress() to provide status updates.

Standards:

  • ISO-IEC-25010-Reliability-Maturity
  • SRE-Observability

return canDo;
}

void checkReturn(Program program, Instruction instr) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused Method Parameter

The program parameter is passed to checkReturn() but never used within the method. This creates maintenance confusion and potential reliability issues if the parameter is intended for future functionality.

Standards
  • ISO-IEC-25010-Functional-Correctness-Appropriateness
  • ISO-IEC-25010-Reliability-Maturity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants