Android-smali文件格式

2017/8/30 posted in  Android

HelloWorld

首先写一个 HelloWorld 类:

package jiuyou.hello.info;

public class HelloWorld {
    public static void main(String[] args){
        System.out.println("hello world");
    }
}

然后生成 apk 再用 apktool 工具转成 smali 文件:

.class public Ljiuyou/hello/info/HelloWorld;    #定义类名
.super Ljava/lang/Object;                       #定义父类
.source "HelloWorld.java"                       #源文件名

# direct methods      #直接方法  (# virtual methods 为虚方法)
.method public constructor <init>()V      #构造函数
    .locals 0     #方法中使用到的局部变量个数

    .prologue     #代码起始指令
    .line 8       #源代码所在行数
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V         #调用父类构造方法

    return-void     #返回空
.end method         #方法结束

.method public static main([Ljava/lang/String;)V      #对应 main 方法
    .locals 2       #方法包含两个局部 v0,v1
    .param p0, "args"    # [Ljava/lang/String;   # main 方法的参数 agrs 标记为 p0

    .prologue       #代码起始指令
    .line 10
    sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;  #将 System.out 这个静态变量赋给 v0

    const-string v1, "hello world"    #构造字符串

    #方法调用(调用 v0 的方法 println ,v1 是参数)
    invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V    

    .line 11
    return-void
.end method

字段

静态字段格式如下:

# static fields
.field <访问权限> static [修饰关键字] <字段名>:<字段类型>

实例字段格式如下:

# instance fields
.field <访问权限> [修饰关键字] <字段名>:<字段类型>

举个栗子

java

private String name;

private final String sex="男";

public static int age;

smali :

# static fields
.field public static age:I

# instance fields
.field private name:Ljava/lang/String;

.field private final sex:Ljava/lang/String;

方法

方法有直接方法和虚方法两种,两者格式基本相同:

# direct methods  (virtual methods)
.method <访问权限> [修饰关键字] <方法原型>
    <.locals>
    [.parameter] or [.param]
    [.prologue]
    [.line]
    <代码体>
.end method

.locals:局部变量个数

.parameter or .param:指定每个参数

.prologue:代码的开始处,混淆过的代码可能没有该指令

.line:指定了该处指令在源代码中的行号,混淆过的代码可能没有该指令

举个栗子:

java

public String test(int a){
    int b=a+10;
    return "test";
}

smali

# virtual methods
.method public test(I)Ljava/lang/String;
    .locals 2
    .param p1, "a"    # I

    .prologue
    .line 11
    add-int/lit8 v0, p1, 0xa

    .line 12
    .local v0, "b":I
    const-string v1, "test"

    return-object v1
.end method

接口

interface 格式如下:

# interfaces
.implements <接口名>

举个例子:

java

public interface If {
    int demo(String s);
}

public class InterfaceTest implements If {
    @Override
    public int demo(String s) {
        return 0;
    }
}

smali

If.smali

# virtual methods
.method public abstract demo(Ljava/lang/String;)I
.end method

InterfaceTest.smali

# interfaces
.implements Ljiuyou/hello/info/If;

# virtual methods
.method public demo(Ljava/lang/String;)I
    .locals 1
    .param p1, "s"    # Ljava/lang/String;

    .prologue
    .line 11
    const/4 v0, 0x0

    return v0
.end method

注解

格式如下:

.annotation [注解属性] <注解类名>
    [注解字段 = 值]
.end annotation

如果注解的作用范围是类, .annotation 指令会直接定义在 smali 文件中,如果作用范围是方法或者字段,则会包含在方法或字段定义中。

举个栗子:

java

@Deprecated
public class AnnotationTest {
    @At(value = "tom")
    public String name;
}

smali

# annotations
.annotation runtime Ljava/lang/Deprecated;
.end annotation


# instance fields
.field public name:Ljava/lang/String;
    .annotation runtime Ljiuyou/hello/info/At;
        value = "tom"
    .end annotation
.end field