I want to add the following call of method "send()" to a smali method:
invoke-direct {p0}, X->send()V
send() is a method of the current class. X is a wildcard for the current class name. Now i have two unresolved problems:
Why does invoke-direct need register p0? I thought this was a parameter.
Do i have take into consideration the p0 register? Is it possible that this additional code makes the entire app not compile if i just keep it? If so, how can i find out which register must be used?
I want to add this method call to an arbitrary method. I don't know the method structure and can't predict any register usage. Therefore I need to know exactly if p0 in the upper code can change and under which conditions.
I provide a simple example to emphasize my intention:
Let's assume we have this method that just reads the contacts that are saved on your smartphone:
.method private getContacts()Ljava/util/ArrayList;
.locals 12
.annotation system Ldalvik/annotation/Signature;
value = {
"()",
"Ljava/util/ArrayList",
"<",
"Ljava/lang/String;",
">;"
}
.end annotation
.prologue
const/4 v2, 0x0
.line 43
new-instance v7, Ljava/util/ArrayList;
invoke-direct {v7}, Ljava/util/ArrayList;-><init>()V
.line 44
.local v7, "contacts":Ljava/util/ArrayList;, "Ljava/util/ArrayList<Ljava/lang/String;>;"
invoke-virtual {p0}, Lorg/puellen/contacts/MainActivity;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v0
sget-object v1, Landroid/provider/ContactsContract$Contacts;->CONTENT_URI:Landroid/net/Uri;
move-object v3, v2
move-object v4, v2
move-object v5, v2
...
I wrote a parser which automatically extracts this code from an .apk file. Now i want to extend the methods functionality, by adding the upper method call.
In this case i can simply add the call at the beginning. The only difference appears in line 13 (see comment)
.method private getContacts()Ljava/util/ArrayList;
.locals 12
.annotation system Ldalvik/annotation/Signature;
value = {
"()",
"Ljava/util/ArrayList",
"<",
"Ljava/lang/String;",
">;"
}
.end annotation
.prologue
invoke-direct {p0}, Lorg/my_package/custom_class/MainActivity;->send()V # added method call
const/4 v2, 0x0
.line 43
new-instance v7, Ljava/util/ArrayList;
invoke-direct {v7}, Ljava/util/ArrayList;-><init>()V
.line 44
.local v7, "contacts":Ljava/util/ArrayList;, "Ljava/util/ArrayList<Ljava/lang/String;>;"
invoke-virtual {p0}, Lorg/puellen/contacts/MainActivity;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v0
sget-object v1, Landroid/provider/ContactsContract$Contacts;->CONTENT_URI:Landroid/net/Uri;
move-object v3, v2
move-object v4, v2
move-object v5, v2
Until know i just add the method call after .prologue. But i am sure that this behaviour does not work always. Is there a "perfect" place to add the call? Can i always use p0 in "invoke-direct" or how do i find out what register can be used?
Question: Can i always use p0 in "invoke-direct" or how do i find out what register can be used?
Answer: "The first parameter to a non-static methods is always the object that the method is being invoked on." (link see blow in first comment). As my method is not static, i can use always p0
Now i only need to know where to place the method call.