[前][次][番号順一覧][スレッド一覧]

ruby-changes:34025

From: nobu <ko1@a...>
Date: Sun, 25 May 2014 12:47:02 +0900 (JST)
Subject: [ruby-changes:34025] nobu:r46106 (trunk): report bug with machine regisiters

nobu	2014-05-25 12:46:55 +0900 (Sun, 25 May 2014)

  New Revision: 46106

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=46106

  Log:
    report bug with machine regisiters
    
    * error.c (rb_bug_context): new function to report bug with
      context.
    * vm_dump.c (rb_vm_bugreport): accepts `ucontext_t` argument to
      dump machine regisiters.  based on [GH-584].
    * signal.c (sigbus, sigsegv): dump machine regisiters if available.

  Modified files:
    trunk/ChangeLog
    trunk/error.c
    trunk/signal.c
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_dump.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 46105)
+++ ChangeLog	(revision 46106)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun May 25 12:46:47 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* error.c (rb_bug_context): new function to report bug with
+	  context.
+
+	* vm_dump.c (rb_vm_bugreport): accepts `ucontext_t` argument to
+	  dump machine regisiters.  based on [GH-584].
+
+	* signal.c (sigbus, sigsegv): dump machine regisiters if available.
+
 Sun May 25 12:32:42 2014  Tanaka Akira  <akr@f...>
 
 	* test/lib/minitest/unit.rb: Sort leaked threads and tempfiles.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 46105)
+++ vm_core.h	(revision 46106)
@@ -836,7 +836,8 @@ extern void rb_vmdebug_debug_print_post( https://github.com/ruby/ruby/blob/trunk/vm_core.h#L836
 
 #define SDR() rb_vmdebug_stack_dump_raw(GET_THREAD(), GET_THREAD()->cfp)
 #define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_THREAD(), (cfp))
-void rb_vm_bugreport(void);
+void rb_vm_bugreport(const void *);
+NORETURN(void rb_bug_context(const void *, const char *fmt, ...));
 
 /* functions about thread/vm execution */
 RUBY_SYMBOL_EXPORT_BEGIN
Index: error.c
===================================================================
--- error.c	(revision 46105)
+++ error.c	(revision 46106)
@@ -292,41 +292,78 @@ rb_bug_reporter_add(void (*func)(FILE *, https://github.com/ruby/ruby/blob/trunk/error.c#L292
     return 1;
 }
 
-static void
-report_bug(const char *file, int line, const char *fmt, va_list args)
+/* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */
+#define REPORT_BUG_BUFSIZ 256
+static FILE *
+bug_report_file(const char *file, int line)
 {
-    /* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */
-    char buf[256];
+    char buf[REPORT_BUG_BUFSIZ];
     FILE *out = stderr;
-    int len = err_position_0(buf, 256, file, line);
+    int len = err_position_0(buf, sizeof(buf), file, line);
 
     if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len ||
 	(ssize_t)fwrite(buf, 1, len, (out = stdout)) == (ssize_t)len) {
+	return out;
+    }
+    return NULL;
+}
+
+static void
+bug_report_begin(FILE *out, const char *fmt, va_list args)
+{
+    char buf[REPORT_BUG_BUFSIZ];
+
+    fputs("[BUG] ", out);
+    vsnprintf(buf, sizeof(buf), fmt, args);
+    fputs(buf, out);
+    snprintf(buf, sizeof(buf), "\n%s\n\n", ruby_description);
+    fputs(buf, out);
+}
 
-	fputs("[BUG] ", out);
-	vsnprintf(buf, 256, fmt, args);
-	fputs(buf, out);
-	snprintf(buf, 256, "\n%s\n\n", ruby_description);
-	fputs(buf, out);
-
-	rb_vm_bugreport();
-
-	/* call additional bug reporters */
-	{
-	    int i;
-	    for (i=0; i<bug_reporters_size; i++) {
-		struct bug_reporters *reporter = &bug_reporters[i];
-		(*reporter->func)(out, reporter->data);
-	    }
+#define bug_report_begin(out, fmt) do { \
+    va_list args; \
+    va_start(args, fmt); \
+    bug_report_begin(out, fmt, args); \
+    va_end(args); \
+} while (0)
+
+static void
+bug_report_end(FILE *out)
+{
+    /* call additional bug reporters */
+    {
+	int i;
+	for (i=0; i<bug_reporters_size; i++) {
+	    struct bug_reporters *reporter = &bug_reporters[i];
+	    (*reporter->func)(out, reporter->data);
 	}
-	fprintf(out, REPORTBUG_MSG);
     }
+    fprintf(out, REPORTBUG_MSG);
+}
+
+#define report_bug(file, line, fmt, ctx) do { \
+    FILE *out = bug_report_file(file, line); \
+    if (out) { \
+	bug_report_begin(out, fmt); \
+	rb_vm_bugreport(ctx); \
+	bug_report_end(out); \
+    } \
+} while (0) \
+
+NORETURN(static void die(void));
+static void
+die(void)
+{
+#if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
+    _set_abort_behavior( 0, _CALL_REPORTFAULT);
+#endif
+
+    abort();
 }
 
 void
 rb_bug(const char *fmt, ...)
 {
-    va_list args;
     const char *file = NULL;
     int line = 0;
 
@@ -335,17 +372,28 @@ rb_bug(const char *fmt, ...) https://github.com/ruby/ruby/blob/trunk/error.c#L372
 	line = rb_sourceline();
     }
 
-    va_start(args, fmt);
-    report_bug(file, line, fmt, args);
-    va_end(args);
+    report_bug(file, line, fmt, NULL);
 
-#if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
-    _set_abort_behavior( 0, _CALL_REPORTFAULT);
-#endif
+    die();
+}
 
-    abort();
+void
+rb_bug_context(const void *ctx, const char *fmt, ...)
+{
+    const char *file = NULL;
+    int line = 0;
+
+    if (GET_THREAD()) {
+	file = rb_sourcefile();
+	line = rb_sourceline();
+    }
+
+    report_bug(file, line, fmt, ctx);
+
+    die();
 }
 
+
 void
 rb_bug_errno(const char *mesg, int errno_arg)
 {
@@ -394,11 +442,7 @@ rb_async_bug_errno(const char *mesg, int https://github.com/ruby/ruby/blob/trunk/error.c#L442
 void
 rb_compile_bug(const char *file, int line, const char *fmt, ...)
 {
-    va_list args;
-
-    va_start(args, fmt);
-    report_bug(file, line, fmt, args);
-    va_end(args);
+    report_bug(file, line, fmt, NULL);
 
     abort();
 }
Index: vm.c
===================================================================
--- vm.c	(revision 46105)
+++ vm.c	(revision 46106)
@@ -2376,7 +2376,7 @@ extern VALUE *rb_gc_register_stack_start https://github.com/ruby/ruby/blob/trunk/vm.c#L2376
 static VALUE
 sdr(void)
 {
-    rb_vm_bugreport();
+    rb_vm_bugreport(NULL);
     return Qnil;
 }
 
Index: vm_dump.c
===================================================================
--- vm_dump.c	(revision 46105)
+++ vm_dump.c	(revision 46106)
@@ -789,8 +789,145 @@ procstat_vm(struct procstat *procstat, s https://github.com/ruby/ruby/blob/trunk/vm_dump.c#L789
 }
 #endif
 
+#if defined __linux__
+# if defined __x86_64__ || defined __i386__
+#  define HAVE_PRINT_MACHINE_REGISTERS 1
+# endif
+#elif defined __APPLE__
+# if defined __x86_64__ || defined __i386__
+#  define HAVE_PRINT_MACHINE_REGISTERS 1
+# endif
+#endif
+
+#ifdef HAVE_PRINT_MACHINE_REGISTERS
+static int
+print_machine_register(size_t reg, const char *reg_name, int col_count, int max_col)
+{
+    int ret;
+    char buf[64];
+
+#ifdef __LP64__
+    ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%016zx", reg_name, reg);
+#else
+    ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%08zx", reg_name, reg);
+#endif
+    if (col_count + ret > max_col) {
+	fputs("\n", stderr);
+	col_count = 0;
+    }
+    col_count += ret;
+    fputs(buf, stderr);
+    return col_count;
+}
+# ifdef __linux__
+#   define dump_machine_register(reg) (col_count = print_machine_register(mctx->gregs[REG_##reg], #reg, col_count, 80))
+# elif defined __APPLE__
+#   define dump_machine_register(reg) (col_count = print_machine_register(mctx->__ss.__##reg, #reg, col_count, 80))
+# endif
+
+static void
+rb_dump_machine_register(const ucontext_t *ctx)
+{
+    int col_count = 0;
+    if (!ctx) return;
+
+    fprintf(stderr, "-- Machine register context "
+	    "------------------------------------------------\n");
+
+# if defined __linux__
+    {
+	const mcontext_t *const mctx = &ctx->uc_mcontext;
+#   if defined __x86_64__
+	dump_machine_register(RIP);
+	dump_machine_register(RBP);
+	dump_machine_register(RSP);
+	dump_machine_register(RAX);
+	dump_machine_register(RBX);
+	dump_machine_register(RCX);
+	dump_machine_register(RDX);
+	dump_machine_register(RDI);
+	dump_machine_register(RSI);
+	dump_machine_register(R8);
+	dump_machine_register(R9);
+	dump_machine_register(R10);
+	dump_machine_register(R11);
+	dump_machine_register(R12);
+	dump_machine_register(R13);
+	dump_machine_register(R14);
+	dump_machine_register(R15);
+	dump_machine_register(EFL);
+#   elif defined __i386__
+	dump_machine_register(GS);
+	dump_machine_register(FS);
+	dump_machine_register(ES);
+	dump_machine_register(DS);
+	dump_machine_register(EDI);
+	dump_machine_register(ESI);
+	dump_machine_register(EBP);
+	dump_machine_register(ESP);
+	dump_machine_register(EBX);
+	dump_machine_register(EDX);
+	dump_machine_register(ECX);
+	dump_machine_register(EAX);
+	dump_machine_register(TRAPNO);
+	dump_machine_register(ERR);
+	dump_machine_register(EIP);
+	dump_machine_register(CS);
+	dump_machine_register(EFL);
+	dump_machine_register(UESP);
+	dump_machine_register(SS);
+#   endif
+    }
+# elif defined __APPLE__
+    {
+	const mcontext_t mctx = ctx->uc_mcontext;
+#   if defined __x86_64__
+	dump_machine_register(rax);
+	dump_machine_register(rbx);
+	dump_machine_register(rcx);
+	dump_machine_register(rdx);
+	dump_machine_register(rdi);
+	dump_machine_register(rsi);
+	dump_machine_register(rbp);
+	dump_machine_register(rsp);
+	dump_machine_register(r8);
+	dump_machine_register(r9);
+	dump_machine_register(r10);
+	dump_machine_register(r11);
+	dump_machine_register(r12);
+	dump_machine_register(r13);
+	dump_machine_register(r14);
+	dump_machine_register(r15);
+	dump_machine_register(rip);
+	dump_machine_register(rflags);
+#   elif defined __i386__
+	dump_machine_register(eax);
+	dump_machine_register(ebx);
+	dump_machine_register(ecx);
+	dump_machine_register(edx);
+	dump_machine_register(edi);
+	dump_machine_register(esi);
+	dump_machine_register(ebp);
+	dump_machine_register(esp);
+	dump_machine_register(ss);
+	dump_machine_register(eflags);
+	dump_machine_register(eip);
+	dump_machine_register(cs);
+	dump_machine_register(ds);
+	dump_machine_register(es);
+	dump_machine_register(fs);
+	dump_machine_register(gs);
+#   endif
+    }
+# endif
+    fprintf(stderr, "\n\n");
+}
+#else
+# define rb_dump_machine_register(ctx) ((void)0)
+#endif /* HAVE_PRINT_MACHINE_REGISTERS */
+
 void
-rb_vm_bugreport(void)
+rb_vm_bugreport(const void *ctx)
 {
 #ifdef __linux__
 # define PROC_MAPS_NAME "/proc/self/maps"
@@ -820,6 +957,8 @@ rb_vm_bugreport(void) https://github.com/ruby/ruby/blob/trunk/vm_dump.c#L957
 	fputs("\n", stderr);
     }
 
+    rb_dump_machine_register(ctx);
+
 #if HAVE_BACKTRACE || defined(_WIN32)
     fprintf(stderr, "-- C level backtrace information "
 	    "-------------------------------------------\n");
Index: signal.c
===================================================================
--- signal.c	(revision 46105)
+++ signal.c	(revision 46106)
@@ -507,9 +507,11 @@ typedef RETSIGTYPE (*sighandler_t)(int); https://github.com/ruby/ruby/blob/trunk/signal.c#L507
 #ifdef USE_SIGALTSTACK
 typedef void ruby_sigaction_t(int, siginfo_t*, void*);
 #define SIGINFO_ARG , siginfo_t *info, void *ctx
+#define SIGINFO_CTX ctx
 #else
 typedef RETSIGTYPE ruby_sigaction_t(int);
 #define SIGINFO_ARG
+#define SIGINFO_CTX 0
 #endif
 
 #ifdef USE_SIGALTSTACK
@@ -776,7 +778,7 @@ sigbus(int sig SIGINFO_ARG) https://github.com/ruby/ruby/blob/trunk/signal.c#L778
 #if defined __APPLE__
     CHECK_STACK_OVERFLOW();
 #endif
-    rb_bug("Bus Error" MESSAGE_FAULT_ADDRESS);
+    rb_bug_context(SIGINFO_CTX, "Bus Error" MESSAGE_FAULT_ADDRESS);
 }
 #endif
 
@@ -813,7 +815,7 @@ sigsegv(int sig SIGINFO_ARG) https://github.com/ruby/ruby/blob/trunk/signal.c#L815
 
     segv_received = 1;
     ruby_disable_gc_stress = 1;
-    rb_bug("Segmentation fault" MESSAGE_FAULT_ADDRESS);
+    rb_bug_context(SIGINFO_CTX, "Segmentation fault" MESSAGE_FAULT_ADDRESS);
 }
 #endif
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]