4

I've been looking at a simple method in smali (coming from Android here), and any I was wondering how I'd do something simple to it, such as return false. I've been trying to understand it from comparing with the Java counterparts to some examples and I think I get how most of it works, but any changes I make don't seem to go well.

Currently, in Java the method is:

public static boolean isEnabled(){
    return com.example.test.isEnabled();
}

and in smali it's:

.method public static isEnabled()Z
    .registers 1

    .prologue
    .line 3714
    invoke-static {}, Lcom/example/test;->isEnabled()Z

    move-result v0

    return v0
.end method

In the context above, how would I modify the method to just do the equivalent of Java return false;? From what I've been able to see, 0x0 is false, but just returning that causing issue when compiling the smali (expecting REGISTER?) so I was wondering what exactly I'd need to do.

A solution, as well as an explanation, would be appreciated! It's not for anything in particular, I just like to look at this stuff.

whitfin
  • 4,539
  • 6
  • 39
  • 67
  • 1
    `move-result` only takes a register. You can load zero into register v0 with `const/4 v0, 0`. See http://milk.com/kodebase/dalvik-docs-mirror/docs/dalvik-bytecode.html (or http://source.android.com/devices/tech/dalvik/dalvik-bytecode.html, but the formatting isn't as easy to deal with). – fadden Aug 26 '13 at 23:32

1 Answers1

15

You could answer this yourself fairly easily by writing a quick java program, compiling it, dx'ing it, then disassembling it.

public class EnabledTest {
    public static boolean isEnabled() {
        return false;
    }
}

And then compile/dx/disassemble it

javac EnabledTest.java
dx --dex --output=EnabledTest.dex EnabledTest.class
baksmali EnabledTest.dex

And you'll end up with something like

.method public static isEnabled()Z
    .registers 1
    const v0, 0
    return v0
.end method
JesusFreke
  • 19,784
  • 5
  • 65
  • 68
  • 1
    Oh, so you can just use 0 for false? And thanks for the commands. Also, would the line reference not need to be there then? – whitfin Aug 26 '13 at 23:56
  • Yes, there is no specific "boolean" type at the bytecode level, just 0 and 1. I'm not positive, but I don't *think* you could use an arbitrary non-zero value as true, I think it has to be 1. – JesusFreke Aug 27 '13 at 02:33
  • 1
    The line numbers are just debug information. They are used to add the line numbers in exception traces, and to map back to the original source location while debugging. But you can safely remove them without affecting the actual functionality of the program. – JesusFreke Aug 27 '13 at 02:35
  • 2
    The bytecode verifier in Dalvik is more picky than the verifier in other popular VMs. A value other than 0 or 1 should not be accepted as a boolean value. – fadden Aug 27 '13 at 05:15
  • @JesusFreke Ah okay, I thought perhaps it was used to keep track of where it was somehow in terms of execution or something. Makes sense it's just debug though. – whitfin Aug 27 '13 at 11:08
  • @fadden Okay, I must've been mistaked then, I thought I saw `const v0, 0x0` on a value which in Java was `var = false`. – whitfin Aug 27 '13 at 11:09
  • 1
    @Zackehh9lives: To be clear: 0 is false, 1 is true. 0x0 is 0. 0 can also be a null reference, and the number zero. Dalvik's bytecode verifier keeps track of the "widest" that a number can be, and tries to prevent you from treating arbitrary `int`s as `boolean`, `byte`, `short`, etc. – fadden Aug 27 '13 at 14:46