diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc index 9352092742..d24e731294 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc @@ -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. @@ -1252,8 +1252,9 @@ AttributeId ATTRIB_VAL = AttributeId("val",24); AttributeId ATTRIB_VALUE = AttributeId("value",25); AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26); AttributeId ATTRIB_STORAGE = AttributeId("storage",149); +AttributeId ATTRIB_STACKSPILL = AttributeId("stackspill",150); -AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",150); // Number serves as next open index +AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",151); // Number serves as next open index ElementId ELEM_DATA = ElementId("data",1); ElementId ELEM_INPUT = ElementId("input",2); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh index 1fca0ed368..3b0ec0e4cc 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh @@ -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. @@ -736,6 +736,7 @@ extern AttributeId ATTRIB_VAL; ///< Marshaling attribute "val" extern AttributeId ATTRIB_VALUE; ///< Marshaling attribute "value" extern AttributeId ATTRIB_WORDSIZE; ///< Marshaling attribute "wordsize" extern AttributeId ATTRIB_STORAGE; ///< Marshaling attribute "storage" +extern AttributeId ATTRIB_STACKSPILL; ///< Marshaling attribute "stackspill" extern ElementId ELEM_DATA; ///< Marshaling element \ extern ElementId ELEM_INPUT; ///< Marshaling element \ diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.cc index f92abbbb56..1986094845 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.cc @@ -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. @@ -689,6 +689,7 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i vector tmpStatus = status; vector pieces; int4 sizeLeft = dt->getSize(); + int4 align = dt->getAlignment(); list::const_iterator iter = firstIter; list::const_iterator endIter = resource->getEntry().end(); if (enforceAlignment) { @@ -699,7 +700,6 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i break; // Reached end of resource list if (entry.getType() == resourceType && entry.getAllGroups().size() == 1) { // Single register if (tmpStatus[entry.getGroup()] == 0) { // Not consumed - int4 align = dt->getAlignment(); int4 regSize = entry.getSize(); if (align <= regSize || (resourcesConsumed % align) == 0) break; @@ -720,19 +720,20 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i if (tmpStatus[entry.getGroup()] != 0) continue; // Already consumed int4 trialSize = entry.getSize(); - Address addr = entry.getAddrBySlot(tmpStatus[entry.getGroup()], trialSize,1); + Address addr = entry.getAddrBySlot(tmpStatus[entry.getGroup()], trialSize,align); tmpStatus[entry.getGroup()] = -1; // Consume the register pieces.push_back(VarnodeData()); pieces.back().space = addr.getSpace(); pieces.back().offset = addr.getOffset(); pieces.back().size = trialSize; sizeLeft -= trialSize; + align = 1; // Treat remaining partial pieces as having no alignment requirement } if (sizeLeft > 0) { // Have to use stack to get enough bytes if (!consumeFromStack) return fail; int4 grp = stackEntry->getGroup(); - Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,1); // Consume all the space we need + Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,align); // Consume all the space we need if (addr.isInvalid()) return fail; pieces.push_back(VarnodeData()); @@ -841,6 +842,9 @@ void MultiSlotAssign::decode(Decoder &decoder) else if (attribId == ATTRIB_ALIGN) { enforceAlignment = decoder.readBool(); } + else if (attribId == ATTRIB_STACKSPILL) { + consumeFromStack = decoder.readBool(); + } } decoder.closeElement(elemId); initializeEntries(); // Need new firstIter diff --git a/Ghidra/Framework/SoftwareModeling/data/languages/compiler_spec.rxg b/Ghidra/Framework/SoftwareModeling/data/languages/compiler_spec.rxg index faacc10022..b34f7c1877 100644 --- a/Ghidra/Framework/SoftwareModeling/data/languages/compiler_spec.rxg +++ b/Ghidra/Framework/SoftwareModeling/data/languages/compiler_spec.rxg @@ -396,6 +396,9 @@ + + + diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/MultiSlotAssign.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/MultiSlotAssign.java index 420ecbdef1..88646c605a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/MultiSlotAssign.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/MultiSlotAssign.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. @@ -150,6 +150,7 @@ public class MultiSlotAssign extends AssignAction { ArrayList pieces = new ArrayList<>(); ParameterPieces param = new ParameterPieces(); int sizeLeft = dt.getLength(); + int align = dt.getAlignment(); int iter = firstIter; int endIter = resource.getNumParamEntry(); if (enforceAlignment) { @@ -161,7 +162,6 @@ public class MultiSlotAssign extends AssignAction { } // Reached end of resource list if (entry.getType() == resourceType && entry.getAllGroups().length == 1) { // Single register if (tmpStatus[entry.getGroup()] == 0) { // Not consumed - int align = dt.getAlignment(); int regSize = entry.getSize(); if (align <= regSize || (resourcesConsumed % align) == 0) { break; @@ -186,11 +186,12 @@ public class MultiSlotAssign extends AssignAction { continue; } // Already consumed int trialSize = entry.getSize(); - entry.getAddrBySlot(tmpStatus[entry.getGroup()], trialSize, 1, param); + entry.getAddrBySlot(tmpStatus[entry.getGroup()], trialSize, align, param); tmpStatus[entry.getGroup()] = -1; // Consume the register Varnode vn = new Varnode(param.address, trialSize); pieces.add(vn); sizeLeft -= trialSize; + align = 1; // Treat remaining partial pieces as having no alignment requirement } boolean onePieceJoin = false; if (sizeLeft > 0) { // Have to use stack to get enough bytes @@ -198,7 +199,7 @@ public class MultiSlotAssign extends AssignAction { return FAIL; } int grp = stackEntry.getGroup(); - tmpStatus[grp] = stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, 1, param); // Consume all the space we need + tmpStatus[grp] = stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, align, param); // Consume all the space we need if (param.address == null) { return FAIL; } @@ -276,6 +277,9 @@ public class MultiSlotAssign extends AssignAction { else if (name.equals(ATTRIB_ALIGN.name())) { enforceAlignment = SpecXmlUtils.decodeBoolean(attrib.getValue()); } + else if (name.equals(ATTRIB_STACKSPILL.name())) { + consumeFromStack = SpecXmlUtils.decodeBoolean(attrib.getValue()); + } } parser.end(elem); try { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AttributeId.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AttributeId.java index 255f403e23..0945439e71 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AttributeId.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/AttributeId.java @@ -242,6 +242,7 @@ public record AttributeId(String name, int id) { // public static final AttributeId ATTRIB_ADDRESS = new AttributeId("address", 148); public static final AttributeId ATTRIB_STORAGE = new AttributeId("storage", 149); + public static final AttributeId ATTRIB_STACKSPILL = new AttributeId("stackspill", 150); - public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 150); + public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 151); }