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

person Edwin Lee    schedule 29.10.2012    source источник
comment
Это очень странно. Я не вижу ничего плохого в коде, который вы упомянули.   -  person JesusFreke    schedule 29.10.2012
comment
существует ли ограничение или ограничение на количество регистров, которые можно использовать в методе? для этого метода, где у меня есть вышеуказанный вызов, он был изначально объявлен как .registers 7, и мне пришлось увеличить его до .registers 10 для моего использования.   -  person Edwin Lee    schedule 30.10.2012
comment
Неа. Есть ли какой-нибудь код между const-string и invoke-static?   -  person JesusFreke    schedule 30.10.2012
comment
На самом деле да. есть предел. Но ты не рядом :)   -  person JesusFreke    schedule 30.10.2012
comment
На случай, если это было пропущено, мне удалось кое-что изменить и заставить все работать, но я не уверен, в чем точная причина. Это описано в ответе ниже.   -  person Edwin Lee    schedule 31.10.2012


Ответы (2)


Ваши подозрения в данном случае верны. Проблема в том, что во втором экземпляре Log->wtf не обязательно была установлена ​​v6.

Что касается почему это происходит, важно отметить, что при повторной сборке байт-кода выполняется очень мало проверок. Во многих случаях ассемблеру просто не хватает информации для выполнения этого уровня проверки — для этого ассемблеру потребуется знание полного набора классов, которые будут присутствовать при запуске приложения, аналогично случаю деодексации (-o ) или создание информации о регистре (-r).

Далвик улавливает такие проблемы, когда проверяет байт-код, что и является причиной упомянутой вами ошибки.

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

Это добавит комментарии до/после каждой инструкции с подробной информацией о типах регистров в этой позиции.

person JesusFreke    schedule 31.10.2012

Я изменил некоторые вещи и заставил его работать, но я не уверен, почему...

изменение, которое я сделал, заключалось в том, чтобы переместить постоянную загрузку (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 (т. е. поток войдет в оба «если-блока»).

Таким образом, казалось, что
1. проверка загрузки регистра v6 перед его использованием была выполнена упреждающе до фактического потока управления?
2. я думал, что такая проверка выполняется только во время компиляции?

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

person Edwin Lee    schedule 30.10.2012
comment
Вероятно, вам следует обновить свой вопрос, указав дополнительную информацию (например, исходный фрагмент байт-кода), а затем реорганизовать свой ответ, чтобы он содержал только те материалы, которые имеют отношение к решению. На самом деле, вы должны были включить это для начала, что дало бы мне достаточно информации, чтобы ответить на ваш вопрос для начала :) - person JesusFreke; 31.10.2012
comment
Спасибо! Да, надо было включить хотя бы до конца второго if-блока. Дело в том, что я продолжал думать, что проблема заключалась в том, как я написал два оператора в своем ОП, и совершенно не произошло, что второй оператор вызова может вызвать проблемы! ;-п - person Edwin Lee; 01.11.2012