Java ASM, как прочитать значение байт-кода LOAD или STORE

Я работаю с asm (здесь документы http://asm.ow2.org/asm40/javadoc/user/), более конкретно, я пытаюсь динамически инструментировать некоторый код. Моя проблема в том, что я не знаю, как и если я могу через то, что предлагает asm, чтобы прочитать фактические переменные инструментального кода. т.е. я могу извлечь LocalVariableNode из соответствующих хранилищ, которые я вычисляю в инструментальном коде, на данный момент я хотел бы знать значение, которое я храню (не только тип, который можно легко получить с помощью методов, предоставленных в классе LocalVariableNode, но фактическое значение (если это логическое значение, я хотел бы получить значение true или false)). Точно так же было бы интересно получить значение, когда происходит инструкция загрузки байт-кода.

Надеюсь, я был достаточно конкретен, я проверил, если что-то подобное уже спрашивали, но, похоже, это не так

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

2 ответа

Решение

Некоторое время назад я делал нечто похожее, забыв про детали, но думаю, что могу дать вам несколько советов по этому поводу.

Конечно, как сказал Крейчен в своем ответе, невозможно получить точное значение, связанное с LocalVariable, но можно как-то получить полное дерево абстрактного синтаксиса байт-кода и узнать, какое возможное значение будет присвоено этому. LocalVariable в какой-то момент программы.

Для каждого LocalVariableNode присваивается индекс, поэтому в байт-коде значение не является статически связанным с LocalVariable, потому что Java допускает изменчивость на этом. Таким образом, чтобы узнать значение, связанное с LocalVariable в некоторой точке программы, вы должны в основном смоделировать выполнение стека байт-кода (JVM), а затем иметь таблицу для отслеживания назначения значения для каждой LocalVariable. Выполнение стека осуществляется посредством имитации инструкции (кода операции), в основном байт-кода. И затем вы постепенно строите древовидную структуру для хранения абстрактного синтаксического дерева.

У меня есть код для этого, но довольно уродливо, вы можете посмотреть: https://github.com/davidlau325/BytecodeASTGenerator

То, что вы просите, вообще невозможно. Булевый магазин (astore, bastore, putfield, putstatic) выскакивает значение вершины стека и сохраняет его в указанном месте. Однако это значение вершины стека может быть результатом любого произвольного вычисления. Например:

boolean b = MyClass.decideWhetherProgramPHalts();

Таким образом, вы зависите от вызова метода, который может или не может даже завершиться. Ваш байт-код может выглядеть примерно так (кратко из памяти):

invokestatic "MyClass.decideWhetherProgramPHalts()Z"
istore 1

Таким образом, значение, которое сохраняется, прибывает из предыдущего invokestatic, который может быть что угодно из простого return true к сетевому вызову к некоторой попытке решить проблему, которая, как мы знаем, неразрешима.

Если вам нужен анализ, который может сказать вам, true или же false или же I-do-not-knowвы можете попробовать статические структуры анализа, такие как WALA ( http://wala.sourceforge.net/). Но имейте в виду, что большую часть времени вы получите I-do-not-know, Вот основные приемы, которые вы можете рассмотреть:

  1. Анализ потока данных
  2. Абстрактная интерпретация

Обратите внимание, что вы можете самостоятельно приступить к анализу тривиального потока данных, посетив инструкции в вашем MethodNode, но ваш отзыв будет хуже, чем использование существующих инструментов (если вы не потратите на это много работы).

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