<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Dear All,<div class=""><br class=""></div><div class="">I am facing a weird problem while instrumenting a Kotlin data class using soot [1].</div><div class=""><br class=""></div><div class="">The problem is that after instrumenting the class, the byte code verifier rejects the class.</div><div class=""><br class=""></div><div class="">The method causing this seems to be “copy” that contains those units:</div><div class=""><br class=""></div><div class=""><div class="">r0 := @this: com.orgzly.android.util.Encoding</div><div class="">$r1 := @parameter0: java.lang.String</div><div class="">$r2 := @parameter1: java.lang.String</div><div class="">$r3 := @parameter2: java.lang.String</div><div class="">staticinvoke <kotlin.jvm.internal.Intrinsics: void checkNotNullParameter(java.lang.Object,java.lang.String)>($r1, "used")</div><div class="">r0 = new com.orgzly.android.util.Encoding</div><div class="">specialinvoke r0.<com.orgzly.android.util.Encoding: void <init>(java.lang.String,java.lang.String,java.lang.String)>($r1, $r2, $r3)</div><div class="">return r0</div></div><div class=""><br class=""></div><div class="">The same method after the instrumentation looks like the one reported below (I simplified it), where the units marked with ** are the code injected via soot.</div><div class=""><br class=""></div><div class="">The instrumentations </div><div class=""><span class="Apple-tab-span" style="white-space:pre">       </span>- encapsulates all the parameters of method calls into generic arrays of objects</div><div class=""><span class="Apple-tab-span" style="white-space:pre">  </span>- invokes a Monitor class to track method invocations (before/after) and captures return values</div><div class=""><span class="Apple-tab-span" style="white-space:pre">   </span>- wraps the method with a generic try-catch-all where the catch block logs the captured exception before rethrowing it</div><div class=""><br class=""></div><div class="">Now the weirdness (IMHO) is that r0 is assigned first to @this and then to something different (<span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">r0 = new com.orgzly.android.util.Encoding).</span></div><div class=""><font color="#000000" class="">This is part of the original code (see above), but I am afraid it might break the instrumented code because we pass r0 as parameter to other invocations in the catch block,</font></div><div class=""><font color="#000000" class="">under the assumption it points to “this”, </font><span style="color: rgb(0, 0, 0);" class="">while in reality it points to another instance of the same type.</span></div><div class=""><font color="#000000" class="">Consequently, </font><font color="#000000" class="">the </font><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">bytecode verifier reports the first call using it </span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""> in the catch block </span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">(</span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">staticinvoke <Monitor: void onAppMethodCaptureException</span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">)  as invalid (with </span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">type conflict)</span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""><br class=""></span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">Maybe someone has experiences something similar and/or can suggest a work around? Assuming this is indeed the problem, the only option I see at the moment</span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""> is to assign the return of </span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""> </span><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">r0 = new com.orgzly.android.util.Encoding to a fresh local variable (rX)</span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""><br class=""></span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">Any help is appreciated !</span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""><br class=""></span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">Best</span></div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class=""><br class=""></span></div><div class=""><font color="#000000" class=""><span style="caret-color: rgb(0, 0, 0);" class="">— Dr. Alessio Gambi</span></font></div><div class=""><font color="#000000" class=""><span style="caret-color: rgb(0, 0, 0);" class="">Chair for SE 2</span></font></div><div class=""><font color="#000000" class=""><span style="caret-color: rgb(0, 0, 0);" class="">University of Passau</span></font></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">—————</div><div class=""><span style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);" class="">[1] </span><a href="https://github.com/orgzly/orgzly-android/blob/master/app/src/main/java/com/orgzly/android/util/Encoding.kt" class="">https://github.com/orgzly/orgzly-android/blob/master/app/src/main/java/com/orgzly/android/util/Encoding.kt</a></div><div class=""><br class=""></div><div class=""><div class="">INSTRUMENTED CODE:</div><div class="">                 r0 := @this: com.orgzly.android.util.Encoding</div><div class="">                 $r1 := @parameter0: java.lang.String</div><div class="">                 $r2 := @parameter1: java.lang.String</div><div class="">                 $r3 := @parameter2: java.lang.String</div><div class="">**               $r5 = newarray (java.lang.Object)[3]</div><div class="">**               $r5[0] = $r1</div><div class="">**               $r5[1] = $r2</div><div class="">**               $r5[2] = $r3</div><div class="">**               staticinvoke <Monitor: void onAppMethodCall(java.lang.String,java.lang.Object,java.lang.String,java.lang.Object[])>("com.orgzly", r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r5)</div><div class="">**               $r6 = newarray (java.lang.Object)[2]</div><div class="">**               $r6[0] = $r1</div><div class="">**               $r6[1] = "used"</div><div class="">**               staticinvoke <Monitor: void onLibMethodCall(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object[])>(null, "<kotlin.jvm.internal.Intrinsics: void checkNotNullParameter(java.lang.Object,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r6)</div><div class="">                 staticinvoke <kotlin.jvm.internal.Intrinsics: void checkNotNullParameter(java.lang.Object,java.lang.String)>($r1, "used")</div><div class="">**               staticinvoke <Monitor: void onLibMethodReturnNormally(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(null, "<kotlin.jvm.internal.Intrinsics: void checkNotNullParameter(java.lang.Object,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", null)</div><div class=""><br class=""></div><div class="">                 r0 = new com.orgzly.android.util.Encoding</div><div class="">                 specialinvoke r0.<com.orgzly.android.util.Encoding: void <init>(java.lang.String,java.lang.String,java.lang.String)>($r1, $r2, $r3)</div><div class="">**               staticinvoke <Monitor: void onAppMethodReturnNormally(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", r0)</div><div class="">                 return r0</div><div class=""><br class=""></div><div class="">**               $r0 := @caughtexception</div><div class="">**               $r7 = $r0</div><div class="">**               staticinvoke <Monitor: void onAppMethodCaptureException(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r0)</div><div class="">**               $r4 = $r0</div><div class="">**               staticinvoke <Monitor: void onAppMethodThrowException(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r4)</div><div class="">**               staticinvoke <Monitor: void onAppMethodReturnExceptionally(java.lang.Object,java.lang.String,java.lang.String,java.lang.Object)>(r0, "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", "<com.orgzly.android.util.Encoding: com.orgzly.android.util.Encoding copy(java.lang.String,java.lang.String,java.lang.String)>", $r4)</div><div class="">**               throw $r4</div></div><div class=""><br class=""></div><div class=""><br class=""></div></body></html>