/** * Test the renaming of variables. */ void CfgTest::testRenameVars() { auto prog = Prog::open(FRONTIER_PENTIUM); CPPUNIT_ASSERT(prog); auto fe = prog->getFrontEnd(); Type::clearNamedTypes(); fe->decode(); UserProc *pProc = (UserProc *)prog->getProc(0); Cfg *cfg = pProc->getCFG(); DataFlow *df = pProc->getDataFlow(); // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8] prog->finishDecode(); df->dominators(cfg); df->placePhiFunctions(pProc); pProc->numberStatements(); // After placing phi functions! df->renameBlockVars(pProc, 0, 1); // Block 0, mem depth 1 // MIKE: something missing here? delete prog; }
/** * Test the placing of phi functions. */ void CfgTest::testPlacePhi() { auto prog = Prog::open(FRONTIER_PENTIUM); CPPUNIT_ASSERT(prog); auto fe = prog->getFrontEnd(); Type::clearNamedTypes(); fe->decode(); UserProc *pProc = (UserProc *)prog->getProc(0); Cfg *cfg = pProc->getCFG(); // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8] prog->finishDecode(); DataFlow *df = pProc->getDataFlow(); df->dominators(cfg); df->placePhiFunctions(pProc); // m[r29 - 8] (x for this program) Exp *e = Location::memOf( new Binary(opMinus, Location::regOf(29), new Const(4))); // A_phi[x] should be the set {7 8 10 15 20 21} (all the join points) std::ostringstream ost; std::set<int> &A_phi = df->getA_phi(e); for (const auto &ii : A_phi) ost << ii << " "; std::string expected("7 8 10 15 20 21 "); CPPUNIT_ASSERT_EQUAL(expected, ost.str()); delete prog; }
/*============================================================================== * FUNCTION: CfgTest::testRenameVars * OVERVIEW: Test the renaming of variables *============================================================================*/ void CfgTest::testRenameVars () { BinaryFileFactory bff; BinaryFile* pBF = bff.Load(FRONTIER_PENTIUM); CPPUNIT_ASSERT(pBF != 0); Prog* prog = new Prog; FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff); Type::clearNamedTypes(); prog->setFrontEnd(pFE); pFE->decode(prog); UserProc* pProc = (UserProc*) prog->getProc(0); Cfg* cfg = pProc->getCFG(); DataFlow* df = pProc->getDataFlow(); // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8] prog->finishDecode(); df->dominators(cfg); df->placePhiFunctions(pProc); pProc->numberStatements(); // After placing phi functions! df->renameBlockVars(pProc, 0, 1); // Block 0, mem depth 1 // MIKE: something missing here? delete pFE; }
/** * Test the dominator frontier code. */ void CfgTest::testDominators() { #define FRONTIER_FOUR 0x08048347 #define FRONTIER_FIVE 0x08048351 #define FRONTIER_TWELVE 0x080483b2 #define FRONTIER_THIRTEEN 0x080483b9 auto prog = Prog::open(FRONTIER_PENTIUM); CPPUNIT_ASSERT(prog); auto fe = prog->getFrontEnd(); Type::clearNamedTypes(); fe->decode(); bool gotMain; ADDRESS addr = fe->getMainEntryPoint(gotMain); CPPUNIT_ASSERT(addr != NO_ADDRESS); UserProc *pProc = (UserProc *)prog->getProc(0); Cfg *cfg = pProc->getCFG(); DataFlow *df = pProc->getDataFlow(); df->dominators(cfg); // Find BB "5" (as per Appel, Figure 19.5). BasicBlock *bb = nullptr; for (const auto &b : *cfg) { if (b->getLowAddr() == FRONTIER_FIVE) { bb = b; break; } } CPPUNIT_ASSERT(bb); std::ostringstream expected, actual; #if 0 expected << std::hex << FRONTIER_FIVE << " " << FRONTIER_THIRTEEN << " " << FRONTIER_TWELVE << " " << FRONTIER_FOUR << " " << std::dec; #endif expected << std::hex << FRONTIER_THIRTEEN << " " << FRONTIER_FOUR << " " << FRONTIER_TWELVE << " " << FRONTIER_FIVE << " " << std::dec; int n5 = df->pbbToNode(bb); std::set<int> &DFset = df->getDF(n5); for (const auto &ii : DFset) actual << std::hex << (unsigned)df->nodeToBB(ii)->getLowAddr() << std::dec << " "; CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str()); delete prog; }
/*============================================================================== * FUNCTION: CfgTest::testPlacePhi2 * OVERVIEW: Test a case where a phi function is not needed *============================================================================*/ void CfgTest::testPlacePhi2 () { BinaryFileFactory bff; BinaryFile* pBF = bff.Load(IFTHEN_PENTIUM); CPPUNIT_ASSERT(pBF != 0); Prog* prog = new Prog; FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff); Type::clearNamedTypes(); prog->setFrontEnd(pFE); pFE->decode(prog); UserProc* pProc = (UserProc*) prog->getProc(0); Cfg* cfg = pProc->getCFG(); DataFlow* df = pProc->getDataFlow(); // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8] prog->finishDecode(); df->dominators(cfg); df->placePhiFunctions(pProc); // In this program, x is allocated at [ebp-4], a at [ebp-8], and // b at [ebp-12] // We check that A_phi[ m[ebp-8] ] is 4, and that // A_phi A_phi[ m[ebp-8] ] is null // (block 4 comes out with n=4) std::string expected = "4 "; std::ostringstream actual; // m[r29 - 8] Exp* e = new Unary(opMemOf, new Binary(opMinus, Location::regOf(29), new Const(8))); std::set<int>& s = df->getA_phi(e); std::set<int>::iterator pp; for (pp = s.begin(); pp != s.end(); pp++) actual << *pp << " "; CPPUNIT_ASSERT_EQUAL(expected, actual.str()); delete e; expected = ""; std::ostringstream actual2; // m[r29 - 12] e = new Unary(opMemOf, new Binary(opMinus, Location::regOf(29), new Const(12))); std::set<int>& s2 = df->getA_phi(e); for (pp = s2.begin(); pp != s2.end(); pp++) actual2 << *pp << " "; CPPUNIT_ASSERT_EQUAL(expected, actual2.str()); delete e; delete pFE; }
/** * Test a case where semi dominators are different to dominators. */ void CfgTest::testSemiDominators() { #define SEMI_L 0x80483b0 #define SEMI_M 0x80483e2 #define SEMI_B 0x8048345 #define SEMI_D 0x8048354 #define SEMI_M 0x80483e2 auto prog = Prog::open(SEMI_PENTIUM); CPPUNIT_ASSERT(prog); auto fe = prog->getFrontEnd(); Type::clearNamedTypes(); fe->decode(); bool gotMain; ADDRESS addr = fe->getMainEntryPoint(gotMain); CPPUNIT_ASSERT(addr != NO_ADDRESS); UserProc *pProc = (UserProc *)prog->getProc(0); Cfg *cfg = pProc->getCFG(); DataFlow *df = pProc->getDataFlow(); df->dominators(cfg); // Find BB "L (6)" (as per Appel, Figure 19.8). BasicBlock *bb = nullptr; for (const auto &b : *cfg) { if (b->getLowAddr() == SEMI_L) { bb = b; break; } } CPPUNIT_ASSERT(bb); int nL = df->pbbToNode(bb); // The dominator for L should be B, where the semi dominator is D // (book says F) unsigned actual_dom = (unsigned)df->nodeToBB(df->getIdom(nL))->getLowAddr(); unsigned actual_semi = (unsigned)df->nodeToBB(df->getSemi(nL))->getLowAddr(); CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_B, actual_dom); CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_D, actual_semi); // Check the final dominator frontier as well; should be M and B std::ostringstream expected, actual; #if 0 expected << std::hex << SEMI_M << " " << SEMI_B << " " << std::dec; #endif expected << std::hex << SEMI_B << " " << SEMI_M << " " << std::dec; std::set<int> &DFset = df->getDF(nL); for (const auto &ii : DFset) actual << std::hex << (unsigned)df->nodeToBB(ii)->getLowAddr() << std::dec << " "; CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str()); delete prog; }
/** * Test a case where a phi function is not needed. */ void CfgTest::testPlacePhi2() { auto prog = Prog::open(IFTHEN_PENTIUM); CPPUNIT_ASSERT(prog); auto fe = prog->getFrontEnd(); Type::clearNamedTypes(); fe->decode(); UserProc *pProc = (UserProc *)prog->getProc(0); Cfg *cfg = pProc->getCFG(); DataFlow *df = pProc->getDataFlow(); // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8] prog->finishDecode(); df->dominators(cfg); df->placePhiFunctions(pProc); // In this program, x is allocated at [ebp-4], a at [ebp-8], and // b at [ebp-12] // We check that A_phi[ m[ebp-8] ] is 4, and that // A_phi A_phi[ m[ebp-8] ] is null // (block 4 comes out with n=4) std::string expected = "4 "; std::ostringstream actual; // m[r29 - 8] Exp *e = Location::memOf( new Binary(opMinus, Location::regOf(29), new Const(8))); std::set<int> &s = df->getA_phi(e); for (const auto &pp : s) actual << pp << " "; CPPUNIT_ASSERT_EQUAL(expected, actual.str()); delete e; expected = ""; std::ostringstream actual2; // m[r29 - 12] e = Location::memOf( new Binary(opMinus, Location::regOf(29), new Const(12))); std::set<int> &s2 = df->getA_phi(e); for (const auto &pp : s2) actual2 << pp << " "; CPPUNIT_ASSERT_EQUAL(expected, actual2.str()); delete e; delete prog; }
void CfgTest::testSemiDominators () { BinaryFileFactory bff; BinaryFile* pBF = bff.Load(SEMI_PENTIUM); CPPUNIT_ASSERT(pBF != 0); Prog* prog = new Prog; FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff); Type::clearNamedTypes(); prog->setFrontEnd(pFE); pFE->decode(prog); bool gotMain; ADDRESS addr = pFE->getMainEntryPoint(gotMain); CPPUNIT_ASSERT (addr != NO_ADDRESS); UserProc* pProc = (UserProc*) prog->getProc(0); Cfg* cfg = pProc->getCFG(); DataFlow* df = pProc->getDataFlow(); df->dominators(cfg); // Find BB "L (6)" (as per Appel, Figure 19.8). BB_IT it; PBB bb = cfg->getFirstBB(it); while (bb && bb->getLowAddr() != SEMI_L) { bb = cfg->getNextBB(it); } CPPUNIT_ASSERT(bb); int nL = df->pbbToNode(bb); // The dominator for L should be B, where the semi dominator is D // (book says F) unsigned actual_dom = (unsigned)df->nodeToBB(df->getIdom(nL))->getLowAddr(); unsigned actual_semi = (unsigned)df->nodeToBB(df->getSemi(nL))->getLowAddr(); CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_B, actual_dom); CPPUNIT_ASSERT_EQUAL((unsigned)SEMI_D, actual_semi); // Check the final dominator frontier as well; should be M and B std::ostringstream expected, actual; //expected << std::hex << SEMI_M << " " << SEMI_B << " "; expected << std::hex << SEMI_B << " " << SEMI_M << " "; std::set<int>::iterator ii; std::set<int>& DFset = df->getDF(nL); for (ii=DFset.begin(); ii != DFset.end(); ii++) actual << std::hex << (unsigned)df->nodeToBB(*ii)->getLowAddr() << " "; CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str()); delete pFE; }
void CfgTest::testDominators () { BinaryFileFactory bff; BinaryFile *pBF = bff.Load(FRONTIER_PENTIUM); CPPUNIT_ASSERT(pBF != 0); Prog* prog = new Prog; FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); Type::clearNamedTypes(); prog->setFrontEnd(pFE); pFE->decode(prog); bool gotMain; ADDRESS addr = pFE->getMainEntryPoint(gotMain); CPPUNIT_ASSERT (addr != NO_ADDRESS); UserProc* pProc = (UserProc*) prog->getProc(0); Cfg* cfg = pProc->getCFG(); DataFlow* df = pProc->getDataFlow(); df->dominators(cfg); // Find BB "5" (as per Appel, Figure 19.5). BB_IT it; PBB bb = cfg->getFirstBB(it); while (bb && bb->getLowAddr() != FRONTIER_FIVE) { bb = cfg->getNextBB(it); } CPPUNIT_ASSERT(bb); std::ostringstream expected, actual; //expected << std::hex << FRONTIER_FIVE << " " << FRONTIER_THIRTEEN << " " << FRONTIER_TWELVE << " " << // FRONTIER_FOUR << " "; expected << std::hex << FRONTIER_THIRTEEN << " " << FRONTIER_FOUR << " " << FRONTIER_TWELVE << " " << FRONTIER_FIVE << " "; int n5 = df->pbbToNode(bb); std::set<int>::iterator ii; std::set<int>& DFset = df->getDF(n5); for (ii=DFset.begin(); ii != DFset.end(); ii++) actual << std::hex << (unsigned)df->nodeToBB(*ii)->getLowAddr() << " "; CPPUNIT_ASSERT_EQUAL(expected.str(), actual.str()); pBF->UnLoad(); delete pFE; }
/*============================================================================== * FUNCTION: CfgTest::testPlacePhi * OVERVIEW: Test the placing of phi functions *============================================================================*/ void CfgTest::testPlacePhi () { BinaryFileFactory bff; BinaryFile* pBF = bff.Load(FRONTIER_PENTIUM); CPPUNIT_ASSERT(pBF != 0); Prog* prog = new Prog; FrontEnd* pFE = new PentiumFrontEnd(pBF, prog, &bff); Type::clearNamedTypes(); prog->setFrontEnd(pFE); pFE->decode(prog); UserProc* pProc = (UserProc*) prog->getProc(0); Cfg* cfg = pProc->getCFG(); // Simplify expressions (e.g. m[ebp + -8] -> m[ebp - 8] prog->finishDecode(); DataFlow* df = pProc->getDataFlow(); df->dominators(cfg); df->placePhiFunctions(pProc); // m[r29 - 8] (x for this program) Exp* e = new Unary(opMemOf, new Binary(opMinus, Location::regOf(29), new Const(4))); // A_phi[x] should be the set {7 8 10 15 20 21} (all the join points) std::ostringstream ost; std::set<int>::iterator ii; std::set<int>& A_phi = df->getA_phi(e); for (ii = A_phi.begin(); ii != A_phi.end(); ++ii) ost << *ii << " "; std::string expected("7 8 10 15 20 21 "); CPPUNIT_ASSERT_EQUAL(expected, ost.str()); delete pFE; }
void FrontSparcTest::testDelaySlot() { BinaryFileFactory bff; BinaryFile *pBF = bff.Load(BRANCH_SPARC); if (pBF == NULL) pBF = new BinaryFileStub(); // fallback on stub CPPUNIT_ASSERT(pBF != 0); CPPUNIT_ASSERT(pBF->GetMachine() == MACHINE_SPARC); Prog* prog = new Prog; FrontEnd *pFE = new SparcFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); // decode calls readLibraryCatalog(), which needs to have definitions for non-sparc architectures cleared Type::clearNamedTypes(); pFE->decode(prog); bool gotMain; ADDRESS addr = pFE->getMainEntryPoint(gotMain); CPPUNIT_ASSERT (addr != NO_ADDRESS); std::string name("testDelaySlot"); UserProc* pProc = new UserProc(prog, name, addr); std::ofstream dummy; bool res = pFE->processProc(addr, pProc, dummy, false); CPPUNIT_ASSERT(res == 1); Cfg* cfg = pProc->getCFG(); BB_IT it; PBB bb = cfg->getFirstBB(it); std::ostringstream o1; bb->print(o1); std::string expected("Call BB:\n" "in edges: \n" "out edges: 10a98 \n" "00010a80 0 *32* tmp := r14 - 120\n" " 0 *32* m[r14] := r16\n" " 0 *32* m[r14 + 4] := r17\n" " 0 *32* m[r14 + 8] := r18\n" " 0 *32* m[r14 + 12] := r19\n" " 0 *32* m[r14 + 16] := r20\n" " 0 *32* m[r14 + 20] := r21\n" " 0 *32* m[r14 + 24] := r22\n" " 0 *32* m[r14 + 28] := r23\n" " 0 *32* m[r14 + 32] := r24\n" " 0 *32* m[r14 + 36] := r25\n" " 0 *32* m[r14 + 40] := r26\n" " 0 *32* m[r14 + 44] := r27\n" " 0 *32* m[r14 + 48] := r28\n" " 0 *32* m[r14 + 52] := r29\n" " 0 *32* m[r14 + 56] := r30\n" " 0 *32* m[r14 + 60] := r31\n" " 0 *32* r24 := r8\n" " 0 *32* r25 := r9\n" " 0 *32* r26 := r10\n" " 0 *32* r27 := r11\n" " 0 *32* r28 := r12\n" " 0 *32* r29 := r13\n" " 0 *32* r30 := r14\n" " 0 *32* r31 := r15\n" " 0 *32* r14 := tmp\n" "00010a84 0 *32* r16 := 0x11400\n" "00010a88 0 *32* r16 := r16 | 808\n" "00010a8c 0 *32* r8 := r16\n" "00010a90 0 *32* tmp := r30\n" " 0 *32* r9 := r30 - 20\n" "00010a90 0 CALL scanf(\n" " )\n" " Reaching definitions: \n" " Live variables: \n"); std::string actual(o1.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); bb = cfg->getNextBB(it); CPPUNIT_ASSERT(bb); std::ostringstream o2; bb->print(o2); expected = std::string("Call BB:\n" "in edges: 10a90 \n" "out edges: 10aa4 \n" "00010a98 0 *32* r8 := r16\n" "00010a9c 0 *32* tmp := r30\n" " 0 *32* r9 := r30 - 24\n" "00010a9c 0 CALL scanf(\n" " )\n" " Reaching definitions: \n" " Live variables: \n"); actual = std::string(o2.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); bb = cfg->getNextBB(it); CPPUNIT_ASSERT(bb); std::ostringstream o3; bb->print(o3); expected = std::string("Twoway BB:\n" "in edges: 10a9c \n" "out edges: 10ac8 10ab8 \n" "00010aa4 0 *32* r8 := m[r30 - 20]\n" "00010aa8 0 *32* r16 := 5\n" "00010aac 0 *32* tmp := r16\n" " 0 *32* r0 := r16 - r8\n" " 0 *v* %flags := SUBFLAGS( tmp, r8, r0 )\n" "00010ab0 0 *32* r8 := 0x11400\n" "00010ab0 0 BRANCH 0x10ac8, condition not equals\n" "High level: %flags\n"); actual = std::string(o3.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); bb = cfg->getNextBB(it); CPPUNIT_ASSERT(bb); std::ostringstream o4; bb->print(o4); expected = std::string("L1: Twoway BB:\n" "in edges: 10ab0 10ac4 \n" "out edges: 10ad8 10ad0 \n" "00010ac8 0 *32* r8 := 0x11400\n" "00010ac8 0 BRANCH 0x10ad8, condition equals\n" "High level: %flags\n"); actual = std::string(o4.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); bb = cfg->getNextBB(it); CPPUNIT_ASSERT(bb); std::ostringstream o5; bb->print(o5); expected = std::string("Call BB:\n" "in edges: 10ab0 \n" "out edges: 10ac0 \n" "00010ab8 0 *32* r8 := r8 | 816\n" "00010ab8 0 CALL printf(\n" " )\n" " Reaching definitions: \n" " Live variables: \n"); actual = std::string(o5.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); delete prog; }