prxモジュールを作ってAPIをフックしたい(2)

2ってつけたけど、挫折するのは早そうだなぁ……。出来るところまではいきたいけど。
とりあえず、関数のジャンプ先がどうなってるのかファイルに書き出して調べてみる。

int module_start(SceSize args, void *argp)
{
	unsigned int *func,tmp;int i;
	SceUID l = sceIoOpen("ms0:/log.txt",PSP_O_CREAT|PSP_O_WRONLY|PSP_O_TRUNC|0777);
	func=(unsigned int*)sceAudioChReserve;
	
 	for(i=0;i<16;++i){
		tmp=*(func++);
		sceIoWrite(l,&tmp,4);
	}
	sceIoClose(l);

	return 0;
}

で、出力をMIPSのドキュメントを読みながらハンド逆アセンブルしたのが下。

sceAudioChReserve=0x8821E2A0
op rs rt rd shamt funct|immed| target
 0 1F  0  0     0     8|    8|F800020 jr $31
 0  0  8 15    11     C| AC4C| 22B130 syscall
 2 10  1  9    1D     3| 4F43|8053D0C j 0x8053D0C

え?最初からreturnしてるとか、おかしいんじゃないの?とりあえず、書き換えてみる。

unsigned int target;
target = (unsigned int)dummyfunc;
target = (target >> 2) & 0x3FFFFFF;
*func = 0xC000000 | target; /*jal target*/

でもdummyfunc呼ばれない……。さらに先まで調べてみるか。

0x88053D0C
op rs rt rd shamt funct|immed| target
 9 1D 1D 1F    1F    30| FFF0|EF7FFC0 addiu $sp,$sp,0xFFF0
 0  0  0  5     0    21| 2821|   A084 addu $5,$0,$0
2B 1D 1F  0     0     0|    0|EFC0000 sw $31,0($sp)
 3 10  1  A     7     C| 51CC|8054730 jal 0x8054730
 9  0  6  0     0     1|    1| 180004 addiu $6,$0,0x1
23 1D 1F  0     0     0|    0|EFC0000 lw $31,$sp(0)
 0 1F  0  0     0     8|    8|F800020 jr $31

お、このjal書き換えるとうまくいきそうだな。

int (*orig)(int,int,int);/* グローバル変数にしてdummyfuncから呼ぶ */

func=(unsigned int*)sceAudioChReserve;
target=(unsigned int)dummyfunc;
target=((target>>2)&0x3FFFFFF);
func+=2;
func=(unsigned int*)((((*func)&0x3FFFFFF)<<2)|0x80000000);
func+=3;
orig=(int(*)(int,int,int))((*func&0x3FFFFFF)<<2|0x80000000);
*func=0xC000000|target;

お!呼ばれた。でも、ちゃんとフック出来てるかどうかはわからない。普通のやつならちゃんと音が出てるかどうかでわかるんだろうけど……。
9月4日 追記:なんてことを書いたけど、ほとんど間違ってた。詳しくはid:iselix:20080904:1220545995