Beispiel #1
0
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 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__ */
    }
}