void CountTraversal::visit ( SgNode* n ) { SgAsmInstruction* asmInstruction = isSgAsmInstruction(n); if (asmInstruction != NULL) { // Use the new interface support for this (this detects all multi-byte nop instructions). if (SageInterface::isNOP(asmInstruction) == true) { if (previousInstructionWasNop == true) { // Increment the length of the identified NOP sequence count++; } else { count = 1; // Record the starting address of the NOP sequence nopSequenceStart = asmInstruction; } previousInstructionWasNop = true; } else { if (count > 0) { // Report the sequence when we have detected the end of the sequence. SgAsmFunction* functionDeclaration = getAsmFunction(asmInstruction); printf ("Reporting NOP sequence of length %3d at address %zu in function %s (reason for this being a function = %u = %s) \n", count,nopSequenceStart->get_address(),functionDeclaration->get_name().c_str(), functionDeclaration->get_reason(), stringifySgAsmFunctionFunctionReason(functionDeclaration->get_reason()).c_str()); nopSequences.push_back(pair<SgAsmInstruction*,int>(nopSequenceStart,count)); SgAsmBlock* block = isSgAsmBlock(nopSequenceStart->get_parent()); ROSE_ASSERT(block != NULL); SgAsmStatementPtrList & l = block->get_statementList(); // Now iterate over the nop instructions in the sequence and report the lenght of each (can be multi-byte nop instructions). SgAsmStatementPtrList::iterator i = find(l.begin(),l.end(),nopSequenceStart); ROSE_ASSERT(i != l.end()); int counter = 0; while ( (*i != asmInstruction) && (i != l.end()) ) { printf ("--- NOP #%2d is length = %2d \n",counter++,(int)isSgAsmInstruction(*i)->get_raw_bytes().size()); i++; } } count = 0; previousInstructionWasNop = false; } } }
void visit(SgNode *node) { if (SgAsmInstruction *insn = isSgAsmInstruction(node)) { SgAsmFunction *func = SageInterface::getEnclosingNode<SgAsmFunction>(insn); if (func && 0==(func->get_reason() & SgAsmFunction::FUNC_LEFTOVERS)) insns.insert(std::make_pair(insn->get_address(), insn)); } }
bool operator()(ControlFlow *analyzer, SgAsmNode *node) { SgAsmFunction *func = SageInterface::getEnclosingNode<SgAsmFunction>(node, true); return func && 0==(func->get_reason() & SgAsmFunction::FUNC_LEFTOVERS); }
int main(int argc, char** argv) { std::string binaryFilename = (argc >= 1 ? argv[argc-1] : "" ); std::vector<std::string> newArgv(argv,argv+argc); newArgv.push_back("-rose:output"); newArgv.push_back(binaryFilename+"-binarySemantics.C"); SgProject* proj = frontend(newArgv); ROSE_ASSERT (proj); SgSourceFile* newFile = isSgSourceFile(proj->get_fileList().front()); ROSE_ASSERT(newFile != NULL); SgGlobal* g = newFile->get_globalScope(); ROSE_ASSERT (g); //I am doing some experimental work to enable functions in the C representation //Set this flag to true in order to enable that work bool enable_functions = true; //Jeremiah did some work to enable a simplification and normalization of the //C representation. Enable this work by setting this flag to true. bool enable_normalizations = false; vector<SgNode*> asmFiles = NodeQuery::querySubTree(proj, V_SgAsmGenericFile); ROSE_ASSERT (asmFiles.size() == 1); if( enable_functions == false) { //Representation of C normalizations withotu functions SgFunctionDeclaration* decl = buildDefiningFunctionDeclaration("run", SgTypeVoid::createType(), buildFunctionParameterList(), g); appendStatement(decl, g); SgBasicBlock* body = decl->get_definition()->get_body(); // ROSE_ASSERT(isSgAsmFile(asmFiles[0])); // X86CTranslationPolicy policy(newFile, isSgAsmFile(asmFiles[0])); X86CTranslationPolicy policy(newFile, isSgAsmGenericFile(asmFiles[0])); ROSE_ASSERT( isSgAsmGenericFile(asmFiles[0]) != NULL); policy.switchBody = buildBasicBlock(); removeDeadStores(policy.switchBody,policy); SgSwitchStatement* sw = buildSwitchStatement(buildVarRefExp(policy.ipSym), policy.switchBody); ROSE_ASSERT(isSgBasicBlock(sw->get_body())); SgWhileStmt* whileStmt = buildWhileStmt(buildBoolValExp(true), sw); appendStatement(whileStmt, body); policy.whileBody = sw; X86InstructionSemantics<X86CTranslationPolicy, WordWithExpression> t(policy); //AS FIXME: This query gets noting in the form in the repository. Doing this hack since we only //have one binary file anyways. //vector<SgNode*> instructions = NodeQuery::querySubTree(asmFiles[0], V_SgAsmX86Instruction); vector<SgNode*> instructions = NodeQuery::querySubTree(proj, V_SgAsmX86Instruction); std::cout << "Instruction\n"; for (size_t i = 0; i < instructions.size(); ++i) { SgAsmX86Instruction* insn = isSgAsmX86Instruction(instructions[i]); ROSE_ASSERT (insn); try { t.processInstruction(insn); } catch (const X86InstructionSemantics<X86CTranslationPolicy, WordWithExpression>::Exception &e) { std::cout <<e.mesg <<": " <<unparseInstructionWithAddress(e.insn) <<"\n"; } } if ( enable_normalizations == true ) { //Enable normalizations of C representation //This is done heuristically where some steps //are repeated. It is not clear which order is //the best { plugInAllConstVarDefs(policy.switchBody,policy) ; simplifyAllExpressions(policy.switchBody); removeIfConstants(policy.switchBody); removeDeadStores(policy.switchBody,policy); removeUnusedVariables(policy.switchBody); } { plugInAllConstVarDefs(policy.switchBody,policy) ; simplifyAllExpressions(policy.switchBody); removeIfConstants(policy.switchBody); removeDeadStores(policy.switchBody,policy); } removeUnusedVariables(policy.switchBody); } }else{ //Experimental changes to introduce functions into the C representation //When trying to add function I get that symbols are not defined //Iterate over the functions separately vector<SgNode*> asmFunctions = NodeQuery::querySubTree(proj, V_SgAsmFunction); for(size_t j = 0; j < asmFunctions.size(); j++ ) { SgAsmFunction* binFunc = isSgAsmFunction( asmFunctions[j] ); // Some functions (probably just one) are generated to hold basic blocks that could not // be assigned to a particular function. This happens when the Disassembler is overzealous // and the Partitioner cannot statically determine where the block belongs. The name of // one such function is "***uncategorized blocks***". [matzke 2010-06-29] if ((binFunc->get_reason() & SgAsmFunction::FUNC_LEFTOVERS)) continue; //Some functions may be unnamed so we need to generate a name for those std::string funcName; if (binFunc->get_name().size()==0) { char addr_str[64]; sprintf(addr_str, "0x%"PRIx64, binFunc->get_statementList()[0]->get_address()); funcName = std::string("my_") + addr_str;; } else { funcName = "my" + binFunc->get_name(); } //Functions can have illegal characters in their name. Need to replace those characters for ( int i = 0 ; i < funcName.size(); i++ ) { char& currentCharacter = funcName.at(i); if ( currentCharacter == '.' ) currentCharacter = '_'; } SgFunctionDeclaration* decl = buildDefiningFunctionDeclaration(funcName, SgTypeVoid::createType(), buildFunctionParameterList(), g); appendStatement(decl, g); SgBasicBlock* body = decl->get_definition()->get_body(); X86CTranslationPolicy policy(newFile, isSgAsmGenericFile(asmFiles[0])); ROSE_ASSERT( isSgAsmGenericFile(asmFiles[0]) != NULL); policy.switchBody = buildBasicBlock(); SgSwitchStatement* sw = buildSwitchStatement(buildVarRefExp(policy.ipSym), policy.switchBody); SgWhileStmt* whileStmt = buildWhileStmt(buildBoolValExp(true), sw); appendStatement(whileStmt, body); policy.whileBody = sw; X86InstructionSemantics<X86CTranslationPolicy, WordWithExpression> t(policy); vector<SgNode*> instructions = NodeQuery::querySubTree(binFunc, V_SgAsmX86Instruction); for (size_t i = 0; i < instructions.size(); ++i) { SgAsmX86Instruction* insn = isSgAsmX86Instruction(instructions[i]); if( insn->get_kind() == x86_nop ) continue; ROSE_ASSERT (insn); try { t.processInstruction(insn); } catch (const X86InstructionSemantics<X86CTranslationPolicy, WordWithExpression>::Exception &e) { std::cout <<e.mesg <<": " <<unparseInstructionWithAddress(e.insn) <<"\n"; } } } //addDirectJumpsToSwitchCases(policy); } proj->get_fileList().erase(proj->get_fileList().end() - 1); // Remove binary file before calling backend // AstTests::runAllTests(proj); //Compile the resulting project return backend(proj); }