Pergunta

Is there anything else that must be done to load a String constant into a register, and then using it in a method invocation, besides doing:

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

?

the following block of instructions

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

gave me the following logcat error messages:

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
Foi útil?

Solução

Your suspicions in this case are correct. The problem is because at the second Log->wtf instance, v6 was not necessarily set.

As to why this happens, it's important to note that very little verification is done when re-assembling the bytecode. In many cases, the assembler simply does not have enough information to do this level of verification - this would require the assembler have knowledge of the full set of classes that will be present when the application runs, similar to the case of deodexing (-o) or generating register info (-r).

These types of problems are caught by dalvik when verifies the bytecode, which is exactly what the error you mentioned is from.

Additionally, you mention "the values i used for p1 and p2 would have failed both if-eqz tests". This does not matter to dalvik's bytecode verifier. The verifier makes sure that all code paths are valid. It can't know or assume any particular value for the parameters that are passed in to the method.

If you want to see some additional information related to how the register types are propagated throughout the method, you can try the -r option for baksmali.

# 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>

This will add comments before/after every instruction with detailed information about the types of registers at that position.

Outras dicas

i changed some things around and got it to work, but i'm not sure why...

the change i did was to move the constant loading (const-string v6, "TEST CONSTANT") outside of the "if-block", resulting in

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

i suspect the reason for the initial problem is that if the flow bypassed the first "if-block" but entered the second "if-block", then the register v6 would not yet have been loaded before it was used.

the reason why i'm not so sure is because, when i ran the reassembled programme, the values i used for p1 and p2 would have failed both if-eqz tests (i.e. the flow would enter both "if-blocks").

so it seemed that,
1. the check for register v6 to be loaded before it was used was done preemptively before the actual control flow?
2. i thought such checking is only done at compile time?

i'm posting this as an answer as i needed more space to explain what i did. however, i'm still curious as to why such a change got it to work, so if anyone could give an explanation i'll mark that as the answer, thanks!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top