smali: строковые константы
Есть ли что-то еще, что нужно сделать, чтобы загрузить константу String в регистр, а затем использовать ее в вызове метода, кроме выполнения:
const-string v6, "TEST CONSTANT"
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
?
следующий блок инструкций
iget-object v4, p0, Lcom/mypackage/MyClass;->myList:Ljava/util/List;
invoke-interface {v4, p1}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_0
const-string v6, "TEST CONSTANT"
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_0
invoke-interface {v4, p2}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_1
invoke-static {v6, p2}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_1
дал мне следующие сообщения об ошибках logcat:
10-29 23:37:37.191: W/dalvikvm(515): VFY: register1 v6 type 2, wanted ref
10-29 23:37:37.241: W/dalvikvm(515): VFY: bad arg 0 (into Ljava/lang/String;)
10-29 23:37:37.241: W/dalvikvm(515): VFY: rejecting call to Landroid/util/Log;.wtf (Ljava/lang/String;Ljava/lang/String;)I
10-29 23:37:37.241: W/dalvikvm(515): VFY: rejecting opcode 0x71 at 0x0028
2 ответа
Ваши подозрения в этом случае верны. Проблема в том, что во втором экземпляре Log->wtf не обязательно был установлен v6.
Что касается того, почему это происходит, важно отметить, что при повторной сборке байт-кода выполняется очень мало проверки. Во многих случаях ассемблеру просто не хватает информации, чтобы выполнить этот уровень проверки - для этого потребуется, чтобы ассемблер знал весь набор классов, которые будут присутствовать при запуске приложения, аналогично случаю деодексирования (-o) или создание регистрационной информации (-r).
Эти типы проблем обнаруживаются Dalvik при проверке байт-кода, что является именно той ошибкой, о которой вы упоминали.
Кроме того, вы упоминаете, что "значения, которые я использовал для p1 и p2, не прошли бы оба теста if-eqz". Это не имеет значения для верификатора байт-кода dalvik. Верификатор проверяет правильность всех путей кода. Он не может знать или принимать какое-либо конкретное значение для параметров, передаваемых в метод.
Если вы хотите увидеть дополнительную информацию о том, как типы регистров распространяются по всему методу, вы можете использовать опцию -r для baksmali.
# grab the full framework directory from your device
adb pull /system/framework framework
# run baksmali with the -r command
baksmali -r ARGS,DEST,FULLMERGE -d framework <apk_or_dex_file>
Это добавит комментарии до / после каждой инструкции с подробной информацией о типах регистров в этой позиции.
Я изменил некоторые вещи и заставил их работать, но я не уверен, почему...
изменение я сделал, чтобы переместить постоянную загрузку (const-string v6, "TEST CONSTANT"
) за пределами блока if, что приводит к
const-string v6, "TEST CONSTANT"
iget-object v4, p0, Lcom/mypackage/MyClass;->myList:Ljava/util/List;
invoke-interface {v4, p1}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_0
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_0
invoke-interface {v4, p2}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_1
invoke-static {v6, p2}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_1
я подозреваю, что причина первоначальной проблемы заключается в том, что если поток обошел первый "блок if", но вошел во второй "блок if", то регистр v6
еще не был бы загружен, прежде чем он был использован.
причина, по которой я не уверен, заключается в том, что когда я запускал пересобранную программу, значения, которые я использовал для p1
а также p2
не удалось бы оба if-eqz
тесты (т. е. поток будет входить в оба блока if).
так что казалось, что
1. чек для регистрации v6
быть загруженным до того, как он был использован, был сделан превентивно перед фактическим потоком управления?
2. я думал, что такая проверка выполняется только во время компиляции?
Я публикую это как ответ, так как мне нужно больше места, чтобы объяснить, что я сделал. однако мне все еще любопытно, почему такое изменение заставило его работать, поэтому, если кто-нибудь сможет дать объяснение, я отмечу это как ответ, спасибо!