Exemplo n.º 1
0
int
rb_thread_method_id_and_class(rb_thread_t *th,
			      ID *idp, VALUE *klassp)
{
    rb_control_frame_t *cfp = th->cfp;
    rb_iseq_t *iseq = cfp->iseq;
    if (!iseq) {
	if (idp) *idp = cfp->me->def->original_id;
	if (klassp) *klassp = cfp->me->klass;
	return 1;
    }
    while (iseq) {
	if (RUBY_VM_IFUNC_P(iseq)) {
	    if (idp) CONST_ID(*idp, "<ifunc>");
	    if (klassp) *klassp = 0;
	    return 1;
	}
	if (iseq->defined_method_id) {
	    if (idp) *idp = iseq->defined_method_id;
	    if (klassp) *klassp = iseq->klass;
	    return 1;
	}
	if (iseq->local_iseq == iseq) {
	    break;
	}
	iseq = iseq->parent_iseq;
    }
    return 0;
}
Exemplo n.º 2
0
static void
vm_caller_setup_arg_block(const rb_thread_t *th, rb_control_frame_t *reg_cfp,
			  struct rb_calling_info *calling, const struct rb_call_info *ci, rb_iseq_t *blockiseq, const int is_super)
{
    if (ci->flag & VM_CALL_ARGS_BLOCKARG) {
	rb_proc_t *po;
	VALUE proc;

	proc = *(--reg_cfp->sp);

	if (NIL_P(proc)) {
	    calling->blockptr = NULL;
	}
	else if (SYMBOL_P(proc) && rb_method_basic_definition_p(rb_cSymbol, idTo_proc)) {
	    calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
	    calling->blockptr->iseq = (rb_iseq_t *)proc;
	    calling->blockptr->proc = proc;
	}
	else if (RUBY_VM_IFUNC_P(proc)) {
	    calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
	    calling->blockptr->iseq = (rb_iseq_t *)proc;
	    calling->blockptr->proc = proc;
	}
	else {
	    if (!rb_obj_is_proc(proc)) {
		VALUE b;
		b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");

		if (NIL_P(b) || !rb_obj_is_proc(b)) {
		    rb_raise(rb_eTypeError,
			     "wrong argument type %s (expected Proc)",
			     rb_obj_classname(proc));
		}
		proc = b;
	    }
	    GetProcPtr(proc, po);
	    calling->blockptr = &po->block;
	    RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp)->proc = proc;
	}
    }
    else if (blockiseq != 0) { /* likely */
	rb_block_t *blockptr = calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
	blockptr->iseq = blockiseq;
	blockptr->proc = 0;
    }
    else {
	if (is_super) {
	    calling->blockptr = GET_BLOCK_PTR();
	}
	else {
	    calling->blockptr = NULL;
	}
    }
}
Exemplo n.º 3
0
static void
proc_mark(void *ptr)
{
    rb_proc_t *proc;
    MARK_REPORT_ENTER("proc");
    if (ptr) {
	proc = ptr;
	MARK_UNLESS_NULL(proc->envval);
	MARK_UNLESS_NULL(proc->blockprocval);
	MARK_UNLESS_NULL((VALUE)proc->special_cref_stack);
	if (proc->block.iseq && RUBY_VM_IFUNC_P(proc->block.iseq)) {
	    MARK_UNLESS_NULL((VALUE)(proc->block.iseq));
	}
    }
    MARK_REPORT_LEAVE("proc");
}
Exemplo n.º 4
0
static void
proc_mark(void *ptr)
{
    rb_proc_t *proc;
    RUBY_MARK_ENTER("proc");
    if (ptr) {
	proc = ptr;
	RUBY_MARK_UNLESS_NULL(proc->envval);
	RUBY_MARK_UNLESS_NULL(proc->blockprocval);
	RUBY_MARK_UNLESS_NULL(proc->block.proc);
	RUBY_MARK_UNLESS_NULL(proc->block.self);
	if (proc->block.iseq && RUBY_VM_IFUNC_P(proc->block.iseq)) {
	    RUBY_MARK_UNLESS_NULL((VALUE)(proc->block.iseq));
	}
    }
    RUBY_MARK_LEAVE("proc");
}
Exemplo n.º 5
0
static void
vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
{
    int i;

    VALUE rstr;
    VALUE *sp = cfp->sp;
    VALUE *lfp = cfp->lfp;
    VALUE *dfp = cfp->dfp;

    int argc = 0, local_size = 0;
    const char *name;
    rb_iseq_t *iseq = cfp->iseq;

    if (iseq == 0) {
	if (RUBYVM_CFUNC_FRAME_P(cfp)) {
	    name = rb_id2name(cfp->me->original_id);
	}
	else {
	    name = "?";
	}
    }
    else if (RUBY_VM_IFUNC_P(iseq)) {
	name = "<ifunc>";
    }
    else {
	argc = iseq->argc;
	local_size = iseq->local_size;
	name = RSTRING_PTR(iseq->name);
    }

    /* stack trace header */

    if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_METHOD ||
	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_TOP ||
	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_BLOCK ||
	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CLASS ||
	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_PROC ||
	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA ||
	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC ||
	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_IFUNC ||
	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_EVAL) {

	VALUE *ptr = dfp - local_size;

	vm_stack_dump_each(th, cfp + 1);
	control_frame_dump(th, cfp);

	if (lfp != dfp) {
	    local_size++;
	}
	for (i = 0; i < argc; i++) {
	    rstr = rb_inspect(*ptr);
	    fprintf(stderr, "  arg   %2d: %8s (%p)\n", i, StringValueCStr(rstr),
		   (void *)ptr++);
	}
	for (; i < local_size - 1; i++) {
	    rstr = rb_inspect(*ptr);
	    fprintf(stderr, "  local %2d: %8s (%p)\n", i, StringValueCStr(rstr),
		   (void *)ptr++);
	}

	ptr = cfp->bp;
	for (; ptr < sp; ptr++, i++) {
	    if (*ptr == Qundef) {
		rstr = rb_str_new2("undef");
	    }
	    else {
		rstr = rb_inspect(*ptr);
	    }
	    fprintf(stderr, "  stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr),
		    (ptr - th->stack));
	}
    }
    else if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_FINISH) {
	if ((th)->stack + (th)->stack_size > (VALUE *)(cfp + 2)) {
	    vm_stack_dump_each(th, cfp + 1);
	}
	else {
	    /* SDR(); */
	}
    }
    else {
	rb_bug("unsupport frame type: %08lx", VM_FRAME_TYPE(cfp));
    }
}
Exemplo n.º 6
0
static void
control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
{
    ptrdiff_t pc = -1, bp = -1;
    ptrdiff_t lfp = cfp->lfp - th->stack;
    ptrdiff_t dfp = cfp->dfp - th->stack;
    char lfp_in_heap = ' ', dfp_in_heap = ' ';
    char posbuf[MAX_POSBUF+1];
    int line = 0;
    int nopos = 0;

    const char *magic, *iseq_name = "-", *selfstr = "-", *biseq_name = "-";
    VALUE tmp;

    if (cfp->block_iseq != 0 && BUILTIN_TYPE(cfp->block_iseq) != T_NODE) {
	biseq_name = "";	/* RSTRING(cfp->block_iseq->name)->ptr; */
    }

    if (lfp < 0 || (size_t)lfp > th->stack_size) {
	lfp = (ptrdiff_t)cfp->lfp;
	lfp_in_heap = 'p';
    }
    if (dfp < 0 || (size_t)dfp > th->stack_size) {
	dfp = (ptrdiff_t)cfp->dfp;
	dfp_in_heap = 'p';
    }
    if (cfp->bp) {
	bp = cfp->bp - th->stack;
    }

    switch (VM_FRAME_TYPE(cfp)) {
      case VM_FRAME_MAGIC_TOP:
	magic = "TOP";
	break;
      case VM_FRAME_MAGIC_METHOD:
	magic = "METHOD";
	break;
      case VM_FRAME_MAGIC_CLASS:
	magic = "CLASS";
	break;
      case VM_FRAME_MAGIC_BLOCK:
	magic = "BLOCK";
	break;
      case VM_FRAME_MAGIC_FINISH:
	magic = "FINISH";
	nopos = 1;
	break;
      case VM_FRAME_MAGIC_CFUNC:
	magic = "CFUNC";
	break;
      case VM_FRAME_MAGIC_PROC:
	magic = "PROC";
	break;
      case VM_FRAME_MAGIC_LAMBDA:
	magic = "LAMBDA";
	break;
      case VM_FRAME_MAGIC_IFUNC:
	magic = "IFUNC";
	break;
      case VM_FRAME_MAGIC_EVAL:
	magic = "EVAL";
	break;
      case 0:
	magic = "------";
	break;
      default:
	magic = "(none)";
	break;
    }

    if (0) {
	tmp = rb_inspect(cfp->self);
	selfstr = StringValueCStr(tmp);
    }
    else {
	selfstr = "";
    }

    if (nopos) {
	/* no name */
    }
    else if (cfp->iseq != 0) {
	if (RUBY_VM_IFUNC_P(cfp->iseq)) {
	    iseq_name = "<ifunc>";
	}
	else {
	    pc = cfp->pc - cfp->iseq->iseq_encoded;
	    iseq_name = RSTRING_PTR(cfp->iseq->name);
	    line = rb_vm_get_sourceline(cfp);
	    if (line) {
		snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(cfp->iseq->filename), line);
	    }
	}
    }
    else if (cfp->me) {
	iseq_name = rb_id2name(cfp->me->def->original_id);
	snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name);
	line = -1;
    }

    fprintf(stderr, "c:%04"PRIdPTRDIFF" ",
	    ((rb_control_frame_t *)(th->stack + th->stack_size) - cfp));
    if (pc == -1) {
	fprintf(stderr, "p:---- ");
    }
    else {
	fprintf(stderr, "p:%04"PRIdPTRDIFF" ", pc);
    }
    fprintf(stderr, "s:%04"PRIdPTRDIFF" b:%04"PRIdPTRDIFF" ", (cfp->sp - th->stack), bp);
    fprintf(stderr, lfp_in_heap == ' ' ? "l:%06"PRIdPTRDIFF" " : "l:%06"PRIxPTRDIFF" ", lfp % 10000);
    fprintf(stderr, dfp_in_heap == ' ' ? "d:%06"PRIdPTRDIFF" " : "d:%06"PRIxPTRDIFF" ", dfp % 10000);
    fprintf(stderr, "%-6s", magic);
    if (line && !nopos) {
	fprintf(stderr, " %s", posbuf);
    }
    if (0) {
	fprintf(stderr, "              \t");
	fprintf(stderr, "iseq: %-24s ", iseq_name);
	fprintf(stderr, "self: %-24s ", selfstr);
	fprintf(stderr, "%-1s ", biseq_name);
    }
    fprintf(stderr, "\n");
}
Exemplo n.º 7
0
static void
control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
{
    ptrdiff_t pc = -1;
    ptrdiff_t ep = cfp->ep - th->stack;
    char ep_in_heap = ' ';
    char posbuf[MAX_POSBUF+1];
    int line = 0;

    const char *magic, *iseq_name = "-", *selfstr = "-", *biseq_name = "-";
    VALUE tmp;

    const rb_callable_method_entry_t *me;

    if (ep < 0 || (size_t)ep > th->stack_size) {
	ep = (ptrdiff_t)cfp->ep;
	ep_in_heap = 'p';
    }

    switch (VM_FRAME_TYPE(cfp)) {
      case VM_FRAME_MAGIC_TOP:
	magic = "TOP";
	break;
      case VM_FRAME_MAGIC_METHOD:
	magic = "METHOD";
	break;
      case VM_FRAME_MAGIC_CLASS:
	magic = "CLASS";
	break;
      case VM_FRAME_MAGIC_BLOCK:
	magic = "BLOCK";
	break;
      case VM_FRAME_MAGIC_CFUNC:
	magic = "CFUNC";
	break;
      case VM_FRAME_MAGIC_PROC:
	magic = "PROC";
	break;
      case VM_FRAME_MAGIC_LAMBDA:
	magic = "LAMBDA";
	break;
      case VM_FRAME_MAGIC_IFUNC:
	magic = "IFUNC";
	break;
      case VM_FRAME_MAGIC_EVAL:
	magic = "EVAL";
	break;
      case VM_FRAME_MAGIC_RESCUE:
	magic = "RESCUE";
	break;
      case 0:
	magic = "------";
	break;
      default:
	magic = "(none)";
	break;
    }

    if (0) {
	tmp = rb_inspect(cfp->self);
	selfstr = StringValueCStr(tmp);
    }
    else {
	selfstr = "";
    }

    if (cfp->iseq != 0) {
#define RUBY_VM_IFUNC_P(ptr)        (RB_TYPE_P((VALUE)(ptr), T_IMEMO) && imemo_type((VALUE)ptr) == imemo_ifunc)
	if (RUBY_VM_IFUNC_P(cfp->iseq)) {
	    iseq_name = "<ifunc>";
	}
	else if (SYMBOL_P(cfp->iseq)) {
	    tmp = rb_sym2str((VALUE)cfp->iseq);
	    iseq_name = RSTRING_PTR(tmp);
	    snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name);
	    line = -1;
	}
	else {
	    pc = cfp->pc - cfp->iseq->body->iseq_encoded;
	    iseq_name = RSTRING_PTR(cfp->iseq->body->location.label);
	    line = rb_vm_get_sourceline(cfp);
	    if (line) {
		snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(cfp->iseq->body->location.path), line);
	    }
	}
    }
    else if ((me = rb_vm_frame_method_entry(cfp)) != NULL) {
	iseq_name = rb_id2name(me->def->original_id);
	snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name);
	line = -1;
    }

    fprintf(stderr, "c:%04"PRIdPTRDIFF" ",
	    ((rb_control_frame_t *)(th->stack + th->stack_size) - cfp));
    if (pc == -1) {
	fprintf(stderr, "p:---- ");
    }
    else {
	fprintf(stderr, "p:%04"PRIdPTRDIFF" ", pc);
    }
    fprintf(stderr, "s:%04"PRIdPTRDIFF" ", cfp->sp - th->stack);
    fprintf(stderr, ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "E:%06"PRIxPTRDIFF" ", ep % 10000);
    fprintf(stderr, "%-6s", magic);
    if (line) {
	fprintf(stderr, " %s", posbuf);
    }
    if (VM_FRAME_FINISHED_P(cfp)) {
	fprintf(stderr, " [FINISH]");
    }
    if (0) {
	fprintf(stderr, "              \t");
	fprintf(stderr, "iseq: %-24s ", iseq_name);
	fprintf(stderr, "self: %-24s ", selfstr);
	fprintf(stderr, "%-1s ", biseq_name);
    }
    fprintf(stderr, "\n");
}
void ruby_backtrace_each(sanspleur_backtrace_iter_func* iterator, void* arg)
{

    rb_thread_t* ruby_current_thread = (rb_thread_t*)(DATA_PTR(rb_thread_current()));
    rb_control_frame_t *cfp = ruby_current_thread->cfp;

    const rb_control_frame_t *cfp_limit = (rb_control_frame_t*)(ruby_current_thread->stack + ruby_current_thread->stack_size);
    cfp_limit -= 2;
    
    while (cfp < cfp_limit) {
        const char* class_name = NULL; 
        ID function_id = 0; 
        VALUE klass = 0;
        const char* file_name = NULL; 
        int line_number = -1; 
        int no_pos = -1;

        rb_iseq_t *iseq = cfp->iseq;
        if (!iseq && cfp->me) {
            function_id = cfp->me->def->original_id;
            klass = cfp->me->klass;
            no_pos = 1;
        }

        while (iseq) {
            if (RUBY_VM_IFUNC_P(iseq)) {
                CONST_ID(function_id, "<ifunc>");
                klass = 0;
                break;
            }
            klass = iseq->klass;

            if (iseq->defined_method_id) {
                function_id = iseq->defined_method_id;
                break;
            }

            if (iseq->local_iseq == iseq) {
                break;
            }
            iseq = iseq->parent_iseq;
        }

        if (iseq != 0 && cfp->pc != 0) {
            file_name = ISEQ_FILENAME(iseq);
        }

        const char* function_name = NULL;
        if (function_id) function_name = rb_id2name(function_id); 


        if (cfp->self) {
            if (TYPE(cfp->self) == RUBY_T_CLASS || TYPE(cfp->self) == RUBY_T_ICLASS) {
                class_name = rb_class2name(cfp->self);
            } else if (TYPE(cfp->self) == RUBY_T_MODULE) {
                VALUE str = rb_obj_as_string(cfp->self);
                char* object_description = RSTRING_PTR(str); 
                class_name = object_description;
            }        
        }
        if (klass && !class_name) {
            class_name = rb_class2name(klass); 
        }

        if (no_pos < 0) {
            line_number = CFP_LINENO(cfp);
        }
        ID class_id = 0; 

        if (VM_FRAME_TYPE(cfp) != 0x51) {
            iterator(arg, file_name, line_number, function_name, function_id, class_name, class_id);
        }

        cfp++;
    }
}