1 /**********************************************************************
6 created at: 04/08/25 02:31:54 JST
8 Copyright (C) 2004-2007 Koichi Sasada
10 **********************************************************************/
12 #include "ruby/internal/config.h"
16 #include "eval_intern.h"
19 #include "internal/signal.h"
20 #include "ruby/encoding.h"
22 #include "ruby/ruby.h"
23 #include "ruby/util.h"
27 #include "vm_callinfo.h"
28 #include "ruby/thread_native.h"
29 #include "ractor_core.h"
31 /* This is the only place struct RIMemo is actually used */
42 enum ruby_special_consts special_consts
;
43 enum ruby_value_type value_type
;
44 enum ruby_tag_type tag_type
;
45 enum node_type node_type
;
46 enum ruby_method_ids method_ids
;
47 enum ruby_id_types id_types
;
48 enum ruby_fl_type fl_types
;
49 enum ruby_fl_ushift fl_ushift
;
50 enum ruby_encoding_consts encoding_consts
;
51 enum ruby_coderange_type enc_coderange_types
;
52 enum ruby_econv_flag_type econv_flag_types
;
53 rb_econv_result_t econv_result
;
54 enum ruby_preserved_encindex encoding_index
;
55 enum ruby_robject_flags robject_flags
;
56 enum ruby_rmodule_flags rmodule_flags
;
57 enum ruby_rstring_flags rstring_flags
;
58 enum ruby_rarray_flags rarray_flags
;
59 enum ruby_rarray_consts rarray_consts
;
61 RUBY_FMODE_READABLE
= FMODE_READABLE
,
62 RUBY_FMODE_WRITABLE
= FMODE_WRITABLE
,
63 RUBY_FMODE_READWRITE
= FMODE_READWRITE
,
64 RUBY_FMODE_BINMODE
= FMODE_BINMODE
,
65 RUBY_FMODE_SYNC
= FMODE_SYNC
,
66 RUBY_FMODE_TTY
= FMODE_TTY
,
67 RUBY_FMODE_DUPLEX
= FMODE_DUPLEX
,
68 RUBY_FMODE_APPEND
= FMODE_APPEND
,
69 RUBY_FMODE_CREATE
= FMODE_CREATE
,
70 RUBY_FMODE_NOREVLOOKUP
= 0x00000100,
71 RUBY_FMODE_TRUNC
= FMODE_TRUNC
,
72 RUBY_FMODE_TEXTMODE
= FMODE_TEXTMODE
,
73 RUBY_FMODE_EXTERNAL
= 0x00010000,
74 RUBY_FMODE_SETENC_BY_BOM
= FMODE_SETENC_BY_BOM
,
75 RUBY_FMODE_UNIX
= 0x00200000,
76 RUBY_FMODE_INET
= 0x00400000,
77 RUBY_FMODE_INET6
= 0x00800000,
79 RUBY_NODE_TYPESHIFT
= NODE_TYPESHIFT
,
80 RUBY_NODE_TYPEMASK
= NODE_TYPEMASK
,
81 RUBY_NODE_LSHIFT
= NODE_LSHIFT
,
82 RUBY_NODE_FL_NEWLINE
= NODE_FL_NEWLINE
85 enum imemo_type types
;
86 enum {RUBY_IMEMO_MASK
= IMEMO_MASK
} mask
;
89 struct RSymbol
*symbol_ptr
;
90 enum vm_call_flag_bits vm_call_flags
;
91 } ruby_dummy_gdb_enums
;
93 const SIGNED_VALUE RUBY_NODE_LMASK
= NODE_LMASK
;
96 ruby_debug_print_indent(int level
, int debug_level
, int indent_level
)
98 if (level
< debug_level
) {
99 fprintf(stderr
, "%*s", indent_level
, "");
107 ruby_debug_printf(const char *format
, ...)
110 va_start(ap
, format
);
111 vfprintf(stderr
, format
, ap
);
115 #include "internal/gc.h"
118 ruby_debug_print_value(int level
, int debug_level
, const char *header
, VALUE obj
)
120 if (level
< debug_level
) {
122 rb_raw_obj_info(buff
, 0x100, obj
);
124 fprintf(stderr
, "DBG> %s: %s\n", header
, buff
);
131 ruby_debug_print_v(VALUE v
)
133 ruby_debug_print_value(0, 1, "", v
);
137 ruby_debug_print_id(int level
, int debug_level
, const char *header
, ID id
)
139 if (level
< debug_level
) {
140 fprintf(stderr
, "DBG> %s: %s\n", header
, rb_id2name(id
));
147 ruby_debug_print_node(int level
, int debug_level
, const char *header
, const NODE
*node
)
149 if (level
< debug_level
) {
150 fprintf(stderr
, "DBG> %s: %s (id: %d, line: %d, location: (%d,%d)-(%d,%d))\n",
151 header
, ruby_node_name(nd_type(node
)), nd_node_id(node
), nd_line(node
),
152 nd_first_lineno(node
), nd_first_column(node
),
153 nd_last_lineno(node
), nd_last_column(node
));
159 ruby_debug_print_n(const NODE
*node
)
161 ruby_debug_print_node(0, 1, "", node
);
165 ruby_debug_breakpoint(void)
171 # if RUBY_MSVCRT_VERSION >= 80
172 extern int ruby_w32_rtc_error
;
175 #if defined _WIN32 || defined __CYGWIN__
177 UINT ruby_w32_codepage
[2];
179 extern int ruby_rgengc_debug
;
180 extern int ruby_on_ci
;
183 ruby_env_debug_option(const char *str
, int len
, void *arg
)
188 #define NAME_MATCH(name) (len == sizeof(name) - 1 && strncmp(str, (name), len) == 0)
189 #define SET_WHEN(name, var, val) do { \
190 if (NAME_MATCH(name)) { \
195 #define NAME_MATCH_VALUE(name) \
196 ((size_t)len >= sizeof(name)-1 && \
197 strncmp(str, (name), sizeof(name)-1) == 0 && \
198 ((len == sizeof(name)-1 && !(len = 0)) || \
199 (str[sizeof(name)-1] == '=' && \
200 (str += sizeof(name), len -= sizeof(name), 1))))
201 #define SET_UINT(val) do { \
202 n = ruby_scan_digits(str, len, 10, &retlen, &ov); \
203 if (!ov && retlen) { \
204 val = (unsigned int)n; \
209 #define SET_UINT_LIST(name, vals, num) do { \
211 for (i = 0; i < (num); ++i) { \
212 SET_UINT((vals)[i]); \
213 if (!len || *str != ':') break; \
218 fprintf(stderr, "ignored "name" option: '%.*s'\n", len, str); \
221 #define SET_WHEN_UINT(name, vals, num, req) \
222 if (NAME_MATCH_VALUE(name)) { \
224 else SET_UINT_LIST(name, vals, num); \
228 if (NAME_MATCH("gc_stress")) {
229 rb_gc_initial_stress_set(Qtrue
);
232 SET_WHEN("core", ruby_enable_coredump
, 1);
233 SET_WHEN("ci", ruby_on_ci
, 1);
234 SET_WHEN_UINT("rgengc", &ruby_rgengc_debug
, 1, ruby_rgengc_debug
= 1);
236 # if RUBY_MSVCRT_VERSION >= 80
237 SET_WHEN("rtc_error", ruby_w32_rtc_error
, 1);
240 #if defined _WIN32 || defined __CYGWIN__
241 SET_WHEN_UINT("codepage", ruby_w32_codepage
, numberof(ruby_w32_codepage
),
242 fprintf(stderr
, "missing codepage argument"));
248 set_debug_option(const char *str
, int len
, void *arg
)
250 if (!ruby_env_debug_option(str
, len
, arg
)) {
251 fprintf(stderr
, "unexpected debug option: %.*s\n", len
, str
);
255 #if USE_RUBY_DEBUG_LOG
256 static void setup_debug_log(void);
258 #define setup_debug_log()
262 ruby_set_debug_option(const char *str
)
264 ruby_each_words(str
, set_debug_option
, 0);
268 #if USE_RUBY_DEBUG_LOG
270 // RUBY_DEBUG_LOG features
271 // See vm_debug.h comments for details.
273 #define MAX_DEBUG_LOG 0x1000
274 #define MAX_DEBUG_LOG_MESSAGE_LEN 0x0200
275 #define MAX_DEBUG_LOG_FILTER_LEN 0x0020
276 #define MAX_DEBUG_LOG_FILTER_NUM 0x0010
278 enum ruby_debug_log_mode ruby_debug_log_mode
;
280 struct debug_log_filter
{
281 enum debug_log_filter_type
{
283 dlf_file
, // "file:..."
284 dlf_func
, // "func:..."
287 char str
[MAX_DEBUG_LOG_FILTER_LEN
];
290 static const char *dlf_type_names
[] = {
297 #define DEBUG_LOG_MAX_PATH (MAX_PATH-1)
299 #define DEBUG_LOG_MAX_PATH 255
305 struct debug_log_filter filters
[MAX_DEBUG_LOG_FILTER_NUM
];
306 unsigned int filters_num
;
308 rb_nativethread_lock_t lock
;
309 char output_file
[DEBUG_LOG_MAX_PATH
+1];
314 RUBY_DEBUG_LOG_MEM_ENTRY(unsigned int index
)
316 return &debug_log
.mem
[MAX_DEBUG_LOG_MESSAGE_LEN
* index
];
319 static enum debug_log_filter_type
320 filter_type(const char *str
, int *skiplen
)
322 if (strncmp(str
, "file:", 5) == 0) {
326 else if(strncmp(str
, "func:", 5) == 0) {
337 setup_debug_log_filter(void)
339 const char *filter_config
= getenv("RUBY_DEBUG_LOG_FILTER");
341 if (filter_config
&& strlen(filter_config
) > 0) {
343 for (i
=0; i
<MAX_DEBUG_LOG_FILTER_NUM
&& filter_config
; i
++) {
345 const char *str
= filter_config
;
348 if ((p
= strchr(str
, ',')) == NULL
) {
350 filter_config
= NULL
;
353 len
= p
- str
- 1; // 1 is ','
354 filter_config
= p
+ 1;
359 debug_log
.filters
[i
].negative
= true;
362 else if (*str
== '+') {
363 // negative is false on default.
369 debug_log
.filters
[i
].type
= filter_type(str
, &skiplen
);
372 if (len
>= MAX_DEBUG_LOG_FILTER_LEN
) {
373 fprintf(stderr
, "too long: %s (max:%d)\n", str
, MAX_DEBUG_LOG_FILTER_LEN
- 1);
378 strncpy(debug_log
.filters
[i
].str
, str
+ skiplen
, len
);
379 debug_log
.filters
[i
].str
[len
] = 0;
381 debug_log
.filters_num
= i
;
383 for (i
=0; i
<debug_log
.filters_num
; i
++) {
384 fprintf(stderr
, "RUBY_DEBUG_LOG_FILTER[%d]=%s (%s%s)\n", i
,
385 debug_log
.filters
[i
].str
,
386 debug_log
.filters
[i
].negative
? "-" : "",
387 dlf_type_names
[debug_log
.filters
[i
].type
]);
393 setup_debug_log(void)
395 // check RUBY_DEBUG_LOG
396 const char *log_config
= getenv("RUBY_DEBUG_LOG");
397 if (log_config
&& strlen(log_config
) > 0) {
398 if (strcmp(log_config
, "mem") == 0) {
399 debug_log
.mem
= (char *)malloc(MAX_DEBUG_LOG
* MAX_DEBUG_LOG_MESSAGE_LEN
);
400 if (debug_log
.mem
== NULL
) {
401 fprintf(stderr
, "setup_debug_log failed (can't allocate memory)\n");
404 ruby_debug_log_mode
|= ruby_debug_log_memory
;
406 else if (strcmp(log_config
, "stderr") == 0) {
407 ruby_debug_log_mode
|= ruby_debug_log_stderr
;
410 ruby_debug_log_mode
|= ruby_debug_log_file
;
412 // pid extension with %p
413 unsigned long len
= strlen(log_config
);
415 for (unsigned long i
=0, j
=0; i
<len
; i
++) {
416 const char c
= log_config
[i
];
420 switch (log_config
[i
]) {
422 debug_log
.output_file
[j
++] = '%';
425 snprintf(debug_log
.output_file
+ j
, DEBUG_LOG_MAX_PATH
- j
, "%d", getpid());
426 j
= strlen(debug_log
.output_file
);
429 fprintf(stderr
, "can not parse RUBY_DEBUG_LOG filename: %s\n", log_config
);
434 debug_log
.output_file
[j
++] = c
;
437 if (j
>= DEBUG_LOG_MAX_PATH
) {
438 fprintf(stderr
, "RUBY_DEBUG_LOG=%s is too long\n", log_config
);
443 if ((debug_log
.output
= fopen(debug_log
.output_file
, "w")) == NULL
) {
444 fprintf(stderr
, "can not open %s for RUBY_DEBUG_LOG\n", log_config
);
447 setvbuf(debug_log
.output
, NULL
, _IONBF
, 0);
450 fprintf(stderr
, "RUBY_DEBUG_LOG=%s %s%s%s\n", log_config
,
451 (ruby_debug_log_mode
& ruby_debug_log_memory
) ? "[mem]" : "",
452 (ruby_debug_log_mode
& ruby_debug_log_stderr
) ? "[stderr]" : "",
453 (ruby_debug_log_mode
& ruby_debug_log_file
) ? "[file]" : "");
454 if (debug_log
.output_file
[0]) {
455 fprintf(stderr
, "RUBY_DEBUG_LOG filename=%s\n", debug_log
.output_file
);
458 rb_nativethread_lock_initialize(&debug_log
.lock
);
460 setup_debug_log_filter();
462 if (getenv("RUBY_DEBUG_LOG_PID")) {
463 debug_log
.show_pid
= true;
469 check_filter(const char *str
, const struct debug_log_filter
*filter
, bool *state
)
471 if (filter
->negative
) {
472 if (strstr(str
, filter
->str
) == NULL
) {
482 if (strstr(str
, filter
->str
) != NULL
) {
494 // RUBY_DEBUG_LOG_FILTER=-foo,-bar,baz,boo
496 // (func_name or file_name) doesn't contain foo
498 // (func_name or file_name) doesn't contain bar
500 // (func_name or file_name) contains baz or boo
502 // RUBY_DEBUG_LOG_FILTER=foo,bar,-baz,-boo
504 // (func_name or file_name) contains foo or bar
506 // (func_name or file_name) doesn't contain baz and
507 // (func_name or file_name) doesn't contain boo and
509 // You can specify "file:" (ex file:foo) or "func:" (ex func:foo)
510 // prefixes to specify the filter for.
513 ruby_debug_log_filter(const char *func_name
, const char *file_name
)
515 if (debug_log
.filters_num
> 0) {
518 for (unsigned int i
= 0; i
<debug_log
.filters_num
; i
++) {
519 const struct debug_log_filter
*filter
= &debug_log
.filters
[i
];
521 switch (filter
->type
) {
523 if (check_filter(func_name
, filter
, &state
)) return state
;
524 if (check_filter(file_name
, filter
, &state
)) return state
;
527 if (check_filter(func_name
, filter
, &state
)) return state
;
530 if (check_filter(file_name
, filter
, &state
)) return state
;
542 pretty_filename(const char *path
)
544 // basename is one idea.
546 while ((s
= strchr(path
, '/')) != NULL
) {
552 #undef ruby_debug_log
554 ruby_debug_log(const char *file
, int line
, const char *func_name
, const char *fmt
, ...)
556 char buff
[MAX_DEBUG_LOG_MESSAGE_LEN
] = {0};
560 if (debug_log
.show_pid
) {
561 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
, "pid:%d\t", getpid());
562 if (r
< 0) rb_bug("ruby_debug_log returns %d", r
);
567 if (func_name
&& len
< MAX_DEBUG_LOG_MESSAGE_LEN
) {
568 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
, "%s\t", func_name
);
569 if (r
< 0) rb_bug("ruby_debug_log returns %d", r
);
574 if (fmt
&& len
< MAX_DEBUG_LOG_MESSAGE_LEN
) {
577 r
= vsnprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
- len
, fmt
, args
);
579 if (r
< 0) rb_bug("ruby_debug_log vsnprintf() returns %d", r
);
583 // optional information
586 if (file
&& len
< MAX_DEBUG_LOG_MESSAGE_LEN
) {
587 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
, "\t%s:%d", pretty_filename(file
), line
);
588 if (r
< 0) rb_bug("ruby_debug_log returns %d", r
);
592 rb_execution_context_t
*ec
= rb_current_execution_context(false);
596 const char *ruby_file
= ec
? rb_source_location_cstr(&ruby_line
) : NULL
;
598 if (len
< MAX_DEBUG_LOG_MESSAGE_LEN
) {
600 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
- len
, "\t%s:%d", pretty_filename(ruby_file
), ruby_line
);
603 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
- len
, "\t");
605 if (r
< 0) rb_bug("ruby_debug_log returns %d", r
);
609 #ifdef RUBY_NT_SERIAL
610 // native thread information
611 if (len
< MAX_DEBUG_LOG_MESSAGE_LEN
) {
612 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
- len
, "\tnt:%d", ruby_nt_serial
);
613 if (r
< 0) rb_bug("ruby_debug_log returns %d", r
);
619 rb_thread_t
*th
= ec
? rb_ec_thread_ptr(ec
) : NULL
;
621 // ractor information
622 if (ruby_single_main_ractor
== NULL
) {
623 rb_ractor_t
*cr
= th
? th
->ractor
: NULL
;
624 rb_vm_t
*vm
= GET_VM();
626 if (r
&& len
< MAX_DEBUG_LOG_MESSAGE_LEN
) {
627 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
- len
, "\tr:#%d/%u (%u)",
628 cr
? (int)rb_ractor_id(cr
) : -1, vm
->ractor
.cnt
, vm
->ractor
.sched
.running_cnt
);
630 if (r
< 0) rb_bug("ruby_debug_log returns %d", r
);
635 // thread information
636 if (th
&& r
&& len
< MAX_DEBUG_LOG_MESSAGE_LEN
) {
637 rb_execution_context_t
*rec
= th
->ractor
? th
->ractor
->threads
.running_ec
: NULL
;
638 const rb_thread_t
*rth
= rec
? rec
->thread_ptr
: NULL
;
639 const rb_thread_t
*sth
= th
->ractor
? th
->ractor
->threads
.sched
.running
: NULL
;
641 if (rth
!= th
|| sth
!= th
) {
642 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
- len
, "\tth:%u (rth:%d,sth:%d)",
643 rb_th_serial(th
), rth
? (int)rb_th_serial(rth
) : -1, sth
? (int)rb_th_serial(sth
) : -1);
646 r
= snprintf(buff
+ len
, MAX_DEBUG_LOG_MESSAGE_LEN
- len
, "\tth:%u", rb_th_serial(th
));
648 if (r
< 0) rb_bug("ruby_debug_log returns %d", r
);
653 rb_nativethread_lock_lock(&debug_log
.lock
);
655 unsigned int cnt
= debug_log
.cnt
++;
657 if (ruby_debug_log_mode
& ruby_debug_log_memory
) {
658 unsigned int index
= cnt
% MAX_DEBUG_LOG
;
659 char *dst
= RUBY_DEBUG_LOG_MEM_ENTRY(index
);
660 strncpy(dst
, buff
, MAX_DEBUG_LOG_MESSAGE_LEN
);
662 if (ruby_debug_log_mode
& ruby_debug_log_stderr
) {
663 fprintf(stderr
, "%4u: %s\n", cnt
, buff
);
665 if (ruby_debug_log_mode
& ruby_debug_log_file
) {
666 fprintf(debug_log
.output
, "%u\t%s\n", cnt
, buff
);
669 rb_nativethread_lock_unlock(&debug_log
.lock
);
674 debug_log_dump(FILE *out
, unsigned int n
)
676 if (ruby_debug_log_mode
& ruby_debug_log_memory
) {
677 unsigned int size
= debug_log
.cnt
> MAX_DEBUG_LOG
? MAX_DEBUG_LOG
: debug_log
.cnt
;
678 unsigned int current_index
= debug_log
.cnt
% MAX_DEBUG_LOG
;
679 if (n
== 0) n
= size
;
680 if (n
> size
) n
= size
;
682 for (unsigned int i
=0; i
<n
; i
++) {
683 int index
= current_index
- size
+ i
;
684 if (index
< 0) index
+= MAX_DEBUG_LOG
;
685 VM_ASSERT(index
<= MAX_DEBUG_LOG
);
686 const char *mesg
= RUBY_DEBUG_LOG_MEM_ENTRY(index
);
687 fprintf(out
, "%4u: %s\n", debug_log
.cnt
- size
+ i
, mesg
);
691 fprintf(stderr
, "RUBY_DEBUG_LOG=mem is not specified.");
698 ruby_debug_log_print(unsigned int n
)
700 debug_log_dump(stderr
, n
);
704 ruby_debug_log_dump(const char *fname
, unsigned int n
)
706 FILE *fp
= fopen(fname
, "w");
708 fprintf(stderr
, "can't open %s. give up.\n", fname
);
711 debug_log_dump(fp
, n
);
715 #endif // #if USE_RUBY_DEBUG_LOG