Coins Java - Experiment04

VTableからインスタンスメソッドを呼び出す

[Coins Java - Experiment]

目的

作業

前回のプログラムを流用する。

$ javac Overridden.java
$ gcc -c Overridden.class
$ gcjh Start
$ gcc -c natStart.cc

objdumpコマンドを利用し、Overridden.oのvtableを探す。

$ objdump -t Overridden.o

Overridden.o:     file format elf32-i386

SYMBOL TABLE:
00000000 l    df *ABS*  00000000 Overridden.class
00000000 l    d  .text  00000000
00000000 l    d  .data  00000000
00000000 l    d  .bss   00000000
000000a4 l     O .data  00000018 _CD_Overridden
00000000 l    d  .rodata        00000000
00000000 l     O .rodata        00000004 _Utf1
0000000c l     O .rodata        00000004 _Utf2
00000014 l     O .rodata        00000004 _Utf3
00000022 l     O .rodata        00000004 _Utf4
0000002a l     O .rodata        00000004 _Utf5
00000038 l     O .rodata        00000004 _Utf6
00000042 l     O .rodata        00000004 _Utf7
0000005c l     O .rodata        00000004 _Utf8
00000068 l     O .rodata        00000004 _Utf9
00000082 l     O .rodata        00000004 _Utf10
00000090 l     O .rodata        00000004 _Utf11
00000000 l     O .data  00000078 _MT_Overridden
000000bc l     O .data  00000006 _CT_Overridden
000000aa l     O .rodata        00000004 _Utf12
00000000 l    d  .jcr   00000000
00000000 l     O .bss   00000018 otable_syms
00000000 l    d  .eh_frame      00000000
00000000 l    d  .note.GNU-stack        00000000
00000000 l    d  .comment       00000000
00000000 g     F .text  00000017 _ZN10OverriddenC1Ev
00000000         *UND*  00000000 _ZN4java4lang6ObjectC1Ev
00000018 g     F .text  00000038 _ZN10Overridden8hashCodeEv
00000000         *UND*  00000000 _ZN4java4lang6System6class$E
00000000         *UND*  00000000 _Jv_InitClass
00000000         *UND*  00000000 _ZN4java4lang6System3outE
00000050 g     F .text  00000033 _ZN10Overridden8finalizeEv
00000084 g     F .text  00000038 _ZN10Overridden5cloneEv
000000bc g     F .text  00000038 _ZN10Overridden6equalsEPN4java4lang6ObjectE
000000f4 g     F .text  00000038 _ZN10Overridden8toStringEv
00000080 g     O .data  00000024 _ZTVN10OverriddenE
000000e0 g     O .data  0000006c _ZN10Overridden6class$E
00000000         *UND*  00000000 _ZTVN4java4lang5ClassE
00000000         *UND*  00000000 _ZN4java4lang6Object6class$E
00000000         *UND*  00000000 __gcj_personality_v0

経験上、以下のシンボルがVTableであると推測される。

c++filtというツールを利用し、本当にVTableであるか調査する。

$ c++filt --format java _ZTVN10OverriddenE
vtable for Overridden

いくつかのメソッドをオーバーライドしたクラスが持つメソッドを宣言する。

$ mv cCallNonvirtual.h cCallVirtual.h
$ emacs cCallVirtual.h
--- cCallVirtual.h
#ifndef __C_CALL_VIRTUAL_H
#define __C_CALL_VIRTUAL_H

extern long _ZTVN10OverriddenE[];

extern void _ZN10Overridden6class$E;
void _Jv_InitClass(void *);

long _ZN10Overridden8hashCodeEv(void *);
void _ZN10Overridden8finalizeEv(void *);
void *_ZN10Overridden5cloneEv(void *);
long _ZN10Overridden6equalsEPN4java4lang6ObjectE(void *, void *);
void *_ZN10Overridden8toStringEv(void *);

#endif /* __C_CALL_VIRTUAL_H */
---

各メソッドが配置されたアドレスと、VTableの中身をダンプするプログラムを書く。

$ emacs CoinsJavaP5.c
--- CoinsJavaP5.c
#include <stdio.h>
#include "cCallVirtual.h"

#define printaddr(func) printf("%s : %d\n", #func, func)
#define printvtable(i) printf("vtable[%d] : %d\n", i, _ZTVN10OverriddenE[i])

void langc(void) {

  _Jv_InitClass(&_ZN10Overridden6class$E);

  printaddr(_ZN10Overridden8hashCodeEv);
  printaddr(_ZN10Overridden5cloneEv);
  printaddr(_ZN10Overridden6equalsEPN4java4lang6ObjectE);
  printaddr(_ZN10Overridden8toStringEv);
  printaddr(_ZN10Overridden8finalizeEv);

  for (i=0; i<10; i++)
    printvtable(i);
}
---

コンパイル

$ gcj --main=Start Start.class natStart.o Overridden.o CoinsJavaP5.o

結果

以下のようになった。

$ ./a.out
_ZN10Overridden8hashCodeEv : 134515072
_ZN10Overridden8finalizeEv : 134515128
_ZN10Overridden5cloneEv : 134515180
_ZN10Overridden6equalsEPN4java4lang6ObjectE : 134515236
_ZN10Overridden8toStringEv : 134515292
vtable[0] : 0
vtable[1] : 0
vtable[2] : 134517248
vtable[3] : 4
vtable[4] : 134515128
vtable[5] : 134515072
vtable[6] : 134515236
vtable[7] : 134515292
vtable[8] : 134515180
vtable[9] : 0

vtable[4..8]に、メソッドがそれぞれ配置されている。

Copyright (C) 2002-2006 s.arakawa