Beispiel #1
0
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;
}
Beispiel #2
0
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
}
Beispiel #3
0
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;
}