/*============================================================================== * FUNCTION: RtlTest::testIsCompare * OVERVIEW: Test the isCompare function *============================================================================*/ void RtlTest::testIsCompare () { BinaryFileFactory bff; BinaryFile *pBF = bff.Load(SWITCH_SPARC); 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 second instruction: "sub %i0, 2, %o1" int iReg; Exp* eOperand = NULL; DecodeResult inst = pFE->decodeInstruction(0x10910); CPPUNIT_ASSERT(inst.rtl != NULL); CPPUNIT_ASSERT(inst.rtl->isCompare(iReg, eOperand) == false); // Decode fifth instruction: "cmp %o1, 5" inst = pFE->decodeInstruction(0x1091c); CPPUNIT_ASSERT(inst.rtl != NULL); CPPUNIT_ASSERT(inst.rtl->isCompare(iReg, eOperand) == true); CPPUNIT_ASSERT_EQUAL(9, iReg); std::string expected("5"); std::ostringstream ost1; eOperand->print(ost1); std::string actual(ost1.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); pBF->UnLoad(); delete pBF; delete pFE; pBF = bff.Load(SWITCH_PENT); CPPUNIT_ASSERT(pBF != 0); CPPUNIT_ASSERT(pBF->GetMachine() == MACHINE_PENTIUM); pFE = new PentiumFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); // Decode fifth instruction: "cmp $0x5,%eax" inst = pFE->decodeInstruction(0x80488fb); CPPUNIT_ASSERT(inst.rtl != NULL); CPPUNIT_ASSERT(inst.rtl->isCompare(iReg, eOperand) == true); CPPUNIT_ASSERT_EQUAL(24, iReg); std::ostringstream ost2; eOperand->print(ost2); actual = ost2.str(); CPPUNIT_ASSERT_EQUAL(expected, actual); // Decode instruction: "add $0x4,%esp" inst = pFE->decodeInstruction(0x804890c); CPPUNIT_ASSERT(inst.rtl != NULL); CPPUNIT_ASSERT(inst.rtl->isCompare(iReg, eOperand) == false); pBF->UnLoad(); delete pFE; }
/*============================================================================== * FUNCTION: LoaderTest::testPentiumLoad * OVERVIEW: Test loading the pentium (Solaris) hello world program *============================================================================*/ void LoaderTest::testPentiumLoad () { std::ostringstream ost; // Load Pentium hello world BinaryFileFactory bff; BinaryFile* pBF = bff.Load(HELLO_PENTIUM); CPPUNIT_ASSERT(pBF != NULL); int n; SectionInfo* si; n = pBF->GetNumSections(); ost << "Number of sections = " << std::dec << n << "\r\n\t"; si = pBF->GetSectionInfo(1); ost << si->pSectionName << "\t"; si = pBF->GetSectionInfo(n-1); ost << si->pSectionName; pBF->UnLoad(); // Note: the string below needs to have embedded tabs. Edit with caution! // (And slightly different string to the sparc test, e.g. rel vs rela) std::string expected("Number of sections = 34\r\n\t" ".interp .strtab"); CPPUNIT_ASSERT_EQUAL(expected, ost.str()); bff.UnLoad(); }
/*============================================================================== * 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; }
/*============================================================================== * FUNCTION: ProcTest::testName * OVERVIEW: Test setting and reading name, constructor, native address *============================================================================*/ void ProcTest::testName () { Prog* prog = new Prog(); BinaryFile *pBF = new BinaryFileStub(); CPPUNIT_ASSERT(pBF != 0); std::string nm("default name"); BinaryFileFactory bff; pBF = bff.Load(HELLO_PENTIUM); FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); CPPUNIT_ASSERT(pFE != 0); prog->setFrontEnd(pFE); CPPUNIT_ASSERT(prog); pFE->readLibraryCatalog(); // Since we are not decoding m_proc = new UserProc(prog, nm, 20000); // Will print in decimal if error std::string actual(m_proc->getName()); CPPUNIT_ASSERT_EQUAL(std::string("default name"), actual); std::string name("printf"); LibProc lp(prog, name, 30000); actual = lp.getName(); CPPUNIT_ASSERT_EQUAL(name, actual); ADDRESS a = lp.getNativeAddress(); ADDRESS expected = 30000; CPPUNIT_ASSERT_EQUAL(expected, a); a = m_proc->getNativeAddress(); expected = 20000; CPPUNIT_ASSERT_EQUAL(expected, a); delete prog; delete m_proc; // delete pFE; // No! Deleting the prog deletes the pFE already (which deletes the BinaryFileFactory) }
/*============================================================================== * FUNCTION: LoaderTest::testPalmLoad * OVERVIEW: Test loading the Palm 68328 Starter.prc program *============================================================================*/ void LoaderTest::testPalmLoad () { std::ostringstream ost; // Load Palm Starter.prc BinaryFileFactory bff; BinaryFile* pBF = bff.Load(STARTER_PALM); CPPUNIT_ASSERT(pBF != NULL); int n; SectionInfo* si; n = pBF->GetNumSections(); ost << "Number of sections = " << std::dec << n << "\r\n"; for (int i=0; i < n; i++) { si = pBF->GetSectionInfo(i); ost << si->pSectionName << "\t"; } pBF->UnLoad(); // Note: the string below needs to have embedded tabs. Edit with caution! std::string expected("Number of sections = 8\r\n" "code1 MBAR1000 tFRM1000 Talt1001 " "data0 code0 tAIN1000 tver1000 "); CPPUNIT_ASSERT_EQUAL(expected, ost.str()); bff.UnLoad(); }
/*============================================================================== * FUNCTION: TypeTest::testNotEqual * OVERVIEW: Test type inequality *============================================================================*/ void TypeTest::testCompound() { BinaryFileFactory bff; BinaryFile *pBF = bff.Load(HELLO_WINDOWS); FrontEnd *pFE = new PentiumFrontEnd(pBF, new Prog, &bff); Boomerang::get()->setLogger(new FileLogger()); // May try to output some messages to LOG pFE->readLibraryCatalog(); // Read definitions Signature* paintSig = pFE->getLibSignature("BeginPaint"); // Second argument should be an LPPAINTSTRUCT Type* ty = paintSig->getParamType(1); const char* p = ty->getCtype(); std::string expected("LPPAINTSTRUCT"); std::string actual(p); CPPUNIT_ASSERT_EQUAL(expected, actual); // Get the type pointed to ty = ty->asPointer()->getPointsTo(); p = ty->getCtype(); expected = "PAINTSTRUCT"; actual = p; CPPUNIT_ASSERT_EQUAL(expected, actual); // Offset 8 should have a RECT Type* subTy = ty->asCompound()->getTypeAtOffset(8*8); p = subTy->getCtype(); expected = "RECT"; actual = p; CPPUNIT_ASSERT_EQUAL(expected, actual); // Name at offset C should be bottom p = subTy->asCompound()->getNameAtOffset(0x0C*8); expected = "bottom"; actual = p; CPPUNIT_ASSERT_EQUAL(expected, actual); // Now figure out the name at offset 8+C p = ty->asCompound()->getNameAtOffset((8 + 0x0C)*8); expected = "rcPaint"; actual = p; CPPUNIT_ASSERT_EQUAL(expected, actual); // Also at offset 8 p = ty->asCompound()->getNameAtOffset((8 + 0)*8); actual = p; CPPUNIT_ASSERT_EQUAL(expected, actual); // Also at offset 8+4 p = ty->asCompound()->getNameAtOffset((8 + 4)*8); actual = p; CPPUNIT_ASSERT_EQUAL(expected, actual); // And at offset 8+8 p = ty->asCompound()->getNameAtOffset((8 + 8)*8); actual = p; CPPUNIT_ASSERT_EQUAL(expected, actual); delete pFE; }
/*============================================================================== * 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; }
FrontEnd* FrontEnd::Load(const char *fname, Prog* prog) { BinaryFileFactory* pbff = new BinaryFileFactory; if (pbff == NULL) return NULL; std::cout<<"in frontend::load pBF =bff->load\n"; BinaryFile *pBF = pbff->Load(fname); std::cout<< fname << "\n"; if(ASS_FILE)prog->m_path=fname;//donbinhvn: remember path for later processing if (pBF == NULL) return NULL; return instantiate(pBF, prog, pbff); }
void FrontPentTest::testFindMain() { // Test the algorithm for finding main, when there is a call to __libc_start_main // Also tests the loader hack BinaryFileFactory bff; BinaryFile *pBF = bff.Load(FEDORA2_TRUE); CPPUNIT_ASSERT(pBF != NULL); Prog *prog = new Prog; FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); CPPUNIT_ASSERT(pFE != NULL); bool found; ADDRESS addr = pFE->getMainEntryPoint(found); ADDRESS expected = 0x8048b10; CPPUNIT_ASSERT_EQUAL(expected, addr); pBF->Close(); bff.UnLoad(); pBF = bff.Load(FEDORA3_TRUE); CPPUNIT_ASSERT(pBF != NULL); pFE = new PentiumFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); CPPUNIT_ASSERT(pFE != NULL); addr = pFE->getMainEntryPoint(found); expected = 0x8048c4a; CPPUNIT_ASSERT_EQUAL(expected, addr); pBF->Close(); bff.UnLoad(); pBF = bff.Load(SUSE_TRUE); CPPUNIT_ASSERT(pBF != NULL); pFE = new PentiumFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); CPPUNIT_ASSERT(pFE != NULL); addr = pFE->getMainEntryPoint(found); expected = 0x8048b60; CPPUNIT_ASSERT_EQUAL(expected, addr); pBF->Close(); delete pFE; }
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; }
/*============================================================================== * FUNCTION: FrontPentTest::test1 * OVERVIEW: Test decoding some pentium instructions *============================================================================*/ void FrontPentTest::test1 () { std::ostringstream ost; BinaryFileFactory bff; BinaryFile *pBF = bff.Load(HELLO_PENT); if (pBF == NULL) pBF = new BinaryFileStub(); CPPUNIT_ASSERT(pBF != 0); CPPUNIT_ASSERT(pBF->GetMachine() == MACHINE_PENTIUM); Prog* prog = new Prog; FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); bool gotMain; ADDRESS addr = pFE->getMainEntryPoint(gotMain); CPPUNIT_ASSERT (addr != NO_ADDRESS); // Decode first instruction DecodeResult inst = pFE->decodeInstruction(addr); inst.rtl->print(ost); std::string expected( "08048328 0 *32* m[r28 - 4] := r29\n" " 0 *32* r28 := r28 - 4\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(ost.str())); std::ostringstream o2; addr += inst.numBytes; inst = pFE->decodeInstruction(addr); inst.rtl->print(o2); expected = std::string("08048329 0 *32* r29 := r28\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o2.str())); std::ostringstream o3; addr = 0x804833b; inst = pFE->decodeInstruction(addr); inst.rtl->print(o3); expected = std::string( "0804833b 0 *32* m[r28 - 4] := 0x80483fc\n" " 0 *32* r28 := r28 - 4\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o3.str())); delete pFE; // delete pBF; }
/*============================================================================== * FUNCTION: ProgTest::testName * OVERVIEW: Test setting and reading name *============================================================================*/ void ProgTest::testName () { BinaryFileFactory bff; BinaryFile *pBF = bff.Load(HELLO_PENTIUM); // Don't actually use it Prog* prog = new Prog(); FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); // We need a Prog object with a pBF (for getEarlyParamExp()) prog->setFrontEnd(pFE); std::string actual(prog->getName()); std::string expected(HELLO_PENTIUM); CPPUNIT_ASSERT_EQUAL(expected, actual); std::string name("Happy prog"); prog->setName(name.c_str()); actual = prog->getName(); CPPUNIT_ASSERT_EQUAL(name, actual); delete pFE; }
void FrontSparcTest::test2() { DecodeResult inst; std::string expected; BinaryFileFactory bff; BinaryFile *pBF = bff.Load(HELLO_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); std::ostringstream o1; inst = pFE->decodeInstruction(0x10690); inst.rtl->print(o1); // This call is to out of range of the program's text limits (to the Program Linkage Table (PLT), calling printf) // This is quite normal. expected = std::string("00010690 0 CALL printf(\n" " )\n" " Reaching definitions: \n" " Live variables: \n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o1.str())); std::ostringstream o2; inst = pFE->decodeInstruction(0x10694); inst.rtl->print(o2); expected = std::string("00010694\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o2.str())); std::ostringstream o3; inst = pFE->decodeInstruction(0x10698); inst.rtl->print(o3); expected = std::string("00010698 0 *32* r8 := 0\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o3.str())); std::ostringstream o4; inst = pFE->decodeInstruction(0x1069c); inst.rtl->print(o4); expected = std::string("0001069c 0 *32* r24 := r8\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o4.str())); delete pFE; // delete pBF; }
void FrontPentTest::testBranch() { DecodeResult inst; std::string expected; BinaryFileFactory bff; BinaryFile *pBF = bff.Load(BRANCH_PENT); if (pBF == NULL) pBF = new BinaryFileStub(); CPPUNIT_ASSERT(pBF != 0); CPPUNIT_ASSERT(pBF->GetMachine() == MACHINE_PENTIUM); Prog* prog = new Prog; FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); // jne std::ostringstream o1; inst = pFE->decodeInstruction(0x8048979); inst.rtl->print(o1); expected = std::string("08048979 0 BRANCH 0x8048988, condition " "not equals\n" "High level: %flags\n"); CPPUNIT_ASSERT_EQUAL(expected, o1.str()); // jg std::ostringstream o2; inst = pFE->decodeInstruction(0x80489c1); inst.rtl->print(o2); expected = std::string( "080489c1 0 BRANCH 0x80489d5, condition signed greater\n" "High level: %flags\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o2.str())); // jbe std::ostringstream o3; inst = pFE->decodeInstruction(0x8048a1b); inst.rtl->print(o3); expected = std::string( "08048a1b 0 BRANCH 0x8048a2a, condition unsigned less or equals\n" "High level: %flags\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o3.str())); delete pFE; // delete pBF; }
void FrontSparcTest::testBranch() { DecodeResult inst; std::string expected; 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); // bne std::ostringstream o1; inst = pFE->decodeInstruction(0x10ab0); inst.rtl->print(o1); expected = std::string( "00010ab0 0 BRANCH 0x10ac8, condition not equals\n" "High level: %flags\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o1.str())); // bg std::ostringstream o2; inst = pFE->decodeInstruction(0x10af8); inst.rtl->print(o2); expected = std::string("00010af8 0 BRANCH 0x10b10, condition " "signed greater\n" "High level: %flags\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o2.str())); // bleu std::ostringstream o3; inst = pFE->decodeInstruction(0x10b44); inst.rtl->print(o3); expected = std::string( "00010b44 0 BRANCH 0x10b54, condition unsigned less or equals\n" "High level: %flags\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o3.str())); delete pFE; // delete pBF; }
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; }
void FrontPentTest::test2() { DecodeResult inst; std::string expected; BinaryFileFactory bff; BinaryFile *pBF = bff.Load(HELLO_PENT); if (pBF == NULL) pBF = new BinaryFileStub(); CPPUNIT_ASSERT(pBF != 0); CPPUNIT_ASSERT(pBF->GetMachine() == MACHINE_PENTIUM); Prog* prog = new Prog; FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); std::ostringstream o1; inst = pFE->decodeInstruction(0x8048345); inst.rtl->print(o1); expected = std::string( "08048345 0 *32* tmp1 := r28\n" " 0 *32* r28 := r28 + 16\n" " 0 *v* %flags := ADDFLAGS32( tmp1, 16, r28 )\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o1.str())); std::ostringstream o2; inst = pFE->decodeInstruction(0x8048348); inst.rtl->print(o2); expected = std::string( "08048348 0 *32* r24 := 0\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o2.str())); std::ostringstream o3; inst = pFE->decodeInstruction(0x8048329); inst.rtl->print(o3); expected = std::string("08048329 0 *32* r29 := r28\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o3.str())); delete pFE; // delete pBF; }
void FrontPentTest::test3() { DecodeResult inst; std::string expected; BinaryFileFactory bff; BinaryFile *pBF = bff.Load(HELLO_PENT); if (pBF == NULL) pBF = new BinaryFileStub(); CPPUNIT_ASSERT(pBF != 0); CPPUNIT_ASSERT(pBF->GetMachine() == MACHINE_PENTIUM); Prog* prog = new Prog; FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff); prog->setFrontEnd(pFE); std::ostringstream o1; inst = pFE->decodeInstruction(0x804834d); inst.rtl->print(o1); expected = std::string( "0804834d 0 *32* r28 := r29\n" " 0 *32* r29 := m[r28]\n" " 0 *32* r28 := r28 + 4\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o1.str())); std::ostringstream o2; inst = pFE->decodeInstruction(0x804834e); inst.rtl->print(o2); expected = std::string( "0804834e 0 *32* %pc := m[r28]\n" " 0 *32* r28 := r28 + 4\n" " 0 RET\n" " Modifieds: \n" " Reaching definitions: \n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o2.str())); delete pFE; // delete pBF; }
/*============================================================================== * 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; }
/*============================================================================== * FUNCTION: LoaderTest::testHppaLoad * OVERVIEW: Test loading the sparc hello world program *============================================================================*/ void LoaderTest::testHppaLoad () { std::ostringstream ost; // Load HPPA hello world BinaryFileFactory bff; BinaryFile* pBF = bff.Load(HELLO_HPPA); CPPUNIT_ASSERT(pBF != NULL); int n; SectionInfo* si; n = pBF->GetNumSections(); ost << "Number of sections = " << std::dec << n << "\r\n"; for (int i=0; i < n; i++) { si = pBF->GetSectionInfo(i); ost << si->pSectionName << "\t"; } pBF->UnLoad(); // Note: the string below needs to have embedded tabs. Edit with caution! std::string expected("Number of sections = 4\r\n" "$HEADER$ $TEXT$ $DATA$ $BSS$ "); CPPUNIT_ASSERT_EQUAL(expected, ost.str()); bff.UnLoad(); }
/*============================================================================== * FUNCTION: LoaderTest::testSparcLoad * OVERVIEW: Test loading the sparc hello world program *============================================================================*/ void LoaderTest::testSparcLoad () { std::ostringstream ost; // Load SPARC hello world BinaryFileFactory bff; BinaryFile* pBF = bff.Load(HELLO_SPARC); CPPUNIT_ASSERT(pBF != NULL); int n; SectionInfo* si; n = pBF->GetNumSections(); ost << "Number of sections = " << std::dec << n << "\r\n\t"; // Just use the first (real one) and last sections si = pBF->GetSectionInfo(1); ost << si->pSectionName << "\t"; si = pBF->GetSectionInfo(n-1); ost << si->pSectionName; pBF->UnLoad(); // Note: the string below needs to have embedded tabs. Edit with caution! std::string expected("Number of sections = 29\r\n\t" ".interp .stab.indexstr"); CPPUNIT_ASSERT_EQUAL(expected, ost.str()); bff.UnLoad(); }
/*============================================================================== * FUNCTION: LoaderTest::testWinLoad * OVERVIEW: Test loading Windows programs *============================================================================*/ void LoaderTest::testWinLoad () { std::ostringstream ost; #if 0 /* FIXME: these tests should use non-proprietary programs */ // Load Windows program calc.exe BinaryFileFactory bff; BinaryFile* pBF = bff.Load(CALC_WINDOWS); CPPUNIT_ASSERT(pBF != NULL); int n; SectionInfo* si; n = pBF->GetNumSections(); ost << "Number of sections = " << std::dec << n << "\r\n"; for (int i=0; i < n; i++) { si = pBF->GetSectionInfo(i); ost << si->pSectionName << "\t"; } // Note: the string below needs to have embedded tabs. Edit with caution! std::string expected("Number of sections = 5\r\n" ".text .rdata .data .rsrc .reloc "); std::string actual(ost.str()); CPPUNIT_ASSERT_EQUAL(expected, actual); ADDRESS addr = pBF->GetMainEntryPoint(); CPPUNIT_ASSERT(addr != NO_ADDRESS); // Test symbol table (imports) const char* s = pBF->SymbolByAddress(0x1292060U); if (s == 0) actual = "<not found>"; else actual = std::string(s); expected = std::string("SetEvent"); CPPUNIT_ASSERT_EQUAL(expected, actual); ADDRESS a = pBF->GetAddressByName("SetEvent"); ADDRESS expectedAddr = 0x1292060; CPPUNIT_ASSERT_EQUAL(expectedAddr, a); pBF->UnLoad(); bff.UnLoad(); // Test loading the "new style" exes, as found in winXP etc pBF = bff.Load(CALC_WINXP); CPPUNIT_ASSERT(pBF != NULL); addr = pBF->GetMainEntryPoint(); std::ostringstream ost1; ost1 << std::hex << addr; actual = ost1.str(); expected = "1001f51"; CPPUNIT_ASSERT_EQUAL(expected, actual); pBF->UnLoad(); bff.UnLoad(); // Test loading the calc.exe found in Windows 2000 (more NT based) pBF = bff.Load(CALC_WIN2000); CPPUNIT_ASSERT(pBF != NULL); expected = "1001680"; addr = pBF->GetMainEntryPoint(); std::ostringstream ost2; ost2 << std::hex << addr; actual = ost2.str(); CPPUNIT_ASSERT_EQUAL(expected, actual); pBF->UnLoad(); bff.UnLoad(); // Test loading the lpq.exe program - console mode PE file pBF = bff.Load(LPQ_WINDOWS); CPPUNIT_ASSERT(pBF != NULL); addr = pBF->GetMainEntryPoint(); std::ostringstream ost3; ost3 << std::hex << addr; actual = ost3.str(); expected = "18c1000"; CPPUNIT_ASSERT_EQUAL(expected, actual); pBF->UnLoad(); bff.UnLoad(); #endif // Borland BinaryFileFactory bff; BinaryFile* pBF = bff.Load(SWITCH_BORLAND); CPPUNIT_ASSERT(pBF != NULL); ADDRESS addr = pBF->GetMainEntryPoint(); std::ostringstream ost4; ost4 << std::hex << addr; std::string actual(ost4.str()); std::string expected("401150"); CPPUNIT_ASSERT_EQUAL(expected, actual); pBF->UnLoad(); bff.UnLoad(); }
/*============================================================================== * FUNCTION: FrontSparcTest::test1 * OVERVIEW: Test decoding some sparc instructions *============================================================================*/ void FrontSparcTest::test1 () { std::ostringstream ost; BinaryFileFactory bff; BinaryFile *pBF = bff.Load(HELLO_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); bool gotMain; ADDRESS addr = pFE->getMainEntryPoint(gotMain); CPPUNIT_ASSERT (addr != NO_ADDRESS); // Decode first instruction DecodeResult inst = pFE->decodeInstruction(addr); CPPUNIT_ASSERT(inst.rtl != NULL); inst.rtl->print(ost); std::string expected( "00010684 0 *32* tmp := r14 - 112\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"); CPPUNIT_ASSERT_EQUAL(expected, std::string(ost.str())); std::ostringstream o2; addr += inst.numBytes; inst = pFE->decodeInstruction(addr); inst.rtl->print(o2); expected = std::string("00010688 0 *32* r8 := 0x10400\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o2.str())); std::ostringstream o3; addr += inst.numBytes; inst = pFE->decodeInstruction(addr); inst.rtl->print(o3); expected = std::string("0001068c 0 *32* r8 := r8 | 848\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o3.str())); delete pFE; //delete pBF; }
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; }
void FrontSparcTest::test3() { DecodeResult inst; std::string expected; BinaryFileFactory bff; BinaryFile *pBF = bff.Load(HELLO_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); std::ostringstream o1; inst = pFE->decodeInstruction(0x106a0); inst.rtl->print(o1); expected = std::string("000106a0\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o1.str())); std::ostringstream o2; inst = pFE->decodeInstruction(0x106a4); inst.rtl->print(o2); expected = std::string("000106a4 0 RET\n" " Modifieds: \n" " Reaching definitions: \n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o2.str())); std::ostringstream o3; inst = pFE->decodeInstruction(0x106a8); inst.rtl->print(o3); expected = std::string( "000106a8 0 *32* tmp := 0\n" " 0 *32* r8 := r24\n" " 0 *32* r9 := r25\n" " 0 *32* r10 := r26\n" " 0 *32* r11 := r27\n" " 0 *32* r12 := r28\n" " 0 *32* r13 := r29\n" " 0 *32* r14 := r30\n" " 0 *32* r15 := r31\n" " 0 *32* r0 := tmp\n" " 0 *32* r16 := m[r14]\n" " 0 *32* r17 := m[r14 + 4]\n" " 0 *32* r18 := m[r14 + 8]\n" " 0 *32* r19 := m[r14 + 12]\n" " 0 *32* r20 := m[r14 + 16]\n" " 0 *32* r21 := m[r14 + 20]\n" " 0 *32* r22 := m[r14 + 24]\n" " 0 *32* r23 := m[r14 + 28]\n" " 0 *32* r24 := m[r14 + 32]\n" " 0 *32* r25 := m[r14 + 36]\n" " 0 *32* r26 := m[r14 + 40]\n" " 0 *32* r27 := m[r14 + 44]\n" " 0 *32* r28 := m[r14 + 48]\n" " 0 *32* r29 := m[r14 + 52]\n" " 0 *32* r30 := m[r14 + 56]\n" " 0 *32* r31 := m[r14 + 60]\n" " 0 *32* r0 := tmp\n"); CPPUNIT_ASSERT_EQUAL(expected, std::string(o3.str())); delete pFE; // delete pBF; }
int main(int argc, char* argv[]) { // Usage if (argc != 2) { printf ("Usage: %s <filename>\n", argv[0]); printf ("%s dumps the contents of the given executable file\n", argv[0]); return 1; } // Load the file BinaryFile *pbf = NULL; BinaryFileFactory bff; pbf = bff.Load(argv[1]); if (pbf == NULL) { return 2; } // Display program and section information // If the DisplayDetails() function has not been implemented // in the derived class (ElfBinaryFile in this case), then // uncomment the commented code below to display section information. pbf->DisplayDetails (argv[0]); // This is an alternative way of displaying binary-file information // by using individual sections. The above approach is more general. /* printf ("%d sections:\n", pbf->GetNumSections()); for (int i=0; i < pbf->GetNumSections(); i++) { SectionInfo* pSect = pbf->GetSectionInfo(i); printf(" Section %s at %X\n", pSect->pSectionName, pSect->uNativeAddr); } printf("\n"); */ // Display the code section in raw hexadecimal notation // Note: this is traditionally the ".text" section in Elf binaries. // In the case of Prc files (Palm), the code section is named "code0". for (int i=0; i < pbf->GetNumSections(); i++) { SectionInfo* pSect = pbf->GetSectionInfo(i); if (pSect->bCode) { printf(" Code section:\n"); ADDRESS a = pSect->uNativeAddr; unsigned char* p = (unsigned char*) pSect->uHostAddr; for (unsigned off = 0; off < pSect->uSectionSize; ) { printf("%04X: ", a); for (int j=0; (j < 16) && (off < pSect->uSectionSize); j++) { printf("%02X ", *p++); a++; off++; } printf("\n"); } printf("\n"); } } // Display the data section(s) in raw hexadecimal notation for (int i=0; i < pbf->GetNumSections(); i++) { SectionInfo* pSect = pbf->GetSectionInfo(i); if (pSect->bData) { printf(" Data section: %s\n", pSect->pSectionName); ADDRESS a = pSect->uNativeAddr; unsigned char* p = (unsigned char*) pSect->uHostAddr; for (unsigned off = 0; off < pSect->uSectionSize; ) { printf("%04X: ", a); for (int j=0; (j < 16) && (off < pSect->uSectionSize); j++) { printf("%02X ", *p++); a++; off++; } printf("\n"); } printf("\n"); } } pbf->UnLoad(); return 0; }