【angr源码分析】8. Angr的插件机制
Angr的插件机制
个人理解:以SimState为例理解Plugin。PluginHub类是一个插件管理器,里面管理若干插件(SimState的插件都是SimStatePlugin的子类实例化的对象)。当需要使用某个插件(比如解析器Solver,Solver是一个插件,memroy和regs都是)的时候,调用PluginHub提供的方法获得对应的插件来使用。为了方便,angr设置了一个新的类——PluginPreset。PluginPreset本身就包含很多插件,也是一个插件的集合。(如果说Hub是一个储藏室,preset就是储藏室里的柜子,plugin就是物品。物品可以放在柜子中,也可以直接放在储藏室里。plugin可以直接添加到Hub中,也可以添加到preset中,再将preset添加到Hub中。)angr设置了默认的preset,里面包含了我们会用到的插件。Hub将默认的preset添加进来,里面的插件可以直接使用。我们也可以编写自己的插件,添加到Hub中。
一个Hub中可以有多个添加的插件,也可以有多个preset。直接添加的插件已经是激活的,可以直接使用;而多个preset中,只能有一个处于激活状态。未激活的preset中的插件不能使用。
Hub的state包括 _active_plugin, _active_preset, provided_by_preset这三个变量。(意思可能是,保存一个Hub的状态,就是保存这三个变量,可以先保存,后面再恢复(调用getstate和setstate))
PluginHub类
Plugin Hub的官方说明:
A plugin hub is an object which contains many plugins, as well as the notion of a “preset”, or a backer that can provide default implementations of plugins which cater to a certain circumstance.
Plugin Hub是包括了很多插件的对象,也包含 “预设(preset)” 的概念,可以针对默认的情况,提供默认的插件实现。
Objects in angr like the SimState, the Analyses hub, the SimEngine selector, etc all use this model to unify their mechanisms for automatically collecting and selecting components to use. If you’re familiar with design patterns this is a configurable Strategy Pattern.
Angr中的对象,比如SimState,Analyses hub,SimEngine selector等,都使用了这个模型来统一自动收集和自动选择原件的机制,如果您熟悉设计模式,这是一个可配置的策略模式 。
Each PluginHub subclass should have a corresponding Plugin subclass, and perhaps a PluginPreset subclass if it wants its presets to be able to specify anything more interesting than a list of defaults.
每个PluginHub子类都应当有一个对应的Plugin子类,而且可能一个PluginPreset子类能指定更多东西。
PluginHub像是一个插槽,在SimState上加载了一个插槽,要扩展SimState的功能,只需要开发插件即可。
代码描述如下:
_init_(self):
设置了三个实例变量:
- _active_plugins:保存Hub中直接添加的插件
- _active_preset:保存当前状态下,被激活的preset
- provided_by_preset:(未知**)
还有一个变量:_presets,保存Hub中的所有preset
1 | _presets = None |
def register_plugin(self, name, plugin):
将一个插件注册到Hub中。注册的插件会被默认激活(加入_active_plugins字典中)。如果已经存在该名字的插件,就覆盖。
1 | def register_plugin(self, name, plugin): |
def register_preset(cls, name, preset):
和register_plugin类似,将一个preset注册到Hub中(只是单纯地添加进来,没有直接激活。)
1 | def register_preset(cls, name, preset): |
def get_plugin(self, name):
从已有的插件中,根据name寻找该插件。寻找插件时,会先从_active_plugins中寻找,再从preset中寻找。
1 | def get_plugin(self, name): |
def use_plugin_preset(self, preset):
将一个preset设置为激活状态
1 | def use_plugin_preset(self, preset): |
def register_default():
如果说register_plugin是把一个插件加入到active_plugins中,那么register_default就是把这个插件插入到一个preset中。给出插件名,插件,和preset名。
1 | def register_default(cls, name, plugin_cls, preset='default'): |
PluginPreset类
1 | class PluginPreset(object): |
preset中包含多个插件。一般,这个preset由angr自己定义。
Angr一次性将可能需要的所有插件放入preset中,然后将这个preset放入Hub中激活。当需要使用该插件时,提供插件的名字即可。angr会自动地在preset中以及active_plugin中寻找这个插件。
sim_state.py中,下面两行代码在import 时就会执行:
1 | default_state_plugin_preset = PluginPreset() |