diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc index a4b2fc2d9d..b85a75b477 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc @@ -431,7 +431,23 @@ int4 ParamEntry::getSlot(const Address &addr,int4 skip) const /// \param sz is the size of the parameter to allocated /// \param typeAlign is the required byte alignment for the parameter /// \return the address of the new parameter (or an invalid address) -Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz,int4 typeAlign) const +Address ParamEntry::getAddrBySlot(int4 &slotnum, int4 sz, int4 typeAlign) const + +{ + return getAddrBySlot(slotnum, sz, typeAlign, !isLeftJustified()); +} + +/// \brief Calculate the storage address assigned when allocating a parameter of a given size +/// +/// Assume \b slotnum slots have already been assigned and increment \b slotnum +/// by the number of slots used. +/// Return an invalid address if the size is too small or if there are not enough slots left. +/// \param slotnum is a reference to used slots (which will be updated) +/// \param sz is the size of the parameter to allocated +/// \param typeAlign is the required byte alignment for the parameter +/// \param justifyRight is true if initial bytes are padding for odd data-type sizes +/// \return the address of the new parameter (or an invalid address) +Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz,int4 typeAlign, bool justifyRight) const { Address res; // Start with an invalid result @@ -471,7 +487,7 @@ Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz,int4 typeAlign) const res = Address(spaceid, addressbase + index * alignment); slotnum += slotsused; // Inform caller of number of slots used } - if (!isLeftJustified()) // Adjust for right justified (big endian) + if (justifyRight) // Adjust for right justified (big endian) res = res + (spaceused - sz); return res; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh index b5c6750965..df41307e4a 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh @@ -146,6 +146,7 @@ public: int4 getSlot(const Address &addr,int4 skip) const; AddrSpace *getSpace(void) const { return spaceid; } ///< Get the address space containing \b this entry uintb getBase(void) const { return addressbase; } ///< Get the starting offset of \b this entry + Address getAddrBySlot(int4 &slot, int4 sz, int4 typeAlign, bool justifyRight) const; Address getAddrBySlot(int4 &slot,int4 sz,int4 typeAlign) const; void decode(Decoder &decoder,bool normalstack,bool grouped,list &curList); bool isParamCheckHigh(void) const { return ((flags & extracheck_high)!=0); } ///< Return \b true if there is a high overlap diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc index 9900e1ea0f..1c138774ac 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc @@ -1254,7 +1254,8 @@ AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26); AttributeId ATTRIB_STORAGE = AttributeId("storage",149); AttributeId ATTRIB_STACKSPILL = AttributeId("stackspill",150); -AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",156); // Number serves as next open index +AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",159); // 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/modelrules.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.cc index b6c316e0d2..3bfd039f1d 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.cc @@ -22,6 +22,9 @@ AttributeId ATTRIB_SIZES = AttributeId("sizes",151); AttributeId ATTRIB_MAX_PRIMITIVES = AttributeId("maxprimitives", 153); AttributeId ATTRIB_REVERSESIGNIF = AttributeId("reversesignif", 154); AttributeId ATTRIB_MATCHSIZE = AttributeId("matchsize", 155); +AttributeId ATTRIB_AFTER_BYTES = AttributeId("afterbytes", 156); +AttributeId ATTRIB_AFTER_STORAGE = AttributeId("afterstorage", 157); +AttributeId ATTRIB_FILL_ALTERNATE = AttributeId("fillalternate", 158); ElementId ELEM_DATATYPE = ElementId("datatype",273); ElementId ELEM_CONSUME = ElementId("consume",274); @@ -662,7 +665,7 @@ AssignAction *AssignAction::decodeSideeffect(Decoder &decoder,const ParamListSta action = new ConsumeExtra(res); } else if (elemId == ELEM_EXTRA_STACK) { - action = new ExtraStack(res,0); + action = new ExtraStack(res); } else if (elemId == ELEM_CONSUME_REMAINING) { action = new ConsumeRemaining(res); @@ -850,7 +853,7 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i if (!consumeFromStack) return fail; int4 grp = stackEntry->getGroup(); - Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,align); // Consume all the space we need + Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,align,justifyRight); // Consume all the space we need if (addr.isInvalid()) return fail; pieces.push_back(VarnodeData()); @@ -1043,11 +1046,15 @@ void MultiSlotDualAssign::initializeEntries(void) { resource->extractTiles(baseTiles,baseType); resource->extractTiles(altTiles,altType); + stackEntry = resource->getStackEntry(); + if (baseTiles.size() == 0 || altTiles.size() == 0) throw LowlevelError("Could not find matching resources for action: join_dual_class"); tileSize = baseTiles[0]->getSize(); if (tileSize != altTiles[0]->getSize()) throw LowlevelError("Storage class register sizes do not match for action: join_dual_class"); + if (consumeFromStack && stackEntry == (const ParamEntry *)0) + throw LowlevelError("Cannot find matching stack resource for action: join_dual_class"); } /// \brief Get the index of the first unused ParamEntry in the given list @@ -1084,6 +1091,8 @@ int4 MultiSlotDualAssign::getTileClass(const PrimitiveExtractor &primitives,int4 int4 res = 1; int4 count = 0; int4 endBoundary = off + tileSize; + if (index >= primitives.size()) return -1; + const PrimitiveExtractor::Primitive &firstPrimitive( primitives.get(index) ); while(index < primitives.size()) { const PrimitiveExtractor::Primitive &element( primitives.get(index) ); if (element.offset < off) return -1; @@ -1096,6 +1105,12 @@ int4 MultiSlotDualAssign::getTileClass(const PrimitiveExtractor &primitives,int4 res = 0; } if (count == 0) return -1; // Must be at least one primitive in section + if (fillAlternate) { // Only use altType if the tile contains one primitive of exactly the tile size + if (count > 1) + res = 0; + if (firstPrimitive.dt->getSize() != tileSize) + res = 0; + } return res; } @@ -1107,6 +1122,7 @@ MultiSlotDualAssign::MultiSlotDualAssign(const ParamListStandard *res) fillinOutputActive = true; baseType = TYPECLASS_GENERAL; // Tile from general purpose registers altType = TYPECLASS_FLOAT; // Use specialized registers for floating-point components + consumeFromStack = false; consumeMostSig = false; justifyRight = false; AddrSpace *spc = res->getSpacebase(); @@ -1114,18 +1130,23 @@ MultiSlotDualAssign::MultiSlotDualAssign(const ParamListStandard *res) consumeMostSig = true; justifyRight = true; } + fillAlternate = false; tileSize = 0; + stackEntry = (const ParamEntry *)0; } -MultiSlotDualAssign::MultiSlotDualAssign(type_class baseStore,type_class altStore,bool mostSig,bool justRight, - const ParamListStandard *res) +MultiSlotDualAssign::MultiSlotDualAssign(type_class baseStore,type_class altStore,bool stack, + bool mostSig,bool justRight,bool fillAlt,const ParamListStandard *res) : AssignAction(res) { fillinOutputActive = true; baseType = baseStore; altType = altStore; + consumeFromStack = stack; consumeMostSig = mostSig; justifyRight = justRight; + fillAlternate = fillAlt; + stackEntry = (const ParamEntry *)0; initializeEntries(); } @@ -1139,6 +1160,7 @@ uint4 MultiSlotDualAssign::assignAddress(Datatype *dt,const PrototypePieces &pro vector tmpStatus = status; vector pieces; int4 typeSize = dt->getSize(); + int4 align = dt->getAlignment(); int4 sizeLeft = typeSize; int4 iterBase = 0; int4 iterAlt = 0; @@ -1149,14 +1171,20 @@ uint4 MultiSlotDualAssign::assignAddress(Datatype *dt,const PrototypePieces &pro return fail; if (iterType == 0) { iterBase = getFirstUnused(iterBase, baseTiles, tmpStatus); - if (iterBase == baseTiles.size()) - return fail; // Out of general purpose registers + if (iterBase == baseTiles.size()) { + if (!consumeFromStack) + return fail; // Out of general purpose registers + break; + } entry = baseTiles[iterBase]; } else { iterAlt = getFirstUnused(iterAlt, altTiles, tmpStatus); - if (iterAlt == altTiles.size()) - return fail; // Out of alternate registers + if (iterAlt == altTiles.size()) { + if (!consumeFromStack) + return fail; // Out of alternate registers + break; + } entry = altTiles[iterAlt]; } int4 trialSize = entry->getSize(); @@ -1168,6 +1196,18 @@ uint4 MultiSlotDualAssign::assignAddress(Datatype *dt,const PrototypePieces &pro pieces.back().size = trialSize; sizeLeft -= trialSize; } + if (sizeLeft > 0) { + if (!consumeFromStack) + return fail; + int4 grp = stackEntry->getGroup(); + Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,align,justifyRight); // Consume all the space we need + if (addr.isInvalid()) + return fail; + pieces.push_back(VarnodeData()); + pieces.back().space = addr.getSpace(); + pieces.back().offset = addr.getOffset(); + pieces.back().size = sizeLeft; + } if (sizeLeft < 0) { // Have odd data-type size if (justifyRight) { pieces.front().offset += -sizeLeft; // Initial bytes of first entry are padding @@ -1248,7 +1288,7 @@ void MultiSlotDualAssign::decode(Decoder &decoder) uint4 attribId = decoder.getNextAttributeId(); if (attribId == 0) break; if (attribId == ATTRIB_REVERSEJUSTIFY) { - if (decoder.readBool()) + if (decoder.readBool()) justifyRight = !justifyRight; } else if (attribId == ATTRIB_REVERSESIGNIF) { @@ -1261,6 +1301,12 @@ void MultiSlotDualAssign::decode(Decoder &decoder) else if (attribId == ATTRIB_B) { altType = string2typeclass(decoder.readString()); } + else if (attribId == ATTRIB_STACKSPILL) { + consumeFromStack = decoder.readBool(); + } + else if (attribId == ATTRIB_FILL_ALTERNATE) { + fillAlternate = decoder.readBool(); + } } decoder.closeElement(elemId); initializeEntries(); // Need new firstIter @@ -1459,16 +1505,19 @@ void ExtraStack::initializeEntry(void) } /// \param res is the new resource set to associate with \b this action -/// \param val is a dummy value -ExtraStack::ExtraStack(const ParamListStandard *res,int4 val) - : AssignAction(res) -{ - stackEntry = (const ParamEntry *)0; -} - ExtraStack::ExtraStack(const ParamListStandard *res) : AssignAction(res) { + afterBytes = -1; + afterStorage = TYPECLASS_GENERAL; + stackEntry = (const ParamEntry *)0; +} + +ExtraStack::ExtraStack(type_class storage, int4 offset, const ParamListStandard *res) + : AssignAction(res) +{ + afterStorage = storage; + afterBytes = offset; stackEntry = (const ParamEntry *)0; initializeEntry(); } @@ -1479,6 +1528,26 @@ uint4 ExtraStack::assignAddress(Datatype *dt,const PrototypePieces &proto,int4 p if (res.addr.getSpace() == stackEntry->getSpace()) return success; // Parameter was already assigned to the stack int4 grp = stackEntry->getGroup(); + // Check whether we have consumed enough storage to need to adjust the stack yet + if (afterBytes > 0) { + const list& entryList = resource->getEntry(); + int4 bytesConsumed = 0; + list::const_iterator iter = entryList.begin(); + list::const_iterator endIter = entryList.end(); + while (iter != endIter) { + const ParamEntry &entry(*iter); + ++iter; + if (entry.getGroup() == grp || entry.getType() != afterStorage) { + continue; + } + if (status[entry.getGroup()] != 0) { + bytesConsumed += entry.getSize(); + } + } + if (bytesConsumed < afterBytes) { + return success; + } + } // We assign the stack address (but ignore the actual address) updating the status for the stack, // which consumes the stack resources. stackEntry->getAddrBySlot(status[grp],dt->getSize(),dt->getAlignment()); @@ -1489,6 +1558,14 @@ void ExtraStack::decode(Decoder &decoder) { uint4 elemId = decoder.openElement(ELEM_EXTRA_STACK); + for (;;) { + uint4 attribId = decoder.getNextAttributeId(); + if (attribId == 0) break; + else if (attribId == ATTRIB_AFTER_BYTES) + afterBytes = decoder.readUnsignedInteger(); + else if (attribId == ATTRIB_AFTER_STORAGE) + afterStorage = string2typeclass(decoder.readString()); + } decoder.closeElement(elemId); initializeEntry(); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.hh index c720ec8220..5d8e40a689 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.hh @@ -32,6 +32,9 @@ extern AttributeId ATTRIB_SIZES; ///< Marshaling attribute "sizes" extern AttributeId ATTRIB_MAX_PRIMITIVES; ///< Marshaling attribute "maxprimitives" extern AttributeId ATTRIB_REVERSESIGNIF; ///< Marshaling attribute "reversesignif" extern AttributeId ATTRIB_MATCHSIZE; ///< Marshaling attribute "matchsize" +extern AttributeId ATTRIB_AFTER_BYTES; ///< Marshaling attribute "afterbytes" +extern AttributeId ATTRIB_AFTER_STORAGE; ///< Marshaling attribute "afterstorage" +extern AttributeId ATTRIB_FILL_ALTERNATE; ///< Marshalling attribute "fillalternate" extern ElementId ELEM_DATATYPE; ///< Marshaling element \ extern ElementId ELEM_CONSUME; ///< Marshaling element \ @@ -396,20 +399,24 @@ public: class MultiSlotDualAssign : public AssignAction { type_class baseType; ///< Resource list from which to consume general tiles type_class altType; ///< Resource list from which to consume alternate tiles + bool consumeFromStack; ///< True if resources should be consumed from the stack bool consumeMostSig; ///< True if resources are consumed starting with most significant bytes bool justifyRight; ///< True if initial bytes are padding for odd data-type sizes + bool fillAlternate; ///< True if a single primitive needs to fill an alternate tile int4 tileSize; ///< Number of bytes in a tile vector baseTiles; ///< General registers to be joined vector altTiles; ///< Alternate registers to be joined + const ParamEntry *stackEntry; ///< The stack resource void initializeEntries(void); ///< Cache specific ParamEntry needed by the action int4 getFirstUnused(int4 iter,const vector &tiles,vector &status) const; int4 getTileClass(const PrimitiveExtractor &primitives,int4 off,int4 &index) const; public: MultiSlotDualAssign(const ParamListStandard *res); ///< Constructor for use with decode - MultiSlotDualAssign(type_class baseStore,type_class altStore,bool mostSig,bool justRight, - const ParamListStandard *res); ///< Constructor + MultiSlotDualAssign(type_class baseStore,type_class altStore,bool stack,bool mostSig, + bool justRight,bool fillAlt,const ParamListStandard *res); ///< Constructor virtual AssignAction *clone(const ParamListStandard *newResource) const { - return new MultiSlotDualAssign(baseType,altType,consumeMostSig,justifyRight,newResource); } + return new MultiSlotDualAssign(baseType,altType,consumeFromStack,consumeMostSig,justifyRight, + fillAlternate,newResource); } virtual uint4 assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist, vector &status,ParameterPieces &res) const; virtual bool fillinOutputMap(ParamActive *active) const; @@ -484,13 +491,15 @@ public: /// stack resources as if the parameter were allocated to the stack. If the current parameter was /// already assigned a stack address, no additional action is taken. class ExtraStack : public AssignAction { + int4 afterBytes; ///< Activate side effect after given number of bytes consumed + type_class afterStorage; ///< Activate side effect after given amount of this storage consumed const ParamEntry *stackEntry; ///< Parameter Entry corresponding to the stack void initializeEntry(void); ///< Find stack entry in resource list public: - ExtraStack(const ParamListStandard *res,int4 val); ///< Constructor for use with decode - ExtraStack(const ParamListStandard *res); ///< Constructor + ExtraStack(const ParamListStandard *res); ///< Constructor for use with decode + ExtraStack(type_class storage,int4 offset,const ParamListStandard *res); ///< Constructor virtual AssignAction *clone(const ParamListStandard *newResource) const { - return new ExtraStack(newResource); } + return new ExtraStack(afterStorage,afterBytes,newResource); } virtual uint4 assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist, vector &status,ParameterPieces &res) const; virtual void decode(Decoder &decoder); diff --git a/Ghidra/Framework/SoftwareModeling/data/languages/compiler_spec.rxg b/Ghidra/Framework/SoftwareModeling/data/languages/compiler_spec.rxg index 02bc2f14c8..69b1f35320 100644 --- a/Ghidra/Framework/SoftwareModeling/data/languages/compiler_spec.rxg +++ b/Ghidra/Framework/SoftwareModeling/data/languages/compiler_spec.rxg @@ -449,6 +449,16 @@ + + + + + + + + + + @@ -461,6 +471,16 @@ + + + + + + + + + + @@ -474,13 +494,8 @@ - - - - - - - + + diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamEntry.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamEntry.java index 53f50a12e3..c7755f505c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamEntry.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamEntry.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. @@ -338,6 +338,22 @@ public class ParamEntry { * @return slotnum plus the number of slots used */ public int getAddrBySlot(int slotnum, int sz, int typeAlign, ParameterPieces res) { + return getAddrBySlot(slotnum, sz, typeAlign, res, !isLeftJustified()); + } + + /** + * Assign the storage address when allocating something of size -sz- assuming -slotnum- slots + * have already been assigned. Set the address to null if the -sz- is too small or if + * there are not enough slots left + * @param slotnum number of slots already assigned + * @param sz number of bytes to being assigned + * @param typeAlign required byte alignment for the parameter + * @param res will hold the final storage address + * @param justifyRight true if initial bytes are padding for odd data-type sizes + * @return slotnum plus the number of slots used + */ + public int getAddrBySlot(int slotnum, int sz, int typeAlign, ParameterPieces res, + boolean justifyRight) { int spaceused; long offset; res.address = null; // Start with an invalid result @@ -387,7 +403,7 @@ public class ParamEntry { offset = addressbase + index * alignment; slotnum += slotsused; // Inform caller of number of slots used } - if (!isLeftJustified()) { + if (justifyRight) { offset += (spaceused - sz); } res.address = spaceid.getAddress(offset); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/ExtraStack.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/ExtraStack.java index 4abd6630ae..b500ef275b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/ExtraStack.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/ExtraStack.java @@ -15,15 +15,19 @@ */ package ghidra.program.model.lang.protorules; +import static ghidra.program.model.pcode.AttributeId.*; import static ghidra.program.model.pcode.ElementId.*; import java.io.IOException; +import java.util.Iterator; +import java.util.Map.Entry; import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataTypeManager; import ghidra.program.model.lang.*; import ghidra.program.model.pcode.Encoder; import ghidra.util.exception.InvalidInputException; +import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.*; /** @@ -37,6 +41,8 @@ import ghidra.xml.*; public class ExtraStack extends AssignAction { private ParamEntry stackEntry; // Parameter entry corresponding to the stack + private int afterBytes; // Activate side effect after given number of bytes consumed + private StorageClass afterStorage; // Active side effect after given amount of this storage consumed /** * Find stack entry in resource list @@ -64,17 +70,22 @@ public class ExtraStack extends AssignAction { public ExtraStack(ParamListStandard res, int val) { super(res); stackEntry = null; + afterStorage = StorageClass.GENERAL; + afterBytes = -1; } - public ExtraStack(ParamListStandard res) throws InvalidInputException { + public ExtraStack(StorageClass storage, int offset, ParamListStandard res) + throws InvalidInputException { super(res); stackEntry = null; + afterStorage = storage; + afterBytes = offset; initializeEntry(); } @Override public AssignAction clone(ParamListStandard newResource) throws InvalidInputException { - return new ExtraStack(newResource); + return new ExtraStack(afterStorage, afterBytes, newResource); } @Override @@ -82,7 +93,13 @@ public class ExtraStack extends AssignAction { if (this.getClass() != op.getClass()) { return false; } + ExtraStack otherAction = (ExtraStack) op; + + if (afterBytes != otherAction.afterBytes || afterStorage != otherAction.afterStorage) { + return false; + } + return stackEntry.isEquivalent(otherAction.stackEntry); } @@ -93,6 +110,21 @@ public class ExtraStack extends AssignAction { return SUCCESS; // Parameter was already assigned to the stack } int grp = stackEntry.getGroup(); + // Check whether we have consumed enough storage to need to adjust stack yet + if (afterBytes > 0) { + int bytesConsumed = 0; + for (int i = 0; i < resource.getNumParamEntry(); i++) { + if (i == grp || resource.getEntry(i).getType() != afterStorage) { + continue; + } + if (status[i] != 0) { + bytesConsumed += resource.getEntry(i).getSize(); + } + } + if (bytesConsumed < afterBytes) { + return SUCCESS; // Don't yet need to consume extra stack space + } + } // We assign the stack address (but ignore the actual address) updating the status for the stack, // which consumes the stack resources. ParameterPieces unused = new ParameterPieces(); @@ -104,12 +136,34 @@ public class ExtraStack extends AssignAction { @Override public void encode(Encoder encoder) throws IOException { encoder.openElement(ELEM_EXTRA_STACK); + if (afterBytes >= 0) { + encoder.writeUnsignedInteger(ATTRIB_AFTER_BYTES, afterBytes); + } + if (afterStorage != StorageClass.GENERAL) { + encoder.writeString(ATTRIB_STORAGE, afterStorage.toString()); + } encoder.closeElement(ELEM_EXTRA_STACK); } + private void restoreAttributesXml(XmlElement el) throws XmlParseException { + Iterator> iter = el.getAttributes().entrySet().iterator(); + while (iter.hasNext()) { + Entry attrib = iter.next(); + String nm = attrib.getKey(); + if (nm.equals(ATTRIB_AFTER_BYTES.name())) { + afterBytes = SpecXmlUtils.decodeInt(attrib.getValue()); + } + else if (nm.equals(ATTRIB_AFTER_STORAGE.name())) { + afterStorage = StorageClass.getClass(attrib.getValue()); + } + } + + } + @Override public void restoreXml(XmlPullParser parser) throws XmlParseException { XmlElement elem = parser.start(ELEM_EXTRA_STACK.name()); + restoreAttributesXml(elem); parser.end(elem); try { initializeEntry(); 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 c84b69e238..8633e06048 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 @@ -227,7 +227,8 @@ public class MultiSlotAssign extends AssignAction { return FAIL; } int grp = stackEntry.getGroup(); - tmpStatus[grp] = stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, align, param); // Consume all the space we need + tmpStatus[grp] = + stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, align, param, justifyRight); // Consume all the space we need if (param.address == null) { return FAIL; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/MultiSlotDualAssign.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/MultiSlotDualAssign.java index 6223a0eb8c..3a9add487c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/MultiSlotDualAssign.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/MultiSlotDualAssign.java @@ -42,11 +42,14 @@ import ghidra.xml.*; public class MultiSlotDualAssign extends AssignAction { private StorageClass baseType; // Resource list from which to consume general tiles private StorageClass altType; // Resource list from which to consume alternate tiles + private boolean consumeFromStack; // True if resources can be consumed from the stack private boolean consumeMostSig; // True if resources are consumed starting with most significant bytes private boolean justifyRight; // True if initial bytes are padding for odd data-type sizes + private boolean fillAlternate; // True if a single primitive needs to fill an alternate tile private int tileSize; // Number of bytes in a tile private ParamEntry[] baseTiles; // General registers for joining - private ParamEntry[] altTiles; // Alternate registers for joininig + private ParamEntry[] altTiles; // Alternate registers for joining + private ParamEntry stackEntry; // The stack resource /** * Find the first ParamEntry matching the baseType, and the first matching altType. @@ -55,6 +58,7 @@ public class MultiSlotDualAssign extends AssignAction { private void initializeEntries() throws InvalidInputException { baseTiles = resource.extractTiles(baseType); altTiles = resource.extractTiles(altType); + stackEntry = resource.extractStack(); if (baseTiles.length == 0 || altTiles.length == 0) { throw new InvalidInputException( "Could not find matching resources for action: join_dual_class"); @@ -64,6 +68,10 @@ public class MultiSlotDualAssign extends AssignAction { throw new InvalidInputException( "Storage class register sizes do not match for action: join_dual_class"); } + if (consumeFromStack && stackEntry == null) { + throw new InvalidInputException( + "Cannot find matching stack resource for action: join_dual_class"); + } } /** @@ -101,6 +109,10 @@ public class MultiSlotDualAssign extends AssignAction { int res = 1; int count = 0; int endBoundary = off + tileSize; + if (index[0] >= primitives.size()) { + return -1; + } + Primitive firstPrimitive = primitives.get(index[0]); while (index[0] < primitives.size()) { Primitive element = primitives.get(index[0]); if (element.offset < off) { @@ -122,6 +134,14 @@ public class MultiSlotDualAssign extends AssignAction { if (count == 0) { return -1; // Must be at least one primitive in section } + if (fillAlternate) { // Only use altType if the tile contains one primitive of exactly the tile size + if (count > 1) { + res = 0; + } + if (firstPrimitive.dt.getLength() != tileSize) { + res = 0; + } + } return res; } @@ -133,29 +153,47 @@ public class MultiSlotDualAssign extends AssignAction { super(res); baseType = StorageClass.GENERAL; // Tile from general purpose registers altType = StorageClass.FLOAT; // Use specialized registers for floating-point components + consumeFromStack = false; consumeMostSig = false; justifyRight = false; if (res.getEntry(0).isBigEndian()) { consumeMostSig = true; justifyRight = true; } + fillAlternate = false; tileSize = 0; + stackEntry = null; } - public MultiSlotDualAssign(StorageClass baseStore, StorageClass altStore, boolean mostSig, - boolean justRight, ParamListStandard res) throws InvalidInputException { + /** + * Constructor + * @param baseStore resource list from which to consume general tiles + * @param altStore resource list form which to consume alternate tiles + * @param stack true if resources can be consumed from the stack + * @param mostSig true if resources are consumed starting with most significant bytes + * @param justRight true if initial bytes are padding for odd data-type sizes + * @param fillAlt true if a single primitive needs to fill an alternate tile + * @param res is the new resource set to associate with this action + * @throws InvalidInputException if the required elements are not available in the resource list + */ + public MultiSlotDualAssign(StorageClass baseStore, StorageClass altStore, boolean stack, + boolean mostSig, boolean justRight, boolean fillAlt, ParamListStandard res) + throws InvalidInputException { super(res); baseType = baseStore; altType = altStore; + consumeFromStack = stack; consumeMostSig = mostSig; justifyRight = justRight; + fillAlternate = fillAlt; + stackEntry = null; initializeEntries(); } @Override public AssignAction clone(ParamListStandard newResource) throws InvalidInputException { - return new MultiSlotDualAssign(baseType, altType, consumeMostSig, justifyRight, - newResource); + return new MultiSlotDualAssign(baseType, altType, consumeFromStack, consumeMostSig, + justifyRight, fillAlternate, newResource); } @Override @@ -164,8 +202,10 @@ public class MultiSlotDualAssign extends AssignAction { return false; } MultiSlotDualAssign otherAction = (MultiSlotDualAssign) op; - if (consumeMostSig != otherAction.consumeMostSig || - justifyRight != otherAction.justifyRight) { + if (consumeFromStack != otherAction.consumeFromStack || + consumeMostSig != otherAction.consumeMostSig || + justifyRight != otherAction.justifyRight || + fillAlternate != otherAction.fillAlternate) { return false; } if (baseType != otherAction.baseType || altType != otherAction.altType) { @@ -203,6 +243,7 @@ public class MultiSlotDualAssign extends AssignAction { int[] tmpStatus = status.clone(); ArrayList pieces = new ArrayList<>(); int typeSize = dt.getLength(); + int align = dt.getAlignment(); int sizeLeft = typeSize; int iterBase = 0; int iterAlt = 0; @@ -215,14 +256,20 @@ public class MultiSlotDualAssign extends AssignAction { if (iterType == 0) { iterBase = getFirstUnused(iterBase, baseTiles, tmpStatus); if (iterBase == baseTiles.length) { - return FAIL; // Out of general registers + if (!consumeFromStack) { + return FAIL; // Out of general registers + } + break; } entry = baseTiles[iterBase]; } else { iterAlt = getFirstUnused(iterAlt, altTiles, tmpStatus); if (iterAlt == altTiles.length) { - return FAIL; // Out of alternate registers + if (!consumeFromStack) { + return FAIL; // Out of alternate registers + } + break; } entry = altTiles[iterAlt]; } @@ -233,6 +280,19 @@ public class MultiSlotDualAssign extends AssignAction { pieces.add(vn); sizeLeft -= trialSize; } + if (sizeLeft > 0) { // Have to use stack to get enough bytes + if (!consumeFromStack) { + return FAIL; + } + int grp = stackEntry.getGroup(); + tmpStatus[grp] = + stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, align, param, justifyRight); + if (param.address == null) { + return FAIL; + } + Varnode vn = new Varnode(param.address, sizeLeft); + pieces.add(vn); + } if (sizeLeft < 0) { // Have odd data-type size if (justifyRight) { // Initial bytes of first entry are padding @@ -271,6 +331,8 @@ public class MultiSlotDualAssign extends AssignAction { if (altType != StorageClass.FLOAT) { encoder.writeString(ATTRIB_B, altType.toString()); } + encoder.writeBool(ATTRIB_STACKSPILL, consumeFromStack); + encoder.writeBool(ATTRIB_FILL_ALTERNATE, fillAlternate); encoder.closeElement(ELEM_JOIN); } @@ -295,6 +357,12 @@ public class MultiSlotDualAssign extends AssignAction { else if (name.equals(ATTRIB_B.name())) { altType = StorageClass.getClass(attrib.getValue()); } + else if (name.equals(ATTRIB_STACKSPILL.name())) { + consumeFromStack = SpecXmlUtils.decodeBoolean(attrib.getValue()); + } + else if (name.equals(ATTRIB_FILL_ALTERNATE.name())) { + fillAlternate = 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 16cc22e629..0f18141a79 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 @@ -247,10 +247,13 @@ public record AttributeId(String name, int id) { // modelrules public static final AttributeId ATTRIB_SIZES = new AttributeId("sizes", 151); public static final AttributeId ATTRIB_BACKFILL = new AttributeId("backfill", 152); - public static final AttributeId ATTRIB_MAX_PRIMITIVES = new AttributeId("maxprimitives", 153); public static final AttributeId ATTRIB_REVERSESIGNIF = new AttributeId("reversesignif", 154); public static final AttributeId ATTRIB_MATCHSIZE = new AttributeId("matchsize", 155); + public static final AttributeId ATTRIB_AFTER_BYTES = new AttributeId("afterbytes", 156); + public static final AttributeId ATTRIB_AFTER_STORAGE = new AttributeId("afterstorage", 157); + public static final AttributeId ATTRIB_FILL_ALTERNATE = new AttributeId("fillalternate", 158); + + public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 159); - public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 156); } diff --git a/Ghidra/Processors/MIPS/certification.manifest b/Ghidra/Processors/MIPS/certification.manifest index d7054bc7d0..278d3705ef 100644 --- a/Ghidra/Processors/MIPS/certification.manifest +++ b/Ghidra/Processors/MIPS/certification.manifest @@ -11,22 +11,22 @@ data/languages/mips32Instructions.sinc||GHIDRA||||END| data/languages/mips32R6.pspec||GHIDRA||||END| data/languages/mips32R6be.slaspec||GHIDRA||||END| data/languages/mips32R6le.slaspec||GHIDRA||||END| +data/languages/mips32_eabi.cspec||GHIDRA||||END| data/languages/mips32_fp64.cspec||GHIDRA||||END| data/languages/mips32be.cspec||GHIDRA||||END| data/languages/mips32be.slaspec||GHIDRA||||END| -data/languages/mips32be_eabi.cspec||GHIDRA||||END| data/languages/mips32le.cspec||GHIDRA||||END| data/languages/mips32le.slaspec||GHIDRA||||END| -data/languages/mips32le_eabi.cspec||GHIDRA||||END| data/languages/mips32micro.pspec||GHIDRA||||END| -data/languages/mips64.cspec||GHIDRA||||END| data/languages/mips64.pspec||GHIDRA||||END| data/languages/mips64Instructions.sinc||GHIDRA||||END| data/languages/mips64R6.pspec||GHIDRA||||END| data/languages/mips64_32_n32.cspec||GHIDRA||||END| data/languages/mips64_32_o32.cspec||GHIDRA||||END| data/languages/mips64_32_o64.cspec||GHIDRA||||END| +data/languages/mips64be.cspec||GHIDRA||||END| data/languages/mips64be.slaspec||GHIDRA||||END| +data/languages/mips64le.cspec||GHIDRA||||END| data/languages/mips64le.slaspec||GHIDRA||||END| data/languages/mips64micro.pspec||GHIDRA||||END| data/languages/mips_dsp.sinc||GHIDRA||||END| diff --git a/Ghidra/Processors/MIPS/data/languages/mips.ldefs b/Ghidra/Processors/MIPS/data/languages/mips.ldefs index 91b44bce2d..e61afe9a65 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips.ldefs +++ b/Ghidra/Processors/MIPS/data/languages/mips.ldefs @@ -12,7 +12,7 @@ MIPS32 32-bit addresses, big endian, with mips16e - + @@ -32,7 +32,7 @@ MIPS32 32-bit addresses, little endian, with mips16e - + @@ -82,7 +82,7 @@ manualindexfile="../manuals/mipsM16.idx" id="MIPS:BE:64:default"> MIPS64 64-bit addresses, big endian, with mips16e - + @@ -100,8 +100,8 @@ manualindexfile="../manuals/mipsM16.idx" id="MIPS:LE:64:default"> MIPS64 64-bit addreses, little endian, with mips16e - - + + @@ -119,7 +119,7 @@ manualindexfile="../manuals/mipsMic.idx" id="MIPS:BE:64:micro"> MIPS64 64-bit addresses, big endian, with microMIPS - + @@ -134,8 +134,8 @@ manualindexfile="../manuals/mipsMic.idx" id="MIPS:LE:64:micro"> MIPS64 64-bit addresses, little endian, with microMIPS - - + + @@ -150,7 +150,7 @@ manualindexfile="../manuals/mipsMic.idx" id="MIPS:BE:64:R6"> MIPS64 Release-6 64-bit addresses, big endian, with microMIPS - + @@ -167,8 +167,8 @@ manualindexfile="../manuals/mipsMic.idx" id="MIPS:LE:64:R6"> MIPS64 Release-6 64-bit addresses, little endian, with microMIPS - - + + diff --git a/Ghidra/Processors/MIPS/data/languages/mips32be_eabi.cspec b/Ghidra/Processors/MIPS/data/languages/mips32_eabi.cspec similarity index 68% rename from Ghidra/Processors/MIPS/data/languages/mips32be_eabi.cspec rename to Ghidra/Processors/MIPS/data/languages/mips32_eabi.cspec index 7236a93088..235b535150 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32be_eabi.cspec +++ b/Ghidra/Processors/MIPS/data/languages/mips32_eabi.cspec @@ -2,7 +2,12 @@ + + + + + @@ -65,6 +70,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -73,9 +106,21 @@ - - + + + + + + + + + + + + + + @@ -97,21 +142,11 @@ - - - - - - - - - - - - - - - + + + + + diff --git a/Ghidra/Processors/MIPS/data/languages/mips32be.cspec b/Ghidra/Processors/MIPS/data/languages/mips32be.cspec index c85f28c669..bd621b777a 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32be.cspec +++ b/Ghidra/Processors/MIPS/data/languages/mips32be.cspec @@ -25,6 +25,7 @@ + @@ -47,6 +48,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -55,9 +102,25 @@ - - + + + + + + + + + + + + + + + + + + @@ -72,12 +135,24 @@ + + + + + + + + + + + + diff --git a/Ghidra/Processors/MIPS/data/languages/mips32le.cspec b/Ghidra/Processors/MIPS/data/languages/mips32le.cspec index aa246286c7..13e5c29940 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32le.cspec +++ b/Ghidra/Processors/MIPS/data/languages/mips32le.cspec @@ -47,6 +47,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -55,9 +93,25 @@ - - + + + + + + + + + + + + + + + + + + @@ -72,12 +126,24 @@ + + + + + + + + + + + + diff --git a/Ghidra/Processors/MIPS/data/languages/mips32le_eabi.cspec b/Ghidra/Processors/MIPS/data/languages/mips32le_eabi.cspec deleted file mode 100644 index f4a6692004..0000000000 --- a/Ghidra/Processors/MIPS/data/languages/mips32le_eabi.cspec +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Ghidra/Processors/MIPS/data/languages/mips64.cspec b/Ghidra/Processors/MIPS/data/languages/mips64.cspec deleted file mode 100644 index e654191cc7..0000000000 --- a/Ghidra/Processors/MIPS/data/languages/mips64.cspec +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Ghidra/Processors/MIPS/data/languages/mips64be.cspec b/Ghidra/Processors/MIPS/data/languages/mips64be.cspec new file mode 100644 index 0000000000..dbcf456ca9 --- /dev/null +++ b/Ghidra/Processors/MIPS/data/languages/mips64be.cspec @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/MIPS/data/languages/mips64le.cspec b/Ghidra/Processors/MIPS/data/languages/mips64le.cspec new file mode 100644 index 0000000000..6cebc64913 --- /dev/null +++ b/Ghidra/Processors/MIPS/data/languages/mips64le.cspec @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/PowerPC/certification.manifest b/Ghidra/Processors/PowerPC/certification.manifest index 8894e81535..d54ea3210c 100644 --- a/Ghidra/Processors/PowerPC/certification.manifest +++ b/Ghidra/Processors/PowerPC/certification.manifest @@ -20,10 +20,10 @@ data/languages/old/oldPPC.lang||GHIDRA||||END| data/languages/old/oldPPC.trans||GHIDRA||||END| data/languages/ppc.dwarf||GHIDRA||||END| data/languages/ppc.ldefs||GHIDRA||||END| +data/languages/ppc_32.cspec||GHIDRA||||END| data/languages/ppc_32.pspec||GHIDRA||||END| data/languages/ppc_32_4xx_be.slaspec||GHIDRA||||END| data/languages/ppc_32_4xx_le.slaspec||GHIDRA||||END| -data/languages/ppc_32_be.cspec||GHIDRA||||END| data/languages/ppc_32_be.slaspec||GHIDRA||||END| data/languages/ppc_32_be_Mac.cspec||GHIDRA||||END| data/languages/ppc_32_e500_be.cspec||GHIDRA||||END| @@ -34,14 +34,13 @@ data/languages/ppc_32_e500mc_be.cspec||GHIDRA||||END| data/languages/ppc_32_e500mc_be.slaspec||GHIDRA||||END| data/languages/ppc_32_e500mc_le.cspec||GHIDRA||||END| data/languages/ppc_32_e500mc_le.slaspec||GHIDRA||||END| -data/languages/ppc_32_le.cspec||GHIDRA||||END| data/languages/ppc_32_le.slaspec||GHIDRA||||END| data/languages/ppc_32_mpc8270.pspec||GHIDRA||||END| data/languages/ppc_32_quicciii_be.slaspec||GHIDRA||||END| data/languages/ppc_32_quicciii_le.slaspec||GHIDRA||||END| -data/languages/ppc_64.cspec||GHIDRA||||END| data/languages/ppc_64.pspec||GHIDRA||||END| data/languages/ppc_64_32.cspec||GHIDRA||||END| +data/languages/ppc_64_be.cspec||GHIDRA||||END| data/languages/ppc_64_be.slaspec||GHIDRA||||END| data/languages/ppc_64_be_Mac.cspec||GHIDRA||||END| data/languages/ppc_64_isa_altivec_be.slaspec||GHIDRA||||END| @@ -50,6 +49,7 @@ data/languages/ppc_64_isa_altivec_vle_be.slaspec||GHIDRA||||END| data/languages/ppc_64_isa_be.slaspec||GHIDRA||||END| data/languages/ppc_64_isa_le.slaspec||GHIDRA||||END| data/languages/ppc_64_isa_vle_be.slaspec||GHIDRA||||END| +data/languages/ppc_64_le.cspec||GHIDRA||||END| data/languages/ppc_64_le.slaspec||GHIDRA||||END| data/languages/ppc_a2.sinc||GHIDRA||||END| data/languages/ppc_common.sinc||GHIDRA||||END| diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc.ldefs b/Ghidra/Processors/PowerPC/data/languages/ppc.ldefs index 797d554cab..742705f1a9 100644 --- a/Ghidra/Processors/PowerPC/data/languages/ppc.ldefs +++ b/Ghidra/Processors/PowerPC/data/languages/ppc.ldefs @@ -11,7 +11,7 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:BE:32:default"> PowerPC 32-bit big endian w/Altivec, G2 - + @@ -29,8 +29,8 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:LE:32:default"> PowerPC 32-bit little endian w/Altivec, G2 - - + + @@ -45,7 +45,7 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:BE:64:default"> PowerPC 64-bit big endian w/Altivec, G2 - + @@ -98,7 +98,7 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:LE:64:default"> PowerPC 64-bit little endian w/Altivec, G2 - + @@ -115,7 +115,7 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:BE:32:4xx"> PowerPC 4xx 32-bit big endian embedded core - + @@ -132,8 +132,8 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:LE:32:4xx"> PowerPC 4xx 32-bit little endian embedded core - - + + @@ -148,7 +148,7 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:BE:32:MPC8270"> Freescale MPC8280 32-bit big endian family (PowerQUICC-III) - + @@ -165,7 +165,7 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:BE:32:QUICC"> PowerQUICC-III 32-bit big endian family - + @@ -182,8 +182,8 @@ manualindexfile="../manuals/PowerPC.idx" id="PowerPC:LE:32:QUICC"> PowerQUICC-III 32-bit little endian family - - + + @@ -334,7 +334,7 @@ manualindexfile="../manuals/PowerISA.idx" id="PowerPC:BE:64:A2ALT"> Power ISA 3.0 Big Endian w/Altivec - + @@ -351,7 +351,7 @@ manualindexfile="../manuals/PowerISA.idx" id="PowerPC:LE:64:A2ALT"> Power ISA 3.0 Little Endian w/Altivec - + diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_32_le.cspec b/Ghidra/Processors/PowerPC/data/languages/ppc_32.cspec similarity index 70% rename from Ghidra/Processors/PowerPC/data/languages/ppc_32_le.cspec rename to Ghidra/Processors/PowerPC/data/languages/ppc_32.cspec index 655b4b1abd..4b87c03588 100644 --- a/Ghidra/Processors/PowerPC/data/languages/ppc_32_le.cspec +++ b/Ghidra/Processors/PowerPC/data/languages/ppc_32.cspec @@ -32,21 +32,6 @@ - - - - - - - - - - - - - - - @@ -74,6 +59,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -82,9 +87,17 @@ - - + + + + + + + + + + @@ -108,10 +121,33 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_32_be.cspec b/Ghidra/Processors/PowerPC/data/languages/ppc_32_be.cspec deleted file mode 100644 index c855a0b582..0000000000 --- a/Ghidra/Processors/PowerPC/data/languages/ppc_32_be.cspec +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_64_be.cspec b/Ghidra/Processors/PowerPC/data/languages/ppc_64_be.cspec new file mode 100644 index 0000000000..eac4523a90 --- /dev/null +++ b/Ghidra/Processors/PowerPC/data/languages/ppc_64_be.cspec @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Inject pcode when returning from a function call to place the r2Save + # value into 0x28(r1) which should be restored by the "ld r2,0x28(r1)" + # which immediately follows calls which comply with the PPC64 ABI spec. + local saveR2ptr = r1 + 0x28; + *:8 saveR2ptr = r2Save; + + + + + diff --git a/Ghidra/Processors/PowerPC/data/languages/ppc_64.cspec b/Ghidra/Processors/PowerPC/data/languages/ppc_64_le.cspec similarity index 58% rename from Ghidra/Processors/PowerPC/data/languages/ppc_64.cspec rename to Ghidra/Processors/PowerPC/data/languages/ppc_64_le.cspec index 7220be77b0..f6f8ecbf34 100644 --- a/Ghidra/Processors/PowerPC/data/languages/ppc_64.cspec +++ b/Ghidra/Processors/PowerPC/data/languages/ppc_64_le.cspec @@ -1,8 +1,28 @@ + - + + + + + + + + + + + + + + + + + + + @@ -50,33 +70,49 @@ - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + @@ -85,6 +121,14 @@ + + + + + + + + @@ -109,7 +153,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + # Inject pcode when returning from a function call to place the r2Save