diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFFunctionImporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFFunctionImporter.java index 0ffe5f73a6..bf64d89ae1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFFunctionImporter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFFunctionImporter.java @@ -347,16 +347,24 @@ public class DWARFFunctionImporter { private void updateFunctionSignatureWithFormalParams(Function gfunc, List params, DataType returnType, boolean varArgs, DIEAggregate diea) { try { + String callingConventionName = null; ReturnParameterImpl returnVar = new ReturnParameterImpl(returnType, currentProgram); try { + if (!params.isEmpty() && Function.THIS_PARAM_NAME.equals(params.get(0).getName())) { + // this handles the common / simple case. More nuanced cases where the param + // didn't have the correct "this" name, but were marked with DW_AT_object_pointer + // or DW_AT_artifical won't be handled by this. + callingConventionName = GenericCallingConvention.thiscall.getDeclarationName(); + } + gfunc.setVarArgs(varArgs); - gfunc.updateFunction(null, returnVar, params, + gfunc.updateFunction(callingConventionName, returnVar, params, FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED); } catch (DuplicateNameException e) { // try again after adjusting param names setUniqueParameterNames(gfunc, params); - gfunc.updateFunction(null, returnVar, params, + gfunc.updateFunction(callingConventionName, returnVar, params, FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, SourceType.IMPORTED); } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/bin/format/dwarf4/next/DWARFFunctionImporterTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/bin/format/dwarf4/next/DWARFFunctionImporterTest.java index 94977f3c70..c95830c0c8 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/bin/format/dwarf4/next/DWARFFunctionImporterTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/bin/format/dwarf4/next/DWARFFunctionImporterTest.java @@ -17,9 +17,10 @@ package ghidra.app.util.bin.format.dwarf4.next; import static org.junit.Assert.*; -import java.io.IOException; import java.util.List; +import java.io.IOException; + import org.junit.Test; import ghidra.app.util.NamespaceUtils; @@ -27,6 +28,7 @@ import ghidra.app.util.bin.format.dwarf4.*; import ghidra.app.util.bin.format.dwarf4.encoding.DWARFSourceLanguage; import ghidra.app.util.bin.format.dwarf4.expression.DWARFExpressionOpCodes; import ghidra.program.model.data.*; +import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.Namespace; import ghidra.util.exception.CancelledException; @@ -157,4 +159,26 @@ public class DWARFFunctionImporterTest extends DWARFTestBase { Structure nestedStructDT2 = VariableUtilities.findExistingClassStruct(fooFunc); assertTrue(nestedStructDT1 == nestedStructDT2); } + + @Test + public void testThisParam() + throws CancelledException, IOException, DWARFException { + + DebugInfoEntry intDIE = addInt(cu); + DebugInfoEntry ptrDIE = addPtr(intDIE, cu); + DebugInfoEntry fooDIE = newSubprogram("foo", intDIE, 0x410, 10).create(cu); + newFormalParam(fooDIE, "this", ptrDIE, + DWARFExpressionOpCodes.DW_OP_implicit_value /* requires this to be non supported location opcode to trigger formal_param_only mode*/, + 0x6c).create(cu); + + importFunctions(); + + Function fooFunc = program.getListing().getFunctionAt(addr(0x410)); + assertNotNull(fooFunc); + + assertEquals("foo", fooFunc.getName()); + Parameter[] fooParams = fooFunc.getParameters(); + assertEquals(fooParams.length, 1); + assertEquals(CompilerSpec.CALLING_CONVENTION_thiscall, fooFunc.getCallingConventionName()); + } }