Skip to content

Commit 04f7366

Browse files
committed
Merge remote-tracking branch 'origin/GT-3150_James_add_override_warnings' into Ghidra_9.1
2 parents a22ee1f + a752302 commit 04f7366

File tree

4 files changed

+103
-14
lines changed

4 files changed

+103
-14
lines changed

Ghidra/Features/Base/src/main/help/help/topics/ReferencesPlugin/References_from.htm

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,10 @@ <H2><A name="refTypes"></A>Ref-Types<BR>
742742
<TD valign="top">Used to change CALLOTHER pcode operations to CALL operations. The new call target is the "to" address of the
743743
reference. The override only takes effect when the reference is primary, and only when there is exactly one primary
744744
CALLOTHER_OVERRIDE_CALL reference at the "from" address of the reference. Only the first CALLOTHER operation at the "from"
745-
address of the reference is changed. Note that this reference override takes precedence over those of CALLOTHER_OVERRIDE_JUMP
746-
references. <BR>
745+
address of the reference is changed. <EM> Applying this override to instances of a CALLOTHER op that have output is not recommended
746+
and can adversely affect decompilation. </EM> You can see whether a particular instance has an output by enabling the "PCode" field
747+
of the Listing. Note that this reference override takes precedence over those of CALLOTHER_OVERRIDE_JUMP
748+
references. <BR>
747749
</TD>
748750
</TR>
749751

@@ -760,7 +762,8 @@ <H2><A name="refTypes"></A>Ref-Types<BR>
760762
<TD valign="top">Used to change CALLOTHER pcode operations to BRANCH operations. The new jump target is the "to" address of the
761763
reference. The override only takes effect when the reference is primary, and only when there is exactly one primary
762764
CALLOTHER_OVERRIDE_JUMP reference at the "from" address of the reference. Only the first CALLOTHER operation at the "from"
763-
address of the reference is changed. <BR>
765+
address of the reference is changed. <EM> Applying this override to an instance of a CALLOTHER op with output is not recommended </EM> (see
766+
the discussion above about CALLOTHER_OVERRIDE_CALL references).<BR>
764767
</TD>
765768
</TR>
766769

Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PostCommentFieldFactory.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,13 @@ private String[] getAutoPostComment(CodeUnit cu) {
223223
if (overrideData.hasMultipleCallOthers()) {
224224
comments.addFirst("-- WARNING: additional CALLOTHER ops present");
225225
}
226-
comments.addFirst(callOtherCallOverrideComment);
226+
String outputWarningString = overrideData.getOutputWarningString();
227+
if (outputWarningString != null) {
228+
comments.addFirst(outputWarningString);
229+
}
230+
else {
231+
comments.addFirst(callOtherCallOverrideComment);
232+
}
227233
}
228234
else {
229235
overrideData =
@@ -237,7 +243,13 @@ private String[] getAutoPostComment(CodeUnit cu) {
237243
if (overrideData.hasMultipleCallOthers()) {
238244
comments.addFirst("-- WARNING: additional CALLOTHER ops present");
239245
}
240-
comments.addFirst(callOtherJumpOverrideComment);
246+
String outputWarningString = overrideData.getOutputWarningString();
247+
if (outputWarningString != null) {
248+
comments.addFirst(outputWarningString);
249+
}
250+
else {
251+
comments.addFirst(callOtherJumpOverrideComment);
252+
}
241253
}
242254
}
243255
}
@@ -596,13 +608,19 @@ else if (type.equals(RefType.CALLOTHER_OVERRIDE_CALL) ||
596608
boolean hasMultipleCallOthers = false;
597609
//used to report the name of the CALLOTHER op that is overridden
598610
String callOtherName = null;
611+
String outputWarningString = null;
599612
for (PcodeOp op : pcodeOps) {
600613
if (ops.contains(op.getOpcode())) {
601614
hasAppropriatePcodeOp = true;
602615
if (op.getOpcode() == PcodeOp.CALLOTHER) {
603616
if (callOtherName == null) {
604617
callOtherName = inst.getProgram().getLanguage().getUserDefinedOpName(
605618
(int) op.getInput(0).getOffset());
619+
if (op.getOutput() != null) {
620+
outputWarningString =
621+
"WARNING: Output of " + callOtherName +
622+
" destroyed by override!";
623+
}
606624
}
607625
else {
608626
hasMultipleCallOthers = true;
@@ -618,21 +636,22 @@ else if (type.equals(RefType.CALLOTHER_OVERRIDE_CALL) ||
618636
if (type.equals(RefType.CALL_OVERRIDE_UNCONDITIONAL)) {
619637
Address ref = pcodeOverride.getOverridingReference(type);
620638
if (ref != null) {
621-
return new OverrideCommentData(ref, null, false);
639+
return new OverrideCommentData(ref, null, false, outputWarningString);
622640
}
623641
return null;
624642
}
625643
if (type.equals(RefType.JUMP_OVERRIDE_UNCONDITIONAL)) {
626644
Address ref = pcodeOverride.getOverridingReference(type);
627645
if (ref != null) {
628-
return new OverrideCommentData(ref, null, false);
646+
return new OverrideCommentData(ref, null, false, outputWarningString);
629647
}
630648
return null;
631649
}
632650
if (type.equals(RefType.CALLOTHER_OVERRIDE_CALL)) {
633651
Address ref = pcodeOverride.getOverridingReference(type);
634652
if (ref != null) {
635-
return new OverrideCommentData(ref, callOtherName, hasMultipleCallOthers);
653+
return new OverrideCommentData(ref, callOtherName, hasMultipleCallOthers,
654+
outputWarningString);
636655
}
637656
return null;
638657
}
@@ -645,20 +664,23 @@ else if (type.equals(RefType.CALLOTHER_OVERRIDE_CALL) ||
645664
if (ref == null) {
646665
return null;
647666
}
648-
return new OverrideCommentData(ref, callOtherName, hasMultipleCallOthers);
667+
return new OverrideCommentData(ref, callOtherName, hasMultipleCallOthers,
668+
outputWarningString);
649669

650670
}
651671

652672
private class OverrideCommentData {
653673
private Address overridingRef;
654674
private String overriddenCallOther;
655675
private boolean hasMultipleCallOthers;
676+
private String outputWarningString = null;
656677

657678
OverrideCommentData(Address overridingRef, String overriddenCallOther,
658-
boolean multipleCallOthers) {
679+
boolean multipleCallOthers, String outputWarningString) {
659680
this.overridingRef = overridingRef;
660681
this.overriddenCallOther = overriddenCallOther;
661682
this.hasMultipleCallOthers = multipleCallOthers;
683+
this.outputWarningString = outputWarningString;
662684
}
663685

664686
Address getOverridingRef() {
@@ -673,6 +695,9 @@ boolean hasMultipleCallOthers() {
673695
return hasMultipleCallOthers;
674696
}
675697

698+
String getOutputWarningString() {
699+
return outputWarningString;
700+
}
676701
}
677702

678703
}

Ghidra/Features/Base/src/test.slow/java/ghidra/app/util/viewer/field/PostCommentFieldFactoryTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ private ProgramDB buildProgram() throws Exception {
161161
builder.disassemble("100d000", 2);
162162
builder.createReturnInstruction("100d002");
163163

164+
builder.createEmptyFunction("override_warning", "0x100e000", 10, null);
165+
builder.setBytes("100e000", "a6 00");
166+
builder.disassemble("100e000", 2);
167+
builder.createReturnInstruction("100e002");
168+
builder.createEmptyFunction("call_dest_12", "0x100e020", 10, null);
169+
164170

165171
return builder.getProgram();
166172
}
@@ -1007,6 +1013,57 @@ public void testMultipleOps2() {
10071013
tf.getText());
10081014
}
10091015

1016+
@Test
1017+
public void testOverrideWarnings() {
1018+
assertFalse(cb.goToField(addr("100e000"), PostCommentFieldFactory.FIELD_NAME, 0, 1));
1019+
//verify CALLOTHER_OVERRIDE_CALL warning
1020+
int transactionID = program.startTransaction("call_warning");
1021+
ReferenceManager refManager = program.getReferenceManager();
1022+
Reference ref = null;
1023+
try {
1024+
ref = refManager.addMemoryReference(addr("100e000"), addr("100e020"),
1025+
RefType.CALLOTHER_OVERRIDE_CALL, SourceType.ANALYSIS, 0);
1026+
refManager.setPrimary(ref, true);
1027+
}
1028+
finally {
1029+
program.endTransaction(transactionID, true);
1030+
}
1031+
assertTrue(cb.goToField(addr("100e000"), PostCommentFieldFactory.FIELD_NAME, 0, 1));
1032+
ListingField tf = cb.getCurrentField();
1033+
assertEquals("WARNING: Output of pcodeop_one destroyed by override!", tf.getText());
1034+
//set ref non-primary, verify that warning goes away
1035+
transactionID = program.startTransaction("turn_off_call_warning");
1036+
try {
1037+
refManager.setPrimary(ref, false);
1038+
}
1039+
finally {
1040+
program.endTransaction(transactionID, true);
1041+
}
1042+
assertFalse(cb.goToField(addr("100e000"), PostCommentFieldFactory.FIELD_NAME, 0, 1));
1043+
//verify CALLOTHER_OVERRIDE_JUMP warning
1044+
transactionID = program.startTransaction("jump_warning");
1045+
try {
1046+
ref = refManager.addMemoryReference(addr("100e000"), addr("100e020"),
1047+
RefType.CALLOTHER_OVERRIDE_JUMP, SourceType.ANALYSIS, 0);
1048+
refManager.setPrimary(ref, true);
1049+
}
1050+
finally {
1051+
program.endTransaction(transactionID, true);
1052+
}
1053+
assertTrue(cb.goToField(addr("100e000"), PostCommentFieldFactory.FIELD_NAME, 0, 1));
1054+
assertEquals("WARNING: Output of pcodeop_one destroyed by override!", tf.getText());
1055+
//set ref non-primary, verify that warning goes away
1056+
transactionID = program.startTransaction("turn_off_jump_warning");
1057+
try {
1058+
refManager.setPrimary(ref, false);
1059+
}
1060+
finally {
1061+
program.endTransaction(transactionID, true);
1062+
}
1063+
assertFalse(cb.goToField(addr("100e000"), PostCommentFieldFactory.FIELD_NAME, 0, 1));
1064+
1065+
}
1066+
10101067
private void setCommentInFunction(Function function, String comment) {
10111068
CodeUnit cu = program.getListing().getCodeUnitAt(function.getEntryPoint());
10121069
int transactionID = program.startTransaction("test");

Ghidra/Processors/Toy/data/languages/toyInstructions.sinc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,12 @@
5555
# 1111 1nnn nnnn nnnn # call n call n
5656
#
5757
#### user-defined
58-
# 1010 0010 ssss 0000 # user_one rs user_one rs
59-
# 1010 0010 ssss 0000 # user_two rs user_two rs
60-
# 1010 0011 0000 0000 # user_three user_three
61-
# 1010 0100 ssss tttt # user_four rs rt user_four rs rt
58+
# 1010 0010 ssss 0000 # user_one rs user_one rs
59+
# 1010 0010 ssss 0000 # user_two rs user_two rs
60+
# 1010 0011 0000 0000 # user_three user_three
61+
# 1010 0100 ssss tttt # user_four rs rt user_four rs rt
62+
# 1010 0101 nnnn nnnn # user_five n user_five n
63+
# 1010 0110 ssss 0000 # user_six rs user_six rs
6264
#
6365
#### RESERVED
6466
# 1101 1001 xxxx xxxx # RESERVED BANK
@@ -218,3 +220,5 @@ define pcodeop pcodeop_three;
218220
:user_three is $(INSTR_PHASE) op1215=0xa & op0811=0x03 & op0007=0x0 { pcodeop_three();}
219221
:user_four rs rt is $(INSTR_PHASE) op1215=0xa & op0811=0x04 & rs & rt { pcodeop_one(rs); call [rt]; pcodeop_three();}
220222
:user_five Rel8 is $(INSTR_PHASE) op1215=0xa & op0811=0x05 & Rel8 { lr = inst_next; call Rel8; pcodeop_three();}
223+
:user_six rs is $(INSTR_PHASE) op1215=0xa & op0811=0x06 & rs & op0003=0x0 { r1 = pcodeop_one(rs); call [r1];}
224+

0 commit comments

Comments
 (0)