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. я думал, что такая проверка выполняется только во время компиляции?

Я публикую это как ответ, так как мне нужно больше места, чтобы объяснить, что я сделал. однако мне все еще любопытно, почему такое изменение заставило его работать, поэтому, если кто-нибудь сможет дать объяснение, я отмечу это как ответ, спасибо!

Другие вопросы по тегам