コード例 #1
0
ファイル: beam_bp.c プロジェクト: AugustoFernandes/otp
/*
** Searches (linear forward) the breakpoint ring for a specified opcode
** and returns a pointer to the breakpoint data structure or NULL if
** not found. If the specified opcode is 0, the last breakpoint is 
** returned. The program counter must point to the first executable
** (breakpoint) instruction of the function.
*/
static BpData *is_break(Uint *pc, Uint break_op) {
    ASSERT(pc[-5] == (Uint) BeamOp(op_i_func_info_IaaI));
    if (! erts_is_native_break(pc)) {
	BpData *bd = (BpData *) pc[-4];
	
	if (break_op == 0) {
	    return bd;
	}
	if (*pc == break_op) {
	    ASSERT(bd);
	    return bd->next;
	}
	if (! bd){
	    return NULL;
	}
	bd = bd->next;
	while (bd != (BpData *) pc[-4]) {
	    ASSERT(bd);
	    if (bd->orig_instr == break_op) {
		bd = bd->next;
		ASSERT(bd);
		return bd;
	    } else {
		bd = bd->next;
	    }
	}
    }
    return NULL;
}
コード例 #2
0
ファイル: beam_bp.c プロジェクト: Duncaen/otp
int 
erts_clear_module_break(Module *modp) {
    BeamCodeHeader* code_hdr;
    Uint n;
    Uint i;

    ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
    ASSERT(modp);
    code_hdr = modp->curr.code_hdr;
    if (!code_hdr) {
	return 0;
    }
    n = (Uint)(UWord) code_hdr->num_functions;
    for (i = 0; i < n; ++i) {
	BeamInstr* pc;

	pc = code_hdr->functions[i] + 5;
	if (erts_is_native_break(pc)) {
	    continue;
	}
	clear_function_break(pc, ERTS_BPF_ALL);
    }

    erts_commit_staged_bp();

    for (i = 0; i < n; ++i) {
	BeamInstr* pc;

	pc = code_hdr->functions[i] + 5;
	if (erts_is_native_break(pc)) {
	    continue;
	}
	uninstall_breakpoint(pc);
	consolidate_bp_data(modp, pc, 1);
	ASSERT(pc[-4] == 0);
    }
    return n;
}
コード例 #3
0
ファイル: beam_bp.c プロジェクト: NaughtyCode/otp
int 
erts_clear_module_break(Module *modp) {
    BeamInstr** code_base;
    Uint n;
    Uint i;

    ERTS_SMP_LC_ASSERT(erts_smp_thr_progress_is_blocking());
    ASSERT(modp);
    code_base = (BeamInstr **) modp->curr.code;
    if (code_base == NULL) {
	return 0;
    }
    n = (Uint)(UWord) code_base[MI_NUM_FUNCTIONS];
    for (i = 0; i < n; ++i) {
	BeamInstr* pc;

	pc = code_base[MI_FUNCTIONS+i] + 5;
	if (erts_is_native_break(pc)) {
	    continue;
	}
	clear_function_break(pc, ERTS_BPF_ALL);
    }

    erts_commit_staged_bp();

    for (i = 0; i < n; ++i) {
	BeamInstr* pc;

	pc = code_base[MI_FUNCTIONS+i] + 5;
	if (erts_is_native_break(pc)) {
	    continue;
	}
	uninstall_breakpoint(pc);
	consolidate_bp_data(modp, pc, 1);
	ASSERT(pc[-4] == 0);
    }
    return n;
}
コード例 #4
0
ファイル: beam_bp.c プロジェクト: Duncaen/otp
void
erts_bp_match_export(BpFunctions* f, Eterm mfa[3], int specified)
{
    ErtsCodeIndex code_ix = erts_active_code_ix();
    int i;
    int num_exps = export_list_size(code_ix);
    int ne;

    f->matching = (BpFunction *) Alloc(num_exps*sizeof(BpFunction));
    ne = 0;
    for (i = 0; i < num_exps; i++) {
	Export* ep = export_list(i, code_ix);
	BeamInstr* pc;
	int j;

	for (j = 0; j < specified && mfa[j] == ep->code[j]; j++) {
	    /* Empty loop body */
	}
	if (j < specified) {
	    continue;
	}
	pc = ep->code+3;
	if (ep->addressv[code_ix] == pc) {
	    if ((*pc == (BeamInstr) em_apply_bif ||
		 *pc == (BeamInstr) em_call_error_handler)) {
		continue;
	    }
	    ASSERT(*pc == (BeamInstr) BeamOp(op_i_generic_breakpoint));
	} else if (erts_is_native_break(ep->addressv[code_ix])) {
	    continue;
	}

	f->matching[ne].pc = pc;
	f->matching[ne].mod = erts_get_module(ep->code[0], code_ix);
	ne++;

    }
    f->matched = ne;
}
コード例 #5
0
ファイル: beam_bp.c プロジェクト: Duncaen/otp
void
erts_bp_match_functions(BpFunctions* f, Eterm mfa[3], int specified)
{
    ErtsCodeIndex code_ix = erts_active_code_ix();
    Uint max_funcs = 0;
    int current;
    int max_modules = module_code_size(code_ix);
    int num_modules = 0;
    Module* modp;
    Module** module;
    Uint i;

    module = (Module **) Alloc(max_modules*sizeof(Module *));
    num_modules = 0;
    for (current = 0; current < max_modules; current++) {
	modp = module_code(current, code_ix);
	if (modp->curr.code_hdr) {
	    max_funcs += modp->curr.code_hdr->num_functions;
	    module[num_modules++] = modp;
	}
    }

    f->matching = (BpFunction *) Alloc(max_funcs*sizeof(BpFunction));
    i = 0;
    for (current = 0; current < num_modules; current++) {
	BeamCodeHeader* code_hdr = module[current]->curr.code_hdr;
	BeamInstr* code;
	Uint num_functions = (Uint)(UWord) code_hdr->num_functions;
	Uint fi;

	if (specified > 0) {
	    if (mfa[0] != make_atom(module[current]->module)) {
		/* Wrong module name */
		continue;
	    }
	}

	for (fi = 0; fi < num_functions; fi++) {
	    BeamInstr* pc;
	    int wi;

	    code = code_hdr->functions[fi];
	    ASSERT(code[0] == (BeamInstr) BeamOp(op_i_func_info_IaaI));
	    pc = code+5;
	    if (erts_is_native_break(pc)) {
		continue;
	    }
	    if (is_nil(code[3])) { /* Ignore BIF stub */
		continue;
	    }
	    for (wi = 0;
		 wi < specified && (Eterm) code[2+wi] == mfa[wi];
		 wi++) {
		/* Empty loop body */
	    }
	    if (wi == specified) {
		/* Store match */
		f->matching[i].pc = pc;
		f->matching[i].mod = module[current];
		i++;
	    }
	}
    }
    f->matched = i;
    Free(module);
}
コード例 #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;
}