void visit(SgNode *node) { SgAsmRegisterReferenceExpression *rre = isSgAsmRegisterReferenceExpression(node); if (rre) { size_t nbits = rre->get_descriptor().get_nbits(); double v = log(nbits) / M_LN2; sum += do_variance ? (v-mean)*(v-mean) : v; ++n; } }
// see base class bool SgAsmMipsInstruction::is_function_return(const std::vector<SgAsmInstruction*> &insns) { if (insns.empty()) return false; SgAsmMipsInstruction *last = isSgAsmMipsInstruction(insns.back()); if (!last) return false; if (last->get_kind()!=mips_jr) return false; const SgAsmExpressionPtrList &args = last->get_operandList()->get_operands(); if (args.size()<1) return false; SgAsmRegisterReferenceExpression *rre = isSgAsmRegisterReferenceExpression(args[0]); if (!rre) return false; if (rre->get_descriptor().get_major()!=mips_regclass_gpr || rre->get_descriptor().get_minor()!=31) return false; return true; // this is a "JR ra" instruction. }
/** HashAST::visit * * Called by traverse. Gets the whatever data is of interest and puts * it in the hash. * * @param[in] node to submit to hash **/ void AstHash::visit(SgNode* node) { //Always include the type of each node in the hash VariantT vType = node->variantT(); hasher_.insert(vType); //If it's an instruction, include the mnemonic, and maybe the address SgAsmInstruction* asmInstruction = isSgAsmInstruction(node); if(asmInstruction != NULL) { std::string mnemonic = asmInstruction->get_mnemonic(); hasher_.insert(mnemonic); if(includeAddresses) { rose_addr_t addr = asmInstruction->get_address(); hasher_.insert(addr); } return; } //Always include register references SgAsmRegisterReferenceExpression* regRef = isSgAsmRegisterReferenceExpression(node); if(regRef != NULL) { unsigned regHash = regRef->get_descriptor().hash(); hasher_.insert(regHash); return; } //Maybe inlcude constants (integers, floats, pointers) if(includeConstants) { SgAsmConstantExpression* constExpr = isSgAsmConstantExpression(node); if(constExpr != NULL) { std::string mnemonic = constExpr->get_bitVector().toHex(); hasher_.insert(mnemonic); return; } } }
void AST_BIN_Traversal::visit(SgNode* n) { if (n) { nrOfInstructions++; std::string name = ""; if (isSgAsmInstruction(n)) name = unparseInstruction(isSgAsmInstruction(n)); SgNode* parent = n->get_parent(); // node std::string add = ",shape=ellipse,regular=0, sides=5,peripheries=1,color=\"Black\",fillcolor=yellow,fontname=\"7x13bold\",fontcolor=black,style=filled"; if (isSgAsmFunction(n)) { add = ",shape=ellipse,regular=0, sides=5,peripheries=1,color=\"Black\",fillcolor=purple,fontname=\"7x13bold\",fontcolor=black,style=filled"; name = isSgAsmFunction(n)->get_name(); } if (isSgAsmX86Instruction(n) && isSgAsmX86Instruction(n)->get_kind() == x86_call) add = ",shape=ellipse,regular=0, sides=5,peripheries=1,color=\"Black\",fillcolor=red,fontname=\"7x13bold\",fontcolor=black,style=filled"; if (isSgAsmValueExpression(n)) add = ",shape=ellipse,regular=0, sides=5,peripheries=1,color=\"Black\",fillcolor=lightgreen,fontname=\"7x13bold\",fontcolor=black,style=filled"; if (isSgAsmMemoryReferenceExpression(n)) add = ",shape=ellipse,regular=0, sides=5,peripheries=1,color=\"Black\",fillcolor=lightblue,fontname=\"7x13bold\",fontcolor=black,style=filled"; if (isSgAsmBinaryExpression(n)) add = ",shape=ellipse,regular=0, sides=5,peripheries=1,color=\"Black\",fillcolor=orange,fontname=\"7x13bold\",fontcolor=black,style=filled"; if (isSgAsmRegisterReferenceExpression(n)) { SgAsmRegisterReferenceExpression* rr = isSgAsmRegisterReferenceExpression(n); std::string exprName = unparseX86Register(rr->get_descriptor(), NULL); name += " "+exprName; add = ",shape=ellipse,regular=0, sides=5,peripheries=1,color=\"Black\",fillcolor=green,fontname=\"7x13bold\",fontcolor=black,style=filled"; } if (isSgAsmOperandList(n)) add = ",shape=ellipse,regular=0, sides=5,peripheries=1,color=\"Black\",fillcolor=white,fontname=\"7x13bold\",fontcolor=black,style=filled"; myfile << "\"" << n << "\"[label=\"" << name << "\\n" << n->class_name() << "\"" << add << " ];\n"; if (parent) { // edge myfile << "\"" << parent << "\" -> \"" << n << "\" [label=\"" << n->class_name() << "\" ];\n"; } } }
/** Return control flow successors. See base class for full documentation. */ BinaryAnalysis::Disassembler::AddressSet SgAsmArmInstruction::getSuccessors(bool *complete) { BinaryAnalysis::Disassembler::AddressSet retval; const std::vector<SgAsmExpression*> &exprs = get_operandList()->get_operands(); *complete = true; /*assume retval is the complete set of successors for now*/ switch (get_kind()) { case arm_b: case arm_bl: case arm_blx: case arm_bx: { /* Branch target */ ROSE_ASSERT(exprs.size()==1); SgAsmExpression *dest = exprs[0]; if (isSgAsmValueExpression(dest)) { rose_addr_t target_va = SageInterface::getAsmConstant(isSgAsmValueExpression(dest)); retval.insert(target_va); } else { /* Could also be a register reference expression, but we don't know the successor in that case. */ *complete = false; } /* Fall-through address */ if (get_condition()!=arm_cond_al) retval.insert(get_address()+4); break; } case arm_bxj: { /* First argument is the register that holds the next instruction pointer value to use in the case that Jazelle is * not available. We only know the successor if the register is the instruction pointer, in which case the * successor is the fall-through address. */ ROSE_ASSERT(exprs.size()==1); SgAsmRegisterReferenceExpression *rre = isSgAsmRegisterReferenceExpression(exprs[0]); ROSE_ASSERT(rre); if (rre->get_descriptor().get_major()==arm_regclass_gpr && rre->get_descriptor().get_minor()==15) { retval.insert(get_address()+4); } else { *complete = false; } break; } case arm_cmn: case arm_cmp: case arm_teq: case arm_tst: /* Comparison and test instructions don't ever affect the instruction pointer; they only fall through */ retval.insert(get_address()+4); break; case arm_bkpt: case arm_swi: case arm_undefined: case arm_unknown_instruction: /* No known successors for interrupt-generating instructions */ break; default: if (!modifies_ip(this) || get_condition()!=arm_cond_al) { retval.insert(get_address()+4); } else { *complete = false; } break; } return retval; }
/* Returns true if the instruction modifies the instruction pointer (r15). */ static bool modifies_ip(SgAsmArmInstruction *insn) { switch (insn->get_kind()) { /* Branch instructions */ case arm_b: case arm_bl: case arm_blx: case arm_bx: case arm_bxj: return true; /* Comparison instructions */ case arm_cmn: case arm_cmp: case arm_teq: case arm_tst: return false; /* Load multiple registers instructions. Second argument is the set of registers to load. If the instruction * pointer (r15) can be one of them. */ case arm_ldm: case arm_ldmda: case arm_ldmdb: case arm_ldmia: case arm_ldmib: { const std::vector<SgAsmExpression*> &exprs = insn->get_operandList()->get_operands(); ROSE_ASSERT(exprs.size()>=2); SgAsmExprListExp *elist = isSgAsmExprListExp(exprs[1]); if (!elist) { SgAsmUnaryArmSpecialRegisterList *rlist = isSgAsmUnaryArmSpecialRegisterList(exprs[1]); ROSE_ASSERT(rlist); elist = isSgAsmExprListExp(rlist->get_operand()); ROSE_ASSERT(elist); } for (size_t i=0; i<elist->get_expressions().size(); i++) { SgAsmRegisterReferenceExpression *reg = isSgAsmRegisterReferenceExpression(elist->get_expressions()[i]); ROSE_ASSERT(reg); if (reg->get_descriptor().get_major()==arm_regclass_gpr && reg->get_descriptor().get_minor()==15) { return true; } } return false; } /* Interrupt-causing instructions */ case arm_bkpt: case arm_swi: case arm_undefined: return true; /* Other instructions modify the instruction pointer if it's the first (destination) argument. */ default: { const std::vector<SgAsmExpression*> &exprs = insn->get_operandList()->get_operands(); if (exprs.size()>=1) { SgAsmRegisterReferenceExpression *rre = isSgAsmRegisterReferenceExpression(exprs[0]); if (rre && rre->get_descriptor().get_major()==arm_regclass_gpr && rre->get_descriptor().get_minor()==15) { return true; } } } } return false; }
// Constructor DataMemberInitializationAttribute::DataMemberInitializationAttribute ( SgAsmInstruction* instruction, SgProject* p ) { ROSE_ASSERT(instruction != NULL); printf ("Building a DataMemberInitializationAttribute object for instruction = %s \n",unparseInstructionWithAddress(instruction).c_str()); // Identify the offset and if this is a stack reference or a global reference. SgAsmMemoryReferenceExpression* memoryReferenceExpression = isSgAsmMemoryReferenceExpression(instruction->get_operandList()->get_operands()[0]); ROSE_ASSERT(memoryReferenceExpression != NULL); SgAsmRegisterReferenceExpression* segmentRegister = isSgAsmRegisterReferenceExpression(memoryReferenceExpression->get_segment()); ROSE_ASSERT(segmentRegister != NULL); #ifdef USE_NEW_ISA_INDEPENDENT_REGISTER_HANDLING // This is a data member isStackVariable = (segmentRegister->get_register_number() == SgAsmRegisterReferenceExpression::e_ss); // This is to test if there is another register being referenced. bool isGlobalVariable = (segmentRegister->get_register_number() == SgAsmRegisterReferenceExpression::e_ds); // This should be either a stack or global variable (no other allowed). ROSE_ASSERT(isStackVariable == true || isGlobalVariable == true); ROSE_ASSERT(isStackVariable == false || isGlobalVariable == false); SgAsmBinaryAdd* binaryAdd = isSgAsmBinaryAdd(memoryReferenceExpression->get_address()); if (binaryAdd != NULL) { // Case of a non-zero offset into the global scope or the stack frame. ROSE_ASSERT(binaryAdd->get_rhs() != NULL); SgAsmValueExpression* offsetExpression = isSgAsmValueExpression(binaryAdd->get_rhs()); ROSE_ASSERT(offsetExpression != NULL); offset = get_value(offsetExpression); } else { // Case of zero offset from stack frame (first variable in the stack) // or a global variable with immediate address. offset = 0; if (isGlobalVariable == true) { // Handle the case of a global variable. ROSE_ASSERT(memoryReferenceExpression != NULL); SgAsmValueExpression* offsetExpression = isSgAsmValueExpression(memoryReferenceExpression->get_address()); if (offsetExpression != NULL) { offset = get_value(offsetExpression); } #if 0 // ... finish me ... printf ("... finish me ... offset = %p \n",(void*)offset); ROSE_ASSERT(false); #else printf ("isGlobalVariable == true: offset = %p \n",(void*)offset); #endif } } SgAsmValueExpression* valueExpression = isSgAsmValueExpression(instruction->get_operandList()->get_operands()[1]); ROSE_ASSERT(valueExpression != NULL); value = get_value(valueExpression); type = valueExpression->get_type(); ROSE_ASSERT(type != NULL); printf (" isStackVariable = %s \n",isStackVariable ? "true" : "false"); printf (" isGlobalVariable = %s \n",isGlobalVariable ? "true" : "false"); printf (" offset = %zu \n",offset); printf (" value = %zu = %p \n",value,(void*)value); printf (" type = %p = %s \n",type,type->class_name().c_str()); #else // DQ (9/2/2013): This allows us to get the existing code compiled and then move to update the code seperately. printf ("This code needs to be updated to handle the new register handling (ISA independence) \n"); ROSE_ASSERT(false); #endif #if 0 printf ("Exiting as a test... \n"); ROSE_ASSERT(false); #endif }
SgAsmInstruction* RoseBin_FlowAnalysis::process_jumps_get_target(SgAsmx86Instruction* inst) { if (inst && x86InstructionIsControlTransfer(inst)) { //cerr << " ..................... processing jmp " << endl; ostringstream addrhex3; int addrsource = inst->get_address(); addrhex3 << hex << setw(8) << addrsource ; string funcName =""; // get the operand and the destination address SgAsmOperandList* opList = inst->get_operandList(); ROSE_ASSERT(opList); SgAsmExpressionPtrList ptrList = opList->get_operands(); std::vector<SgAsmExpression*>::iterator itList= ptrList.begin(); for (;itList!=ptrList.end();++itList) { SgAsmExpression* exp = *itList; ROSE_ASSERT(exp); SgAsmRegisterReferenceExpression* regRef = isSgAsmRegisterReferenceExpression(exp); //if (RoseBin_support::DEBUG_MODE()) // cout << " inst (jmp):: " << inst->get_mnemonic() << " addr : " << addrhex3.str() << endl; SgAsmValueExpression* valExpr = isSgAsmValueExpression(exp); SgAsmMemoryReferenceExpression* memExpr = isSgAsmMemoryReferenceExpression(exp); string valStr = ""; if (valExpr) { uint8_t byte_val=0xF; uint16_t word_val=0xFF; uint32_t double_word_val=0xFFFF; uint64_t quad_word_val=0xFFFFFFFFU; valStr = RoseBin_support::resolveValue(valExpr, true, byte_val, word_val, double_word_val, quad_word_val); //if (RoseBin_support::DEBUG_MODE()) //cout << " found value ....... :: " << valStr << endl; funcName = valExpr->get_replacement(); //if (funcName=="") // funcName="noName"; } if (memExpr) { continue; // this is a jump to data ... do not handle right now!! } // convert val string to long uint64_t val=0; if(from_string<uint64_t>(val, valStr, std::hex)) { ostringstream addrhex2; addrhex2 << hex << setw(8) << val ; //if (RoseBin_support::DEBUG_MODE()) //cerr << " looking for value ("<<valStr << " ) in InstrSet: " // << val << " " << addrhex2.str() << endl; rose_hash::unordered_map <uint64_t, SgAsmInstruction* >::const_iterator itc = rememberInstructions.find(val); if (itc!=rememberInstructions.end()) { SgAsmInstruction* target = itc->second; // we set the target (jump to for each control instruction) ROSE_ASSERT(target); //if (RoseBin_support::DEBUG_MODE()) //cout << " >>> target found! " << target << " funcName " << funcName << endl; if (funcName!="") { SgAsmNode* block = target; if (!db) block = isSgAsmNode(target->get_parent()); ROSE_ASSERT(block); SgAsmFunction* func = isSgAsmFunction(block->get_parent()); if (func) { string fname = func->get_name(); uint64_t val_f=0; if(from_string<uint64_t>(val_f, fname, std::hex)) { // func name is a hex number func->set_name(funcName); // inst->set_comment(funcName); } else { // its a name } } } return target; } else { //if (RoseBin_support::DEBUG_MODE()) // cerr << " >>>>>>>>>>>>>>> !!! OPS :: Target not found ... \n" << endl; } } else{ // std::cerr << "FlowAnalysis :: from_string failed .. " << std::endl; if (valStr!="") if (RoseBin_support::DEBUG_MODE()) cerr << " WARNING: Cant convert string to long - in process_jump :: " << regRef->class_name() << " inst :: " << inst->get_mnemonic() << " addr : " << addrhex3.str() << " target : " << valStr << endl; } } } return NULL; }