void get_prog_point(CPUState* cpu, prog_point *p) { CPUArchState* env = (CPUArchState*)cpu->env_ptr; if (!p) return; // Get address space identifier target_ulong asid = panda_current_asid(ENV_GET_CPU(env)); // Lump all kernel-mode CR3s together if(!in_kernelspace(env)) p->cr3 = asid; // Try to get the caller int n_callers = 0; n_callers = get_callers(&p->caller, 1, cpu); if (n_callers == 0) { #ifdef TARGET_I386 // fall back to EBP on x86 int word_size = (env->hflags & HF_LMA_MASK) ? 8 : 4; panda_virtual_memory_rw(cpu, env->regs[R_EBP]+word_size, (uint8_t *)&p->caller, word_size, 0); #endif #ifdef TARGET_ARM p->caller = env->regs[14]; // LR #endif } p->pc = cpu->panda_guest_pc; }
static stackid get_stackid(CPUArchState* env) { #ifdef USE_STACK_HEURISTIC target_ulong asid; // Track all kernel-mode stacks together if (in_kernelspace(env)) asid = 0; else asid = panda_current_asid(ENV_GET_CPU(env)); // Invalidate cached stack pointer on ASID change if (cached_asid == 0 || cached_asid != asid) { cached_sp = 0; cached_asid = asid; } target_ulong sp = get_stack_pointer(env); // We can short-circuit the search in most cases if (std::abs(sp - cached_sp) < MAX_STACK_DIFF) { return std::make_pair(asid, cached_sp); } auto &stackset = stacks_seen[asid]; if (stackset.empty()) { stackset.insert(sp); cached_sp = sp; return std::make_pair(asid,sp); } else { // Find the closest stack pointer we've seen auto lb = std::lower_bound(stackset.begin(), stackset.end(), sp); target_ulong stack1 = *lb; lb--; target_ulong stack2 = *lb; target_ulong stack = (std::abs(stack1 - sp) < std::abs(stack2 - sp)) ? stack1 : stack2; int diff = std::abs(stack-sp); if (diff < MAX_STACK_DIFF) { return std::make_pair(asid,stack); } else { stackset.insert(sp); cached_sp = sp; return std::make_pair(asid,sp); } } #else return panda_current_asid(ENV_GET_CPU(env)); #endif }
static bool returned_check_callback(CPUState *env, TranslationBlock* tb){ // First, check if any of the PANDA VMI callbacks needs to be triggered #if defined(CONFIG_PANDA_VMI) panda_cb_list *plist; for(auto& retVal :fork_returns){ if (retVal.retaddr == tb->pc && retVal.process_id == get_asid(env, tb->pc)){ // we returned from fork for(plist = panda_cbs[PANDA_CB_VMI_AFTER_FORK]; plist != NULL; plist = plist->next) { plist->entry.return_from_fork(env); } // set to 0,0 so we can remove after we finish iterating retVal.retaddr = retVal.process_id = 0; } } fork_returns.remove_if(is_empty); for(auto& retVal :exec_returns){ if(retVal.process_id == get_asid(env, tb->pc) && !in_kernelspace(env)){ //if (retVal.retaddr == tb->pc /*&& retVal.process_id == get_asid(env, tb->pc)*/){ // we returned from fork for(plist = panda_cbs[PANDA_CB_VMI_AFTER_EXEC]; plist != NULL; plist = plist->next) { plist->entry.return_from_exec(env); } // set to 0,0 so we can remove after we finish iterating retVal.retaddr = retVal.process_id = 0; } } exec_returns.remove_if(is_empty); for(auto& retVal :clone_returns){ if (retVal.retaddr == tb->pc && retVal.process_id == get_asid(env, tb->pc)){ // we returned from fork for(plist = panda_cbs[PANDA_CB_VMI_AFTER_CLONE]; plist != NULL; plist = plist->next) { plist->entry.return_from_clone(env); } // set to 0,0 so we can remove after we finish iterating retVal.retaddr = retVal.process_id = 0; } } clone_returns.remove_if(is_empty); #else fork_returns.clear(); exec_returns.clear(); clone_returns.clear(); #endif //check if any of the internally tracked syscalls has returned //only one should be at its return point for any given basic block bool invalidate = false; for(auto& retVal : other_returns){ if(retVal.retaddr == tb->pc && retVal.process_id == get_asid(env, tb->pc)){ Callback_RC rc = retVal.callback(retVal.opaque.get(), env, retVal.process_id); if(Callback_RC::INVALIDATE == rc){ invalidate = true; } else if(Callback_RC::NORMAL == rc){ retVal.retaddr = retVal.process_id = 0; } else if(Callback_RC::ERROR == rc){ fprintf(stderr, "Syscalls caused an error\n"); assert(0); } else { fprintf(stderr, "Unknown syscalls internal callback return value\n"); assert(0); } } } other_returns.remove_if(is_empty); return invalidate; }