void rb_vm_bugreport(const void *ctx) { #ifdef __linux__ # define PROC_MAPS_NAME "/proc/self/maps" #endif #ifdef PROC_MAPS_NAME enum {other_runtime_info = 1}; #else enum {other_runtime_info = 0}; #endif const rb_vm_t *const vm = GET_VM(); preface_dump(); if (vm) { SDR(); rb_backtrace_print_as_bugreport(); fputs("\n", stderr); } rb_dump_machine_register(ctx); #if HAVE_BACKTRACE || defined(_WIN32) fprintf(stderr, "-- C level backtrace information " "-------------------------------------------\n"); rb_print_backtrace(); fprintf(stderr, "\n"); #endif /* HAVE_BACKTRACE */ if (other_runtime_info || vm) { fprintf(stderr, "-- Other runtime information " "-----------------------------------------------\n\n"); } if (vm) { int i; VALUE name; long len; const int max_name_length = 1024; # define LIMITED_NAME_LENGTH(s) \ (((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len) name = vm->progname; fprintf(stderr, "* Loaded script: %.*s\n", LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); fprintf(stderr, "\n"); fprintf(stderr, "* Loaded features:\n\n"); for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) { name = RARRAY_AREF(vm->loaded_features, i); if (RB_TYPE_P(name, T_STRING)) { fprintf(stderr, " %4d %.*s\n", i, LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); } else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) { const char *const type = RB_TYPE_P(name, T_CLASS) ? "class" : "module"; name = rb_search_class_path(rb_class_real(name)); if (!RB_TYPE_P(name, T_STRING)) { fprintf(stderr, " %4d %s:<unnamed>\n", i, type); continue; } fprintf(stderr, " %4d %s:%.*s\n", i, type, LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); } else { VALUE klass = rb_search_class_path(rb_obj_class(name)); if (!RB_TYPE_P(klass, T_STRING)) { fprintf(stderr, " %4d #<%p:%p>\n", i, (void *)CLASS_OF(name), (void *)name); continue; } fprintf(stderr, " %4d #<%.*s:%p>\n", i, LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass), (void *)name); } } fprintf(stderr, "\n"); } { #ifdef PROC_MAPS_NAME { FILE *fp = fopen(PROC_MAPS_NAME, "r"); if (fp) { fprintf(stderr, "* Process memory map:\n\n"); while (!feof(fp)) { char buff[0x100]; size_t rn = fread(buff, 1, 0x100, fp); if (fwrite(buff, 1, rn, stderr) != rn) break; } fclose(fp); fprintf(stderr, "\n\n"); } } #endif /* __linux__ */ #ifdef HAVE_LIBPROCSTAT # define MIB_KERN_PROC_PID_LEN 4 int mib[MIB_KERN_PROC_PID_LEN]; struct kinfo_proc kp; size_t len = sizeof(struct kinfo_proc); mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = getpid(); if (sysctl(mib, MIB_KERN_PROC_PID_LEN, &kp, &len, NULL, 0) == -1) { perror("sysctl"); } else { struct procstat *prstat = procstat_open_sysctl(); fprintf(stderr, "* Process memory map:\n\n"); procstat_vm(prstat, &kp); procstat_close(prstat); fprintf(stderr, "\n"); } #endif /* __FreeBSD__ */ } }
void rb_vm_bugreport(void) { #ifdef __linux__ # define PROC_MAPS_NAME "/proc/self/maps" #endif #ifdef PROC_MAPS_NAME enum {other_runtime_info = 1}; #else enum {other_runtime_info = 0}; #endif const rb_vm_t *const vm = GET_VM(); if (vm) { SDR(); rb_backtrace_print_as_bugreport(); fputs("\n", stderr); } #if HAVE_BACKTRACE || defined(_WIN32) fprintf(stderr, "-- C level backtrace information " "-------------------------------------------\n"); { #if defined __APPLE__ fprintf(stderr, "\n"); fprintf(stderr, " See Crash Report log file under the one of following:\n" " * ~/Library/Logs/CrashReporter\n" " * /Library/Logs/CrashReporter\n" " * ~/Library/Logs/DiagnosticReports\n" " * /Library/Logs/DiagnosticReports\n" " the more detail of.\n"); #elif HAVE_BACKTRACE #define MAX_NATIVE_TRACE 1024 static void *trace[MAX_NATIVE_TRACE]; int n = backtrace(trace, MAX_NATIVE_TRACE); char **syms = backtrace_symbols(trace, n); if (syms) { #ifdef USE_ELF rb_dump_backtrace_with_lines(n, trace, syms); #else int i; for (i=0; i<n; i++) { fprintf(stderr, "%s\n", syms[i]); } #endif free(syms); } #elif defined(_WIN32) DWORD tid = GetCurrentThreadId(); HANDLE th = (HANDLE)_beginthread(dump_thread, 0, &tid); if (th != (HANDLE)-1) WaitForSingleObject(th, INFINITE); #endif } fprintf(stderr, "\n"); #endif /* HAVE_BACKTRACE */ if (other_runtime_info || vm) { fprintf(stderr, "-- Other runtime information " "-----------------------------------------------\n\n"); } if (vm) { int i; VALUE name; long len; const int max_name_length = 1024; # define LIMITED_NAME_LENGTH(s) \ (((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len) name = vm->progname; fprintf(stderr, "* Loaded script: %.*s\n", LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); fprintf(stderr, "\n"); fprintf(stderr, "* Loaded features:\n\n"); for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) { name = RARRAY_PTR(vm->loaded_features)[i]; if (RB_TYPE_P(name, T_STRING)) { fprintf(stderr, " %4d %.*s\n", i, LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); } else { fprintf(stderr, " %4d #<%s:%p>\n", i, rb_class2name(CLASS_OF(name)), (void *)name); } } fprintf(stderr, "\n"); } { #ifdef PROC_MAPS_NAME { FILE *fp = fopen(PROC_MAPS_NAME, "r"); if (fp) { fprintf(stderr, "* Process memory map:\n\n"); while (!feof(fp)) { char buff[0x100]; size_t rn = fread(buff, 1, 0x100, fp); if (fwrite(buff, 1, rn, stderr) != rn) break; } fclose(fp); fprintf(stderr, "\n\n"); } } #endif /* __linux__ */ } }
void rb_vm_bugreport(void) { #ifdef __linux__ # define PROC_MAPS_NAME "/proc/self/maps" #endif #ifdef PROC_MAPS_NAME enum {other_runtime_info = 1}; #else enum {other_runtime_info = 0}; #endif const rb_vm_t *const vm = GET_VM(); #if defined __APPLE__ fputs("-- Crash Report log information " "--------------------------------------------\n" " See Crash Report log file under the one of following:\n" " * ~/Library/Logs/CrashReporter\n" " * /Library/Logs/CrashReporter\n" " * ~/Library/Logs/DiagnosticReports\n" " * /Library/Logs/DiagnosticReports\n" " for more details.\n" "\n", stderr); #endif if (vm) { SDR(); rb_backtrace_print_as_bugreport(); fputs("\n", stderr); } #if HAVE_BACKTRACE || defined(_WIN32) fprintf(stderr, "-- C level backtrace information " "-------------------------------------------\n"); rb_print_backtrace(); fprintf(stderr, "\n"); #endif /* HAVE_BACKTRACE */ if (other_runtime_info || vm) { fprintf(stderr, "-- Other runtime information " "-----------------------------------------------\n\n"); } if (vm) { int i; VALUE name; long len; const int max_name_length = 1024; # define LIMITED_NAME_LENGTH(s) \ (((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len) name = vm->progname; fprintf(stderr, "* Loaded script: %.*s\n", LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); fprintf(stderr, "\n"); fprintf(stderr, "* Loaded features:\n\n"); for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) { name = RARRAY_AREF(vm->loaded_features, i); if (RB_TYPE_P(name, T_STRING)) { fprintf(stderr, " %4d %.*s\n", i, LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); } else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) { const char *const type = RB_TYPE_P(name, T_CLASS) ? "class" : "module"; name = rb_class_name(name); fprintf(stderr, " %4d %s:%.*s\n", i, type, LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); } else { VALUE klass = rb_class_name(CLASS_OF(name)); fprintf(stderr, " %4d #<%.*s:%p>\n", i, LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass), (void *)name); } } fprintf(stderr, "\n"); } { #ifdef PROC_MAPS_NAME { FILE *fp = fopen(PROC_MAPS_NAME, "r"); if (fp) { fprintf(stderr, "* Process memory map:\n\n"); while (!feof(fp)) { char buff[0x100]; size_t rn = fread(buff, 1, 0x100, fp); if (fwrite(buff, 1, rn, stderr) != rn) break; } fclose(fp); fprintf(stderr, "\n\n"); } } #endif /* __linux__ */ } }