dexlib2 - Инструментарий покрытия филиалов - PullRequest
0 голосов
/ 15 декабря 2018

Я пытаюсь обработать код smali с помощью dexlib2, чтобы измерить охват филиала.В частности, я вставляю в каждую ветку (если и соответствующую метку) в основном две инструкции;const-string для загрузки уникальной трассировки для каждой ветви и invoke-static для вызова статического метода.Однако есть несколько проблем:

Сначала мне пришлось увеличить количество регистров на один.Это привело к реорганизации регистров некоторых команд, что, кажется, работает (использовало отражение для увеличения номера регистра, например, первоначально p0 получил v20 путем введения нового локального регистра v21).Тем не менее, я заметил, что некоторые метки, например .end local v15, также требуют такого рода модификации, что, по-видимому, невозможно при использовании dexlib2, поскольку метки не отслеживают ни такую ​​информацию, ни имя.Я также не знаю, в чем смысл / намерение тех .end / .restart. / Start местных меток.Интересны ли эти метки для сборки мусора или также какая-то информация о типе для соответствующих регистров?

Во-вторых, некоторые инструкции принимают только в качестве аргументов v0-v15.Вот почему мне пришлось различать, превышает ли количество локальных регистров 16 или нет.В этом случае я в основном использую две дополнительные инструкции перемещения: (в другом случае инструментарий намного проще)

move-object / 16 vNew, v0 # значение сохранения v0
(две вышеупомянутыеинструкции) # использовать v0 для хранения трассировки
move-object / 16 v0, vNew # восстановить значение v0

Однако недавно я получаю следующую ошибку (и подобные ошибки проверки):

[0x25C] 'this' аргумент 'Ссылка: java.lang.Object' не экземпляр 'Reference: com.android.calendar.GeneralPreferences'

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

В-третьих, я заметил, что метки, связанные с ветвями, ведут себя несколько странно внекоторые редкие случаи.Во всем файле smali есть ветки, которые инструментируются дважды.Отладка показывает, что запрос команды if для ее целевых меток (другой ветви) один раз возвращает больше меток, чем в другой раз.Вот почему я сейчас использую индекс целевой метки (инструкция.getTarget (). GetLocation (). GetIndex ()), но я все еще получаю одну ветвь, которая получает инструментарий дважды.

Я прошулюбая помощь по этому конкретному вопросу, а также общие советы / факты, которые я должен рассмотреть.Есть ли лучший способ получить более подробную информацию об ошибках;вывод logcat не лучший, например, какая именно инструкция вызвала ошибку проверки (шестнадцатеричное значение, рассматриваемое как offest, не имеет для меня никакого смысла).

Заранее спасибо.

1 Ответ

0 голосов
/ 15 декабря 2018

Лучший способ, который я видел, чтобы справиться с проблемами, которые вы заметили при увеличении количества регистров, - это добавить пролог, который перемещает все регистры параметров после увеличения обратно в их места до увеличения, а затем использовать последний регистр / регистрыкак новые «чистые» регистры.

например, если параметры были в v14-v20, и вы увеличили количество регистров на единицу, вы бы добавили код, который бы переместил v15 обратно в v14, v16 обратно в v15,и т. д. и используйте v21 в качестве нового рабочего регистра.

В качестве альтернативы вы можете попытаться не выделять какие-либо регистры.Например, создайте новый метод и передайте значение из целевого метода, который вы хотите использовать.Вы можете использовать invoke - * / range для передачи в любой отдельный регистр.Но в вашем случае это кажется не слишком выполнимым, поскольку вы хотите передать дополнительную строку для идентификации ветви.Теоретически вы можете создать новый метод для каждой ветви, но вы сразу же столкнетесь с ограничениями методов.


.end / .restart. / Start local предназначены исключительно для отладки информации.Они сообщают отладчику, какой регистр связан с какой локальной переменной в исходном коде Java.Самым простым было бы просто раздеть их.См. https://source.android.com/devices/tech/dalvik/dex-format#debug-info-item для получения дополнительной информации.


Да, объект move должен использоваться для ссылочных типов, ширину move для примитивных длинных / двойных чисел и move для других примитивов.Кроме того, не забывайте, что широкие типы занимают 2 регистра.Поэтому, если вам может потребоваться выделить 2 дополнительных чистых регистра, если вам понадобится переместить широкое значение (длинный или двойной примитив)

dexlib2 имеет API для выполнения анализа типов в регистрах, если это необходимо.Смотри https://github.com/JesusFreke/smali/blob/master/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java

...