@@ -806,35 +806,13 @@ DUAnalysis::fake_read(SgAsmX86Instruction* insn, const AbstractAccess& aa) const
806
806
// This approach is a little lazy but I didn't want to have to write my own visitor class to
807
807
// look for a specific subexpression.
808
808
809
- // JSG updated this with Robb M's guideance on searching for a subexpression.
810
- using VisitAction = Rose::BinaryAnalysis::SymbolicExpr::VisitAction;
811
- using Visitor = Rose::BinaryAnalysis::SymbolicExpr::Visitor;
812
-
813
809
TreeNodePtr read_tn = aa.value ->get_expression ();
814
810
815
- // The visitor needed to search for the fake read (subexpression)
816
- struct SubxVisitor : Visitor {
817
- TreeNodePtr needle_;
818
-
819
- SubxVisitor (const TreeNodePtr &needle) : needle_(needle) { }
820
-
821
- VisitAction preVisit (const TreeNodePtr &expr) {
822
- if (expr->isEquivalentTo (needle_)) {
823
- return Rose::BinaryAnalysis::SymbolicExpr::TERMINATE;
824
- }
825
- return Rose::BinaryAnalysis::SymbolicExpr::CONTINUE;
826
- }
827
- VisitAction postVisit (const TreeNodePtr&) {
828
- return Rose::BinaryAnalysis::SymbolicExpr::CONTINUE;
829
- }
830
- };
831
-
832
811
for (const AbstractAccess& waa : get_writes (insn->get_address ())) {
833
812
TreeNodePtr write_tn = waa.value ->get_expression ();
834
- SubxVisitor read_subx (read_tn);
835
813
836
814
// search if this write includes the read. If it does, then it is not fake
837
- if (write_tn-> depthFirstTraversal (read_subx) == Rose::BinaryAnalysis::SymbolicExpr::TERMINATE ) {
815
+ if (has_subexp (write_tn, read_tn) ) {
838
816
// The read was somewhere in the write, so the value was _truly_ read, and we've already
839
817
// established that it was initialized by someone else, so it's not a truly uninitialized
840
818
// read.
@@ -1291,7 +1269,7 @@ DUAnalysis::make_call_dependencies(SgAsmX86Instruction* insn, SymbolicStatePtr&
1291
1269
// the parameter onto the stack before the call. This code is a little bit incorrect in
1292
1270
// that we're assuming that all four bytes have still been modified by the same instruction
1293
1271
// as the first byte was.
1294
- SymbolicValuePtr mca = SymbolicValue::promote (memcell->get_address ());
1272
+ SymbolicValuePtr mca = SymbolicValue::promote (memcell->address ());
1295
1273
1296
1274
// Use rops->readMemory to read memory to read either 32 or 64 bits depending on the
1297
1275
// architecture. In truth, we have no idea how large the object being pointed to is and
@@ -1380,6 +1358,39 @@ void update_jump_targets(const DescriptorSet& ds, SgAsmInstruction* insn) {
1380
1358
}
1381
1359
}
1382
1360
1361
+ void DUAnalysis::guess_function_delta () {
1362
+ // Because it's shorter than current_function...
1363
+ FunctionDescriptor* fd = current_function;
1364
+
1365
+
1366
+ for (CFGVertex vertex : fd->get_return_vertices ()) {
1367
+ const SgAsmBlock *block = convert_vertex_to_bblock (cfg, vertex);
1368
+ // Find the return instruction.
1369
+ const SgAsmStatementPtrList &insns = block->get_statementList ();
1370
+ assert (insns.size () > 0 );
1371
+ SgAsmX86Instruction *last = isSgAsmX86Instruction (insns[insns.size () - 1 ]);
1372
+ if (last != NULL and last->get_kind () == x86_ret) {
1373
+ // Get the number of bytes popped off the stack by the return instruction (not counting the
1374
+ // return address).
1375
+ SgAsmExpressionPtrList &ops = last->get_operandList ()->get_operands ();
1376
+ if (ops.size () > 0 ) {
1377
+ SgAsmIntegerValueExpression *val = isSgAsmIntegerValueExpression (ops[0 ]);
1378
+ if (val != NULL ) {
1379
+ // This is the number on the RETN instruction and is also our expected stack delta.
1380
+ int64_t retn_size = val->get_absoluteValue ();
1381
+ SDEBUG << " Guessing that function " << fd->address_string () << " pops "
1382
+ << retn_size << " additional bytes off the stack." << LEND;
1383
+ // Mak a StackDelta() obect and record it as _our_ stack delta. This value will get
1384
+ // used if the analyzed function is recursive and calls itself.
1385
+ StackDelta guessed = StackDelta (retn_size, ConfidenceGuess);
1386
+ fd->update_stack_delta (guessed);
1387
+ return ;
1388
+ }
1389
+ }
1390
+ }
1391
+ }
1392
+ }
1393
+
1383
1394
void DUAnalysis::update_function_delta () {
1384
1395
// Because it's shorter than current_function...
1385
1396
FunctionDescriptor* fd = current_function;
@@ -2196,6 +2207,11 @@ DUAnalysis::solve_flow_equation_iteratively()
2196
2207
sp_tracker.update_delta (current_function->get_address (), StackDelta (0 , ConfidenceCertain),
2197
2208
sd_failures);
2198
2209
2210
+ // If this function is recursive, we need a better guess for our own stack delta than just
2211
+ // zero. Make that guess and store it in the stack delta tracker cache before starting
2212
+ // anlaysis.
2213
+ guess_function_delta ();
2214
+
2199
2215
// Do most of the real work. Visit each block in the control flow graph, possibly multiple
2200
2216
// times, merging predecessor states, emulating each block, and updating state histories.
2201
2217
rstatus = loop_over_cfg ();
0 commit comments