Abort dumping when output failed
This commit is contained in:
parent
ac244938e8
commit
85984a53e8
@ -1678,13 +1678,13 @@ VALUE rb_proc_alloc(VALUE klass);
|
|||||||
VALUE rb_proc_dup(VALUE self);
|
VALUE rb_proc_dup(VALUE self);
|
||||||
|
|
||||||
/* for debug */
|
/* for debug */
|
||||||
extern void rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
|
extern bool rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
|
||||||
extern void rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *);
|
extern bool rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *);
|
||||||
extern void rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
|
extern bool rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
|
||||||
|
|
||||||
#define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp, stderr)
|
#define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp, stderr)
|
||||||
#define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp), stderr)
|
#define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp), stderr)
|
||||||
void rb_vm_bugreport(const void *, FILE *);
|
bool rb_vm_bugreport(const void *, FILE *);
|
||||||
typedef void (*ruby_sighandler_t)(int);
|
typedef void (*ruby_sighandler_t)(int);
|
||||||
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5)
|
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5)
|
||||||
NORETURN(void rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *, const char *fmt, ...));
|
NORETURN(void rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *, const char *fmt, ...));
|
||||||
|
261
vm_dump.c
261
vm_dump.c
@ -46,7 +46,10 @@
|
|||||||
const char *rb_method_type_name(rb_method_type_t type);
|
const char *rb_method_type_name(rb_method_type_t type);
|
||||||
int ruby_on_ci;
|
int ruby_on_ci;
|
||||||
|
|
||||||
static void
|
#define kprintf(...) if (fprintf(errout, __VA_ARGS__) < 0) goto error
|
||||||
|
#define kputs(s) if (fputs(s, errout) < 0) goto error
|
||||||
|
|
||||||
|
static bool
|
||||||
control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
|
control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
|
||||||
{
|
{
|
||||||
ptrdiff_t pc = -1;
|
ptrdiff_t pc = -1;
|
||||||
@ -140,30 +143,30 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
|
|||||||
line = -1;
|
line = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(errout, "c:%04"PRIdPTRDIFF" ",
|
kprintf("c:%04"PRIdPTRDIFF" ",
|
||||||
((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size) - cfp));
|
((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size) - cfp));
|
||||||
if (pc == -1) {
|
if (pc == -1) {
|
||||||
fprintf(errout, "p:---- ");
|
kprintf("p:---- ");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(errout, "p:%04"PRIdPTRDIFF" ", pc);
|
kprintf("p:%04"PRIdPTRDIFF" ", pc);
|
||||||
}
|
}
|
||||||
fprintf(errout, "s:%04"PRIdPTRDIFF" ", cfp->sp - ec->vm_stack);
|
kprintf("s:%04"PRIdPTRDIFF" ", cfp->sp - ec->vm_stack);
|
||||||
fprintf(errout, ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "E:%06"PRIxPTRDIFF" ", ep % 10000);
|
kprintf(ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "E:%06"PRIxPTRDIFF" ", ep % 10000);
|
||||||
fprintf(errout, "%-6s", magic);
|
kprintf("%-6s", magic);
|
||||||
if (line) {
|
if (line) {
|
||||||
fprintf(errout, " %s", posbuf);
|
kprintf(" %s", posbuf);
|
||||||
}
|
}
|
||||||
if (VM_FRAME_FINISHED_P(cfp)) {
|
if (VM_FRAME_FINISHED_P(cfp)) {
|
||||||
fprintf(errout, " [FINISH]");
|
kprintf(" [FINISH]");
|
||||||
}
|
}
|
||||||
if (0) {
|
if (0) {
|
||||||
fprintf(errout, " \t");
|
kprintf(" \t");
|
||||||
fprintf(errout, "iseq: %-24s ", iseq_name);
|
kprintf("iseq: %-24s ", iseq_name);
|
||||||
fprintf(errout, "self: %-24s ", selfstr);
|
kprintf("self: %-24s ", selfstr);
|
||||||
fprintf(errout, "%-1s ", biseq_name);
|
kprintf("%-1s ", biseq_name);
|
||||||
}
|
}
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
|
|
||||||
// additional information for CI machines
|
// additional information for CI machines
|
||||||
if (ruby_on_ci) {
|
if (ruby_on_ci) {
|
||||||
@ -171,35 +174,38 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
|
|||||||
|
|
||||||
if (me) {
|
if (me) {
|
||||||
if (IMEMO_TYPE_P(me, imemo_ment)) {
|
if (IMEMO_TYPE_P(me, imemo_ment)) {
|
||||||
fprintf(errout, " me:\n");
|
kprintf(" me:\n");
|
||||||
fprintf(errout, " called_id: %s, type: %s\n", rb_id2name(me->called_id), rb_method_type_name(me->def->type));
|
kprintf(" called_id: %s, type: %s\n", rb_id2name(me->called_id), rb_method_type_name(me->def->type));
|
||||||
fprintf(errout, " owner class: %s\n", rb_raw_obj_info(buff, 0x100, me->owner));
|
kprintf(" owner class: %s\n", rb_raw_obj_info(buff, 0x100, me->owner));
|
||||||
if (me->owner != me->defined_class) {
|
if (me->owner != me->defined_class) {
|
||||||
fprintf(errout, " defined_class: %s\n", rb_raw_obj_info(buff, 0x100, me->defined_class));
|
kprintf(" defined_class: %s\n", rb_raw_obj_info(buff, 0x100, me->defined_class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(errout, " me is corrupted (%s)\n", rb_raw_obj_info(buff, 0x100, (VALUE)me));
|
kprintf(" me is corrupted (%s)\n", rb_raw_obj_info(buff, 0x100, (VALUE)me));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(errout, " self: %s\n", rb_raw_obj_info(buff, 0x100, cfp->self));
|
kprintf(" self: %s\n", rb_raw_obj_info(buff, 0x100, cfp->self));
|
||||||
|
|
||||||
if (iseq) {
|
if (iseq) {
|
||||||
if (ISEQ_BODY(iseq)->local_table_size > 0) {
|
if (ISEQ_BODY(iseq)->local_table_size > 0) {
|
||||||
fprintf(errout, " lvars:\n");
|
kprintf(" lvars:\n");
|
||||||
for (unsigned int i=0; i<ISEQ_BODY(iseq)->local_table_size; i++) {
|
for (unsigned int i=0; i<ISEQ_BODY(iseq)->local_table_size; i++) {
|
||||||
const VALUE *argv = cfp->ep - ISEQ_BODY(cfp->iseq)->local_table_size - VM_ENV_DATA_SIZE + 1;
|
const VALUE *argv = cfp->ep - ISEQ_BODY(cfp->iseq)->local_table_size - VM_ENV_DATA_SIZE + 1;
|
||||||
fprintf(errout, " %s: %s\n",
|
kprintf(" %s: %s\n",
|
||||||
rb_id2name(ISEQ_BODY(iseq)->local_table[i]),
|
rb_id2name(ISEQ_BODY(iseq)->local_table[i]),
|
||||||
rb_raw_obj_info(buff, 0x100, argv[i]));
|
rb_raw_obj_info(buff, 0x100, argv[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
|
rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@ -207,58 +213,66 @@ rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_fra
|
|||||||
const VALUE *ep = cfp->ep;
|
const VALUE *ep = cfp->ep;
|
||||||
VALUE *p, *st, *t;
|
VALUE *p, *st, *t;
|
||||||
|
|
||||||
fprintf(errout, "-- stack frame ------------\n");
|
kprintf("-- stack frame ------------\n");
|
||||||
for (p = st = ec->vm_stack; p < sp; p++) {
|
for (p = st = ec->vm_stack; p < sp; p++) {
|
||||||
fprintf(errout, "%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p);
|
kprintf("%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p);
|
||||||
|
|
||||||
t = (VALUE *)*p;
|
t = (VALUE *)*p;
|
||||||
if (ec->vm_stack <= t && t < sp) {
|
if (ec->vm_stack <= t && t < sp) {
|
||||||
fprintf(errout, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF((VALUE)t) - ec->vm_stack));
|
kprintf(" (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF((VALUE)t) - ec->vm_stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == ep)
|
if (p == ep)
|
||||||
fprintf(errout, " <- ep");
|
kprintf(" <- ep");
|
||||||
|
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fprintf(errout, "-- Control frame information "
|
kprintf("-- Control frame information "
|
||||||
"-----------------------------------------------\n");
|
"-----------------------------------------------\n");
|
||||||
while ((void *)cfp < (void *)(ec->vm_stack + ec->vm_stack_size)) {
|
while ((void *)cfp < (void *)(ec->vm_stack + ec->vm_stack_size)) {
|
||||||
control_frame_dump(ec, cfp, errout);
|
control_frame_dump(ec, cfp, errout);
|
||||||
cfp++;
|
cfp++;
|
||||||
}
|
}
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_stack_dump_raw_current(void)
|
rb_vmdebug_stack_dump_raw_current(void)
|
||||||
{
|
{
|
||||||
const rb_execution_context_t *ec = GET_EC();
|
const rb_execution_context_t *ec = GET_EC();
|
||||||
rb_vmdebug_stack_dump_raw(ec, ec->cfp, stderr);
|
return rb_vmdebug_stack_dump_raw(ec, ec->cfp, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_env_dump_raw(const rb_env_t *env, const VALUE *ep, FILE *errout)
|
rb_vmdebug_env_dump_raw(const rb_env_t *env, const VALUE *ep, FILE *errout)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
fprintf(errout, "-- env --------------------\n");
|
kprintf("-- env --------------------\n");
|
||||||
|
|
||||||
while (env) {
|
while (env) {
|
||||||
fprintf(errout, "--\n");
|
kprintf("--\n");
|
||||||
for (i = 0; i < env->env_size; i++) {
|
for (i = 0; i < env->env_size; i++) {
|
||||||
fprintf(errout, "%04d: %08"PRIxVALUE" (%p)", i, env->env[i], (void *)&env->env[i]);
|
kprintf("%04d: %08"PRIxVALUE" (%p)", i, env->env[i], (void *)&env->env[i]);
|
||||||
if (&env->env[i] == ep) fprintf(errout, " <- ep");
|
if (&env->env[i] == ep) kprintf(" <- ep");
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
env = rb_vm_env_prev_env(env);
|
env = rb_vm_env_prev_env(env);
|
||||||
}
|
}
|
||||||
fprintf(errout, "---------------------------\n");
|
kprintf("---------------------------\n");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_proc_dump_raw(rb_proc_t *proc, FILE *errout)
|
rb_vmdebug_proc_dump_raw(rb_proc_t *proc, FILE *errout)
|
||||||
{
|
{
|
||||||
const rb_env_t *env;
|
const rb_env_t *env;
|
||||||
@ -266,17 +280,21 @@ rb_vmdebug_proc_dump_raw(rb_proc_t *proc, FILE *errout)
|
|||||||
VALUE val = rb_inspect(vm_block_self(&proc->block));
|
VALUE val = rb_inspect(vm_block_self(&proc->block));
|
||||||
selfstr = StringValueCStr(val);
|
selfstr = StringValueCStr(val);
|
||||||
|
|
||||||
fprintf(errout, "-- proc -------------------\n");
|
kprintf("-- proc -------------------\n");
|
||||||
fprintf(errout, "self: %s\n", selfstr);
|
kprintf("self: %s\n", selfstr);
|
||||||
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&proc->block));
|
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&proc->block));
|
||||||
rb_vmdebug_env_dump_raw(env, vm_block_ep(&proc->block), errout);
|
rb_vmdebug_env_dump_raw(env, vm_block_ep(&proc->block), errout);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_stack_dump_th(VALUE thval, FILE *errout)
|
rb_vmdebug_stack_dump_th(VALUE thval, FILE *errout)
|
||||||
{
|
{
|
||||||
rb_thread_t *target_th = rb_thread_ptr(thval);
|
rb_thread_t *target_th = rb_thread_ptr(thval);
|
||||||
rb_vmdebug_stack_dump_raw(target_th->ec, target_th->ec->cfp, errout);
|
return rb_vmdebug_stack_dump_raw(target_th->ec, target_th->ec->cfp, errout);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VMDEBUG > 2
|
#if VMDEBUG > 2
|
||||||
@ -325,12 +343,12 @@ vm_stack_dump_each(const rb_execution_context_t *ec, const rb_control_frame_t *c
|
|||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
rstr = rb_inspect(*ptr);
|
rstr = rb_inspect(*ptr);
|
||||||
fprintf(errout, " arg %2d: %8s (%p)\n", i, StringValueCStr(rstr),
|
kprintf(" arg %2d: %8s (%p)\n", i, StringValueCStr(rstr),
|
||||||
(void *)ptr++);
|
(void *)ptr++);
|
||||||
}
|
}
|
||||||
for (; i < local_table_size - 1; i++) {
|
for (; i < local_table_size - 1; i++) {
|
||||||
rstr = rb_inspect(*ptr);
|
rstr = rb_inspect(*ptr);
|
||||||
fprintf(errout, " local %2d: %8s (%p)\n", i, StringValueCStr(rstr),
|
kprintf(" local %2d: %8s (%p)\n", i, StringValueCStr(rstr),
|
||||||
(void *)ptr++);
|
(void *)ptr++);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,7 +365,7 @@ vm_stack_dump_each(const rb_execution_context_t *ec, const rb_control_frame_t *c
|
|||||||
rstr = rb_inspect(*ptr);
|
rstr = rb_inspect(*ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(errout, " stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr),
|
kprintf(" stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr),
|
||||||
(ptr - ec->vm_stack));
|
(ptr - ec->vm_stack));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,7 +383,7 @@ vm_stack_dump_each(const rb_execution_context_t *ec, const rb_control_frame_t *c
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_debug_print_register(const rb_execution_context_t *ec, FILE *errout)
|
rb_vmdebug_debug_print_register(const rb_execution_context_t *ec, FILE *errout)
|
||||||
{
|
{
|
||||||
rb_control_frame_t *cfp = ec->cfp;
|
rb_control_frame_t *cfp = ec->cfp;
|
||||||
@ -382,17 +400,21 @@ rb_vmdebug_debug_print_register(const rb_execution_context_t *ec, FILE *errout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfpi = ((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size)) - cfp;
|
cfpi = ((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size)) - cfp;
|
||||||
fprintf(errout, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n",
|
kprintf(" [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n",
|
||||||
pc, (cfp->sp - ec->vm_stack), ep, cfpi);
|
pc, (cfp->sp - ec->vm_stack), ep, cfpi);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_thread_dump_regs(VALUE thval, FILE *errout)
|
rb_vmdebug_thread_dump_regs(VALUE thval, FILE *errout)
|
||||||
{
|
{
|
||||||
rb_vmdebug_debug_print_register(rb_thread_ptr(thval)->ec, errout);
|
return rb_vmdebug_debug_print_register(rb_thread_ptr(thval)->ec, errout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *errout)
|
rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *errout)
|
||||||
{
|
{
|
||||||
const rb_iseq_t *iseq = cfp->iseq;
|
const rb_iseq_t *iseq = cfp->iseq;
|
||||||
@ -402,10 +424,10 @@ rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_fr
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<(int)VM_CFP_CNT(ec, cfp); i++) {
|
for (i=0; i<(int)VM_CFP_CNT(ec, cfp); i++) {
|
||||||
printf(" ");
|
kprintf(" ");
|
||||||
}
|
}
|
||||||
printf("| ");
|
kprintf("| ");
|
||||||
if(0)printf("[%03ld] ", (long)(cfp->sp - ec->vm_stack));
|
if(0) kprintf("[%03ld] ", (long)(cfp->sp - ec->vm_stack));
|
||||||
|
|
||||||
/* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(ec, cfp)); */
|
/* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(ec, cfp)); */
|
||||||
if (pc >= 0) {
|
if (pc >= 0) {
|
||||||
@ -416,20 +438,24 @@ rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_fr
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if VMDEBUG > 3
|
#if VMDEBUG > 3
|
||||||
fprintf(errout, " (1)");
|
kprintf(" (1)");
|
||||||
rb_vmdebug_debug_print_register(errout, ec);
|
rb_vmdebug_debug_print_register(errout, ec);
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
|
rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
|
||||||
{
|
{
|
||||||
#if VMDEBUG > 9
|
#if VMDEBUG > 9
|
||||||
rb_vmdebug_stack_dump_raw(ec, cfp, errout);
|
if (!rb_vmdebug_stack_dump_raw(ec, cfp, errout)) goto errout;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if VMDEBUG > 3
|
#if VMDEBUG > 3
|
||||||
fprintf(errout, " (2)");
|
kprintf(" (2)");
|
||||||
rb_vmdebug_debug_print_register(errout, ec);
|
rb_vmdebug_debug_print_register(errout, ec);
|
||||||
#endif
|
#endif
|
||||||
/* stack_dump_raw(ec, cfp); */
|
/* stack_dump_raw(ec, cfp); */
|
||||||
@ -438,8 +464,14 @@ rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_f
|
|||||||
/* stack_dump_thobj(ec); */
|
/* stack_dump_thobj(ec); */
|
||||||
vm_stack_dump_each(ec, ec->cfp, errout);
|
vm_stack_dump_each(ec, ec->cfp, errout);
|
||||||
|
|
||||||
printf
|
kprintf
|
||||||
("--------------------------------------------------------------\n");
|
("--------------------------------------------------------------\n");
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#if VMDEBUG > 2
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,10 +481,11 @@ rb_vmdebug_thread_dump_state(FILE *errout, VALUE self)
|
|||||||
rb_thread_t *th = rb_thread_ptr(self);
|
rb_thread_t *th = rb_thread_ptr(self);
|
||||||
rb_control_frame_t *cfp = th->ec->cfp;
|
rb_control_frame_t *cfp = th->ec->cfp;
|
||||||
|
|
||||||
fprintf(errout, "Thread state dump:\n");
|
kprintf("Thread state dump:\n");
|
||||||
fprintf(errout, "pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp);
|
kprintf("pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp);
|
||||||
fprintf(errout, "cfp: %p, ep : %p\n", (void *)cfp, (void *)cfp->ep);
|
kprintf("cfp: %p, ep : %p\n", (void *)cfp, (void *)cfp->ep);
|
||||||
|
|
||||||
|
error:
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,19 +779,20 @@ dump_thread(void *arg)
|
|||||||
info->MaxNameLen = MAX_SYM_NAME;
|
info->MaxNameLen = MAX_SYM_NAME;
|
||||||
if (pSymFromAddr(ph, addr, &displacement, info)) {
|
if (pSymFromAddr(ph, addr, &displacement, info)) {
|
||||||
if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
|
if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
|
||||||
fprintf(errout, "%s", libpath);
|
kprintf("%s", libpath);
|
||||||
fprintf(errout, "(%s+0x%"PRI_64_PREFIX"x)",
|
kprintf("(%s+0x%"PRI_64_PREFIX"x)",
|
||||||
info->Name, displacement);
|
info->Name, displacement);
|
||||||
}
|
}
|
||||||
fprintf(errout, " [0x%p]", (void *)(VALUE)addr);
|
kprintf(" [0x%p]", (void *)(VALUE)addr);
|
||||||
memset(&line, 0, sizeof(line));
|
memset(&line, 0, sizeof(line));
|
||||||
line.SizeOfStruct = sizeof(line);
|
line.SizeOfStruct = sizeof(line);
|
||||||
if (pSymGetLineFromAddr64(ph, addr, &tmp, &line))
|
if (pSymGetLineFromAddr64(ph, addr, &tmp, &line))
|
||||||
fprintf(errout, " %s:%lu", line.FileName, line.LineNumber);
|
kprintf(" %s:%lu", line.FileName, line.LineNumber);
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
ResumeThread(th);
|
ResumeThread(th);
|
||||||
}
|
}
|
||||||
CloseHandle(th);
|
CloseHandle(th);
|
||||||
@ -783,7 +817,7 @@ rb_print_backtrace(FILE *errout)
|
|||||||
if (syms) {
|
if (syms) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<n; i++) {
|
for (i=0; i<n; i++) {
|
||||||
fprintf(errout, "%s\n", syms[i]);
|
kprintf("%s\n", syms[i]);
|
||||||
}
|
}
|
||||||
free(syms);
|
free(syms);
|
||||||
}
|
}
|
||||||
@ -827,21 +861,24 @@ print_machine_register(FILE *errout, size_t reg, const char *reg_name, int col_c
|
|||||||
|
|
||||||
ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%.*" PRIxSIZE, reg_name, size_width, reg);
|
ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%.*" PRIxSIZE, reg_name, size_width, reg);
|
||||||
if (col_count + ret > max_col) {
|
if (col_count + ret > max_col) {
|
||||||
fputs("\n", errout);
|
kputs("\n");
|
||||||
col_count = 0;
|
col_count = 0;
|
||||||
}
|
}
|
||||||
col_count += ret;
|
col_count += ret;
|
||||||
fputs(buf, errout);
|
kputs(buf);
|
||||||
return col_count;
|
return col_count;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
rb_dump_machine_register(FILE *errout, const ucontext_t *ctx)
|
rb_dump_machine_register(FILE *errout, const ucontext_t *ctx)
|
||||||
{
|
{
|
||||||
int col_count = 0;
|
int col_count = 0;
|
||||||
if (!ctx) return;
|
if (!ctx) return true;
|
||||||
|
|
||||||
fprintf(errout, "-- Machine register context "
|
kprintf("-- Machine register context "
|
||||||
"------------------------------------------------\n");
|
"------------------------------------------------\n");
|
||||||
|
|
||||||
# if defined __linux__
|
# if defined __linux__
|
||||||
@ -1034,13 +1071,17 @@ rb_dump_machine_register(FILE *errout, const ucontext_t *ctx)
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
fprintf(errout, "\n\n");
|
kprintf("\n\n");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
# define rb_dump_machine_register(errout, ctx) ((void)0)
|
# define rb_dump_machine_register(errout, ctx) ((void)0)
|
||||||
#endif /* dump_machine_register */
|
#endif /* dump_machine_register */
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vm_bugreport(const void *ctx, FILE *errout)
|
rb_vm_bugreport(const void *ctx, FILE *errout)
|
||||||
{
|
{
|
||||||
const char *cmd = getenv("RUBY_ON_BUG");
|
const char *cmd = getenv("RUBY_ON_BUG");
|
||||||
@ -1058,8 +1099,8 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
{
|
{
|
||||||
static bool crashing = false;
|
static bool crashing = false;
|
||||||
if (crashing) {
|
if (crashing) {
|
||||||
fprintf(errout, "Crashed while printing bug report\n");
|
kprintf("Crashed while printing bug report\n");
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
crashing = true;
|
crashing = true;
|
||||||
}
|
}
|
||||||
@ -1082,26 +1123,26 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
// If we get here, hopefully things are intact enough that
|
// If we get here, hopefully things are intact enough that
|
||||||
// we can read these two numbers. It is an estimate because
|
// we can read these two numbers. It is an estimate because
|
||||||
// we are reading without synchronization.
|
// we are reading without synchronization.
|
||||||
fprintf(errout, "-- Threading information "
|
kprintf("-- Threading information "
|
||||||
"---------------------------------------------------\n");
|
"---------------------------------------------------\n");
|
||||||
fprintf(errout, "Total ractor count: %u\n", vm->ractor.cnt);
|
kprintf("Total ractor count: %u\n", vm->ractor.cnt);
|
||||||
fprintf(errout, "Ruby thread count for this ractor: %u\n", rb_ec_ractor_ptr(ec)->threads.cnt);
|
kprintf("Ruby thread count for this ractor: %u\n", rb_ec_ractor_ptr(ec)->threads.cnt);
|
||||||
fputs("\n", errout);
|
fputs("\n", errout);
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_dump_machine_register(errout, ctx);
|
rb_dump_machine_register(errout, ctx);
|
||||||
|
|
||||||
#if USE_BACKTRACE || defined(_WIN32)
|
#if USE_BACKTRACE || defined(_WIN32)
|
||||||
fprintf(errout, "-- C level backtrace information "
|
kprintf("-- C level backtrace information "
|
||||||
"-------------------------------------------\n");
|
"-------------------------------------------\n");
|
||||||
rb_print_backtrace(errout);
|
rb_print_backtrace(errout);
|
||||||
|
|
||||||
|
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
#endif /* USE_BACKTRACE */
|
#endif /* USE_BACKTRACE */
|
||||||
|
|
||||||
if (other_runtime_info || vm) {
|
if (other_runtime_info || vm) {
|
||||||
fprintf(errout, "-- Other runtime information "
|
kprintf("-- Other runtime information "
|
||||||
"-----------------------------------------------\n\n");
|
"-----------------------------------------------\n\n");
|
||||||
}
|
}
|
||||||
if (vm && !rb_during_gc()) {
|
if (vm && !rb_during_gc()) {
|
||||||
@ -1114,16 +1155,16 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
|
|
||||||
name = vm->progname;
|
name = vm->progname;
|
||||||
if (name) {
|
if (name) {
|
||||||
fprintf(errout, "* Loaded script: %.*s\n",
|
kprintf("* Loaded script: %.*s\n",
|
||||||
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
|
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
if (vm->loaded_features) {
|
if (vm->loaded_features) {
|
||||||
fprintf(errout, "* Loaded features:\n\n");
|
kprintf("* Loaded features:\n\n");
|
||||||
for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) {
|
for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) {
|
||||||
name = RARRAY_AREF(vm->loaded_features, i);
|
name = RARRAY_AREF(vm->loaded_features, i);
|
||||||
if (RB_TYPE_P(name, T_STRING)) {
|
if (RB_TYPE_P(name, T_STRING)) {
|
||||||
fprintf(errout, " %4d %.*s\n", i,
|
kprintf(" %4d %.*s\n", i,
|
||||||
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
|
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
|
||||||
}
|
}
|
||||||
else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) {
|
else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) {
|
||||||
@ -1131,26 +1172,26 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
"class" : "module";
|
"class" : "module";
|
||||||
name = rb_search_class_path(rb_class_real(name));
|
name = rb_search_class_path(rb_class_real(name));
|
||||||
if (!RB_TYPE_P(name, T_STRING)) {
|
if (!RB_TYPE_P(name, T_STRING)) {
|
||||||
fprintf(errout, " %4d %s:<unnamed>\n", i, type);
|
kprintf(" %4d %s:<unnamed>\n", i, type);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fprintf(errout, " %4d %s:%.*s\n", i, type,
|
kprintf(" %4d %s:%.*s\n", i, type,
|
||||||
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
|
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VALUE klass = rb_search_class_path(rb_obj_class(name));
|
VALUE klass = rb_search_class_path(rb_obj_class(name));
|
||||||
if (!RB_TYPE_P(klass, T_STRING)) {
|
if (!RB_TYPE_P(klass, T_STRING)) {
|
||||||
fprintf(errout, " %4d #<%p:%p>\n", i,
|
kprintf(" %4d #<%p:%p>\n", i,
|
||||||
(void *)CLASS_OF(name), (void *)name);
|
(void *)CLASS_OF(name), (void *)name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fprintf(errout, " %4d #<%.*s:%p>\n", i,
|
kprintf(" %4d #<%.*s:%p>\n", i,
|
||||||
LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass),
|
LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass),
|
||||||
(void *)name);
|
(void *)name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -1158,7 +1199,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
{
|
{
|
||||||
FILE *fp = fopen(PROC_MAPS_NAME, "r");
|
FILE *fp = fopen(PROC_MAPS_NAME, "r");
|
||||||
if (fp) {
|
if (fp) {
|
||||||
fprintf(errout, "* Process memory map:\n\n");
|
kprintf("* Process memory map:\n\n");
|
||||||
|
|
||||||
while (!feof(fp)) {
|
while (!feof(fp)) {
|
||||||
char buff[0x100];
|
char buff[0x100];
|
||||||
@ -1168,7 +1209,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
fprintf(errout, "\n\n");
|
kprintf("\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
@ -1182,14 +1223,14 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
mib[2] = KERN_PROC_PID;
|
mib[2] = KERN_PROC_PID;
|
||||||
mib[3] = getpid();
|
mib[3] = getpid();
|
||||||
if (sysctl(mib, MIB_KERN_PROC_PID_LEN, &kp, &len, NULL, 0) == -1) {
|
if (sysctl(mib, MIB_KERN_PROC_PID_LEN, &kp, &len, NULL, 0) == -1) {
|
||||||
fprintf(errout, "sysctl: %s\n", strerror(errno));
|
kprintf("sysctl: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct procstat *prstat = procstat_open_sysctl();
|
struct procstat *prstat = procstat_open_sysctl();
|
||||||
fprintf(errout, "* Process memory map:\n\n");
|
kprintf("* Process memory map:\n\n");
|
||||||
procstat_vm(prstat, &kp);
|
procstat_vm(prstat, &kp);
|
||||||
procstat_close(prstat);
|
procstat_close(prstat);
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
#endif /* __FreeBSD__ */
|
#endif /* __FreeBSD__ */
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@ -1199,7 +1240,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT;
|
mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT;
|
||||||
natural_t depth = 0;
|
natural_t depth = 0;
|
||||||
|
|
||||||
fprintf(errout, "* Process memory map:\n\n");
|
kprintf("* Process memory map:\n\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
if (vm_region_recurse(mach_task_self(), &addr, &size, &depth,
|
if (vm_region_recurse(mach_task_self(), &addr, &size, &depth,
|
||||||
(vm_region_recurse_info_t)&map, &count) != KERN_SUCCESS) {
|
(vm_region_recurse_info_t)&map, &count) != KERN_SUCCESS) {
|
||||||
@ -1211,17 +1252,17 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
depth++;
|
depth++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(errout, "%lx-%lx %s%s%s", addr, (addr+size),
|
kprintf("%lx-%lx %s%s%s", addr, (addr+size),
|
||||||
((map.protection & VM_PROT_READ) != 0 ? "r" : "-"),
|
((map.protection & VM_PROT_READ) != 0 ? "r" : "-"),
|
||||||
((map.protection & VM_PROT_WRITE) != 0 ? "w" : "-"),
|
((map.protection & VM_PROT_WRITE) != 0 ? "w" : "-"),
|
||||||
((map.protection & VM_PROT_EXECUTE) != 0 ? "x" : "-"));
|
((map.protection & VM_PROT_EXECUTE) != 0 ? "x" : "-"));
|
||||||
#ifdef HAVE_LIBPROC_H
|
#ifdef HAVE_LIBPROC_H
|
||||||
char buff[PATH_MAX];
|
char buff[PATH_MAX];
|
||||||
if (proc_regionfilename(getpid(), addr, buff, sizeof(buff)) > 0) {
|
if (proc_regionfilename(getpid(), addr, buff, sizeof(buff)) > 0) {
|
||||||
fprintf(errout, " %s", buff);
|
kprintf(" %s", buff);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fprintf(errout, "\n");
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += size;
|
addr += size;
|
||||||
@ -1229,9 +1270,13 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
rb_vmdebug_stack_dump_all_threads(void)
|
rb_vmdebug_stack_dump_all_threads(void)
|
||||||
{
|
{
|
||||||
rb_thread_t *th = NULL;
|
rb_thread_t *th = NULL;
|
||||||
@ -1241,10 +1286,14 @@ rb_vmdebug_stack_dump_all_threads(void)
|
|||||||
// TODO: now it only shows current ractor
|
// TODO: now it only shows current ractor
|
||||||
ccan_list_for_each(&r->threads.set, th, lt_node) {
|
ccan_list_for_each(&r->threads.set, th, lt_node) {
|
||||||
#ifdef NON_SCALAR_THREAD_ID
|
#ifdef NON_SCALAR_THREAD_ID
|
||||||
fprintf(errout, "th: %p, native_id: N/A\n", th);
|
kprintf("th: %p, native_id: N/A\n", th);
|
||||||
#else
|
#else
|
||||||
fprintf(errout, "th: %p, native_id: %p\n", (void *)th, (void *)(uintptr_t)th->nt->thread_id);
|
kprintf("th: %p, native_id: %p\n", (void *)th, (void *)(uintptr_t)th->nt->thread_id);
|
||||||
#endif
|
#endif
|
||||||
rb_vmdebug_stack_dump_raw(th->ec, th->ec->cfp, errout);
|
if (!rb_vmdebug_stack_dump_raw(th->ec, th->ec->cfp, errout)) goto error;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user