From 38445e387b3f2b17fc043e557458cd1e7fa851cd Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 30 Aug 2024 15:01:43 -0400 Subject: [PATCH 1/2] GP-4886 Do not assign storage for DEFAULT/unassigned datatype and create undefined-typedef instead of DWORD-typedef as a default named type when demangling. --- .../app/util/demangler/DemangledDataType.java | 8 +-- .../util/demangler/gnu/GnuDemanglerTest.java | 58 ++++++++++++++++++- .../program/model/lang/ParamListStandard.java | 13 +++-- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledDataType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledDataType.java index d6f907aa0e..0cc409fc72 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledDataType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledDataType.java @@ -95,8 +95,8 @@ public class DemangledDataType extends DemangledType { private static final String UNSIGNED_LONG = "unsigned long"; public final static String[] PRIMITIVES = - { VOID, BOOL, CHAR, WCHAR_T, WCHAR16, WCHAR32, CHAR8_T, SHORT, INT, INT0_T, LONG, - LONG_LONG, FLOAT, FLOAT2, DOUBLE, INT128, FLOAT128, LONG_DOUBLE, }; + { VOID, BOOL, CHAR, WCHAR_T, WCHAR16, WCHAR32, CHAR8_T, SHORT, INT, INT0_T, LONG, LONG_LONG, + FLOAT, FLOAT2, DOUBLE, INT128, FLOAT128, LONG_DOUBLE, }; private int arrayDimensions = 0; private boolean isClass; @@ -200,10 +200,10 @@ public class DemangledDataType extends DemangledType { else if (dt == null) { // I don't know what this is - // If it isn't pointed to, or isn't a referent, then assume typedef. + // If it isn't pointed to, or isn't a referent, then assume undefined typedef. if (!(isReference() || isPointer())) { // Unknown type dt = new TypedefDataType(getDemanglerCategoryPath(getNamespace()), name, - new DWordDataType()); + DataType.DEFAULT); } else { // try creating empty structures for unknown types instead. diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java index e8458bee39..444e38bf29 100644 --- a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java +++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java @@ -23,10 +23,10 @@ import org.junit.Before; import org.junit.Test; import generic.test.AbstractGenericTest; -import ghidra.app.util.demangler.DemangledException; -import ghidra.app.util.demangler.DemangledObject; +import ghidra.app.util.demangler.*; import ghidra.program.database.ProgramDB; import ghidra.program.model.address.Address; +import ghidra.program.model.data.DataType; import ghidra.program.model.data.TerminatedStringDataType; import ghidra.program.model.listing.CodeUnit; import ghidra.program.model.listing.Data; @@ -125,6 +125,60 @@ public class GnuDemanglerTest extends AbstractGenericTest { fullSignature); } + @Test + public void testUseStandardReplacements2() throws Exception { + + // + // Mangled: _ZN7Greeter5greetENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE + // + // Demangled: undefined Greeter::greet(std::__cxx11::basic_string,std::allocator>) + // + // Replaced: undefined Greeter::greet(std::string) + // + String mangled = "_ZN7Greeter5greetENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE"; + + GnuDemangler demangler = new GnuDemangler(); + demangler.canDemangle(program);// this perform initialization + + GnuDemanglerOptions options = new GnuDemanglerOptions(); + options.setUseStandardReplacements(true); + DemangledFunction dobj = (DemangledFunction) demangler.demangle(mangled, options); + assertNotNull(dobj); + + String signature = dobj.getSignature(); + assertEquals("undefined Greeter::greet(std::string)", signature); + + DemangledParameter demangledParameter = dobj.getParameters().get(0); + DemangledDataType type = demangledParameter.getType(); + DataType dt = type.getDataType(program.getDataTypeManager()); + assertTrue(dt.isNotYetDefined()); + //@formatter:off + assertEquals("/Demangler/std/string\n" + + "pack(disabled)\n" + + "Structure string {\n" + + "}\n" + + "Length: 0 Alignment: 1\n", dt.toString()); + //@formatter:on + + // + // Now disable demangled string replacement + // + options.setUseStandardReplacements(false); + dobj = (DemangledFunction) demangler.demangle(mangled, options); + assertNotNull(dobj); + + String fullSignature = dobj.getSignature(); + assertEquals( + "undefined Greeter::greet(std::__cxx11::basic_string,std::allocator>)", + fullSignature); + + demangledParameter = dobj.getParameters().get(0); + type = demangledParameter.getType(); + dt = type.getDataType(program.getDataTypeManager()); + assertEquals("typedef basic_string undefined", dt.toString()); + + } + @Test public void testDemangleOnlyKnownPatterns_True() throws Exception { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java index f03b5b74ad..247c59523c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java @@ -4,9 +4,9 @@ * 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. @@ -23,8 +23,7 @@ import java.util.ArrayList; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; -import ghidra.program.model.data.DataType; -import ghidra.program.model.data.DataTypeManager; +import ghidra.program.model.data.*; import ghidra.program.model.lang.protorules.*; import ghidra.program.model.listing.Program; import ghidra.program.model.listing.VariableStorage; @@ -133,6 +132,12 @@ public class ParamListStandard implements ParamList { if (dt.isZeroLength()) { return AssignAction.NO_ASSIGNMENT; } + if (dt == DataType.DEFAULT) { + return AssignAction.NO_ASSIGNMENT; + } + if (dt instanceof TypeDef td && td.getBaseDataType() == DataType.DEFAULT) { + return AssignAction.NO_ASSIGNMENT; + } for (ModelRule modelRule : modelRules) { int responseCode = modelRule.assignAddress(dt, proto, pos, dtManager, status, res); if (responseCode != AssignAction.FAIL) { From 33646bbcdc8342b6b6fae9ec098d258d16eac2a6 Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Wed, 9 Oct 2024 23:03:32 +0000 Subject: [PATCH 2/2] Move UNASSIGNED check into LocalSymbolMap --- .../program/database/function/FunctionDB.java | 14 ++------------ .../program/model/pcode/LocalSymbolMap.java | 15 +++++++++++---- .../program/model/pcode/PcodeDataTypeManager.java | 9 +++------ 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionDB.java index ace0699cd5..50a6ff780c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/function/FunctionDB.java @@ -4,9 +4,9 @@ * 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. @@ -2470,16 +2470,6 @@ public class FunctionDB extends DatabaseObject implements Function { return thunkedFunction.getSignatureSource(); } - // Force DEFAULT source if any param has unassigned storage - if (!getReturn().isValid()) { - return SourceType.DEFAULT; - } - for (Parameter param : getParameters()) { - if (!param.isValid()) { - return SourceType.DEFAULT; - } - } - return getStoredSignatureSource(); } finally { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java index c4179411f2..9209d212d1 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java @@ -4,9 +4,9 @@ * 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. @@ -210,11 +210,12 @@ public class LocalSymbolMap { pcaddr = pcaddr.subtractWrap(1); List paramList = new ArrayList<>(); + boolean internalInvalid = false; for (int i = 0; i < p.length; ++i) { Parameter var = p[i]; if (!var.isValid()) { - // TODO: exclude parameters which don't have valid storage ?? - continue; + internalInvalid = true; + break; } DataType dt = var.getDataType(); String name = var.getName(); @@ -243,6 +244,12 @@ public class LocalSymbolMap { paramSymbol.setNameLock(namelock); paramSymbol.setTypeLock(lock); } + if (internalInvalid) { + // Can only send down a partial prototype. Let decompiler try to recover the whole. + for (HighSymbol paramSymbol : paramList) { + paramSymbol.setTypeLock(false); + } + } paramSymbols = new HighSymbol[paramList.size()]; paramList.toArray(paramSymbols); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java index 9af94f1f9c..5e5d057aee 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java @@ -4,9 +4,9 @@ * 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. @@ -1145,10 +1145,7 @@ public class PcodeDataTypeManager { private void generateCoreTypes() { voidDt = new VoidDataType(progDataTypes); coreBuiltin = new HashMap(); - TypeMap type = new TypeMap(DataType.DEFAULT, "undefined", "unknown", false, false, - DEFAULT_DECOMPILER_ID); - coreBuiltin.put(type.id, type); - type = new TypeMap(displayLanguage, VoidDataType.dataType, "void", false, false, + TypeMap type = new TypeMap(displayLanguage, VoidDataType.dataType, "void", false, false, builtInDataTypes); coreBuiltin.put(type.id, type);