0

String 定数をレジスタにロードし、それをメソッド呼び出しで使用するために行う必要があることは他にありますか?

const-string v6, "TEST CONSTANT"
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I

?

次の命令ブロック

iget-object v4, p0, Lcom/mypackage/MyClass;->myList:Ljava/util/List;
invoke-interface {v4, p1}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_0
const-string v6, "TEST CONSTANT"
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_0

invoke-interface {v4, p2}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_1
invoke-static {v6, p2}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_1

次のlogcatエラーメッセージが表示されました:

10-29 23:37:37.191: W/dalvikvm(515): VFY: register1 v6 type 2, wanted ref
10-29 23:37:37.241: W/dalvikvm(515): VFY: bad arg 0 (into Ljava/lang/String;)
10-29 23:37:37.241: W/dalvikvm(515): VFY:  rejecting call to Landroid/util/Log;.wtf (Ljava/lang/String;Ljava/lang/String;)I
10-29 23:37:37.241: W/dalvikvm(515): VFY:  rejecting opcode 0x71 at 0x0028
4

2 に答える 2

1

この場合のあなたの疑いは正しいです。問題は、2 番目の Log->wtf インスタンスで、v6 が必ずしも設定されていなかったためです。

なぜこれが起こるのかについては、バイトコードを再アセンブルするときに検証がほとんど行われないことに注意することが重要です。多くの場合、アセンブラは、このレベルの検証を行うための十分な情報を持っていません。これには、アセンブラが、dedexing (-o ) またはレジスタ情報の生成 (-r)。

これらのタイプの問題は、バイトコードを検証するときにdalvikによってキャッチされます。これは、まさにあなたが言及したエラーの原因です。

さらに、「p1 と p2 に使用した値は両方の if-eqz テストに失敗しただろう」と述べています。これは、dalvik のバイトコード ベリファイアには関係ありません。ベリファイアは、すべてのコード パスが有効であることを確認します。メソッドに渡されるパラメーターの特定の値を認識したり、想定したりすることはできません。

レジスタの型がメソッド全体にどのように伝播されるかに関する追加情報を確認したい場合は、baksmali の -r オプションを試すことができます。

# grab the full framework directory from your device
adb pull /system/framework framework
# run baksmali with the -r command
baksmali -r ARGS,DEST,FULLMERGE -d framework <apk_or_dex_file>

これにより、各命令の前後にコメントが追加され、その位置にあるレジスタのタイプに関する詳細情報が表示されます。

于 2012-10-31T18:18:37.373 に答える
0

いくつかのことを変更して動作させましたが、理由はわかりません...

私が行った変更は、定数読み込み ( const-string v6, "TEST CONSTANT") を「if ブロック」の外に移動することでした。

const-string v6, "TEST CONSTANT"
iget-object v4, p0, Lcom/mypackage/MyClass;->myList:Ljava/util/List;

invoke-interface {v4, p1}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_0
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_0

invoke-interface {v4, p2}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_1
invoke-static {v6, p2}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_1

最初の問題の理由は、フローが最初の「if-block」をバイパスして 2 番目の「if-block」に入った場合、レジスタv6が使用される前にまだロードされていないことにあると思われます。

よくわからない理由は、再アセンブルされたプログラムを実行したときに、使用した値p1p2両方のif-eqzテストに失敗したためです (つまり、フローが両方の「if ブロック」に入るためです)。

そのため、
1.使用される前にロードされるレジスタのチェックはv6、実際の制御フローの前にプリエンプティブに行われましたか?
2. このようなチェックはコンパイル時にのみ行われると思いましたか?

私がしたことを説明するためにより多くのスペースが必要だったので、これを回答として投稿しています。ただし、なぜそのような変更が機能するようになったのかについてはまだ興味があるので、誰かが説明を与えることができれば、それを答えとしてマークします、ありがとう!

于 2012-10-30T14:12:54.543 に答える