Exemplo n.º 1
0
int
main(int argc, char **argv)
{
    char *endptr;
    unsigned long nsteps = 1000000;
    VMState *state;
    bool hit_bp = false;
#ifdef WITH_DIFF
    VMStateDiff *diff;
#endif
    
    if (argc <= 1) {
        printf("Using a default of %lu steps\n", nsteps);
    } else {
        nsteps = strtoul(argv[1], &endptr, 0);
        
        if (errno) {
            perror("Invalid command line argument.");
            return 1;
        }
        
        if (*endptr)
            fprintf(stderr, "Warning: junk at end of number.\n");
    }
    

    check_error(state = vm_newstate_no_code(VM_POLICY_INTERRUPT_ALWAYS));
    
    put_code(state);
    
#ifdef WITH_DIFF
    check_error(diff = vm_newdiff());
    if (!vm_step(state, nsteps, diff, &hit_bp))
        goto error;
#else
    if (!vm_step(state, nsteps, NULL, &hit_bp))
        goto error;
#endif
    
    return EXIT_SUCCESS;
error:
    fputs(vm_strerror(-1), stderr);
    fputc('\n', stderr);
    return EXIT_FAILURE;
}
Exemplo n.º 2
0
Arquivo: vm.c Projeto: 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;
}
Exemplo n.º 3
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
}
Exemplo n.º 4
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
}