Beispiel #1
0
static void
_vm_rstep(VMState *state, int nsteps, VMStateDiff **diff, bool *hit_bp,
          bool first)
{
    VMSingleStateDiff *singlediff;
    VMStateDiff *next;

    *hit_bp = false;
    state->stopped_running = false;

    while (nsteps-- && (*diff)->next) {
        if (!first && _hit_breakpoint(state)) {
            *hit_bp = true;
            break;
        }

        first = false;

#if 0
        printf("Applying diff: ");
        _print_diff(state, *diff);
#endif

        state->cycles = (*diff)->cycles;
        state->registers[PC] = (*diff)->pc;

        singlediff = (*diff)->singlediff;
        /* Apply singlediff changes */
        while (singlediff) {
            OPCODE_TYPE *location;

            location = _get_location(state, singlediff->type,
                                     singlediff->location);
            *location = singlediff->oldval;

            singlediff = singlediff->next;
        }

        /* Deallocate diff */
        _vm_close_iterable((VMIterable *) (*diff)->singlediff);
        next = (*diff)->next;
        free(*diff);
        *diff = next;
    }
}
Beispiel #2
0
static void
_vm_rstep(VMState *state, unsigned long nsteps, VMStateDiff **diff, 
          bool *hit_bp, bool first)
{
    VMSingleStateDiff *singlediff;
    VMStateDiff *next;
    
    *hit_bp = false;
    state->stopped_running = false;
    
    while (nsteps-- && (*diff)->next) {
        if (!first && _hit_breakpoint(state)) {
            *hit_bp = true;
            break; 
        }
        
        first = false;
        
        state->cycles = (*diff)->cycles;
        SETPC(state, (*diff)->pc);
        
        singlediff = (*diff)->singlediff;
        /* Apply singlediff changes */
        while (singlediff) {
            vm_write_nbytes(
                state,
                NULL,
                singlediff->type,
                singlediff->location,
                singlediff->oldval,
                singlediff->nbytes
            );
            
            singlediff = singlediff->next;
        }
        
        /* Deallocate diff */
        _vm_close_iterable((VMIterable *) (*diff)->singlediff);
        next = (*diff)->next;
        free(*diff);
        *diff = next;
    }
}
Beispiel #3
0
Datei: vm.c Projekt: sihida/essig
bool 
vm_step(VMState *state, int nsteps, VMStateDiff *diff, bool *hit_bp)
{
    Opcode *opcode;
    opcode_handler *handler;
    VMStateDiff *newdiff;
    VMIterable *interrupt_item, *previous_interrupt_item = NULL;
    
    *hit_bp = false;
    while (nsteps > 0) {
        /* acquire and release for every step. This allows for some nice 
           contention! */
        ACQUIRE_STATE(state);
        if (state->break_async) {
            *hit_bp = true;
            RELEASE_STATE(state); 
            break;
        }
        
        if (state->interrupts != NULL) {
            /* interrupt */
            interrupt_item = (VMIterable *) state->interrupts;
            while (interrupt_item) {
                VMInterruptItem *item; 
                
                item = (VMInterruptItem *) interrupt_item; 
                if (item->cycles == state->cycles) {
                    bool result; 
                    interrupt_handler *handler;
                    
                    handler = state->interrupt_handlers[item->interrupt_type];
                    result = handler(state, item->interrupt_type);
                    
                    /* delete item from the queue */
                    if (previous_interrupt_item) {
                        previous_interrupt_item->next = interrupt_item->next;
                    } else {
                        state->interrupts = 
                            (VMInterruptItem *) interrupt_item->next;
                    }
                    free(interrupt_item);
                    interrupt_item = previous_interrupt_item;
                    
                    if (!result)
                        return false;
                }
                interrupt_item = interrupt_item->next;
            }
        } else if (_hit_breakpoint(state)) {
            /* breakpoint */
            *hit_bp = true;
             RELEASE_STATE(state);
            break;
        } else {
            /* Save PC */
            newdiff = vm_newdiff();
            if (!newdiff)
                return false;
            newdiff->pc = state->pc;
            newdiff->cycles = state->cycles;
            diff->next = (VMIterable *) newdiff;
            diff = newdiff;
            
            /* Execute instruction */
            opcode = OPCODE(state);
            handler = opcode_handlers[opcode->opcode_index].handler;
            if (!handler(state, diff, opcode->opcode))
                return false;
        }
        nsteps--;
        
        RELEASE_STATE(state);
    }
    return true;
}
Beispiel #4
0
static bool
_vm_step(VMState *state, int nsteps, VMStateDiff **diff, bool *hit_bp, bool first)
{
    Opcode *opcode;
    opcode_handler *handler;
    VMInterruptCallable *callable;
    VMInterruptItem *interrupt_item, *previous_interrupt_item = NULL;
    VMStateDiff *newdiff = NULL;

#define RETURN(x) do { RELEASE_STATE(state); return (x); } while(0)

    *hit_bp = false;
    while (nsteps > 0) {
        /* acquire and release for every step. This allows for some nice
           contention! */
        ACQUIRE_STATE(state);
        if (state->break_async) {
            RETURN(true);
        }

        callable = state->interrupt_callables;
        while (callable) {
            if (!callable->func(state, callable->argument)) {
                vm_seterrno(VM_INTERRUPT_CALLABLE_ERROR);
                RETURN(false);
            }
            callable = callable->next;
        }


        if (!first && _hit_breakpoint(state)) {
            /* breakpoint */
            *hit_bp = true;
            RETURN(true);
        } else {

            /* PC error checking */
            {
                /* offsets in bytes */
                size_t pc;

                pc = GETPC(state);

                if (pc < state->executable_segment_offset ||
                        pc >= state->instructions_size) {
                    vm_seterrno(VM_PC_OUT_OF_BOUNDS);
#ifdef VM_DEBUG
                    printf(LOCATION " pc: %lu max pc: %lu\n",
                           (unsigned long) pc,
                           (unsigned long) state->instructions_size - 1);
#endif
                    RETURN(false);
                }
            }

            /* Save changes in diff */
            if (diff) {
                if (!(newdiff = vm_newdiff()))
                    RETURN(false);

                newdiff->next = *diff;
                newdiff->pc = state->registers[PC];
                newdiff->cycles = state->cycles;

                *diff = newdiff;
            }

            if (state->interrupt_policy != VM_POLICY_INTERRUPT_NEVER) {
                if (state->interrupts != NULL) {
                    /* There are interrupts specified in the queue, call the
                       user-written set_interrupt callback. */
                    if (!set_interrupt(state, newdiff))
                        RETURN(false);
                }

                /* For every step, handle an interrupt in the debuggee (if present)
                   bytes calling a user-written function (or a default noop). */
                if (!handle_interrupt(state, newdiff)) {
                    RETURN(false);
                }
            }

            /* Execute instruction */
            opcode = (Opcode *) OPCODE(state);
            handler = opcode_handlers[opcode->opcode_index].handler;
            if (!handler(state, newdiff, opcode->instruction)) {
                RETURN(state->stopped_running);
            }
        }
        nsteps--;
        first = false;
        RELEASE_STATE(state);
    }

    return true;
#undef RETURN
}
Beispiel #5
0
static bool 
_vm_step(VMState *state, unsigned long nsteps, VMStateDiff **diff, 
         bool *hit_bp, bool first)
{
    VMInterruptCallable *callable;
    VMStateDiff *newdiff = NULL;
    
#define RETURN(x) do { RELEASE_STATE(state); return (x); } while(0)
    
    *hit_bp = false;
    while (nsteps > 0) {
        /* acquire and release for every step. This allows for some nice 
           contention! */
        ACQUIRE_STATE(state);
        if (state->break_async) {
            RETURN(true);
        }
        
        callable = state->interrupt_callables;
        while (callable) {
            if (!callable->func(state, callable->argument)) {
                vm_seterrno(VM_INTERRUPT_CALLABLE_ERROR);
                RETURN(false);
            }
            callable = callable->next;
        }
        
        
        if (!first && _hit_breakpoint(state)) {
            /* breakpoint */
            *hit_bp = true;
            RETURN(true);
        } else {
            Opcode *opcode;
            opcode_handler *handler;

            /* Do the PC validity checks before updating any diffs. */
            if (!(opcode = get_opcode(state, GETPC(state))))
                RETURN(false);
           
            /* Save changes in diff */
            if (diff) {
                if (!(newdiff = vm_newdiff()))
                    RETURN(false);
                
                newdiff->next = *diff;
                newdiff->pc = GETPC(state);
                newdiff->cycles = state->cycles;
                
                *diff = newdiff;
            }
            
            if (state->interrupt_policy != VM_POLICY_INTERRUPT_NEVER) {
                if (state->interrupts != NULL) {
                    /* There are interrupts specified in the queue, call the 
                       user-written set_interrupt callback. */
                    if (!set_interrupt(state, newdiff))
                        RETURN(false);
                }
                
                /* For every step, handle an interrupt in the debuggee (if present)
                   bytes calling a user-written function (or a default noop). */
                if (!handle_interrupt(state, newdiff)) {
                    RETURN(false);
                }
            }
            
            /* Execute instruction */
            handler = opcode_handlers[opcode->opcode_index].handler;
            if (!handler(state, newdiff, opcode->instruction))
                RETURN(state->stopped_running);
        }

        nsteps--;
        first = false;
        RELEASE_STATE(state);
    }
    
    return true;
#undef RETURN
}