Skip to content

Commit f765690

Browse files
committed
Merge remote-tracking branch 'origin/patch'
2 parents cc2e634 + 89de5d2 commit f765690

File tree

7 files changed

+91
-37
lines changed

7 files changed

+91
-37
lines changed

Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,8 @@ void ParamListStandard::assignMap(const PrototypePieces &proto,TypeFactory &type
731731
for(int4 i=0;i<proto.intypes.size();++i) {
732732
res.emplace_back();
733733
Datatype *dt = proto.intypes[i];
734-
if (assignAddress(dt,proto,i,typefactory,status,res.back()) == AssignAction::fail)
734+
uint4 responseCode = assignAddress(dt,proto,i,typefactory,status,res.back());
735+
if (responseCode == AssignAction::fail || responseCode == AssignAction::no_assignment)
735736
throw ParamUnassignedError("Cannot assign parameter address for " + dt->getName());
736737
}
737738
}
@@ -1503,7 +1504,12 @@ void ParamListStandardOut::assignMap(const PrototypePieces &proto,TypeFactory &t
15031504
return; // Leave the address as invalid
15041505
}
15051506
uint4 responseCode = assignAddress(proto.outtype,proto,-1,typefactory,status,res.back());
1506-
if (responseCode != AssignAction::success) { // Could not assign an address (too big)
1507+
1508+
if (responseCode == AssignAction::fail)
1509+
responseCode = AssignAction::hiddenret_ptrparam; // Invoke default hidden return input assignment action
1510+
1511+
if (responseCode == AssignAction::hiddenret_ptrparam || responseCode == AssignAction::hiddenret_specialreg ||
1512+
responseCode == AssignAction::hiddenret_specialreg_void) { // Could not assign an address (too big)
15071513
AddrSpace *spc = spacebase;
15081514
if (spc == (AddrSpace *)0)
15091515
spc = typefactory.getArch()->getDefaultDataSpace();

Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.cc

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ AssignAction *AssignAction::decodeAction(Decoder &decoder,const ParamListStandar
356356
action = new ConvertToPointer(res);
357357
}
358358
else if (elemId == ELEM_HIDDEN_RETURN) {
359-
action = new HiddenReturnAssign(res,false);
359+
action = new HiddenReturnAssign(res,hiddenret_specialreg);
360360
}
361361
else if (elemId == ELEM_JOIN_PER_PRIMITIVE) {
362362
bool consumeMostSig = false;
@@ -721,10 +721,10 @@ void ConsumeAs::decode(Decoder &decoder)
721721
decoder.closeElement(elemId);
722722
}
723723

724-
HiddenReturnAssign::HiddenReturnAssign(const ParamListStandard *res,bool voidLock)
724+
HiddenReturnAssign::HiddenReturnAssign(const ParamListStandard *res,uint4 code)
725725
: AssignAction(res)
726726
{
727-
retCode = voidLock ? hiddenret_specialreg_void : hiddenret_specialreg;
727+
retCode = code;
728728
}
729729

730730
uint4 HiddenReturnAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist,
@@ -736,12 +736,24 @@ uint4 HiddenReturnAssign::assignAddress(Datatype *dt,const PrototypePieces &prot
736736
void HiddenReturnAssign::decode(Decoder &decoder)
737737

738738
{
739+
retCode = hiddenret_specialreg;
739740
uint4 elemId = decoder.openElement(ELEM_HIDDEN_RETURN);
740-
uint4 attribId = decoder.getNextAttributeId();
741-
if (attribId == ATTRIB_VOIDLOCK)
742-
retCode = hiddenret_specialreg_void;
743-
else
744-
retCode = hiddenret_specialreg;
741+
for(;;) {
742+
uint4 attribId = decoder.getNextAttributeId();
743+
if (attribId == ATTRIB_VOIDLOCK)
744+
retCode = hiddenret_specialreg_void;
745+
else if (attribId == ATTRIB_STRATEGY) {
746+
string strategyString = decoder.readString();
747+
if (strategyString == "normalparam")
748+
retCode = hiddenret_ptrparam;
749+
else if (strategyString == "special")
750+
retCode = hiddenret_specialreg;
751+
else
752+
throw DecoderError("Bad <hidden_return> strategy: " + strategyString);
753+
}
754+
else
755+
break;
756+
}
745757
decoder.closeElement(elemId);
746758
}
747759

Ghidra/Features/Decompiler/src/decompile/cpp/modelrules.hh

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ class AssignAction {
200200
public:
201201
enum {
202202
success, ///< Data-type is fully assigned
203-
fail, ///< Action could not be applied (not enough resources)
203+
fail, ///< Action could not be applied
204+
no_assignment, ///< Do not assign storage for this parameter
204205
hiddenret_ptrparam, ///< Hidden return pointer as first input parameter
205206
hiddenret_specialreg, ///< Hidden return pointer in dedicated input register
206207
hiddenret_specialreg_void ///< Hidden return pointer, but no normal return
@@ -327,19 +328,24 @@ public:
327328
virtual void decode(Decoder &decoder);
328329
};
329330

330-
/// \brief Allocate the return value as special input register
331+
/// \brief Allocate the return value as an input parameter
331332
///
332-
/// The assignAddress() method signals with \b hiddenret_specialreg, indicating that the
333-
/// input register assignMap() method should use storage class TYPECLASS_HIDDENRET to assign
334-
/// an additional input register to hold a pointer to the return value. This is different than
335-
/// the default \e hiddenret action that assigns a location based TYPECLASS_PTR and generally
336-
/// consumes a general purpose input register.
333+
/// A pointer to where the return value is to be stored is passed in as an input parameter.
334+
/// This action signals this by returning one of
335+
/// - \b hiddenret_ptrparam - indicating the pointer is allocated as a normal input parameter
336+
/// - \b hiddenret_specialreg - indicating the pointer is passed in a dedicated register
337+
/// - \b hiddenret_specialreg_void
338+
///
339+
/// Usually, if a hidden return input is present, the normal register used for return
340+
/// will also hold the pointer at the point(s) where the function returns. A signal of
341+
/// \b hiddenret_specialreg_void indicates the normal return register is not used to pass back
342+
/// the pointer.
337343
class HiddenReturnAssign : public AssignAction {
338344
uint4 retCode; ///< The specific signal to pass back
339345
public:
340-
HiddenReturnAssign(const ParamListStandard *res,bool voidLock); ///< Constructor
346+
HiddenReturnAssign(const ParamListStandard *res,uint4 code); ///< Constructor
341347
virtual AssignAction *clone(const ParamListStandard *newResource) const {
342-
return new HiddenReturnAssign(newResource, retCode == hiddenret_specialreg_void); }
348+
return new HiddenReturnAssign(newResource, retCode); }
343349
virtual uint4 assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist,
344350
vector<int4> &status,ParameterPieces &res) const;
345351
virtual void decode(Decoder &decoder);

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandard.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public int assignAddress(DataType dt, PrototypePieces proto, int pos, DataTypeMa
131131

132132
{
133133
if (dt.isZeroLength()) {
134-
return AssignAction.FAIL;
134+
return AssignAction.NO_ASSIGNMENT;
135135
}
136136
for (ModelRule modelRule : modelRules) {
137137
int responseCode = modelRule.assignAddress(dt, proto, pos, dtManager, status, res);
@@ -183,7 +183,7 @@ public void assignMap(PrototypePieces proto, DataTypeManager dtManager,
183183
ParameterPieces store = new ParameterPieces();
184184
res.add(store);
185185
int resCode = assignAddress(proto.intypes.get(i), proto, i, dtManager, status, store);
186-
if (resCode == AssignAction.FAIL) {
186+
if (resCode == AssignAction.FAIL || resCode == AssignAction.NO_ASSIGNMENT) {
187187
// Do not continue to assign after first failure
188188
++i;
189189
while (i < proto.intypes.size()) {

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/ParamListStandardOut.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ public void assignMap(PrototypePieces proto, DataTypeManager dtManager,
5050
return; // Don't assign storage for VOID
5151
}
5252
int responseCode = assignAddress(proto.outtype, proto, -1, dtManager, status, store);
53-
if (responseCode != AssignAction.SUCCESS) {
53+
if (responseCode == AssignAction.FAIL) {
54+
// Invoke default hidden return input assignment action
55+
responseCode = AssignAction.HIDDENRET_PTRPARAM;
56+
}
57+
if (responseCode == AssignAction.HIDDENRET_PTRPARAM ||
58+
responseCode == AssignAction.HIDDENRET_SPECIALREG ||
59+
responseCode == AssignAction.HIDDENRET_SPECIALREG_VOID) {
5460
// If the storage is not assigned (because the datatype is too big) create a hidden input parameter
5561
int sz = (spacebase == null) ? -1 : spacebase.getPointerSize();
5662
DataType pointerType = dtManager.getPointer(proto.outtype, sz);

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/AssignAction.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@
3535
*/
3636
public abstract class AssignAction {
3737
public static final int SUCCESS = 0; // Data-type is fully assigned
38-
public static final int FAIL = 1; // Action could not be applied (not enough resources)
39-
public static final int HIDDENRET_PTRPARAM = 2; // Hidden return pointer as first input parameter
40-
public static final int HIDDENRET_SPECIALREG = 3; // Hidden return pointer in special register
41-
public static final int HIDDENRET_SPECIALREG_VOID = 4; // Hidden return pointer, but no normal return
38+
public static final int FAIL = 1; // Action could not be applied
39+
public static final int NO_ASSIGNMENT = 2; // Do not assign a storage location
40+
public static final int HIDDENRET_PTRPARAM = 3; // Hidden return pointer as first input parameter
41+
public static final int HIDDENRET_SPECIALREG = 4; // Hidden return pointer in special register
42+
public static final int HIDDENRET_SPECIALREG_VOID = 5; // Hidden return pointer, but no normal return
4243

4344
protected ParamListStandard resource; // Resources to which this action applies
4445

@@ -120,7 +121,7 @@ else if (nm.equals(ELEM_CONVERT_TO_PTR.name())) {
120121
action = new ConvertToPointer(res);
121122
}
122123
else if (nm.equals(ELEM_HIDDEN_RETURN.name())) {
123-
action = new HiddenReturnAssign(res, false);
124+
action = new HiddenReturnAssign(res, HIDDENRET_SPECIALREG);
124125
}
125126
else if (nm.equals(ELEM_JOIN_PER_PRIMITIVE.name())) {
126127
boolean consumeMostSig = res.getEntry(0).isBigEndian();

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/protorules/HiddenReturnAssign.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,34 @@
2929
import ghidra.xml.*;
3030

3131
/**
32-
* Allocate the return value as special input register
32+
* Allocate the return value as an input parameter
3333
*
34-
* The assignAddress() method signals with hiddenret_specialreg, indicating that the
35-
* input register assignMap() method should use storage class TYPECLASS_HIDDENRET to assign
36-
* an additional input register to hold a pointer to the return value. This is different than
37-
* the default hiddenret action that assigns a location based TYPECLASS_PTR and generally
38-
* consumes a general purpose input register.
34+
* A pointer to where the return value is to be stored is passed in as an input parameter.
35+
* This action signals this by returning one of
36+
* - HIDDENRET_PTRPARAM - indicating the pointer is allocated as a normal input parameter
37+
* - HIDDENRET_SPECIALREG - indicating the pointer is passed in a dedicated register
38+
* - HIDDENRET_SPECIALREG_VOID
39+
*
40+
* Usually, if a hidden return input is present, the normal register used for return
41+
* will also hold the pointer at the point(s) where the function returns. A signal of
42+
* HIDDENRET_SPECIALREG_VOID indicates the normal return register is not used to pass back
43+
* the pointer.
3944
*/
4045
public class HiddenReturnAssign extends AssignAction {
4146

47+
static public final String STRATEGY_SPECIAL = "special"; // Return pointer in special reg
48+
static public final String STRATEGY_NORMAL = "normalparam"; // Return pointer as normal param
49+
4250
private int retCode; // The specific signal to pass back
4351

44-
public HiddenReturnAssign(ParamListStandard res, boolean voidLock) {
52+
public HiddenReturnAssign(ParamListStandard res, int code) {
4553
super(res);
46-
retCode = voidLock ? HIDDENRET_SPECIALREG_VOID : HIDDENRET_SPECIALREG;
54+
retCode = code;
4755
}
4856

4957
@Override
5058
public AssignAction clone(ParamListStandard newResource) throws InvalidInputException {
51-
return new HiddenReturnAssign(newResource, retCode == HIDDENRET_SPECIALREG_VOID);
59+
return new HiddenReturnAssign(newResource, retCode);
5260
}
5361

5462
@Override
@@ -69,7 +77,10 @@ public int assignAddress(DataType dt, PrototypePieces proto, int pos, DataTypeMa
6977
@Override
7078
public void encode(Encoder encoder) throws IOException {
7179
encoder.openElement(ELEM_HIDDEN_RETURN);
72-
if (retCode == HIDDENRET_SPECIALREG_VOID) {
80+
if (retCode == HIDDENRET_PTRPARAM) {
81+
encoder.writeString(ATTRIB_STRATEGY, STRATEGY_NORMAL);
82+
}
83+
else if (retCode == HIDDENRET_SPECIALREG_VOID) {
7384
encoder.writeBool(ATTRIB_VOIDLOCK, true);
7485
}
7586
encoder.closeElement(ELEM_HIDDEN_RETURN);
@@ -79,6 +90,18 @@ public void encode(Encoder encoder) throws IOException {
7990
public void restoreXml(XmlPullParser parser) throws XmlParseException {
8091
retCode = HIDDENRET_SPECIALREG;
8192
XmlElement elem = parser.start(ELEM_HIDDEN_RETURN.name());
93+
String strategyString = elem.getAttribute(ATTRIB_STRATEGY.name());
94+
if (strategyString != null) {
95+
if (strategyString.equals(STRATEGY_NORMAL)) {
96+
retCode = HIDDENRET_PTRPARAM;
97+
}
98+
else if (strategyString.equals(STRATEGY_SPECIAL)) {
99+
retCode = HIDDENRET_SPECIALREG;
100+
}
101+
else {
102+
throw new XmlParseException("Bad <hidden_return> strategy: " + strategyString);
103+
}
104+
}
82105
String voidLockString = elem.getAttribute(ATTRIB_VOIDLOCK.name());
83106
if (SpecXmlUtils.decodeBoolean(voidLockString)) {
84107
retCode = HIDDENRET_SPECIALREG_VOID;

0 commit comments

Comments
 (0)