mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GP-5851 Fix tiling truncations for odd data-type sizes in
MultiSlotAssign. Fix for big endian multi-slot return value.
This commit is contained in:
parent
eb7dbaa04f
commit
f6495e4146
13 changed files with 280 additions and 89 deletions
|
@ -167,6 +167,13 @@ public class ParamListStandard implements ParamList {
|
|||
return entry[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if resources are from a big endian address space
|
||||
*/
|
||||
public boolean isBigEndian() {
|
||||
return entry[0].isBigEndian();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignMap(PrototypePieces proto, DataTypeManager dtManager,
|
||||
ArrayList<ParameterPieces> res, boolean addAutoParams) {
|
||||
|
|
|
@ -18,11 +18,14 @@ package ghidra.program.model.lang.protorules;
|
|||
import static ghidra.program.model.pcode.ElementId.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
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.program.model.pcode.Varnode;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.xml.*;
|
||||
|
||||
|
@ -124,8 +127,7 @@ public abstract class AssignAction {
|
|||
action = new HiddenReturnAssign(res, HIDDENRET_SPECIALREG);
|
||||
}
|
||||
else if (nm.equals(ELEM_JOIN_PER_PRIMITIVE.name())) {
|
||||
boolean consumeMostSig = res.getEntry(0).isBigEndian();
|
||||
action = new MultiMemberAssign(StorageClass.GENERAL, false, consumeMostSig, res);
|
||||
action = new MultiMemberAssign(StorageClass.GENERAL, false, res.isBigEndian(), res);
|
||||
}
|
||||
else if (nm.equals(ELEM_JOIN_DUAL_CLASS.name())) {
|
||||
action = new MultiSlotDualAssign(res);
|
||||
|
@ -191,4 +193,20 @@ public abstract class AssignAction {
|
|||
action.restoreXml(parser);
|
||||
return action;
|
||||
}
|
||||
|
||||
public static void justifyPieces(ArrayList<Varnode> pieces, int offset, boolean isBigEndian,
|
||||
boolean consumeMostSig,
|
||||
boolean justifyRight) {
|
||||
boolean addOffset = isBigEndian ^ consumeMostSig ^ justifyRight;
|
||||
int pos = justifyRight ? 0 : pieces.size() - 1;
|
||||
|
||||
Varnode vn = pieces.get(pos);
|
||||
Address addr = vn.getAddress();
|
||||
if (addOffset) {
|
||||
addr = addr.add(offset);
|
||||
}
|
||||
int sz = vn.getSize() - offset;
|
||||
vn = new Varnode(addr, sz);
|
||||
pieces.set(pos, vn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.lang.*;
|
||||
|
@ -41,6 +40,7 @@ import ghidra.xml.*;
|
|||
*/
|
||||
public class MultiSlotAssign extends AssignAction {
|
||||
private StorageClass resourceType; // Resource list from which to consume
|
||||
private boolean isBigEndian; // True for big endian architectures
|
||||
private boolean consumeFromStack; // True if resources should be consumed from the stack
|
||||
private boolean consumeMostSig; // True if resources are consumed starting with most significant bytes
|
||||
private boolean enforceAlignment; // True if register resources are discarded to match alignment
|
||||
|
@ -74,6 +74,7 @@ public class MultiSlotAssign extends AssignAction {
|
|||
*/
|
||||
protected MultiSlotAssign(ParamListStandard res) {
|
||||
super(res);
|
||||
isBigEndian = res.isBigEndian();
|
||||
resourceType = StorageClass.GENERAL; // Join general purpose registers
|
||||
consumeFromStack = !(res instanceof ParamListStandardOut); // Spill into stack by default
|
||||
consumeMostSig = false;
|
||||
|
@ -81,7 +82,7 @@ public class MultiSlotAssign extends AssignAction {
|
|||
justifyRight = false;
|
||||
adjacentEntries = true;
|
||||
allowBackfill = false;
|
||||
if (res.getEntry(0).isBigEndian()) {
|
||||
if (isBigEndian) {
|
||||
consumeMostSig = true;
|
||||
justifyRight = true;
|
||||
}
|
||||
|
@ -92,6 +93,7 @@ public class MultiSlotAssign extends AssignAction {
|
|||
boolean justRight, boolean backfill, ParamListStandard res)
|
||||
throws InvalidInputException {
|
||||
super(res);
|
||||
isBigEndian = res.isBigEndian();
|
||||
resourceType = store;
|
||||
consumeFromStack = stack;
|
||||
consumeMostSig = mostSig;
|
||||
|
@ -240,20 +242,8 @@ public class MultiSlotAssign extends AssignAction {
|
|||
// Floating-point register holding extended lower precision value
|
||||
onePieceJoin = true; // Treat as "join" of full size register
|
||||
}
|
||||
else if (justifyRight) {
|
||||
// Initial bytes are padding
|
||||
Varnode vn = pieces.get(0);
|
||||
Address addr = vn.getAddress().add(-sizeLeft);
|
||||
int sz = vn.getSize() + sizeLeft;
|
||||
vn = new Varnode(addr, sz);
|
||||
pieces.set(0, vn);
|
||||
}
|
||||
else {
|
||||
int end = pieces.size() - 1;
|
||||
Varnode vn = pieces.get(end);
|
||||
int sz = vn.getSize() + sizeLeft;
|
||||
vn = new Varnode(vn.getAddress(), sz);
|
||||
pieces.set(end, vn);
|
||||
justifyPieces(pieces, -sizeLeft, isBigEndian, consumeMostSig, justifyRight);
|
||||
}
|
||||
}
|
||||
System.arraycopy(tmpStatus, 0, status, 0, tmpStatus.length); // Commit resource usage for all the pieces
|
||||
|
@ -265,10 +255,10 @@ public class MultiSlotAssign extends AssignAction {
|
|||
@Override
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_JOIN);
|
||||
if (resource.getEntry(0).isBigEndian() != justifyRight) {
|
||||
if (resource.isBigEndian() != justifyRight) {
|
||||
encoder.writeBool(ATTRIB_REVERSEJUSTIFY, true);
|
||||
}
|
||||
if (resource.getEntry(0).isBigEndian() != consumeMostSig) {
|
||||
if (resource.isBigEndian() != consumeMostSig) {
|
||||
encoder.writeBool(ATTRIB_REVERSESIGNIF, true);
|
||||
}
|
||||
if (resourceType != StorageClass.GENERAL) {
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.lang.*;
|
||||
|
@ -42,6 +41,7 @@ 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 isBigEndian; // True for big endian architectures
|
||||
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
|
||||
|
@ -151,12 +151,13 @@ public class MultiSlotDualAssign extends AssignAction {
|
|||
*/
|
||||
protected MultiSlotDualAssign(ParamListStandard res) {
|
||||
super(res);
|
||||
isBigEndian = res.isBigEndian();
|
||||
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()) {
|
||||
if (isBigEndian) {
|
||||
consumeMostSig = true;
|
||||
justifyRight = true;
|
||||
}
|
||||
|
@ -180,6 +181,7 @@ public class MultiSlotDualAssign extends AssignAction {
|
|||
boolean mostSig, boolean justRight, boolean fillAlt, ParamListStandard res)
|
||||
throws InvalidInputException {
|
||||
super(res);
|
||||
isBigEndian = res.isBigEndian();
|
||||
baseType = baseStore;
|
||||
altType = altStore;
|
||||
consumeFromStack = stack;
|
||||
|
@ -294,21 +296,7 @@ public class MultiSlotDualAssign extends AssignAction {
|
|||
pieces.add(vn);
|
||||
}
|
||||
if (sizeLeft < 0) { // Have odd data-type size
|
||||
if (justifyRight) {
|
||||
// Initial bytes of first entry are padding
|
||||
Varnode vn = pieces.get(0);
|
||||
Address addr = vn.getAddress().add(-sizeLeft);
|
||||
int sz = vn.getSize() + sizeLeft;
|
||||
vn = new Varnode(addr, sz);
|
||||
pieces.set(0, vn);
|
||||
}
|
||||
else {
|
||||
int end = pieces.size() - 1;
|
||||
Varnode vn = pieces.get(end);
|
||||
int sz = vn.getSize() + sizeLeft;
|
||||
vn = new Varnode(vn.getAddress(), sz);
|
||||
pieces.set(end, vn);
|
||||
}
|
||||
justifyPieces(pieces, -sizeLeft, isBigEndian, consumeMostSig, justifyRight);
|
||||
}
|
||||
System.arraycopy(tmpStatus, 0, status, 0, tmpStatus.length); // Commit resource usage for all the pieces
|
||||
res.type = dt;
|
||||
|
@ -319,10 +307,10 @@ public class MultiSlotDualAssign extends AssignAction {
|
|||
@Override
|
||||
public void encode(Encoder encoder) throws IOException {
|
||||
encoder.openElement(ELEM_JOIN_DUAL_CLASS);
|
||||
if (resource.getEntry(0).isBigEndian() != justifyRight) {
|
||||
if (resource.isBigEndian() != justifyRight) {
|
||||
encoder.writeBool(ATTRIB_REVERSEJUSTIFY, true);
|
||||
}
|
||||
if (resource.getEntry(0).isBigEndian() != consumeMostSig) {
|
||||
if (resource.isBigEndian() != consumeMostSig) {
|
||||
encoder.writeBool(ATTRIB_REVERSESIGNIF, true);
|
||||
}
|
||||
if (baseType != StorageClass.GENERAL) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue