Skip to content

Commit a3846c3

Browse files
committed
Merge remote-tracking branch 'origin/GP-1277_LostDeindirects' into patch
(Closes #3104)
2 parents 415e4ce + 40c6202 commit a3846c3

File tree

4 files changed

+82
-5
lines changed

4 files changed

+82
-5
lines changed

Ghidra/Features/Decompiler/certification.manifest

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ src/decompile/cpp/Doxyfile||GHIDRA|||Most of this file is autogenerated by doxyg
1111
src/decompile/cpp/Makefile||GHIDRA||||END|
1212
src/decompile/datatests/convert.xml||GHIDRA||||END|
1313
src/decompile/datatests/deadvolatile.xml||GHIDRA||||END|
14+
src/decompile/datatests/deindirect.xml||GHIDRA||||END|
1415
src/decompile/datatests/floatprint.xml||GHIDRA||||END|
1516
src/decompile/datatests/forloop1.xml||GHIDRA||||END|
1617
src/decompile/datatests/forloop_loaditer.xml||GHIDRA||||END|
1718
src/decompile/datatests/forloop_thruspecial.xml||GHIDRA||||END|
1819
src/decompile/datatests/forloop_varused.xml||GHIDRA||||END|
1920
src/decompile/datatests/forloop_withskip.xml||GHIDRA||||END|
21+
src/decompile/datatests/indproto.xml||GHIDRA||||END|
2022
src/decompile/datatests/loopcomment.xml||GHIDRA||||END|
2123
src/decompile/datatests/multiret.xml||GHIDRA||||END|
2224
src/decompile/datatests/namespace.xml||GHIDRA||||END|

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4581,6 +4581,8 @@ void FuncCallSpecs::deindirect(Funcdata &data,Funcdata *newfd)
45814581
if (isOverride()) // If we are overridden at the call-site
45824582
return; // Don't use the discovered function prototype
45834583

4584+
data.getOverride().insertIndirectOverride(op->getAddr(),entryaddress);
4585+
45844586
// Try our best to merge existing prototype
45854587
// with the one we have just been handed
45864588
vector<Varnode *> newinput;
@@ -4592,7 +4594,6 @@ void FuncCallSpecs::deindirect(Funcdata &data,Funcdata *newfd)
45924594
commitNewOutputs(data,newoutput);
45934595
}
45944596
else {
4595-
data.getOverride().insertIndirectOverride(op->getAddr(),entryaddress);
45964597
data.setRestartPending(true);
45974598
}
45984599
}
@@ -4613,16 +4614,19 @@ void FuncCallSpecs::forceSet(Funcdata &data,const FuncProto &fp)
46134614
{
46144615
vector<Varnode *> newinput;
46154616
Varnode *newoutput;
4617+
4618+
// Copy the recovered prototype into the override manager so that
4619+
// future restarts don't have to rediscover it
4620+
FuncProto *newproto = new FuncProto();
4621+
newproto->copy(fp);
4622+
data.getOverride().insertProtoOverride(op->getAddr(),newproto);
46164623
if (lateRestriction(fp,newinput,newoutput)) {
46174624
commitNewInputs(data,newinput);
46184625
commitNewOutputs(data,newoutput);
46194626
}
46204627
else {
46214628
// Too late to make restrictions to correct prototype
4622-
// Add a restart override with the forcing prototype
4623-
FuncProto *newproto = new FuncProto();
4624-
newproto->copy(fp);
4625-
data.getOverride().insertProtoOverride(op->getAddr(),newproto);
4629+
// Force a restart
46264630
data.setRestartPending(true);
46274631
}
46284632
// Regardless of what happened, lock the prototype so it doesn't happen again
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<decompilertest>
2+
<binaryimage arch="x86:LE:64:default:gcc">
3+
<!--
4+
A contrived function with 2 indirect calls that share the same parameter set up.
5+
The parameter setup initially gets associated with only one of the two indirect calls.
6+
The indirects eventually collapse to direct calls and a prototype is associated with
7+
both calls, but too late for one, forcing a restart. The decompiler should be
8+
able to collapse both indirects to direct calls AND associate the correct prototype.
9+
-->
10+
<bytechunk space="ram" offset="0x10071a" readonly="true">
11+
554889e54883
12+
ec20897dec8975e88955e4488d0598ff
13+
ffff488945f88b45e48d50058b45e883
14+
c00389d689c79090909090837dec097f
15+
14488b45f8ffd0488d3d2c010000e81d
16+
feffffeb12488b45f8ffd0488d3d1d01
17+
0000e809feffff90c9c3
18+
</bytechunk>
19+
<bytechunk space="ram" offset="0x10088a" readonly="true">
20+
4c657373004d6f726500
21+
</bytechunk>
22+
<symbol space="ram" offset="0x10071a" name="deindirect"/>
23+
<symbol space="ram" offset="0x1006ca" name="realfunc"/>
24+
<symbol space="ram" offset="0x100580" name="puts"/>
25+
</binaryimage>
26+
<script>
27+
<com>parse line extern void deindirect(int4 a,int4 b,int4 c);</com>
28+
<com>parse line extern void realfunc(int4 a,int4 b);</com>
29+
<com>lo fu deindirect</com>
30+
<com>decompile</com>
31+
<com>print C</com>
32+
<com>quit</com>
33+
</script>
34+
<stringmatch name="Deindirect #1" min="0" max="0">Exceeded maximum restarts</stringmatch>
35+
<stringmatch name="Deindirect #2" min="2" max="2">realfunc\(b \+ 3,c \+ 5\)</stringmatch>
36+
</decompilertest>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<decompilertest>
2+
<binaryimage arch="x86:LE:64:default:gcc">
3+
<!--
4+
A contrived function with 2 indirect calls that share the same parameter set up.
5+
The parameter setup initially gets associated with only one of the two indirect calls.
6+
A prototype data-type is eventually propagated to both indirect calls
7+
but too late for one, forcing a restart. The decompiler should be able to
8+
associate the correct prototype with both indirect calls.
9+
-->
10+
<bytechunk space="ram" offset="0x100771" readonly="true">
11+
554889e54883ec10897dfc8975f848
12+
8955f08b45fc89c79090909090837df8
13+
647517488b45f0488b00ffd0488d3d53
14+
010000e838feffffeb16488b45f0488b
15+
4008ffd0488d3d40010000e820feffff
16+
90c9c3
17+
</bytechunk>
18+
<bytechunk space="ram" offset="0x1008f6" readonly="true">
19+
5065656b0047657400
20+
</bytechunk>
21+
<symbol space="ram" offset="0x100771" name="indproto"/>
22+
<symbol space="ram" offset="0x1005e0" name="puts"/>
23+
</binaryimage>
24+
<script>
25+
<com>parse line struct methods { void (*peek)(int4 a); void (*get)(int4 b); };</com>
26+
<com>parse line extern void indproto(int4 a,int4 b,methods *ptr);</com>
27+
<com>lo fu indproto</com>
28+
<com>decompile</com>
29+
<com>print C</com>
30+
<com>quit</com>
31+
</script>
32+
<stringmatch name="Indirect prototype #1" min="0" max="0">Exceeded maximum restarts</stringmatch>
33+
<stringmatch name="Indirect prototype #2" min="1" max="1">ptr-&gt;peek\)\(a\)</stringmatch>
34+
<stringmatch name="Indirect prototype #3" min="1" max="1">ptr-&gt;get\)\(a\)</stringmatch>
35+
</decompilertest>

0 commit comments

Comments
 (0)