Wednesday, May 13, 2009

About quick method invocation

A good 3 months ago I wrote about the ODEX format when support for that DEX variant was added to the dedexer tool. Then I asked if there is anybody out there who knows, how the index in the invoke-virtual-quick Dalvik instruction can be interpreted. For example:

invoke-virtual-quick {v1,v2},vtable #0x3b

That 3BH is an offset but into what? I did not know, therefore dedexer does not interpret the offset which makes its output on ODEX files less useful. Then Nenik (nickname according to his request) finally gave me the solution. Here comes his mail, verbatim.

The index computation is pretty simple, but for reverse analysis you need more data.

The vtable contains all the methods that can be invoked by invoke-virtual, that isall nonprivate member methods (even those final and native).The vtable is obviously constructed by copying superclass's vtable, then replacingoverridden methods and appending all additional virtual methods.

The methods in the vtable are ordered as they were in the dex file.Let's look at android.view.KeyCharacterMap for example. It extends java.lang.Object,so it starts with:Object:0: .method protected clone()Ljava/lang/Object;1: .method public equals(Ljava/lang/Object;)Z2: .method protected finalize()V3: .method public final native getClass()Ljava/lang/Class;4: .method public native hashCode()I5: .method public final native notify()V6: .method public final native notifyAll()V7: .method public toString()Ljava/lang/String;8: .method public final wait()V9: .method public final wait(J)Va: .method public final native wait(JI)V

Then it replaces:2: .method protected finalize()Vwith the implementation from KeyCharacterMap

and adds:b: .method public get(II)Ic: .method public getDisplayLabel(I)Cd: .method public getEvents([C)[Landroid/view/KeyEvent;e: .method public getKeyData(ILandroid/view/KeyCharacterMap$KeyData;)Zf: .method public getKeyboardType()I10: .method public getMatch(I[C)C11: .method public getMatch(I[CI)C12: .method public getNumber(I)C13: .method public isPrintingKey(I)Z

Anyway,invoke-virtual-quick {v1},vtable #0x2on an instance of any kind is simply the quick variant ofinvoke-virtual {v1}, Ljava/lang/Object;.finalize:()V

Obviously for decoding invoke-virtual-quick opcodes inside, say,framework.odex, you need the coresponding core.odex and ext.odexto reconstruct the vtables of all the base classes.

An .odex file contains a list of such dependencies appendedafter the body of the encapsulated dex, together with their SHA-1s:

2 comments:

One wrinkle that was elided above is that in order to know which vtable to look at, you need to know at least a superclass of the object being invoked on. Methods on Object are easy, but for anything else, you need to do at least a little bit of data flow analysis, along the lines of what the verifier does. You could of course start with the vm's verifier as a reference if nothing else.

About the blog

This blog is a personal diary about my adventures with the Google Android platform. I write it in the hope that others may find my experiences useful but please, beware. The blog is created as I gain experience about the platform myself so errors, omissions, etc. may be found in the entries.