The this
Reference
For every instance (virtual, non-static) method in Dalvik, the first parameter is a reference to itself, or, in Java, the this
reference. I wanted to know if it was legal to reassign the register value.
Just so I’m sure you know what I’m talking about, here’s a simple Java class with an instance method called instanceMethod
:
1 | public class Instance { |
The above Smali gets turned into this (you can safely ignore the <init>()V
method):
1 | .class public LInstance; |
For more information on how to convert Java to Smali, check out: Understanding Dalvik Static Fields 1 of 2 and Building with and Detecting Android’s Jack Compiler.
PROTIP: If your decompilation looks different than mine, it may be because mine was generated using baksmali --use-locals
which separates the registers into those registers used within the method body (locals) and those passed as parameters. Local registers are named v0
, v1
, v2
, and so on and the parameters are named p0
, p1
, etc. I always use --use-locals
because it makes it a bit easier to visually distinguish between local method registers and method arguments.
The default behavior is to name all registers based on how they’re actually laid out by Dalvik: r0
, r1
, r2
and so on, regardless of if they’re local or parameters. To clarify, a method like this:
1 | public example(JI)V |
Has a register layout like this:
r0
,r1
,r2
- local registersr3
-this
register (p0
with--use-locals
)r4
&r5
-J
parameter (wide types use two registers)r6
-I
parameter
The Question
I wondered if p0
was somehow special and if it was possible to rewrite it. One of the optimizers I’m working on needs to rewrite Smali, and it works best if it knows all of the available registers at a certain point in code. A register is “available” if it’s not used for the rest of the execution. If you’ve ever written a tool to automatically modify Smali, you have probably run into this problem.
Spoiler warning: p0
is not special and it is possible to reassign!
Here’s the code I used to test:
1 | .class public LHello; |
And then to compile and run it:
1 | $ smali hello.smali -o classes.dex && zip Hello.zip classes.dex && adb push Hello.zip /data/local && adb shell dalvikvm -cp /data/local/Hello.zip Hello |
The test code outputs the expected 5
with no errors or warnings. It makes sense that a register should be able to hold a reference to anything, but the only way to be absolutely sure (without closely examining the source) is to test it.
Summary
Now you know the p0
register can be re-purposed within code, but more importantly you’ve hopefully also picked up some techniques for testing hypotheses. If you’re doing a lot of low-level Smali analysis, it’s really handy to know how to translate Java to Smali and how to execute DEX files directly on the command line.