バイナリーパッチを試してみた

前回の話(http://d.hatena.ne.jp/miura1729/20080806/1218026143)を試してみました。こんな感じの手抜きプログラムを使って試しました。本当はこの後write barrierのチェックコードの挿入が必要ですが、今回は手抜きでどこがストア命令か教えてくれるだけです。

#!/bin/env ruby

# ニモニックパターンの定義

NIMONIC_FILE_NAME = /^\s*\.file\s+\"(.*?)\"/
NIMONIC_LINE_NUMNER = /^\s*\.stabn\s+.*?,.*?,(.*?),/
NIMONIC_STORE  = /^\s*movl\s+(.*?)\s*,\s*(-?[0-9]+)?\((.*?)\)/
REGISTOR_STACK = ["%esp"]
REGISTOR_BESE_POINTER = ["%ebp"]

REGISTOR_SPBP = REGISTOR_BESE_POINTER + REGISTOR_STACK

@curfile = nil
@file_content = nil
@curline = nil
ARGF.each_line do |lin|
  case lin
  when NIMONIC_FILE_NAME
    @curfile = $1
    @file_content = File.readlines(@curfile)

  when NIMONIC_LINE_NUMNER
    @curline = $1

  when NIMONIC_STORE
    src = $1
    offset =  $2 ? $2 : ""
    basereg = $3

    if !REGISTOR_SPBP.include?(basereg) then
      print "#{@curfile}:#{@curline}"
      print @file_content[@curline.to_i - 1]
    end
  end
end

いろいろ調べたところ、.file命令でCのファイル名が.stabnの第3引数でCレベルの行番号が得られるようです。
これを、使ってruby 1.9.0のgc.cで-S -gオプションをつけて試してみました。
一見、代入じゃないところも検出しているように見えますが、多分代入になっていると思います。
結果です。

gc.c:387	rb_thread_raised_clear(th);
gc.c:388	GET_THREAD()->errinfo = nomem_error;
gc.c:391    rb_thread_raised_set(th, RAISED_NOMEMORY);
gc.c:426    ruby_gc_stress = RTEST(bool);
gc.c:462    ruby_gc_profile = RTEST(bool);
gc.c:465 objspace->profile.count = 0;
gc.c:497    malloc_increase += size;
gc.c:536    malloc_increase += size;
gc.c:629    dont_gc = Qfalse;
gc.c:651    dont_gc = Qtrue;
gc.c:671    tmp->next = global_List;
gc.c:672    tmp->varptr = addr;
gc.c:673    global_List = tmp;
gc.c:683	global_List = tmp->next;
gc.c:691	    tmp->next = tmp->next->next;
gc.c:707    RUBY_CRITICAL(
gc.c:707    RUBY_CRITICAL(
gc.c:717    heaps_length = next_heaps_length;
gc.c:760    heaps[hi].membase = membase;
gc.c:761    heaps[hi].slot = p;
gc.c:762    heaps[hi].limit = objs;
gc.c:764    if (lomem == 0 || lomem > p) lomem = p;
gc.c:765    if (himem < pend) himem = pend;
gc.c:769	p->as.free.flags = 0;
gc.c:770	p->as.free.next = freelist;
gc.c:771	freelist = p;
gc.c:790    heaps_inc = 0;
gc.c:798    heaps_inc = next_heaps_length - heaps_used;
gc.c:830    freelist = freelist->as.free.next;
gc.c:886	dont_gc = 1;
gc.c:887	during_gc = 0;
gc.c:915    n->flags |= T_NODE;
gc.c:916    nd_set_type(n, type);
gc.c:918    n->u1.value = a0;
gc.c:919    n->u2.value = a1;
gc.c:920    n->u3.value = a2;
gc.c:930    OBJSETUP(data, klass, T_DATA);
gc.c:930    OBJSETUP(data, klass, T_DATA);
gc.c:930    OBJSETUP(data, klass, T_DATA);
gc.c:931    data->data = datap;
gc.c:932    data->dfree = dfree;
gc.c:933    data->dmark = dmark;
gc.c:975    SET_STACK_END;
gc.c:976    if (p) *p = STACK_UPPER(STACK_END, STACK_START, STACK_END);
gc.c:985    SET_STACK_END;
gc.c:999    mark_stack_overflow = 0;
gc.c:1000    mark_stack_ptr = mark_stack;
gc.c:1221		*mark_stack_ptr = ptr;
gc.c:1225		mark_stack_overflow = 1;
gc.c:1510	    p->as.free.flags = 0;
gc.c:1511	    p->as.free.next = freelist;
gc.c:1512	    freelist = p;
gc.c:1536		heaps[j] = heaps[i];
gc.c:1536		heaps[j] = heaps[i];
gc.c:1536		heaps[j] = heaps[i];
gc.c:1544	    heaps_freed = last;
gc.c:1567    freelist = 0;
gc.c:1569    deferred_final_list = 0;
gc.c:1582		    p->as.free.flags = FL_MARK; /* remain marked */
gc.c:1583		    p->as.free.next = final_list;
gc.c:1588		    p->as.free.flags = 0;
gc.c:1589		    p->as.free.next = freelist;
gc.c:1590		    freelist = p;
gc.c:1599		RBASIC(p)->flags &= ~FL_MARK;
gc.c:1607	    heaps[i].limit = 0;
gc.c:1609		p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
gc.c:1611	    freelist = free;	/* cancel this page from freelist */
gc.c:1617    GC_PROF_SET_MALLOC_INFO;
gc.c:1617    GC_PROF_SET_MALLOC_INFO;
gc.c:1619	malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
gc.c:1620	if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
gc.c:1622    malloc_increase = 0;
gc.c:1627    during_gc = 0;
gc.c:1636   deferred_final_list = final_list;
gc.c:1644	GC_PROF_SET_HEAP_INFO;
gc.c:1644	GC_PROF_SET_HEAP_INFO;
gc.c:1644	GC_PROF_SET_HEAP_INFO;
gc.c:1644	GC_PROF_SET_HEAP_INFO;
gc.c:1644	GC_PROF_SET_HEAP_INFO;
gc.c:1645	deferred_final_list = final_list;
gc.c:1649    GC_PROF_SET_HEAP_INFO;
gc.c:1649    GC_PROF_SET_HEAP_INFO;
gc.c:1649    GC_PROF_SET_HEAP_INFO;
gc.c:1649    GC_PROF_SET_HEAP_INFO;
gc.c:1649    GC_PROF_SET_HEAP_INFO;
gc.c:1657    RANY(p)->as.free.flags = 0;
gc.c:1658    RANY(p)->as.free.next = freelist;
gc.c:1659    freelist = RANY(p);
gc.c:1823    SET_STACK_END;
gc.c:1886    GC_PROF_TIMER_START;
gc.c:1886    GC_PROF_TIMER_START;
gc.c:1886    GC_PROF_TIMER_START;
gc.c:1886    GC_PROF_TIMER_START;
gc.c:1888    SET_STACK_END;
gc.c:2163    FL_SET(obj, FL_FINALIZE);
gc.c:2168	finalizer_table = st_init_numtable();
gc.c:2190    FL_SET(dest, FL_FINALIZE);
gc.c:2231    deferred_final_list = 0;
gc.c:2249	p->as.free.flags = FL_MARK; /* remain marked */
gc.c:2250	p->as.free.next = *final_list;
gc.c:2251	*final_list = p;
gc.c:2267	    deferred_final_list = 0;
gc.c:2282		p->as.free.flags = 0;
gc.c:2293		    p->as.free.flags = 0;
gc.c:2300    during_gc = 0;
gc.c:2475        counts[i] = 0;
gc.c:2667			      rb_obj_freeze(rb_str_new2("failed to allocate memory")));
gc.c:2668    OBJ_TAINT(nomem_error);
gc.c:2669    OBJ_FREEZE(nomem_error);