diff --git a/baksmali/src/test/smali/deodex_test1/main.smali b/baksmali/src/test/smali/deodex_test1/main.smali index 52d2eadf..e13aa8d2 100644 --- a/baksmali/src/test/smali/deodex_test1/main.smali +++ b/baksmali/src/test/smali/deodex_test1/main.smali @@ -5,40 +5,70 @@ .method public static main([Ljava/lang/String;)V .registers 3 - const v2, 0 + here4: + const v0, 0 + + here3: + + new-instance v2, Lsuperclass; + invoke-direct {v2}, Lsuperclass;->()V + + if-eqz v0, here2: - new-instance v0, Lsubclass; - invoke-direct {v0}, Lsubclass;->()V + #this is the unresolvable instruction. v0 is always null, + #and this will always throw an exception. Everything below + #here, until the here2: label is dead code, and should be + #commented out. This instruction itself should be be replaced + #with a call to Ljava/lang/Object;->hashCode()I, followed + #by a goto/32 0, which is just there to prevent dexopt from + #thinking that execution will fall off the end of the method + #i.e. if all the code following this was dead (and thus commented + #out) + invoke-virtual {v0}, Lrandomclass;->getSuperclass()Lsuperclass; + move-result-object v1 - invoke-virtual {v0}, Lsubclass;->somemethod()V + + #a branch to outside the dead code. The branch label should not + #be commented out, because there is a non-dead instruction + #that branches to it + if-eqz v0, here2: - goto here2: + + #a branch to inside the dead code. the branch label should be + #commented out + if-eqz v0, here: + + #another branch to outside the dead code. In this case, the "dead" + #instruction is the first instruction that references the label. + #the label should not be commented out, because it is referenced + #be a non-dead instruction + if-eqz v0, here3: + + #one more branch to out the dead code. the branch label should be + #commented out, because there are no other non-dead instructions + #referenceding it + if-eqz v0, here4: + + #another odexed instruction that uses the result of the + #first unresolveable odex instruction. this should + #appear as a commented invoke-virtual-quick instruction + invoke-virtual {v1}, Lsuperclass;->somemethod()V here: - const v2, 1 + #a resolveable odex instruction in the dead code. It should be resolved, + #but still commented out + invoke-virtual {v2}, Lsuperclass;->somemethod()V + + here2: - #this instruction is tricky for the deodexer, because once everything gets - #odexed, then static inspection shows the type of v0 to be Lsubclass; - #from the above new-instance instruction. - #so the first pass at deodexing this instruction will incorrectly resolve it - #to Lsubclass->somemethod()V - #It's not until the following invoke-virtual call to - #Lrandomclass;->getSuperclass()Lsuperclass is deodexed that it will be able to - #determine that the type of v0 is actually Lsuperclass;, and not Lsubclass;, and - #so it has to be re-deodexed when it discovers the new register type information - invoke-virtual {v0}, Lsuperclass;->somemethod()V + #and we're back to the non-dead code + invoke-virtual {v2}, Lsuperclass;->somemethod()V + + if-nez v0, here3: - new-instance v1, Lrandomclass; - invoke-direct {v1}, Lrandomclass;->()V - - invoke-virtual {v1}, Lrandomclass;->getSuperclass()Lsuperclass; - move-result-object v0 - - if-eqz v2, here: - return-void .end method \ No newline at end of file