ruby-dev (Japanese) list archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-dev:49993] メソッド呼び出し時の引数の値を VM 側で取得する方法について
@ 2017-02-28  5:06 Tetsuo Handa
  2017-02-28  5:13 ` [ruby-dev:49994] " SASADA Koichi
  2017-02-28  5:16 ` [ruby-dev:49995] " SASADA Koichi
  0 siblings, 2 replies; 12+ messages in thread
From: Tetsuo Handa @ 2017-02-28  5:06 UTC (permalink / raw
  To: ruby-dev

初めまして。 Linux カーネルプログラマの熊猫と申します。

現在、 Ruby VM に手を加えることで、メソッド呼び出し時の引数の値/メソッドから
復帰する時の戻り値の値を取得する方法を探しています。( SystemTap による
Statically Defined Tracepoints を用いたフックでは、メソッド名は取得できても
値までは取得できないことが判明したため、 Ruby VM に手を加える方法を試している
ところです。)

メソッド呼び出し時のフックを挿入すべき個所の見当は付いており、以下のパッチを
当てれば大抵の呼び出しについては rb_inspect() 呼び出しで引数の値を取得することが
できるようになるのですが、 make 中に実行される特定の rb_inspect() 呼び出しで
プロセスが終了してしまうという謎の挙動に遭遇しているため、開発者の方々に質問
させていただきます。


事象再現手順( CentOS 7 向け)

(1) 普通にソースコードからコンパイルします。

----------------------------------------
# yumdownloader --source ruby
# rpm --checksig ruby-2.0.0.648-29.el7.src.rpm
# yum-builddep -y ruby-2.0.0.648-29.el7.src.rpm
# rpm -ivh ruby-2.0.0.648-29.el7.src.rpm
# rpmbuild -bb ~/rpmbuild/SPECS/ruby.spec
(中略。テスト途中で無応答になるものがありますが本題ではないので省略します。)
make: *** [yes-test-all] Error 63
error: Bad exit status from /var/tmp/rpm-tmp.1xpTWi (%check)


RPM build errors:
    Bad exit status from /var/tmp/rpm-tmp.1xpTWi (%check)
----------------------------------------

(2) 以下のパッチを当てて再コンパイルします。

----------------------------------------
# cd ~/rpmbuild/BUILD/ruby-2.0.0-p648/
# patch -p1
--- ruby-2.0.0-p648.orig/vm_insnhelper.c
+++ ruby-2.0.0-p648/vm_insnhelper.c
@@ -1295,6 +1295,58 @@ vm_call_iseq_setup_2(rb_thread_t *th, rb
     }
 }
 
+/* ///// */
+static void dump_function_entry(rb_thread_t *th, int argc, VALUE *argv)
+{
+    static FILE *fp = NULL;
+    static __thread _Bool dump_recurse = 0;
+    VALUE _klass = 0;
+    VALUE _id = 0;
+    if (dump_recurse)
+	return;
+    dump_recurse = 1;
+    if (!fp)
+	fp = fopen("/tmp/ruby.log", "a");
+    rb_thread_method_id_and_class((th), &_id, &_klass);
+    if (!_klass || !fp) {
+	dump_recurse = 0;
+	return;
+    }
+    if (RB_TYPE_P(_klass, T_ICLASS))
+	_klass = RBASIC(_klass)->klass;
+    else if (FL_TEST(_klass, FL_SINGLETON))
+	_klass = rb_iv_get(_klass, "__attached__");
+    switch (TYPE(_klass)) {
+    case T_CLASS:
+    case T_ICLASS:
+    case T_MODULE:
+	{
+	    int i;
+	    VALUE _name = rb_class_path_no_cache(_klass);
+	    const char *classname = !NIL_P(_name) ? StringValuePtr(_name) : "<unknown>";
+	    const char *methodname = rb_id2name(_id);
+	    const char *filename = rb_sourcefile();
+	    fprintf(fp, "class=%s method=%s filename=%s line=%u argc=%u",
+		    classname, methodname, filename, rb_sourceline(), argc);
+	    fflush(fp);
+	    for (i = 0; i < argc; i++) {
+		VALUE rstr;
+		fprintf(fp, " argv[%u](%lx)", i, argv[i]);
+		fflush(fp);
+		rstr = rb_inspect(argv[i]);
+		fprintf(fp, "=");
+		fflush(fp);
+		fprintf(fp, "%s", StringValueCStr(rstr));
+		fflush(fp);
+	    }
+	    fprintf(fp, "\n");
+	    fflush(fp);
+	    break;
+	}
+    }
+    dump_recurse = 0;
+}
+
 static inline VALUE
 vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
 {
@@ -1313,6 +1365,7 @@ vm_call_iseq_setup_normal(rb_thread_t *t
     vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class,
 		  VM_ENVVAL_BLOCK_PTR(ci->blockptr),
 		  iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me);
+    dump_function_entry(th, ci->argc, argv);
 
     cfp->sp = argv - 1 /* recv */;
     return Qundef;
@@ -1352,6 +1405,7 @@ vm_call_iseq_setup_tailcall(rb_thread_t
     vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
 		  ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr),
 		  iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me);
+    dump_function_entry(th, ci->argc, argv);
 
     cfp->sp = sp_orig;
     return Qundef;
(ここまでコピペしたら Ctrl-D を押します。)
patching file vm_insnhelper.c
# make
(中略)
Generating RDoc documentation
Parsing sources...
Before reporting this, could you check that the file you're documenting
has proper syntax:

  /usr/bin/ruby -c prelude.c

RDoc is not a full Ruby parser and will fail when fed invalid ruby programs.

The internal error was:

        (TypeError) no implicit conversion of nil into String

/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb:111:in `basename'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb:111:in `base_name'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb:175:in `inspect'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context/section.rb:41:in `initialize'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context.rb:128:in `new'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context.rb:128:in `initialize'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb:43:in `initialize'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/store.rb:181:in `new'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/store.rb:181:in `add_file'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:358:in `parse_file'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:417:in `block in parse_files'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:415:in `map'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:415:in `parse_files'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:485:in `document'
        ./bin/rdoc:20:in `<main>'
no implicit conversion of nil into String
/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb:111:in `basename'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb:111:in `base_name'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb:175:in `inspect'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context/section.rb:41:in `initialize'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context.rb:128:in `new'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context.rb:128:in `initialize'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb:43:in `initialize'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/store.rb:181:in `new'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/store.rb:181:in `add_file'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:358:in `parse_file'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:417:in `block in parse_files'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:415:in `map'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:415:in `parse_files'
        /root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/rdoc.rb:485:in `document'
        ./bin/rdoc:20:in `<main>'

make: *** [rdoc] Error 1
----------------------------------------

ログを確認すると、 = の前で終了していることから、 rb_inspect(argv[0]) の
呼び出しの中でプロセスが終了していると判断できます。

----------------------------------------
# tail /tmp/ruby.log
class=Pathname method=chop_basename filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/.ext/common/pathname.rb line=43 argc=1 argv[0](182b8c8)="/root/rpmbuild/BUILD/"
class=Pathname method=chop_basename filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/.ext/common/pathname.rb line=43 argc=1 argv[0](182b710)="/root/rpmbuild/"
class=Pathname method=chop_basename filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/.ext/common/pathname.rb line=43 argc=1 argv[0](182b580)="/root/"
class=Pathname method=chop_basename filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/.ext/common/pathname.rb line=43 argc=1 argv[0](182b440)="/"
class=RDoc::Store method=add_file filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/store.rb line=179 argc=2 argv[0](180c3b0)="prelude.c" argv[1](182b148)="prelude.c"
class=RDoc::TopLevel method=initialize filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb line=42 argc=2 argv[0](180c3b0)="prelude.c" argv[1](182b148)="prelude.c"
class=RDoc::Context method=initialize filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context.rb line=119 argc=0
class=RDoc::CodeObject method=initialize filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/code_object.rb line=107 argc=0
class=RDoc::CodeObject method=initialize_visibility filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/code_object.rb line=125 argc=0
class=RDoc::Context::Section method=initialize filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context/section.rb line=41 argc=3 argv[0](182b0a8)
----------------------------------------

lib/rdoc/context/section.rb の 41 行目は以下のメソッド呼び出しです。

----------------------------------------
  ##
  # Creates a new section with +title+ and +comment+

  def initialize parent, title, comment
    @parent = parent
    @title = title ? title.strip : title

    @@sequence.succ!
    @sequence = @@sequence.dup

    @comments = []

    add_comment comment
  end
----------------------------------------

182b0a8 という argv[0] の VALUE は、直前の呼び出しで渡されている VALUE と
比べて不自然な感じはしないため、何故コケるのか判断できないでいます。
パッチに問題がある(排他制御が必要? argc として渡している変数または
argv として渡しているポインタが間違っている?)ということでしょうか?

よろしくお願いします。

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:49994] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-02-28  5:06 [ruby-dev:49993] メソッド呼び出し時の引数の値を VM 側で取得する方法について Tetsuo Handa
@ 2017-02-28  5:13 ` SASADA Koichi
  2017-02-28  5:47   ` [ruby-dev:49996] " Tetsuo Handa
  2017-02-28  5:16 ` [ruby-dev:49995] " SASADA Koichi
  1 sibling, 1 reply; 12+ messages in thread
From: SASADA Koichi @ 2017-02-28  5:13 UTC (permalink / raw
  To: Ruby developers (Japanese)

On 2017/02/28 14:06, Tetsuo Handa wrote:
> 現在、 Ruby VM に手を加えることで、メソッド呼び出し時の引数の値/メソッドから
> 復帰する時の戻り値の値を取得する方法を探しています。

まず、後者から。TracePoint#return_value にて採れますので、そのあたりの
コードをチェックされると良いと思います。

引数については、全部をチェックする方法はありませんが、例えば rb_inspect
が問題であるのなら、rb_obj_info_dump() や rb_raw_obj_info() を使うと、
inspect 呼び出しをせずに、全部じゃないですが、なんとなく値を取得すること
が可能です。

これらは、Ruby 的な正攻法では、TracePoint を利用して下さい、ということに
なるかと思いますが、Ruby を弄るようでしたら、これらも選択肢ということで。

用途がはっきりわかると、もう少し何か言えるかもしれません。

-- 
// SASADA Koichi at atdot dot net

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:49995] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-02-28  5:06 [ruby-dev:49993] メソッド呼び出し時の引数の値を VM 側で取得する方法について Tetsuo Handa
  2017-02-28  5:13 ` [ruby-dev:49994] " SASADA Koichi
@ 2017-02-28  5:16 ` SASADA Koichi
  2017-02-28  5:53   ` [ruby-dev:49997] " Tetsuo Handa
  1 sibling, 1 reply; 12+ messages in thread
From: SASADA Koichi @ 2017-02-28  5:16 UTC (permalink / raw
  To: Ruby developers (Japanese)

On 2017/02/28 14:06, Tetsuo Handa wrote:
> @@ -1352,6 +1405,7 @@ vm_call_iseq_setup_tailcall(rb_thread_t
>      vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
>  		  ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr),
>  		  iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me);
> +    dump_function_entry(th, ci->argc, argv);
>  
>      cfp->sp = sp_orig;
>      return Qundef;

肝心のパッチですが、cfp->sp = sp_orig; の後に dump_function_entry() を呼
んだ方がいいかも。ちゃんと動かしてないので勘ですが。

-- 
// SASADA Koichi at atdot dot net

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:49996] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-02-28  5:13 ` [ruby-dev:49994] " SASADA Koichi
@ 2017-02-28  5:47   ` Tetsuo Handa
  2017-02-28  7:50     ` [ruby-dev:49998] " SASADA Koichi
  0 siblings, 1 reply; 12+ messages in thread
From: Tetsuo Handa @ 2017-02-28  5:47 UTC (permalink / raw
  To: ruby-dev, ko1

SASADA さん、早速の回答ありがとうございます。

SASADA Koichi さんは書きました:
> On 2017/02/28 14:06, Tetsuo Handa wrote:
> > 現在、 Ruby VM に手を加えることで、メソッド呼び出し時の引数の値/メソッドから
> > 復帰する時の戻り値の値を取得する方法を探しています。
> 
> まず、後者から。TracePoint#return_value にて採れますので、そのあたりの
> コードをチェックされると良いと思います。

TracePoint では .rb ファイルの側からAPIを呼び出すための修正が
必要ですよね?下記の理由により、 .rb ファイルに対する変更は避けたいです。

> 
> 引数については、全部をチェックする方法はありませんが、例えば rb_inspect
> が問題であるのなら、rb_obj_info_dump() や rb_raw_obj_info() を使うと、
> inspect 呼び出しをせずに、全部じゃないですが、なんとなく値を取得すること
> が可能です。

ruby-2.0.0 には rb_obj_info_dump() も rb_raw_obj_info() も存在しないようです。

> 
> これらは、Ruby 的な正攻法では、TracePoint を利用して下さい、ということに
> なるかと思いますが、Ruby を弄るようでしたら、これらも選択肢ということで。
> 
> 用途がはっきりわかると、もう少し何か言えるかもしれません。

イベントのシーケンスを用いた侵入検知システム(WAF)の研究です。
カーネルレイヤではシステムコールに渡される引数を、アプリケーション
レイヤでは関数呼び出しに渡される引数を追跡し、発生する筈のない
シーケンスが渡されたら攻撃と判断するというものです。そのため、
オブジェクトとしてメソッドに渡される引数の内容(例: HTTP リクエストや
レスポンス)を、スクリプトに対して特定のAPIを呼び出すための修正を
要求せず、かつ、パフォーマンス以外には動作への影響が出ないように
取得したいと考えています。

> 
> -- 
> // SASADA Koichi at atdot dot net
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:49997] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-02-28  5:16 ` [ruby-dev:49995] " SASADA Koichi
@ 2017-02-28  5:53   ` Tetsuo Handa
  2017-02-28  7:56     ` [ruby-dev:49999] " SASADA Koichi
  0 siblings, 1 reply; 12+ messages in thread
From: Tetsuo Handa @ 2017-02-28  5:53 UTC (permalink / raw
  To: ruby-dev, ko1

SASADA Koichi さんは書きました:
> On 2017/02/28 14:06, Tetsuo Handa wrote:
> > @@ -1352,6 +1405,7 @@ vm_call_iseq_setup_tailcall(rb_thread_t
> >      vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
> >  		  ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr),
> >  		  iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me);
> > +    dump_function_entry(th, ci->argc, argv);
> >  
> >      cfp->sp = sp_orig;
> >      return Qundef;
> 
> 肝心のパッチですが、cfp->sp = sp_orig; の後に dump_function_entry() を呼
> んだ方がいいかも。ちゃんと動かしてないので勘ですが。
> 
> -- 
> // SASADA Koichi at atdot dot net
> 

dump_function_entry() 呼び出しを cfp->sp の設定後に移動させてみましたが、
同じ結果でした。 rb_inspect() に渡すことができないオブジェクトが存在するのでしょうか?

----------------------------------------
# tail /tmp/ruby.log
class=Pathname method=chop_basename filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/.ext/common/pathname.rb line=43 argc=1 argv[0](30a7960)="/root/rpmbuild/BUILD/"
class=Pathname method=chop_basename filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/.ext/common/pathname.rb line=43 argc=1 argv[0](30a77d0)="/root/rpmbuild/"
class=Pathname method=chop_basename filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/.ext/common/pathname.rb line=43 argc=1 argv[0](30a7618)="/root/"
class=Pathname method=chop_basename filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/.ext/common/pathname.rb line=43 argc=1 argv[0](30a74d8)="/"
class=RDoc::Store method=add_file filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/store.rb line=179 argc=2 argv[0](3088448)="prelude.c" argv[1](30a71e0)="prelude.c"
class=RDoc::TopLevel method=initialize filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/top_level.rb line=42 argc=2 argv[0](3088448)="prelude.c" argv[1](30a71e0)="prelude.c"
class=RDoc::Context method=initialize filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context.rb line=119 argc=0
class=RDoc::CodeObject method=initialize filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/code_object.rb line=107 argc=0
class=RDoc::CodeObject method=initialize_visibility filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/code_object.rb line=125 argc=0
class=RDoc::Context::Section method=initialize filename=/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context/section.rb line=41 argc=3 argv[0](30a7140)
----------------------------------------

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:49998] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-02-28  5:47   ` [ruby-dev:49996] " Tetsuo Handa
@ 2017-02-28  7:50     ` SASADA Koichi
  0 siblings, 0 replies; 12+ messages in thread
From: SASADA Koichi @ 2017-02-28  7:50 UTC (permalink / raw
  To: ruby-dev

On 2017/02/28 14:47, Tetsuo Handa wrote:
>> まず、後者から。TracePoint#return_value にて採れますので、そのあたりの
>> コードをチェックされると良いと思います。
> 
> TracePoint では .rb ファイルの側からAPIを呼び出すための修正が
> 必要ですよね?下記の理由により、 .rb ファイルに対する変更は避けたいです。

いえ、意図としては、return_value メソッドをどう実装しているか見るのはど
うでしょうか、という提案でした。

>> 引数については、全部をチェックする方法はありませんが、例えば rb_inspect
>> が問題であるのなら、rb_obj_info_dump() や rb_raw_obj_info() を使うと、
>> inspect 呼び出しをせずに、全部じゃないですが、なんとなく値を取得すること
>> が可能です。
> 
> ruby-2.0.0 には rb_obj_info_dump() も rb_raw_obj_info() も存在しないようです。

なるほど!
2.1 以降(できれば、最新版)を参考にされるのも良いかもしれません。

>> これらは、Ruby 的な正攻法では、TracePoint を利用して下さい、ということに
>> なるかと思いますが、Ruby を弄るようでしたら、これらも選択肢ということで。
>>
>> 用途がはっきりわかると、もう少し何か言えるかもしれません。
> 
> イベントのシーケンスを用いた侵入検知システム(WAF)の研究です。
> カーネルレイヤではシステムコールに渡される引数を、アプリケーション
> レイヤでは関数呼び出しに渡される引数を追跡し、発生する筈のない
> シーケンスが渡されたら攻撃と判断するというものです。そのため、
> オブジェクトとしてメソッドに渡される引数の内容(例: HTTP リクエストや
> レスポンス)を、スクリプトに対して特定のAPIを呼び出すための修正を
> 要求せず、かつ、パフォーマンス以外には動作への影響が出ないように
> 取得したいと考えています。

なるほど。本当は(おそらくライブラリの) .rb 側にモンキーパッチを入れる
のが適切な気がしますね。シーケンスだけなら、method id だけでも良さそうで
すが、パラメータはどの辺で必要になるんでしょうか(ちょっと、脱線になっ
ちゃいますが)。

-- 
// SASADA Koichi at atdot dot net

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:49999] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-02-28  5:53   ` [ruby-dev:49997] " Tetsuo Handa
@ 2017-02-28  7:56     ` SASADA Koichi
  2017-03-01 11:28       ` [ruby-dev:50000] " Tetsuo Handa
  0 siblings, 1 reply; 12+ messages in thread
From: SASADA Koichi @ 2017-02-28  7:56 UTC (permalink / raw
  To: ruby-dev

On 2017/02/28 14:53, Tetsuo Handa wrote:
> dump_function_entry() 呼び出しを cfp->sp の設定後に移動させてみましたが、
> 同じ結果でした。 rb_inspect() に渡すことができないオブジェクトが存在するのでしょうか?

うーん、そんなことはないと思うんですが、そういうこともあるのかもしれませ
ん。これ以上はちゃんとデバッグしないとわかんないっすね...。

-- 
// SASADA Koichi at atdot dot net

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:50000] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-02-28  7:56     ` [ruby-dev:49999] " SASADA Koichi
@ 2017-03-01 11:28       ` Tetsuo Handa
  2017-03-02  6:37         ` [ruby-dev:50001] " Nobuyoshi Nakada
  0 siblings, 1 reply; 12+ messages in thread
From: Tetsuo Handa @ 2017-03-01 11:28 UTC (permalink / raw
  To: ruby-dev, ko1

SASADA Koichi さんは書きました:
> On 2017/02/28 14:53, Tetsuo Handa wrote:
> > dump_function_entry() 呼び出しを cfp->sp の設定後に移動させてみましたが、
> > 同じ結果でした。 rb_inspect() に渡すことができないオブジェクトが存在するのでしょうか?
> 
> うーん、そんなことはないと思うんですが、そういうこともあるのかもしれませ
> ん。これ以上はちゃんとデバッグしないとわかんないっすね...。
> 
git のソースに対して同様の処理を試したところ、 core ファイルを取得できました。
以下に事象の再現手順を示します。何か手がかりが得られそうでしょうか?

(1) 普通にコンパイルする。

----------------------------------------
# git clone git://github.com/ruby/ruby.git
# cd ruby/
# autoconf
# ./configure
# make
----------------------------------------

(2) 以下のパッチを当てて再コンパイルする。

----------------------------------------
# patch -p1
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 9e8ea9c..09b3fb2 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1503,6 +1503,78 @@ vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling
     }
 }
 
+/* ///// */
+VALUE rb_class_path_no_cache(VALUE _klass);
+static void dump_function_entry(rb_thread_t *th, int argc, VALUE *argv)
+{
+    static FILE *fp = NULL;
+    static __thread _Bool dump_recurse = 0;
+    VALUE _klass = 0;
+    VALUE _id = 0;
+    if (dump_recurse)
+	return;
+    dump_recurse = 1;
+    if (!fp)
+	fp = fopen("/tmp/ruby.log", "a");
+    rb_thread_method_id_and_class((th), &_id, 0, &_klass);
+    if (!_klass || !fp) {
+	dump_recurse = 0;
+	return;
+    }
+    if (RB_TYPE_P(_klass, T_ICLASS))
+	_klass = RBASIC(_klass)->klass;
+    else if (FL_TEST(_klass, FL_SINGLETON))
+	_klass = rb_iv_get(_klass, "__attached__");
+    switch (TYPE(_klass)) {
+    case T_CLASS:
+    case T_ICLASS:
+    case T_MODULE:
+	{
+	    int i;
+	    VALUE _name = rb_class_path_no_cache(_klass);
+	    const char *classname = !NIL_P(_name) ? StringValuePtr(_name) : "<unknown>";
+	    const char *methodname = rb_id2name(_id);
+	    const char *filename = rb_sourcefile();
+	    fprintf(fp, "class=%s method=%s filename=%s line=%u argc=%u",
+		    classname, methodname, filename, rb_sourceline(), argc);
+	    fflush(fp);
+	    for (i = 0; i < argc; i++) {
+		VALUE rstr;
+		/*
+		switch (TYPE(argv[i])) {
+		case T_CLASS:
+		case T_FLOAT:
+		case T_STRING:
+		case T_REGEXP:
+		case T_ARRAY:
+		case T_HASH:
+		case T_STRUCT:
+		case T_BIGNUM:
+		case T_DATA:
+		case T_COMPLEX:
+		case T_RATIONAL:
+		case T_SYMBOL:
+		    break;
+		default:
+		    continue;
+		}
+		*/
+		fprintf(fp, " argv[%u,%u]", i, TYPE(argv[i]));
+		fflush(fp);
+		rstr = rb_inspect(argv[i]);
+		fprintf(fp, "=");
+		fflush(fp);
+		fprintf(fp, "%s", StringValueCStr(rstr));
+		fflush(fp);
+	    }
+	    fprintf(fp, "\n");
+	    fflush(fp);
+	    break;
+	}
+    }
+    dump_recurse = 0;
+}
+
 static inline VALUE
 vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc,
 			  int opt_pc, int param_size, int local_size)
@@ -1518,6 +1590,7 @@ vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_ca
 		  iseq->body->iseq_encoded + opt_pc, sp,
 		  local_size - param_size,
 		  iseq->body->stack_max);
+    dump_function_entry(th, calling->argc, argv);
     return Qundef;
 }
 
@@ -1564,6 +1637,7 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_
 		  iseq->body->iseq_encoded + opt_pc, sp,
 		  iseq->body->local_table_size - iseq->body->param.size,
 		  iseq->body->stack_max);
+    dump_function_entry(th, calling->argc, argv);
 
     cfp->sp = sp_orig;
     RUBY_VM_CHECK_INTS(th);
# ulimit -c unlimited
# make
        CC = gcc
        LD = ld
        LDSHARED = gcc -shared
        CFLAGS = -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wno-tautological-compare -Wno-parentheses-equality -Wno-constant-logical-operand -Wno-self-assign -Wunused-variable -Werror=implicit-int -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=implicit-function-declaration -Werror=deprecated-declarations -Wno-packed-bitfield-compat -Wsuggest-attribute=noreturn -Wsuggest-attribute=format -std=gnu99
        XCFLAGS = -D_FORTIFY_SOURCE=2 -fstack-protector -fno-strict-overflow -fvisibility=hidden -fexcess-precision=standard -DRUBY_EXPORT -fPIE
        CPPFLAGS =   -I. -I.ext/include/x86_64-linux -I./include -I. -I./enc/unicode/9.0.0
        DLDFLAGS = -fstack-protector -pie
        SOLIBS =
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

compiling vm.c
linking miniruby
generating encdb.h
/root/ruby/lib/optparse.rb:655: [BUG] Segmentation fault at 0x000000000074f9
ruby 2.5.0dev (2017-03-01 trunk 57751) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0013 p:---- s:0100 e:000099 CFUNC  :to_s
c:0012 p:0000 s:0097 e:000096 METHOD /root/ruby/lib/optparse.rb:655
c:0011 p:0099 s:0092 e:000091 METHOD /root/ruby/lib/optparse.rb:496
c:0010 p:0858 s:0086 E:000868 BLOCK  /root/ruby/lib/optparse.rb:1409 [FINISH]
c:0009 p:---- s:0082 e:000081 CFUNC  :each
c:0008 p:0101 s:0078 E:002560 METHOD /root/ruby/lib/optparse.rb:1341
c:0007 p:0016 s:0052 e:000050 METHOD /root/ruby/lib/optparse.rb:1466
c:0006 p:0015 s:0044 e:000043 METHOD /root/ruby/lib/optparse.rb:1475
c:0005 p:0014 s:0038 E:001198 BLOCK  ./tool/generic_erb.rb:20
c:0004 p:0109 s:0034 e:000033 METHOD /root/ruby/lib/optparse.rb:1062 [FINISH]
c:0003 p:---- s:0027 e:000026 CFUNC  :new
c:0002 p:0109 s:0023 E:0024f8 EVAL   ./tool/generic_erb.rb:19 [FINISH]
c:0001 p:0000 s:0003 E:000790 (none) [FINISH]

-- Ruby level backtrace information ----------------------------------------
./tool/generic_erb.rb:19:in `<main>'
./tool/generic_erb.rb:19:in `new'
/root/ruby/lib/optparse.rb:1062:in `initialize'
./tool/generic_erb.rb:20:in `block in <main>'
/root/ruby/lib/optparse.rb:1475:in `on'
/root/ruby/lib/optparse.rb:1466:in `define'
/root/ruby/lib/optparse.rb:1341:in `make_switch'
/root/ruby/lib/optparse.rb:1341:in `each'
/root/ruby/lib/optparse.rb:1409:in `block in make_switch'
/root/ruby/lib/optparse.rb:496:in `guess'
/root/ruby/lib/optparse.rb:655:in `incompatible_argument_styles'
/root/ruby/lib/optparse.rb:655:in `to_s'

-- Machine register context ------------------------------------------------
 RIP: 0x00007f9ada3f2e88 RBP: 0x00007f9adad1c500 RSP: 0x00007ffc19a801d0
 RAX: 0x00000000000074f1 RBX: 0x00007f9adad1c500 RCX: 0x0000000000000000
 RDX: 0x000000000000001a RDI: 0x00007f9adad1c500 RSI: 0x00000000000072e1
  R8: 0x00007f9ada1e4dd0  R9: 0x0000000000000001 R10: 0x00007ffc19a802e0
 R11: 0x0000000000000000 R12: 0x0000000000000008 R13: 0x00007f9adad1c500
 R14: 0x00007f9adabab810 R15: 0x0000000000000000 EFL: 0x0000000000010206

-- C level backtrace information -------------------------------------------
/root/ruby/miniruby(rb_vm_bugreport+0x528) [0x7f9ada41bb78] vm_dump.c:683
/root/ruby/miniruby(rb_bug_context+0xd0) [0x7f9ada28fa60] error.c:502
/root/ruby/miniruby(sigsegv+0x3e) [0x7f9ada389d6e] signal.c:907
/lib64/libpthread.so.0 [0x7f9ad9dc6370]
/root/ruby/miniruby(rb_class_name+0x28) [0x7f9ada3f2e88] variable.c:186
/root/ruby/miniruby(rb_mod_to_s+0xf0) [0x7f9ada306990] object.c:1577
/root/ruby/miniruby(vm_call0_body.constprop.140+0x1ca) [0x7f9ada40e9ba] vm_eval.c:131
/root/ruby/miniruby(rb_call0+0x1b8) [0x7f9ada40f7a8] vm_eval.c:61
/root/ruby/miniruby(rb_inspect+0x14) [0x7f9ada306824] object.c:553
/root/ruby/miniruby(dump_function_entry.isra.118+0x198) [0x7f9ada401108] vm_insnhelper.c:1564
/root/ruby/miniruby(vm_call_iseq_setup+0x290) [0x7f9ada401530] vm_insnhelper.c:1593
/root/ruby/miniruby(vm_call_method+0xe3) [0x7f9ada40ce93] vm_insnhelper.c:2376
/root/ruby/miniruby(vm_exec_core+0x2241) [0x7f9ada406591] insns.def:1066
/root/ruby/miniruby(vm_exec+0x87) [0x7f9ada40ab77] vm.c:1705
/root/ruby/miniruby(rb_yield+0x5df) [0x7f9ada4155ff] vm.c:962
/root/ruby/miniruby(rb_ary_each+0x3d) [0x7f9ada21bc3d] array.c:1824
/root/ruby/miniruby(vm_call_cfunc+0xf1) [0x7f9ada3fcd81] vm_insnhelper.c:1836
/root/ruby/miniruby(vm_call_method+0xe3) [0x7f9ada40ce93] vm_insnhelper.c:2376
/root/ruby/miniruby(vm_exec_core+0x2f80) [0x7f9ada4072d0] insns.def:967
/root/ruby/miniruby(vm_exec+0x87) [0x7f9ada40ab77] vm.c:1705
/root/ruby/miniruby(rb_call0+0x1b8) [0x7f9ada40f7a8] vm_eval.c:61
/root/ruby/miniruby(rb_class_s_new+0x21) [0x7f9ada306cd1] object.c:1935
/root/ruby/miniruby(vm_call_cfunc+0xf1) [0x7f9ada3fcd81] vm_insnhelper.c:1836
/root/ruby/miniruby(vm_call_method+0xe3) [0x7f9ada40ce93] vm_insnhelper.c:2376
/root/ruby/miniruby(vm_exec_core+0x2f80) [0x7f9ada4072d0] insns.def:967
/root/ruby/miniruby(vm_exec+0x87) [0x7f9ada40ab77] vm.c:1705
/root/ruby/miniruby(ruby_exec_internal+0xad) [0x7f9ada295b3d] eval.c:244
/root/ruby/miniruby(ruby_run_node+0x2d) [0x7f9ada29907d] eval.c:308
/root/ruby/miniruby(main+0x4b) [0x7f9ada21a13b] addr2line.c:177

-- Other runtime information -----------------------------------------------

* Loaded script: ./tool/generic_erb.rb

* Loaded features:

    0 enumerator.so
    1 thread.rb
    2 rational.so
    3 complex.so
    4 /root/ruby/lib/cgi/util.rb
    5 /root/ruby/lib/erb.rb
    6 /root/ruby/lib/optparse.rb
    7 /root/ruby/lib/fileutils.rb
    8 /root/ruby/tool/vpath.rb

* Process memory map:

7f9ad17fc000-7f9ad1a02000 r--s 00000000 fd:01 67151207                   /usr/lib64/libc-2.17.so
7f9ad1a02000-7f9ad2977000 r--s 00000000 fd:01 687169                     /root/ruby/miniruby
7f9ad2977000-7f9ad298c000 r-xp 00000000 fd:01 69752800                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f9ad298c000-7f9ad2b8b000 ---p 00015000 fd:01 69752800                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f9ad2b8b000-7f9ad2b8c000 r--p 00014000 fd:01 69752800                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f9ad2b8c000-7f9ad2b8d000 rw-p 00015000 fd:01 69752800                   /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f9ad2b8d000-7f9ad90b6000 r--p 00000000 fd:01 100675358                  /usr/lib/locale/locale-archive
7f9ad90b6000-7f9ad90b8000 r-xp 00000000 fd:01 67151197                   /usr/lib64/libfreebl3.so
7f9ad90b8000-7f9ad92b7000 ---p 00002000 fd:01 67151197                   /usr/lib64/libfreebl3.so
7f9ad92b7000-7f9ad92b8000 r--p 00001000 fd:01 67151197                   /usr/lib64/libfreebl3.so
7f9ad92b8000-7f9ad92b9000 rw-p 00002000 fd:01 67151197                   /usr/lib64/libfreebl3.so
7f9ad92b9000-7f9ad946f000 r-xp 00000000 fd:01 67151207                   /usr/lib64/libc-2.17.so
7f9ad946f000-7f9ad966f000 ---p 001b6000 fd:01 67151207                   /usr/lib64/libc-2.17.so
7f9ad966f000-7f9ad9673000 r--p 001b6000 fd:01 67151207                   /usr/lib64/libc-2.17.so
7f9ad9673000-7f9ad9675000 rw-p 001ba000 fd:01 67151207                   /usr/lib64/libc-2.17.so
7f9ad9675000-7f9ad967a000 rw-p 00000000 00:00 0
7f9ad967a000-7f9ad977a000 r-xp 00000000 fd:01 67151567                   /usr/lib64/libm-2.17.so
7f9ad977a000-7f9ad997a000 ---p 00100000 fd:01 67151567                   /usr/lib64/libm-2.17.so
7f9ad997a000-7f9ad997b000 r--p 00100000 fd:01 67151567                   /usr/lib64/libm-2.17.so
7f9ad997b000-7f9ad997c000 rw-p 00101000 fd:01 67151567                   /usr/lib64/libm-2.17.so
7f9ad997c000-7f9ad9984000 r-xp 00000000 fd:01 67151261                   /usr/lib64/libcrypt-2.17.so
7f9ad9984000-7f9ad9b83000 ---p 00008000 fd:01 67151261                   /usr/lib64/libcrypt-2.17.so
7f9ad9b83000-7f9ad9b84000 r--p 00007000 fd:01 67151261                   /usr/lib64/libcrypt-2.17.so
7f9ad9b84000-7f9ad9b85000 rw-p 00008000 fd:01 67151261                   /usr/lib64/libcrypt-2.17.so
7f9ad9b85000-7f9ad9bb3000 rw-p 00000000 00:00 0
7f9ad9bb3000-7f9ad9bb5000 r-xp 00000000 fd:01 67151265                   /usr/lib64/libdl-2.17.so
7f9ad9bb5000-7f9ad9db5000 ---p 00002000 fd:01 67151265                   /usr/lib64/libdl-2.17.so
7f9ad9db5000-7f9ad9db6000 r--p 00002000 fd:01 67151265                   /usr/lib64/libdl-2.17.so
7f9ad9db6000-7f9ad9db7000 rw-p 00003000 fd:01 67151265                   /usr/lib64/libdl-2.17.so
7f9ad9db7000-7f9ad9dce000 r-xp 00000000 fd:01 67151686                   /usr/lib64/libpthread-2.17.so
7f9ad9dce000-7f9ad9fcd000 ---p 00017000 fd:01 67151686                   /usr/lib64/libpthread-2.17.so
7f9ad9fcd000-7f9ad9fce000 r--p 00016000 fd:01 67151686                   /usr/lib64/libpthread-2.17.so
7f9ad9fce000-7f9ad9fcf000 rw-p 00017000 fd:01 67151686                   /usr/lib64/libpthread-2.17.so
7f9ad9fcf000-7f9ad9fd3000 rw-p 00000000 00:00 0
7f9ad9fd3000-7f9ad9ff3000 r-xp 00000000 fd:01 67151200                   /usr/lib64/ld-2.17.so
7f9ada0ba000-7f9ada0de000 r--s 00000000 fd:01 67151686                   /usr/lib64/libpthread-2.17.so
7f9ada0de000-7f9ada0e5000 r--s 00000000 fd:01 118432                     /usr/lib64/gconv/gconv-modules.cache
7f9ada0e5000-7f9ada1ec000 rw-p 00000000 00:00 0
7f9ada1ec000-7f9ada1ed000 rw-p 00000000 00:00 0
7f9ada1ed000-7f9ada1ee000 ---p 00000000 00:00 0
7f9ada1ee000-7f9ada1f2000 rw-p 00000000 00:00 0                          [stack:20783]
7f9ada1f2000-7f9ada1f3000 r--p 0001f000 fd:01 67151200                   /usr/lib64/ld-2.17.so
7f9ada1f3000-7f9ada1f4000 rw-p 00020000 fd:01 67151200                   /usr/lib64/ld-2.17.so
7f9ada1f4000-7f9ada1f5000 rw-p 00000000 00:00 0
7f9ada1f5000-7f9ada4f9000 r-xp 00000000 fd:01 687169                     /root/ruby/miniruby
7f9ada6f8000-7f9ada6fd000 r--p 00303000 fd:01 687169                     /root/ruby/miniruby
7f9ada6fd000-7f9ada6fe000 rw-p 00308000 fd:01 687169                     /root/ruby/miniruby
7f9ada6fe000-7f9ada710000 rw-p 00000000 00:00 0
7f9adab48000-7f9adadf9000 rw-p 00000000 00:00 0                          [heap]
7ffc19284000-7ffc19a83000 rw-p 00000000 00:00 0
7ffc19bb8000-7ffc19bba000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html

make: *** [encdb.h] Aborted (core dumped)
# gdb miniruby core.20782
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/ruby/miniruby...done.
[New LWP 20782]
[New LWP 20783]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `./miniruby -I./lib -I. -I.ext/common ./tool/generic_erb.rb -c -o encdb.h ./temp'.
Program terminated with signal 6, Aborted.
#0  0x00007f9ad92ee1d7 in __GI_raise (sig=sig@entry=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56        return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
warning: File "/root/ruby/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load:/usr/bin/mono-gdb.py".
To enable execution of this file add
        add-auto-load-safe-path /root/ruby/.gdbinit
line to your configuration file "/root/.gdbinit".
To completely disable this security protection add
        set auto-load safe-path /
line to your configuration file "/root/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual.  E.g., run from the shell:
        info "(gdb)Auto-loading safe path"
(gdb) bt
#0  0x00007f9ad92ee1d7 in __GI_raise (sig=sig@entry=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007f9ad92ef8c8 in __GI_abort () at abort.c:90
#2  0x00007f9ada28fa6d in die () at error.c:474
#3  rb_bug_context (ctx=ctx@entry=0x7f9adabb7980,
    fmt=fmt@entry=0x7f9ada44fcc2 "Segmentation fault at %p") at error.c:504
#4  0x00007f9ada389d6e in sigsegv (sig=<optimized out>, info=0x7f9adabb7ab0, ctx=0x7f9adabb7980)
    at signal.c:907
#5  <signal handler called>
#6  0x00007f9ada3f2e88 in classname (permanent=<synthetic pointer>, klass=140303072871680)
    at variable.c:186
#7  rb_tmp_class_path (cache_path=0x7f9ada3efa60 <ivar_cache>, permanent=<synthetic pointer>,
    klass=140303072871680) at variable.c:262
#8  rb_class_path (klass=140303072871680) at variable.c:298
#9  rb_class_name (klass=klass@entry=140303072871680) at variable.c:446
#10 0x00007f9ada306990 in rb_mod_to_s (klass=140303072871680) at object.c:1577
#11 0x00007f9ada40e9ba in vm_call0_cfunc_with_frame (ci=<optimized out>, cc=<optimized out>,
    argv=0x0, calling=<optimized out>, th=0x7f9adab495d0) at vm_eval.c:131
#12 vm_call0_cfunc (argv=0x0, cc=0x7f9adabab810, ci=<optimized out>, calling=0x7ffc19a80230,
    th=0x7f9adab495d0) at vm_eval.c:148
#13 vm_call0_body (th=0x7f9adab495d0, calling=calling@entry=0x7ffc19a802f0,
    ci=ci@entry=0x7ffc19a802e0, cc=cc@entry=0x7ffc19a80310, argv=argv@entry=0x0) at vm_eval.c:180
#14 0x00007f9ada40f7a8 in vm_call0 (me=<optimized out>, argv=0x0, argc=0, id=2721,
    recv=140303072871680, th=<optimized out>) at vm_eval.c:61
#15 rb_call0 (recv=140303072871680, mid=mid@entry=2721, argc=argc@entry=0, argv=argv@entry=0x0,
    scope=scope@entry=CALL_FCALL, self=<optimized out>) at vm_eval.c:342
#16 0x00007f9ada4100ca in rb_call (scope=CALL_FCALL, argv=argv@entry=0x0, argc=argc@entry=0,
    mid=mid@entry=2721, recv=<optimized out>) at vm_eval.c:852
#17 rb_funcallv (recv=<optimized out>, mid=mid@entry=2721, argc=argc@entry=0, argv=argv@entry=0x0)
    at vm_eval.c:853
#18 0x00007f9ada306824 in rb_inspect (obj=<optimized out>) at object.c:553
#19 0x00007f9ada401108 in dump_function_entry (argc=argc@entry=2, argv=<optimized out>,
    th=<optimized out>) at vm_insnhelper.c:1564
#20 0x00007f9ada401530 in vm_call_iseq_setup_normal (cfp=<optimized out>, ci=<optimized out>,
    cc=<optimized out>, local_size=<optimized out>, param_size=<optimized out>,
    opt_pc=<optimized out>, calling=<optimized out>, th=0x7f9adab495d0) at vm_insnhelper.c:1593
#21 vm_call_iseq_setup_2 (ci=<optimized out>, local_size=<optimized out>,
    param_size=<optimized out>, opt_pc=<optimized out>, cc=<optimized out>,
    calling=<optimized out>, cfp=<optimized out>, th=0x7f9adab495d0) at vm_insnhelper.c:1499
#22 vm_call_iseq_setup (th=0x7f9adab495d0, cfp=<optimized out>, calling=<optimized out>,
    ci=<optimized out>, cc=<optimized out>) at vm_insnhelper.c:1491
#23 0x00007f9ada40ce93 in vm_call_method (th=0x7f9adab495d0, cfp=0x7f9ada1e4e00,
    calling=<optimized out>, ci=<optimized out>, cc=<optimized out>) at vm_insnhelper.c:2376
#24 0x00007f9ada406591 in vm_exec_core (th=th@entry=0x7f9adab495d0, initial=initial@entry=0)
    at insns.def:1066
#25 0x00007f9ada40ab77 in vm_exec (th=th@entry=0x7f9adab495d0) at vm.c:1705
#26 0x00007f9ada4155ff in invoke_block (captured=<optimized out>, opt_pc=<optimized out>,
    type=<optimized out>, cref=0x0, self=140303071166360, iseq=0x7f9adace8a20, th=0x7f9adab495d0)
    at vm.c:962
#27 invoke_iseq_block_from_c (is_lambda=<optimized out>, splattable=1, cref=0x0,
    passed_block_handler=0, argv=0x7ffc19a80a68, argc=1, self=140303071166360,
    captured=0x7f9ada1e4ea8, th=0x7f9adab495d0) at vm.c:1007
#28 invoke_block_from_c_splattable (passed_block_handler=<optimized out>,
    is_lambda=<optimized out>, cref=<optimized out>, argv=<optimized out>, argc=<optimized out>,
    block_handler=<optimized out>, th=<optimized out>) at vm.c:1025
#29 vm_yield (argc=1, argv=0x7ffc19a80a68, th=0x7f9adab495d0) at vm.c:1062
#30 rb_yield_0 (argv=0x7ffc19a80a68, argc=1) at vm_eval.c:1009
#31 rb_yield_1 (val=140303071155360) at vm_eval.c:1015
#32 rb_yield (val=<optimized out>) at vm_eval.c:1025
#33 0x00007f9ada21bc3d in rb_ary_each (ary=140303071153600) at array.c:1824
#34 0x00007f9ada3fcd81 in vm_call_cfunc_with_frame (ci=0x7f9adad00890, cc=<optimized out>,
    calling=<optimized out>, reg_cfp=0x7f9ada1e4e90, th=0x7f9adab495d0) at vm_insnhelper.c:1836
#35 vm_call_cfunc (th=0x7f9adab495d0, reg_cfp=0x7f9ada1e4e90, calling=<optimized out>,
    ci=0x7f9adad00890, cc=<optimized out>) at vm_insnhelper.c:1931
#36 0x00007f9ada40ce93 in vm_call_method (th=0x7f9adab495d0, cfp=0x7f9ada1e4e90,
    calling=<optimized out>, ci=<optimized out>, cc=<optimized out>) at vm_insnhelper.c:2376
#37 0x00007f9ada4072d0 in vm_exec_core (th=th@entry=0x7f9adab495d0, initial=initial@entry=0)
    at insns.def:967
#38 0x00007f9ada40ab77 in vm_exec (th=0x7f9adab495d0) at vm.c:1705
#39 0x00007f9ada40e90a in vm_call0_body (th=<optimized out>, calling=calling@entry=0x7ffc19a81190,
    ci=ci@entry=0x7ffc19a81180, cc=cc@entry=0x7ffc19a811b0, argv=argv@entry=0x7f9ada0e50d0)
    at vm_eval.c:176
#40 0x00007f9ada40f7a8 in vm_call0 (me=<optimized out>, argv=0x7f9ada0e50d0, argc=0, id=3057,
    recv=140303071166360, th=<optimized out>) at vm_eval.c:61
#41 rb_call0 (recv=recv@entry=140303071166360, mid=mid@entry=3057, argc=0, argc@entry=3057,
    argv=0x7f9ada0e50d0, argv@entry=0x0, scope=scope@entry=CALL_FCALL, self=<optimized out>)
    at vm_eval.c:342
#42 0x00007f9ada4100ca in rb_call (scope=CALL_FCALL, argv=argv@entry=0x0, argc=argc@entry=3057,
    mid=mid@entry=3057, recv=recv@entry=140303071166360) at vm_eval.c:852
#43 rb_funcallv (recv=recv@entry=140303071166360, mid=mid@entry=3057, argc=argc@entry=0,
    argv=argv@entry=0x7f9ada0e50d0) at vm_eval.c:853
#44 0x00007f9ada29a6e3 in rb_obj_call_init (obj=obj@entry=140303071166360, argc=argc@entry=0,
    argv=argv@entry=0x7f9ada0e50d0) at eval.c:1425
#45 0x00007f9ada306cd1 in rb_class_s_new (argc=0, argv=0x7f9ada0e50d0, klass=<optimized out>)
    at object.c:1935
#46 0x00007f9ada3fcd81 in vm_call_cfunc_with_frame (ci=0x7f9adac73360, cc=<optimized out>,
    calling=<optimized out>, reg_cfp=0x7f9ada1e4fb0, th=0x7f9adab495d0) at vm_insnhelper.c:1836
#47 vm_call_cfunc (th=0x7f9adab495d0, reg_cfp=0x7f9ada1e4fb0, calling=<optimized out>,
    ci=0x7f9adac73360, cc=<optimized out>) at vm_insnhelper.c:1931
#48 0x00007f9ada40ce93 in vm_call_method (th=0x7f9adab495d0, cfp=0x7f9ada1e4fb0,
    calling=<optimized out>, ci=<optimized out>, cc=<optimized out>) at vm_insnhelper.c:2376
#49 0x00007f9ada4072d0 in vm_exec_core (th=th@entry=0x7f9adab495d0, initial=initial@entry=0)
    at insns.def:967
#50 0x00007f9ada40ab77 in vm_exec (th=0x7f9adab495d0) at vm.c:1705
#51 0x00007f9ada415b51 in rb_iseq_eval_main (iseq=iseq@entry=0x7f9adab6d1c8) at vm.c:1951
#52 0x00007f9ada295b3d in ruby_exec_internal (n=0x7f9adab6d1c8) at eval.c:244
#53 0x00007f9ada29907d in ruby_exec_node (n=0x7f9adab6d1c8) at eval.c:308
#54 ruby_run_node (n=<optimized out>) at eval.c:300
#55 0x00007f9ada21a13b in main (argc=11, argv=0x7ffc19a81b18) at main.c:36
(gdb)
----------------------------------------

/tmp/ruby.log の最後は以下のようになっていました。

----------------------------------------
class=OptionParser::List method=search filename=/root/ruby/lib/optparse.rb line=825 argc=2 argv[0,20]=:atype argv[1,5]="-t"
class=OptionParser::List method=search filename=/root/ruby/lib/optparse.rb line=825 argc=2 argv[0,20]=:atype argv[1,5]="-t"
class=OptionParser method=search filename=/root/ruby/lib/optparse.rb line=1716 argc=2 argv[0,20]=:atype argv[1,5]="--timestamp[=PATH]"
class=OptionParser method=visit filename=/root/ruby/lib/optparse.rb line=1705 argc=3 argv[0,20]=:search argv[1,7]=[:atype, "--timestamp[=PATH]"] argv[2,12]=#<Proc:0x007f9adab73a78@/root/ruby/lib/optparse.rb:1718>
class=OptionParser::List method=search filename=/root/ruby/lib/optparse.rb line=825 argc=2 argv[0,20]=:atype argv[1,5]="--timestamp[=PATH]"
class=OptionParser::List method=search filename=/root/ruby/lib/optparse.rb line=825 argc=2 argv[0,20]=:atype argv[1,5]="--timestamp[=PATH]"
class=OptionParser::List method=search filename=/root/ruby/lib/optparse.rb line=825 argc=2 argv[0,20]=:atype argv[1,5]="--timestamp[=PATH]"
class=OptionParser method=notwice filename=/root/ruby/lib/optparse.rb line=1264 argc=3 argv[0,2]=NilClass argv[1,17]=nil argv[2,5]="type"
class=OptionParser::Switch method=guess filename=/root/ruby/lib/optparse.rb line=485 argc=1 argv[0,5]="[=PATH]"
class=OptionParser::Switch::NoArgument method=incompatible_argument_styles filename=/root/ruby/lib/optparse.rb line=655 argc=2 argv[0,7]=["[=PATH]", OptionParser::Switch::OptionalArgument] argv[1,26]
----------------------------------------

26 は T_IMEMO なので、 compile.c の dump_object_functions[] が
ibf_dump_object_unsupported となっている種別をスキップするように
してみましたが、他の場所で問題が発生するため、解決策になっていませんでした。

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [ruby-dev:50001] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-03-01 11:28       ` [ruby-dev:50000] " Tetsuo Handa
@ 2017-03-02  6:37         ` Nobuyoshi Nakada
  2017-03-02  7:41           ` [ruby-dev:50002] " Tetsuo Handa
  0 siblings, 1 reply; 12+ messages in thread
From: Nobuyoshi Nakada @ 2017-03-02  6:37 UTC (permalink / raw
  To: Ruby developers (Japanese)

On 2017/03/01 20:28, Tetsuo Handa wrote:
> +    dump_function_entry(th, calling->argc, argv);

とりあえず calling->argc の代わりに (int)(sp->argv) にしてみてください。

-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:50002] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-03-02  6:37         ` [ruby-dev:50001] " Nobuyoshi Nakada
@ 2017-03-02  7:41           ` Tetsuo Handa
  2017-03-13 10:18             ` [ruby-dev:50019] " Tetsuo Handa
  0 siblings, 1 reply; 12+ messages in thread
From: Tetsuo Handa @ 2017-03-02  7:41 UTC (permalink / raw
  To: ruby-dev, nobu

中田さん、ありがとうございます。

sp は VALUE * で VALUE は構造体ではないので -> を使えないようです。
(int)(sp - argv) にしたら少し先へ進むことができましたが、
/root/rpmbuild/BUILD/ruby-2.0.0-p648/lib/rdoc/context/section.rb と
同じメソッドでコケました。

class=RDoc::Context::Section method=initialize filename=/root/ruby/lib/rdoc/context/section.rb line=42 argc=3 argv[0,1]

  def initialize parent, title, comment
    @parent = parent
    @title = title ? title.strip : title

    @@sequence.succ!
    @sequence = @@sequence.dup

    @comments = []

    add_comment comment
  end

Nobuyoshi Nakada wrote:
> On 2017/03/01 20:28, Tetsuo Handa wrote:
> > +    dump_function_entry(th, calling->argc, argv);
> 
> とりあえず calling->argc の代わりに (int)(sp->argv) にしてみてください。
> 
> -- 
> --- 僕の前にBugはない。
> --- 僕の後ろにBugはできる。
>     中田 伸悦

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [ruby-dev:50019] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-03-02  7:41           ` [ruby-dev:50002] " Tetsuo Handa
@ 2017-03-13 10:18             ` Tetsuo Handa
  2017-03-16  2:13               ` [ruby-dev:50020] " Tetsuo Handa
  0 siblings, 1 reply; 12+ messages in thread
From: Tetsuo Handa @ 2017-03-13 10:18 UTC (permalink / raw
  To: ruby-dev

 間が空いてしまいましたが、その後の状況についてです。

以下のパッチを適用すると、 make 中の Generating RDoc documentation という段階で
lib/rdoc/token_stream.rb:59: [BUG] Segmentation fault at 0x00000000000000 という
エラーが出るところまで進みました。

----------------------------------------
diff --git a/signal.c b/signal.c
index 888c8ea..29ba6c2 100644
--- a/signal.c
+++ b/signal.c
@@ -1415,7 +1415,7 @@ ruby_sig_finalize(void)
 
 int ruby_enable_coredump = 0;
 #ifndef RUBY_DEBUG_ENV
-#define ruby_enable_coredump 0
+//#define ruby_enable_coredump 0
 #endif
 
 /*
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index f04d836..9576489 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1500,6 +1500,74 @@ vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling
     }
 }
 
+/* ///// */
+VALUE rb_class_path_no_cache(VALUE _klass);
+static void dump_function_entry(rb_thread_t *th, int argc, VALUE *argv)
+{
+    static FILE *fp = NULL;
+    static __thread _Bool dump_recurse = 0;
+    VALUE _klass = 0;
+    VALUE _id = 0;
+    if (dump_recurse)
+	return;
+    dump_recurse = 1;
+    if (!fp)
+	fp = fopen("/dev/null", "a"); //fp = fopen("/tmp/ruby.log", "a");
+    rb_thread_method_id_and_class((th), &_id, 0, &_klass);
+    if (!_klass || !fp) {
+	dump_recurse = 0;
+	return;
+    }
+    if (RB_TYPE_P(_klass, T_ICLASS))
+	_klass = RBASIC(_klass)->klass;
+    else if (FL_TEST(_klass, FL_SINGLETON))
+	_klass = rb_iv_get(_klass, "__attached__");
+    switch (TYPE(_klass)) {
+    case T_CLASS:
+    case T_ICLASS:
+    case T_MODULE:
+	{
+	    int i;
+	    volatile int raised = rb_threadptr_reset_raised(th);
+	    VALUE _name = rb_class_path_no_cache(_klass);
+	    const char *classname = !NIL_P(_name) ? StringValuePtr(_name) : "<unknown>";
+	    const char *methodname = rb_id2name(_id);
+	    const char *filename = rb_sourcefile();
+	    int state;
+	    fprintf(fp, "class=%s method=%s filename=%s line=%u argc=%u",
+		    classname, methodname, filename, rb_sourceline(), argc);
+	    fflush(fp);
+	    if (argc) {
+		    TH_PUSH_TAG(th);
+		    if ((state = TH_EXEC_TAG()) == 0) {
+		    for (i = 0; i < argc; i++) {
+			VALUE rstr;
+			char buff[0x100];
+			fprintf(fp, " argv[%u,%u]", i, TYPE(argv[i]));
+			fflush(fp);
+			fprintf(fp, "[%s]", rb_raw_obj_info(buff, 0x100, argv[i]));
+			fflush(fp);
+			rstr = rb_inspect(argv[i]);
+			fprintf(fp, "=");
+			fflush(fp);
+			fprintf(fp, "%s", StringValueCStr(rstr));
+			fflush(fp);
+		    }
+		    }
+		    TH_POP_TAG();
+	    }
+	    fprintf(fp, "\n");
+	    fflush(fp);
+	    if (raised)
+		rb_threadptr_set_raised(th);
+	    else
+		rb_threadptr_reset_raised(th);
+	    break;
+	}
+    }
+    dump_recurse = 0;
+}
+
 static inline VALUE
 vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc,
 			  int opt_pc, int param_size, int local_size)
@@ -1515,6 +1583,7 @@ vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_ca
 		  iseq->body->iseq_encoded + opt_pc, sp,
 		  local_size - param_size,
 		  iseq->body->stack_max);
+    dump_function_entry(th, (int) (sp - argv), argv);
     return Qundef;
 }
 
@@ -1561,6 +1630,7 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_
 		  iseq->body->iseq_encoded + opt_pc, sp,
 		  iseq->body->local_table_size - iseq->body->param.size,
 		  iseq->body->stack_max);
+    dump_function_entry(th, (int) (sp - argv), argv);
 
     cfp->sp = sp_orig;
     RUBY_VM_CHECK_INTS(th);
----------------------------------------

----------------------------------------
Generating RDoc documentation
Parsing sources...
/root/ruby/lib/rdoc/token_stream.rb:59: [BUG] Segmentation fault at 0x00000000000000
ruby 2.5.0dev (2017-03-13 trunk 57949) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0015 p:---- s:0107 e:000106 CFUNC  :inspect
c:0014 p:0000 s:0104 e:000103 METHOD /root/ruby/lib/rdoc/token_stream.rb:59
c:0013 p:0379 s:0099 e:000098 METHOD /root/ruby/lib/rdoc/parser/c.rb:671
c:0012 p:0284 s:0083 e:000082 METHOD /root/ruby/lib/rdoc/parser/c.rb:1061
c:0011 p:0067 s:0065 e:000064 BLOCK  /root/ruby/lib/rdoc/parser/c.rb:480 [FINISH]
c:0010 p:---- s:0056 e:000055 CFUNC  :scan
c:0009 p:0013 s:0051 e:000050 METHOD /root/ruby/lib/rdoc/parser/c.rb:461
c:0008 p:0043 s:0047 e:000046 METHOD /root/ruby/lib/rdoc/parser/c.rb:1259
c:0007 p:0231 s:0043 e:000042 METHOD /root/ruby/lib/rdoc/rdoc.rb:367
c:0006 p:0017 s:0031 e:000030 BLOCK  /root/ruby/lib/rdoc/rdoc.rb:419 [FINISH]
c:0005 p:---- s:0027 e:000026 CFUNC  :map
c:0004 p:0086 s:0023 e:000022 METHOD /root/ruby/lib/rdoc/rdoc.rb:417
c:0003 p:0254 s:0015 e:000014 METHOD /root/ruby/lib/rdoc/rdoc.rb:488
c:0002 p:0053 s:0008 E:001960 EVAL   ./bin/rdoc:20 [FINISH]
c:0001 p:0000 s:0003 E:002210 (none) [FINISH]

-- Ruby level backtrace information ----------------------------------------
../bin/rdoc:20:in `<main>'
/root/ruby/lib/rdoc/rdoc.rb:488:in `document'
/root/ruby/lib/rdoc/rdoc.rb:417:in `parse_files'
/root/ruby/lib/rdoc/rdoc.rb:417:in `map'
/root/ruby/lib/rdoc/rdoc.rb:419:in `block in parse_files'
/root/ruby/lib/rdoc/rdoc.rb:367:in `parse_file'
/root/ruby/lib/rdoc/parser/c.rb:1259:in `scan'
/root/ruby/lib/rdoc/parser/c.rb:461:in `do_methods'
/root/ruby/lib/rdoc/parser/c.rb:461:in `scan'
/root/ruby/lib/rdoc/parser/c.rb:480:in `block in do_methods'
/root/ruby/lib/rdoc/parser/c.rb:1061:in `handle_method'
/root/ruby/lib/rdoc/parser/c.rb:671:in `find_body'
/root/ruby/lib/rdoc/token_stream.rb:59:in `add_tokens'
/root/ruby/lib/rdoc/token_stream.rb:59:in `inspect'

-- Machine register context ------------------------------------------------
 RIP: 0x00007f54d1036fb6 RBP: 0x00007f54d3323080 RSP: 0x00007fff776ecd80
 RAX: 0x0000000000000000 RBX: 0x00007f54d3323050 RCX: 0x00007f54cfdd8c7d
 RDX: 0x0000000000000000 RDI: 0x00007f54d2a085d0 RSI: 0x00007f54d2b80300
  R8: 0x00007f54d0e8b740  R9: 0x00007f54d0e8b740 R10: 0x0000000000000019
 R11: 0x0000000000000000 R12: 0x00007f54d3324b88 R13: 0x00007f54d3324620
 R14: 0x0000000000000000 R15: 0x00007f54d0e89d40 EFL: 0x0000000000010246

-- C level backtrace information -------------------------------------------
/root/ruby/ruby(rb_vm_bugreport+0x528) [0x7f54d10cdf08] vm_dump.c:683
/root/ruby/ruby(rb_bug_context+0xd0) [0x7f54d10c3170] error.c:502
/root/ruby/ruby(sigsegv+0x3e) [0x7f54d0fbcb4e] signal.c:907
/lib64/libpthread.so.0 [0x7f54d0a74370]
/root/ruby/ruby(vm_exec_core+0x3c96) [0x7f54d1036fb6] insns.def:1066
/root/ruby/ruby(vm_exec+0x9c) [0x7f54d1039c4c] vm.c:1705
/root/ruby/ruby(rb_yield+0x47e) [0x7f54d104434e] vm.c:962
/root/ruby/ruby(rb_str_scan+0x24e) [0x7f54d0fd415e] string.c:8587
/root/ruby/ruby(vm_call_cfunc+0x100) [0x7f54d1031420] vm_insnhelper.c:1829
/root/ruby/ruby(vm_exec_core+0x2f3e) [0x7f54d103625e] insns.def:967
/root/ruby/ruby(vm_exec+0x9c) [0x7f54d1039c4c] vm.c:1705
/root/ruby/ruby(rb_yield+0x47e) [0x7f54d104434e] vm.c:962
/root/ruby/ruby(rb_ary_collect+0x5d) [0x7f54d1058fed] array.c:2739
/root/ruby/ruby(vm_call_cfunc+0x100) [0x7f54d1031420] vm_insnhelper.c:1829
/root/ruby/ruby(vm_call_method+0xe3) [0x7f54d103bac3] vm_insnhelper.c:2369
/root/ruby/ruby(vm_exec_core+0x2f3e) [0x7f54d103625e] insns.def:967
/root/ruby/ruby(vm_exec+0x9c) [0x7f54d1039c4c] vm.c:1705
/root/ruby/ruby(ruby_exec_internal+0xad) [0x7f54d0ec866d] eval.c:244
/root/ruby/ruby(ruby_run_node+0x2d) [0x7f54d0ecbbfd] eval.c:308
/root/ruby/ruby(main+0x5f) [0x7f54d0ec7e3f] main.c:36

-- Other runtime information -----------------------------------------------

* Loaded script: ./bin/rdoc

* Loaded features:

    0 enumerator.so
    1 thread.rb
    2 rational.so
    3 complex.so
    4 /root/ruby/.ext/x86_64-linux/enc/encdb.so
    5 /root/ruby/.ext/x86_64-linux/enc/trans/transdb.so
    6 /root/ruby/lib/unicode_normalize.rb
    7 /root/ruby/lib/rdoc.rb
    8 /root/ruby/lib/find.rb
    9 /root/ruby/.ext/x86_64-linux/etc.so
   10 /root/ruby/lib/fileutils.rb
   11 /root/ruby/.ext/x86_64-linux/pathname.so
   12 /root/ruby/.ext/common/pathname.rb
   13 /root/ruby/.ext/x86_64-linux/date_core.so
   14 /root/ruby/.ext/common/date.rb
   15 /root/ruby/lib/time.rb
   16 /root/ruby/rbconfig.rb
   17 /root/ruby/lib/rubygems/compatibility.rb
   18 /root/ruby/lib/rubygems/defaults.rb
   19 /root/ruby/lib/rubygems/deprecate.rb
   20 /root/ruby/lib/rubygems/errors.rb
   21 /root/ruby/lib/rubygems/version.rb
   22 /root/ruby/lib/rubygems/requirement.rb
   23 /root/ruby/lib/rubygems/platform.rb
   24 /root/ruby/lib/rubygems/basic_specification.rb
   25 /root/ruby/lib/rubygems/stub_specification.rb
   26 /root/ruby/lib/rubygems/util/list.rb
   27 /root/ruby/.ext/x86_64-linux/stringio.so
   28 /root/ruby/lib/rubygems/specification.rb
   29 /root/ruby/lib/rubygems/exceptions.rb
   30 /root/ruby/lib/rubygems/core_ext/kernel_gem.rb
   31 /root/ruby/lib/monitor.rb
   32 /root/ruby/lib/rubygems/core_ext/kernel_require.rb
   33 /root/ruby/lib/rubygems.rb
   34 /root/ruby/lib/rubygems/path_support.rb
   35 /root/ruby/.ext/x86_64-linux/cgi/escape.so
   36 /root/ruby/lib/cgi/util.rb
   37 /root/ruby/.ext/x86_64-linux/strscan.so
   38 /root/ruby/lib/erb.rb
   39 /root/ruby/lib/rdoc/generator.rb
   40 /root/ruby/lib/rubygems/dependency.rb
   41 /root/ruby/lib/rdoc/markup.rb
   42 /root/ruby/lib/rdoc/markup/formatter.rb
   43 /root/ruby/lib/rdoc/markup/to_joined_paragraph.rb
   44 /root/ruby/lib/rdoc/markdown/entities.rb
   45 /root/ruby/lib/rdoc/markdown/literals.rb
   46 /root/ruby/lib/rdoc/markdown.rb
   47 /root/ruby/lib/rdoc/rd.rb
   48 /root/ruby/lib/rdoc/markup/parser.rb
   49 /root/ruby/lib/rdoc/markup/pre_process.rb
   50 /root/ruby/lib/rdoc/tom_doc.rb
   51 /root/ruby/lib/rdoc/text.rb
   52 /root/ruby/lib/rdoc/code_object.rb
   53 /root/ruby/lib/rdoc/method_attr.rb
   54 /root/ruby/lib/cgi/core.rb
   55 /root/ruby/lib/cgi/cookie.rb
   56 /root/ruby/lib/cgi.rb
   57 /root/ruby/lib/rdoc/context.rb
   58 /root/ruby/lib/rdoc/class_module.rb
   59 /root/ruby/lib/rdoc/context/section.rb
   60 /root/ruby/lib/rdoc/top_level.rb
   61 /root/ruby/lib/rdoc/generator/markup.rb
   62 /root/ruby/lib/rdoc/generator/darkfish.rb
   63 /root/ruby/lib/rdoc/generator/ri.rb
   64 /root/ruby/lib/rdoc/generator/pot.rb
   65 /root/ruby/lib/rdoc/rdoc.rb
   66 /root/ruby/lib/rdoc/store.rb
   67 /root/ruby/lib/optparse.rb
   68 /root/ruby/lib/rdoc/options.rb
   69 /root/ruby/lib/rdoc/parser/text.rb
   70 /root/ruby/lib/rdoc/parser/simple.rb
   71 /root/ruby/lib/tsort.rb
   72 /root/ruby/lib/rdoc/parser/c.rb
   73 /root/ruby/lib/rdoc/parser/changelog.rb
   74 /root/ruby/lib/rdoc/parser/markdown.rb
   75 /root/ruby/lib/rdoc/parser/rd.rb
   76 /root/ruby/lib/rdoc/ruby_token.rb
   77 /root/ruby/lib/rdoc/token_stream.rb
   78 /root/ruby/lib/rdoc/parser/ruby_tools.rb
   79 /root/ruby/lib/rdoc/parser/ruby.rb
   80 /root/ruby/lib/rdoc/parser.rb
   81 /root/ruby/lib/rdoc/ri.rb
   82 /root/ruby/lib/rdoc/ri/paths.rb
   83 /root/ruby/lib/rdoc/stats.rb
   84 /root/ruby/.ext/x86_64-linux/io/console.so
   85 /root/ruby/.ext/common/io/console/size.rb
   86 /root/ruby/lib/rdoc/stats/quiet.rb
   87 /root/ruby/lib/rdoc/stats/normal.rb
   88 /root/ruby/lib/rdoc/encoding.rb
   89 /root/ruby/lib/rdoc/comment.rb
   90 /root/ruby/lib/rdoc/markup/document.rb
   91 /root/ruby/lib/rdoc/markup/heading.rb
   92 /root/ruby/lib/rdoc/markup/blank_line.rb
   93 /root/ruby/lib/rdoc/markup/list.rb
   94 /root/ruby/lib/rdoc/markup/raw.rb
   95 /root/ruby/lib/rdoc/markup/paragraph.rb
   96 /root/ruby/lib/rdoc/markup/list_item.rb
   97 /root/ruby/lib/rdoc/known_classes.rb
   98 /root/ruby/lib/rdoc/normal_class.rb
   99 /root/ruby/lib/rdoc/any_method.rb

* Process memory map:

7f54c6f12000-7f54c7118000 r--s 00000000 fd:00 1242                       /usr/lib64/libc-2.17.so
7f54c7118000-7f54c71b6000 r--s 00000000 fd:00 50926939                   /usr/lib/debug/usr/lib64/libpthread-2.17.so.debug
7f54c71b6000-7f54c8146000 r--s 00000000 fd:00 34034897                   /root/ruby/ruby
7f54c8146000-7f54c815b000 r-xp 00000000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f54c815b000-7f54c835a000 ---p 00015000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f54c835a000-7f54c835b000 r--p 00014000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f54c835b000-7f54c835c000 rw-p 00015000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f54c835c000-7f54c8360000 r-xp 00000000 fd:00 16886103                   /root/ruby/.ext/x86_64-linux/io/console.so
7f54c8360000-7f54c8560000 ---p 00004000 fd:00 16886103                   /root/ruby/.ext/x86_64-linux/io/console.so
7f54c8560000-7f54c8561000 r--p 00004000 fd:00 16886103                   /root/ruby/.ext/x86_64-linux/io/console.so
7f54c8561000-7f54c8562000 rw-p 00005000 fd:00 16886103                   /root/ruby/.ext/x86_64-linux/io/console.so
7f54c8562000-7f54c8568000 r-xp 00000000 fd:00 50515921                   /root/ruby/.ext/x86_64-linux/strscan.so
7f54c8568000-7f54c8767000 ---p 00006000 fd:00 50515921                   /root/ruby/.ext/x86_64-linux/strscan.so
7f54c8767000-7f54c8768000 r--p 00005000 fd:00 50515921                   /root/ruby/.ext/x86_64-linux/strscan.so
7f54c8768000-7f54c8769000 rw-p 00006000 fd:00 50515921                   /root/ruby/.ext/x86_64-linux/strscan.so
7f54c8769000-7f54c876c000 r-xp 00000000 fd:00 921544                     /root/ruby/.ext/x86_64-linux/cgi/escape.so
7f54c876c000-7f54c896b000 ---p 00003000 fd:00 921544                     /root/ruby/.ext/x86_64-linux/cgi/escape.so
7f54c896b000-7f54c896c000 r--p 00002000 fd:00 921544                     /root/ruby/.ext/x86_64-linux/cgi/escape.so
7f54c896c000-7f54c896d000 rw-p 00003000 fd:00 921544                     /root/ruby/.ext/x86_64-linux/cgi/escape.so
7f54c896d000-7f54c8975000 r-xp 00000000 fd:00 50515920                   /root/ruby/.ext/x86_64-linux/stringio.so
7f54c8975000-7f54c8b74000 ---p 00008000 fd:00 50515920                   /root/ruby/.ext/x86_64-linux/stringio.so
7f54c8b74000-7f54c8b75000 r--p 00007000 fd:00 50515920                   /root/ruby/.ext/x86_64-linux/stringio.so
7f54c8b75000-7f54c8b76000 rw-p 00008000 fd:00 50515920                   /root/ruby/.ext/x86_64-linux/stringio.so
7f54c8b76000-7f54c8bab000 r-xp 00000000 fd:00 50425545                   /root/ruby/.ext/x86_64-linux/date_core.so
7f54c8bab000-7f54c8daa000 ---p 00035000 fd:00 50425545                   /root/ruby/.ext/x86_64-linux/date_core.so
7f54c8daa000-7f54c8dab000 r--p 00034000 fd:00 50425545                   /root/ruby/.ext/x86_64-linux/date_core.so
7f54c8dab000-7f54c8dac000 rw-p 00035000 fd:00 50425545                   /root/ruby/.ext/x86_64-linux/date_core.so
7f54c8dac000-7f54c8dae000 rw-p 00000000 00:00 0
7f54c8dae000-7f54c8db5000 r-xp 00000000 fd:00 50515908                   /root/ruby/.ext/x86_64-linux/pathname.so
7f54c8db5000-7f54c8fb4000 ---p 00007000 fd:00 50515908                   /root/ruby/.ext/x86_64-linux/pathname.so
7f54c8fb4000-7f54c8fb5000 r--p 00006000 fd:00 50515908                   /root/ruby/.ext/x86_64-linux/pathname.so
7f54c8fb5000-7f54c8fb6000 rw-p 00007000 fd:00 50515908                   /root/ruby/.ext/x86_64-linux/pathname.so
7f54c8fb6000-7f54c8fbc000 r-xp 00000000 fd:00 50425552                   /root/ruby/.ext/x86_64-linux/etc.so
7f54c8fbc000-7f54c91bb000 ---p 00006000 fd:00 50425552                   /root/ruby/.ext/x86_64-linux/etc.so
7f54c91bb000-7f54c91bc000 r--p 00005000 fd:00 50425552                   /root/ruby/.ext/x86_64-linux/etc.so
7f54c91bc000-7f54c91bd000 rw-p 00006000 fd:00 50425552                   /root/ruby/.ext/x86_64-linux/etc.so
7f54c91bd000-7f54c91c0000 r-xp 00000000 fd:00 17024646                   /root/ruby/.ext/x86_64-linux/enc/trans/transdb.so
7f54c91c0000-7f54c93bf000 ---p 00003000 fd:00 17024646                   /root/ruby/.ext/x86_64-linux/enc/trans/transdb.so
7f54c93bf000-7f54c93c0000 r--p 00002000 fd:00 17024646                   /root/ruby/.ext/x86_64-linux/enc/trans/transdb.so
7f54c93c0000-7f54c93c1000 rw-p 00003000 fd:00 17024646                   /root/ruby/.ext/x86_64-linux/enc/trans/transdb.so
7f54c93c1000-7f54c93c3000 r-xp 00000000 fd:00 1054116                    /root/ruby/.ext/x86_64-linux/enc/encdb.so
7f54c93c3000-7f54c95c2000 ---p 00002000 fd:00 1054116                    /root/ruby/.ext/x86_64-linux/enc/encdb.so
7f54c95c2000-7f54c95c3000 r--p 00001000 fd:00 1054116                    /root/ruby/.ext/x86_64-linux/enc/encdb.so
7f54c95c3000-7f54c95c4000 rw-p 00002000 fd:00 1054116                    /root/ruby/.ext/x86_64-linux/enc/encdb.so
7f54c95c4000-7f54cfaed000 r--p 00000000 fd:00 50333274                   /usr/lib/locale/locale-archive
7f54cfaed000-7f54cfaef000 r-xp 00000000 fd:00 1233                       /usr/lib64/libfreebl3.so
7f54cfaef000-7f54cfcee000 ---p 00002000 fd:00 1233                       /usr/lib64/libfreebl3.so
7f54cfcee000-7f54cfcef000 r--p 00001000 fd:00 1233                       /usr/lib64/libfreebl3.so
7f54cfcef000-7f54cfcf0000 rw-p 00002000 fd:00 1233                       /usr/lib64/libfreebl3.so
7f54cfcf0000-7f54cfea6000 r-xp 00000000 fd:00 1242                       /usr/lib64/libc-2.17.so
7f54cfea6000-7f54d00a6000 ---p 001b6000 fd:00 1242                       /usr/lib64/libc-2.17.so
7f54d00a6000-7f54d00aa000 r--p 001b6000 fd:00 1242                       /usr/lib64/libc-2.17.so
7f54d00aa000-7f54d00ac000 rw-p 001ba000 fd:00 1242                       /usr/lib64/libc-2.17.so
7f54d00ac000-7f54d00b1000 rw-p 00000000 00:00 0
7f54d00b1000-7f54d01b1000 r-xp 00000000 fd:00 3919                       /usr/lib64/libm-2.17.so
7f54d01b1000-7f54d03b1000 ---p 00100000 fd:00 3919                       /usr/lib64/libm-2.17.so
7f54d03b1000-7f54d03b2000 r--p 00100000 fd:00 3919                       /usr/lib64/libm-2.17.so
7f54d03b2000-7f54d03b3000 rw-p 00101000 fd:00 3919                       /usr/lib64/libm-2.17.so
7f54d03b3000-7f54d03bb000 r-xp 00000000 fd:00 3915                       /usr/lib64/libcrypt-2.17.so
7f54d03bb000-7f54d05ba000 ---p 00008000 fd:00 3915                       /usr/lib64/libcrypt-2.17.so
7f54d05ba000-7f54d05bb000 r--p 00007000 fd:00 3915                       /usr/lib64/libcrypt-2.17.so
7f54d05bb000-7f54d05bc000 rw-p 00008000 fd:00 3915                       /usr/lib64/libcrypt-2.17.so
7f54d05bc000-7f54d05ea000 rw-p 00000000 00:00 0
7f54d05ea000-7f54d05ec000 r-xp 00000000 fd:00 3917                       /usr/lib64/libdl-2.17.so
7f54d05ec000-7f54d07ec000 ---p 00002000 fd:00 3917                       /usr/lib64/libdl-2.17.so
7f54d07ec000-7f54d07ed000 r--p 00002000 fd:00 3917                       /usr/lib64/libdl-2.17.so
7f54d07ed000-7f54d07ee000 rw-p 00003000 fd:00 3917                       /usr/lib64/libdl-2.17.so
7f54d07ee000-7f54d0864000 r-xp 00000000 fd:00 1730                       /usr/lib64/libgmp.so.10.2.0
7f54d0864000-7f54d0a63000 ---p 00076000 fd:00 1730                       /usr/lib64/libgmp.so.10.2.0
7f54d0a63000-7f54d0a64000 r--p 00075000 fd:00 1730                       /usr/lib64/libgmp.so.10.2.0
7f54d0a64000-7f54d0a65000 rw-p 00076000 fd:00 1730                       /usr/lib64/libgmp.so.10.2.0
7f54d0a65000-7f54d0a7c000 r-xp 00000000 fd:00 1245                       /usr/lib64/libpthread-2.17.so
7f54d0a7c000-7f54d0c7b000 ---p 00017000 fd:00 1245                       /usr/lib64/libpthread-2.17.so
7f54d0c7b000-7f54d0c7c000 r--p 00016000 fd:00 1245                       /usr/lib64/libpthread-2.17.so
7f54d0c7c000-7f54d0c7d000 rw-p 00017000 fd:00 1245                       /usr/lib64/libpthread-2.17.so
7f54d0c7d000-7f54d0c81000 rw-p 00000000 00:00 0
7f54d0c81000-7f54d0ca1000 r-xp 00000000 fd:00 3911                       /usr/lib64/ld-2.17.so
7f54d0cc7000-7f54d0d59000 rw-p 00000000 00:00 0
7f54d0d66000-7f54d0d8a000 r--s 00000000 fd:00 1245                       /usr/lib64/libpthread-2.17.so
7f54d0d8a000-7f54d0e90000 rw-p 00000000 00:00 0
7f54d0e92000-7f54d0e94000 rw-p 00000000 00:00 0
7f54d0e94000-7f54d0e9b000 r--s 00000000 fd:00 16828441                   /usr/lib64/gconv/gconv-modules.cache
7f54d0e9b000-7f54d0e9c000 ---p 00000000 00:00 0
7f54d0e9c000-7f54d0ea0000 rw-p 00000000 00:00 0                          [stack:42915]
7f54d0ea0000-7f54d0ea1000 r--p 0001f000 fd:00 3911                       /usr/lib64/ld-2.17.so
7f54d0ea1000-7f54d0ea2000 rw-p 00020000 fd:00 3911                       /usr/lib64/ld-2.17.so
7f54d0ea2000-7f54d0ea3000 rw-p 00000000 00:00 0
7f54d0ea3000-7f54d11a7000 r-xp 00000000 fd:00 34034897                   /root/ruby/ruby
7f54d13a6000-7f54d13ab000 r--p 00303000 fd:00 34034897                   /root/ruby/ruby
7f54d13ab000-7f54d13ac000 rw-p 00308000 fd:00 34034897                   /root/ruby/ruby
7f54d13ac000-7f54d13be000 rw-p 00000000 00:00 0
7f54d2a07000-7f54da535000 rw-p 00000000 00:00 0                          [heap]
7fff76ef1000-7fff776f0000 rw-p 00000000 00:00 0
7fff777de000-7fff777e0000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html

make: *** [rdoc] Aborted (core dumped)
----------------------------------------

lib/rdoc/token_stream.rb は lib/rdoc/parser/c.rb から呼ばれているとのことなので、
以下のように add_token に渡す値を tk ではなく nil に差し替えてみたところ、最後の
ファイルまで処理した後でエラーが出るようになりました。

下記の出力は上記の出力よりは先の段階ですので、 tk を渡したことで NULL pointer
dereference になっているものと推測されます。下記の結果が出るまでは、パッチが
行っている処理の中で何かの手続きを忘れているものと考えていたのですが、下記の
結果からは、何らかの状態の引数を渡すとエラーになるようにも思えます。
何か手がかりになりそうでしょうか?

----------------------------------------
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 087d56f..18a6304 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -668,7 +668,7 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
       meth_obj.start_collecting_tokens
       tk = RDoc::RubyToken::Token.new nil, 1, 1
       tk.set_text body
-      meth_obj.add_token tk
+      meth_obj.add_token nil #tk
       meth_obj.comment = comment
       meth_obj.offset  = offset
       meth_obj.line    = file_content[0, offset].count("\n") + 1
@@ -687,7 +687,7 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
       meth_obj.start_collecting_tokens
       tk = RDoc::RubyToken::Token.new nil, 1, 1
       tk.set_text body
-      meth_obj.add_token tk
+      meth_obj.add_token nil #tk
       meth_obj.comment = comment
       meth_obj.offset  = offset
       meth_obj.line    = file_content[0, offset].count("\n") + 1
----------------------------------------

----------------------------------------
Generating RDoc documentation
Parsing sources...
100% [895/895]  vsnprintf.c
uh-oh! RDoc had a problem:
stack level too deep

run with --debug for full backtrace
make: *** [rdoc] Error 1
----------------------------------------

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [ruby-dev:50020] Re: メソッド呼び出し時の引数の値を VM 側で取得する方法について
  2017-03-13 10:18             ` [ruby-dev:50019] " Tetsuo Handa
@ 2017-03-16  2:13               ` Tetsuo Handa
  0 siblings, 0 replies; 12+ messages in thread
From: Tetsuo Handa @ 2017-03-16  2:13 UTC (permalink / raw
  To: ruby-dev

> lib/rdoc/token_stream.rb は lib/rdoc/parser/c.rb から呼ばれているとのことなので、
> 以下のように add_token に渡す値を tk ではなく nil に差し替えてみたところ、最後の
> ファイルまで処理した後でエラーが出るようになりました。
> 
> 下記の出力は上記の出力よりは先の段階ですので、 tk を渡したことで NULL pointer
> dereference になっているものと推測されます。下記の結果が出るまでは、パッチが
> 行っている処理の中で何かの手続きを忘れているものと考えていたのですが、下記の
> 結果からは、何らかの状態の引数を渡すとエラーになるようにも思えます。
> 何か手がかりになりそうでしょうか?

VM 側に修正を加えていない ruby で以下のプログラムを実行した場合に
can't convert nil into Integer (TypeError) というエラーが発生することを
確認できました。

---------- test.rb ----------
require '/usr/share/rubygems/rubygems/rdoc.rb'
tk = RDoc::RubyToken::Token.new nil, 1, 1
p tk
---------- test.rb ----------

---------- 実行結果 ----------
/usr/share/gems/gems/rdoc-4.0.0/lib/rdoc/ruby_token.rb:65:in `%': can't convert nil into Integer (TypeError)
        from /usr/share/gems/gems/rdoc-4.0.0/lib/rdoc/ruby_token.rb:65:in `inspect'
        from test.rb:3:in `p'
        from test.rb:3:in `<main>'
---------- 実行結果 ----------

当該箇所は以下の部分で、 @seek の値が nil になっていることが原因でした。

---------- ruby_token.rb ----------
    def inspect # :nodoc:
      klass = self.class.name.split('::').last
      "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @text]
    end
---------- ruby_token.rb ----------

以下のように nil の代わりに値を渡してやると、正常に実行できました。

---------- test.rb ----------
require '/usr/share/rubygems/rubygems/rdoc.rb'
tk = RDoc::RubyToken::Token.new 0, 1, 1
p tk
---------- test.rb ----------

---------- 実行結果 ----------
{Token 0, 1:1 nil}
---------- 実行結果 ----------

これは、 VM 側のバグなのでしょうか?それとも、 inspect 処理の中で想定外の値が
入っていると実行時エラーになるため、想定外の値が入っていないことを保証できない
オブジェクトに対して rb_inspect() を呼ぶのは危険であるということでしょうか?

とりあえず、以下のように修正をすることで、

./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems "./bin/rdoc" --root "." --page-dir "./doc" --encoding=UTF-8 --all --ri --op ".ext/rdoc"  "." --debug

というコマンドラインが最後のファイルまで処理した後でエラーが出るという段階まで
進めることを確認できました。

----------
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 087d56f..d42bf0a 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -666,7 +666,7 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
 
       #meth_obj.params = params
       meth_obj.start_collecting_tokens
-      tk = RDoc::RubyToken::Token.new nil, 1, 1
+      tk = RDoc::RubyToken::Token.new 0, 1, 1
       tk.set_text body
       meth_obj.add_token tk
       meth_obj.comment = comment
@@ -685,7 +685,7 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
       find_modifiers comment, meth_obj
 
       meth_obj.start_collecting_tokens
-      tk = RDoc::RubyToken::Token.new nil, 1, 1
+      tk = RDoc::RubyToken::Token.new 0, 1, 1
       tk.set_text body
       meth_obj.add_token tk
       meth_obj.comment = comment
----------

----------
Parsing sources...
  0% [ 1/895]  /root/ruby/doc/ChangeLog-0.06_to_0.52
  0% [ 2/895]  /root/ruby/doc/ChangeLog-0.50_to_0.60
  0% [ 3/895]  /root/ruby/doc/ChangeLog-0.60_to_1.1
(中略)
 99% [893/895]  vm_method.c
 99% [894/895]  vm_trace.c
100% [895/895]  vsnprintf.c
stack level too deep
/root/ruby/lib/rdoc/class_module.rb:700:in `superclass'
        /root/ruby/lib/rdoc/normal_class.rb:13:in `ancestors'
        /root/ruby/lib/rdoc/normal_class.rb:18:in `ancestors' (という行の 10915 回繰り返し)
        /root/ruby/lib/rdoc/store.rb:307:in `block in complete'
        /root/ruby/lib/rdoc/store.rb:307:in `each'
        /root/ruby/lib/rdoc/store.rb:307:in `complete'
        /root/ruby/lib/rdoc/rdoc.rb:492:in `document'
        ./bin/rdoc:20:in `<main>'
----------

キャパシティオーバーのように見えますが、何故 10915 回も再帰呼出しが
発生しているのかは不明です。

---------- normal_class.rb ----------
class RDoc::NormalClass < RDoc::ClassModule

  ##
  # The ancestors of this class including modules.  Unlike Module#ancestors,
  # this class is not included in the result.  The result will contain both
  # RDoc::ClassModules and Strings.

  def ancestors
    if String === superclass then (←ここが13行目の呼出しです。)
      super << superclass
    elsif superclass then
      ancestors = super
      ancestors << superclass
      ancestors.concat superclass.ancestors (←ここが18行目の呼出しです。)
    else
      super
    end
  end
---------- normal_class.rb ----------

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-03-16  1:39 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-28  5:06 [ruby-dev:49993] メソッド呼び出し時の引数の値を VM 側で取得する方法について Tetsuo Handa
2017-02-28  5:13 ` [ruby-dev:49994] " SASADA Koichi
2017-02-28  5:47   ` [ruby-dev:49996] " Tetsuo Handa
2017-02-28  7:50     ` [ruby-dev:49998] " SASADA Koichi
2017-02-28  5:16 ` [ruby-dev:49995] " SASADA Koichi
2017-02-28  5:53   ` [ruby-dev:49997] " Tetsuo Handa
2017-02-28  7:56     ` [ruby-dev:49999] " SASADA Koichi
2017-03-01 11:28       ` [ruby-dev:50000] " Tetsuo Handa
2017-03-02  6:37         ` [ruby-dev:50001] " Nobuyoshi Nakada
2017-03-02  7:41           ` [ruby-dev:50002] " Tetsuo Handa
2017-03-13 10:18             ` [ruby-dev:50019] " Tetsuo Handa
2017-03-16  2:13               ` [ruby-dev:50020] " Tetsuo Handa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).