libgcj2

コンパイラの解析 (2)
GCJのデータ構造 - 1
Suguru ARAKAWA
Faculty of Computer and Information Sciences,
Hosei University
Table of Contents
おさらい
Cygnus Native Interface
インスタンス構造の推測
Virtual Method Table
Instance Fields
おさらい (1)
GNU Java Compiler (gcj)が使用するJavaの
実行時ライブラリ
 Java
VM + Java APIをコンパイルしたもの
これを外側から使用すれば、Javaコンパイラの
作成が可能
おさらい (2)
ちょっとしたルールさえ知っていれば、JavaのAPI
をC言語からも使える
例:sin.java.lang.Math.sinの外部利用 (2)
実行例
double _ZN4java4lang4Math3sinEd(double);
int main() {
printf("sin(3.14) = %lf\n", _ZN4java4lang4Math3sinEd(3.14));
}
おさらい (3)
 Javaの機能を全て実現するには、下記のことも考慮し
なければならない










Javaの名前空間とオブジェクトファイルの名前空間
クラスの登録
クラスの初期化
インスタンスの生成
ポリモーフィズムの実現
配列の扱い
インスタンスの破棄
ガーベジコレクタとの調和
例外の処理
synchronizeの処理
Cygnus Native Interface (CNI)
GCJでC++を使ってネィティブメソッドを書く方法
 JNIより効率よくメソッド呼び出し
 移植性は低い
(GCJでしか動かない)
CNIの利用 (1)
まずは単純なクラスを作成
 nativeメソッドとして宣言
public class Cni {
public static native void main(String[] args);
}
CNIの利用 (2)
次のコマンドを入力
javac Cni.java
gcjh Cni
javac Cni.java
 クラスファイルを生成
(gcj –C Cni.java と同様)
gcjh Cni
 CniクラスのCNIヘッダを生成
CNIの利用 (3)
以下のような宣言を含むヘッダが生成される
class Cni : public ::java::lang::Object
{
public:
Cni ();
static void main (JArray< ::java::lang::String *> *);
static ::java::lang::Class class$;
};
CNIの利用 (4)
次のように書ける
#include "Cni.h"
#include <stdio.h>
#include <gcj/array.h>
#include <java/lang/String.h>
void Cni::main(JArray<java::lang::String *> *args) {
puts("Hello, CNI!");
}
CNIの利用 (5)
コンパイルして実行
$ gcj --main=Cni Cni.class natCni.cc
$ ./a.out
Hello, CNI!
仮説
同じようなオブジェクトコードを生成すればJava
から呼び出せる
C言語からJavaの関数を呼び出せるのは前述
の通り
問題点
GCJはJavaをC言語に変換できない
 -S
でアセンブルコードには変換できる
アセンブラを読む/オブジェクトコードを読む
 デバッガも併用
大規模なので相当がんばる必要あり
インスタンス構造の推測
インスタンスは2つの情報を持つ
インスタンスごとに固有の情報
 インスタンスフィールド
同じクラスのインスタンスで共通の情報
(instance of java.lang.Class)
 Virtual Method Table (vtable)
 クラスの情報
For your information…
古いOfficial Java VMでのインスタンス構造
 Instance
Fields + Instance Methods
Virtual Method Table (VTable)
仮想メソッド(Javaの普通のメソッド)を呼び出す
ためのテーブル
 ポリモーフィズムの実現に
Interface Method Tableもある
VTableの構造 (1)
基底クラスでは通常のメソッドテーブル
 call
obj->vtable[5] : Object::toString()
VTableの構造 (2)
オーバーライドしたメソッドはテーブルを上書き
 call
obj->vtable[6] : Hoge::toString()
VTableの構造 (3)
同じシーケンスで子クラスのメソッドを呼べる
 インスタンスごとに何を呼ぶのか変動する
Virtual Method呼び出しのトレース
Hoge.javaをコンパイルして追ってみる
 Hoge::foo
_ZN4Hoge3fooEv:
... (prologue)
movl (%eax), %edx
addl $20, %edx
>vtable[5])
pushl %eax
movl (%edx), %eax
call *%eax
;
;
;
;
Hoge::foo()
eax = this
edx = this->vtable
edx = &(this-
; args[0] = this
; eax = this->vtable[5]
; call this->vtable[5]
解析1 – VTableを探す (1)
どうやって解析しよう?
VTableを探す (2)
下記(Hoge.s:34)にブレークポイントを貼る
_ZN4Hoge3fooEv:
... (prologue)
movl
; Hoge::foo()
; eax = this
(%eax), %edx ; edx = this->vtable
addl $20, %edx
>vtable[5])
pushl %eax
; edx = &(this; args[0] = this
movl
(%edx), %eax ; eax = this->vtable[5]
call
*%eax
; call this->vtable[5]
VTableを探す (3)
Break Point + Examine Memory
$ gdb a.out
(gdb) break Hoge.s:34
(gdb) run
Breakpoint 1, Hoge::foo () at Hoge.s:34
34
movl
(%eax), %edx
(gdb) x *$eax
0x80492c8 <_ZTVN4HogeE+8>: ...
VTableを探す (4)
Hoge.s:163 – 明らかにVTable
_ZTVN4HogeE:
.long 0
.long 0
.long _ZN4Hoge6class$E
.long 4
.long _ZN4java4lang6Object8finalizeEv
.long _ZN4java4lang6Object8hashCodeEv
.long _ZN4java4lang6Object6equalsEPS1_
.long _ZN4Hoge8toStringEv
.long _ZN4java4lang6Object5cloneEv
.long _ZN4Hoge3fooEv
インスタンスの構造 (1)
ここまでは判明
解析2 – Instance Fieldを探す (1)
今度はどうする?
Instance Fieldを探す (2)
方針
 インスタンスフィールドを使うプログラムを用意
 アセンブルファイルへとコンパイル
 ハンドトレース
 デバッガで確認
Instance Fieldを探す (3)
下記のようなクラスを作ってコンパイル
 gcj
–S –O0 Foo.java # -> Foo.s
public class Foo {
int field0;
int field1;
void m0() { this.field0 = 123; }
void m1() { this.field1 = 456; }
}
Instance Fieldを探す (4)
ハンドトレースすると自明なものが登場
 デバッガでトレースするまでも無い
_ZN3Foo2m0Ev:
.. (prologue)
; this.field0 = 123
; eax = this
movl $123, 4(%eax) ; *(int *)(this+4) = 123
_ZN3Foo2m1Ev:
.. (prologue)
; this.field1 = 456
; eax = this
movl $456, 8(%eax) ; *(int *)(this+8) = 456
インスタンスの構造 (2)
最低限は判明
次回
 興味のあるところから










Javaの名前空間とオブジェクトファイルの名前空間
クラスの登録
クラスの初期化
インスタンスの生成
ポリモーフィズムの実現 : 今回分
配列の扱い
インスタンスの破棄
ガーベジコレクタとの調和
例外の処理
synchronizeの処理