コード例 #1
0
ファイル: beam_bp.c プロジェクト: AugustoFernandes/otp
void
erts_clear_mtrace_bif(Uint *pc) {
    BpDataTrace *bdt;
    ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));
    
    bdt = (BpDataTrace *) pc[-4];
    if (bdt) {
	if (bdt->match_spec) {
	    MatchSetUnref(bdt->match_spec);
	}
	Free(bdt);
    }
    pc[-4] = (Uint) NULL;
}
コード例 #2
0
ファイル: beam_bp.c プロジェクト: AugustoFernandes/otp
void
erts_set_mtrace_bif(Uint *pc, Binary *match_spec, Eterm tracer_pid) {
    BpDataTrace *bdt;
    ERTS_SMP_LC_ASSERT(erts_smp_is_system_blocked(0));

    bdt = (BpDataTrace *) pc[-4];
    if (bdt) {
	MatchSetUnref(bdt->match_spec);
	MatchSetRef(match_spec);
	bdt->match_spec = match_spec;
	bdt->tracer_pid = tracer_pid;
    } else {
	bdt = Alloc(sizeof(BpDataTrace));
	BpInit((BpData *) bdt, 0);
	MatchSetRef(match_spec);
	bdt->match_spec = match_spec;
	bdt->tracer_pid = tracer_pid;
	pc[-4] = (Uint) bdt;
    }
}
コード例 #3
0
ファイル: beam_bif_load.c プロジェクト: system/erlang-otp
static void
delete_export_references(Eterm module)
{
    int i;

    ASSERT(is_atom(module));

    for (i = 0; i < export_list_size(); i++) {
	Export *ep = export_list(i);
        if (ep != NULL && (ep->code[0] == module)) {
	    if (ep->address == ep->code+3 &&
		(ep->code[3] == (Eterm) em_apply_bif)) {
		continue;
	    }
	    ep->address = ep->code+3;
	    ep->code[3] = (Uint) em_call_error_handler;
	    ep->code[4] = 0;
	    MatchSetUnref(ep->match_prog_set);
	    ep->match_prog_set = NULL;
	}
    }
}
コード例 #4
0
ファイル: beam_bif_load.c プロジェクト: bitonic/otp
static void
delete_code(Module* modp)
{
    ErtsCodeIndex code_ix = erts_staging_code_ix();
    Eterm module = make_atom(modp->module);
    int i;

    for (i = 0; i < export_list_size(code_ix); i++) {
	Export *ep = export_list(i, code_ix);
        if (ep != NULL && (ep->code[0] == module)) {
	    if (ep->addressv[code_ix] == ep->code+3) {
		if (ep->code[3] == (BeamInstr) em_apply_bif) {
		    continue;
		}
		else if (ep->code[3] == (BeamInstr) em_call_traced_function) {
		    ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
		    ASSERT(modp->curr.num_traced_exports > 0);
		    --modp->curr.num_traced_exports;
		    MatchSetUnref(ep->match_prog_set);
		    ep->match_prog_set = NULL;
		}
		else ASSERT(ep->code[3] == (BeamInstr) em_call_error_handler
			    || !erts_initialized);
	    }
	    ep->addressv[code_ix] = ep->code+3;
	    ep->code[3] = (BeamInstr) em_call_error_handler;
	    ep->code[4] = 0;
	    ASSERT(ep->match_prog_set == NULL);
	}
    }

    ASSERT(modp->curr.num_breakpoints == 0);
    ASSERT(modp->curr.num_traced_exports == 0);
    modp->old = modp->curr;
    modp->curr.code = NULL;
    modp->curr.code_length = 0;
    modp->curr.catches = BEAM_CATCHES_NIL;
    modp->curr.nif = NULL;
}
コード例 #5
0
ファイル: beam_bp.c プロジェクト: Duncaen/otp
static void
consolidate_bp_data(Module* modp, BeamInstr* pc, int local)
{
    GenericBp* g = (GenericBp *) pc[-4];
    GenericBpData* src;
    GenericBpData* dst;
    Uint flags;

    if (g == 0) {
	return;
    }

    src = &g->data[erts_active_bp_ix()];
    dst = &g->data[erts_staging_bp_ix()];

    /*
     * The contents of the staging area may be out of date.
     * Decrement all reference pointers.
     */

    flags = dst->flags;
    if (flags & (ERTS_BPF_LOCAL_TRACE|ERTS_BPF_GLOBAL_TRACE)) {
	MatchSetUnref(dst->local_ms);
    }
    if (flags & ERTS_BPF_META_TRACE) {
	bp_meta_unref(dst->meta_tracer);
	MatchSetUnref(dst->meta_ms);
    }
    if (flags & ERTS_BPF_COUNT) {
	bp_count_unref(dst->count);
    }
    if (flags & ERTS_BPF_TIME_TRACE) {
	bp_time_unref(dst->time);
    }

    /*
     * If all flags are zero, deallocate all breakpoint data.
     */

    flags = dst->flags = src->flags;
    if (flags == 0) {
	if (modp) {
	    if (local) {
		modp->curr.num_breakpoints--;
	    } else {
		modp->curr.num_traced_exports--;
	    }
	    ASSERT(modp->curr.num_breakpoints >= 0);
	    ASSERT(modp->curr.num_traced_exports >= 0);
	    ASSERT(*pc != (BeamInstr) BeamOp(op_i_generic_breakpoint));
	}
	pc[-4] = 0;
	Free(g);
	return;
    }

    /*
     * Copy the active data to the staging area (making it ready
     * for the next time it will be used).
     */

    if (flags & (ERTS_BPF_LOCAL_TRACE|ERTS_BPF_GLOBAL_TRACE)) {
	dst->local_ms = src->local_ms;
	MatchSetRef(dst->local_ms);
    }
    if (flags & ERTS_BPF_META_TRACE) {
	dst->meta_tracer = src->meta_tracer;
	erts_refc_inc(&dst->meta_tracer->refc, 1);
	dst->meta_ms = src->meta_ms;
	MatchSetRef(dst->meta_ms);
    }
    if (flags & ERTS_BPF_COUNT) {
	dst->count = src->count;
	erts_refc_inc(&dst->count->refc, 1);
    }
    if (flags & ERTS_BPF_TIME_TRACE) {
	dst->time = src->time;
	erts_refc_inc(&dst->time->refc, 1);
	ASSERT(dst->time->hash);
    }
}
コード例 #6
0
ファイル: beam_bp.c プロジェクト: AugustoFernandes/otp
static int clear_function_break(Module *m, Uint *pc, Uint break_op) {
    BpData *bd;
    Uint **code_base = (Uint **)m->code;
    
    ASSERT(code_base);
    ASSERT(code_base <= (Uint **)pc);
    ASSERT((Uint **)pc < code_base + (m->code_length/sizeof(Uint *)));
    /*
     * Currently no trace support for native code.
     */
    if (erts_is_native_break(pc)) {
	return 0;
    }
    while ( (bd = is_break(pc, break_op))) {
	/* Remove all breakpoints of this type.
	 * There should be only one of each type, 
	 * but break_op may be 0 which matches any type. 
	 */
	Uint op;
	BpData **r = (BpData **) (pc-4);
	
	ASSERT(*r);
	/* Find opcode for this breakpoint */
	if (break_op) {
	    op = break_op;
	} else {
	    if (bd == (*r)->next) {
		/* First breakpoint in ring */
		op = *pc;
	    } else {
		op = bd->prev->orig_instr;
	    }
	}
	if (BpSingleton(bd)) {
	    ASSERT(*r == bd);
	    /* Only one breakpoint to remove */
	    *r  = NULL;
	    *pc = bd->orig_instr;
	} else {
	    BpData *bd_prev = bd->prev;
	    
	    BpSpliceNext(bd, bd_prev);
	    ASSERT(BpSingleton(bd));
	    if (bd == *r) {
		/* We removed the last breakpoint in the ring */
		*r = bd_prev;
		bd_prev->orig_instr = bd->orig_instr;
	    } else if (bd_prev == *r) {
		/* We removed the first breakpoint in the ring */
		*pc = bd->orig_instr;
	    } else {
		bd_prev->orig_instr = bd->orig_instr;
	    }
	}
	if (op == (Uint) BeamOp(op_i_trace_breakpoint) ||
	    op == (Uint) BeamOp(op_i_mtrace_breakpoint)) {
	    
	    BpDataTrace *bdt = (BpDataTrace *) bd;
	    
	    MatchSetUnref(bdt->match_spec);
	}
	Free(bd);
	ASSERT(((Uint) code_base[MI_NUM_BREAKPOINTS]) > 0);
	--(*(Uint*)&code_base[MI_NUM_BREAKPOINTS]);
    }
    return 1;
}
コード例 #7
0
ファイル: beam_bp.c プロジェクト: AugustoFernandes/otp
static int set_function_break(Module *modp, Uint *pc, 
			      Binary *match_spec, Uint break_op, 
			      enum erts_break_op count_op, Eterm tracer_pid) {
    BpData *bd, **r;
    size_t size;
    Uint **code_base = (Uint **)modp->code;
    
    ASSERT(code_base);
    ASSERT(code_base <= (Uint **)pc);
    ASSERT((Uint **)pc < code_base + (modp->code_length/sizeof(Uint *)));
    /*
     * Currently no trace support for native code.
     */
    if (erts_is_native_break(pc)) {
	return 0;
    }
    /* Do not allow two breakpoints of the same kind */
    if ( (bd = is_break(pc, break_op))) {
	if (break_op == (Uint) BeamOp(op_i_trace_breakpoint) 
	    || break_op == (Uint) BeamOp(op_i_mtrace_breakpoint)) {
	    BpDataTrace *bdt = (BpDataTrace *) bd;
	    Binary *old_match_spec;
	    
	    /* Update match spec and tracer */
	    MatchSetRef(match_spec);
	    ErtsSmpBPLock(bdt);
	    old_match_spec = bdt->match_spec;
	    bdt->match_spec = match_spec;
	    bdt->tracer_pid = tracer_pid;
	    ErtsSmpBPUnlock(bdt);
	    MatchSetUnref(old_match_spec);
	} else {
	    ASSERT(! match_spec);
	    ASSERT(is_nil(tracer_pid));
	    if (break_op == (Uint) BeamOp(op_i_count_breakpoint)) {
		BpDataCount *bdc = (BpDataCount *) bd;
		
		ErtsSmpBPLock(bdc);
		if (count_op == erts_break_stop) {
		    if (bdc->count >= 0) {
			bdc->count = -bdc->count-1; /* Stop call counter */
		    }
		} else {
		    bdc->count = 0; /* Reset call counter */
		}
		ErtsSmpBPUnlock(bdc);
	    } else {
		ASSERT (! count_op);
	    }
	}
	return 1;
    }
    if (break_op == (Uint) BeamOp(op_i_trace_breakpoint) ||
	break_op == (Uint) BeamOp(op_i_mtrace_breakpoint)) {
	size = sizeof(BpDataTrace);
    } else {
	ASSERT(! match_spec);
	ASSERT(is_nil(tracer_pid));
	if (break_op == (Uint) BeamOp(op_i_count_breakpoint)) {
	    if (count_op == erts_break_reset
		|| count_op == erts_break_stop) {
		/* Do not insert a new breakpoint */
		return 1;
	    }
	    size = sizeof(BpDataCount);
	} else {
	    ASSERT(! count_op);
	    ASSERT(break_op == (Uint) BeamOp(op_i_debug_breakpoint));
	    size = sizeof(BpDataDebug);
	}
    }
    r = (BpData **) (pc-4);
    if (! *r) {
	ASSERT(*pc != (Uint) BeamOp(op_i_trace_breakpoint));
	ASSERT(*pc != (Uint) BeamOp(op_i_mtrace_breakpoint));
	ASSERT(*pc != (Uint) BeamOp(op_i_debug_breakpoint));
	ASSERT(*pc != (Uint) BeamOp(op_i_count_breakpoint));
	/* First breakpoint; create singleton ring */
	bd = Alloc(size);
	BpInit(bd, *pc);
	*pc = break_op;
	*r = bd;
    } else {
	ASSERT(*pc == (Uint) BeamOp(op_i_trace_breakpoint) ||
	       *pc == (Uint) BeamOp(op_i_mtrace_breakpoint) ||
	       *pc == (Uint) BeamOp(op_i_debug_breakpoint) ||
	       *pc == (Uint) BeamOp(op_i_count_breakpoint));
	if (*pc == (Uint) BeamOp(op_i_debug_breakpoint)) {
	    /* Debug bp must be last, so if it is also first; 
	     * it must be singleton. */
	    ASSERT(BpSingleton(*r)); 
	    /* Insert new bp first in the ring, i.e second to last. */
	    bd = Alloc(size);
	    BpInitAndSpliceNext(bd, *pc, *r);
	    *pc = break_op;
	} else if ((*r)->prev->orig_instr 
		   == (Uint) BeamOp(op_i_debug_breakpoint)) {
	    /* Debug bp last in the ring; insert new second to last. */
	    bd = Alloc(size);
	    BpInitAndSplicePrev(bd, (*r)->prev->orig_instr, *r);
	    (*r)->prev->orig_instr = break_op;
	} else {
	    /* Just insert last in the ring */
	    bd = Alloc(size);
	    BpInitAndSpliceNext(bd, (*r)->orig_instr, *r);
	    (*r)->orig_instr = break_op;
	    *r = bd;
	}
    }
    /* Init the bp type specific data */
    if (break_op == (Uint) BeamOp(op_i_trace_breakpoint) ||
	break_op == (Uint) BeamOp(op_i_mtrace_breakpoint)) {
		
	BpDataTrace *bdt = (BpDataTrace *) bd;
		
	MatchSetRef(match_spec);
	bdt->match_spec = match_spec;
	bdt->tracer_pid = tracer_pid;
    } else if (break_op == (Uint) BeamOp(op_i_count_breakpoint)) {
	BpDataCount *bdc = (BpDataCount *) bd;

	bdc->count = 0;
    }
    ++(*(Uint*)&code_base[MI_NUM_BREAKPOINTS]);
    return 1;
}