|
| 1 | +Copyright (C) 2015 ISP RAS |
| 2 | + |
| 3 | + |
| 4 | +Using plugins |
| 5 | +------------- |
| 6 | + |
| 7 | +You should run configure with parameter "--enable-plugins". After that just run make |
| 8 | +and make install as usual |
| 9 | + |
| 10 | +To load a plugin with name "example_name" you should: |
| 11 | + * Stop qemu with "stop" command |
| 12 | + * Then execute "load_plugin example_name" command |
| 13 | + * Then happily continue the work of stopped qemu, you should be fine |
| 14 | + (sidenote: all commands should be executed via monitor) |
| 15 | + |
| 16 | + You can also execute "list_plugins" to see the list of loaded plugins, and |
| 17 | + "stop_plugin example_name" to stop plugin, as the name suggests. |
| 18 | + |
| 19 | +Writing plugins |
| 20 | +------------- |
| 21 | + |
| 22 | +All plugins should be located in path_to_qemu/plugins/plugins_src/ and be written in pure C. |
| 23 | + |
| 24 | +Every plugin should have mandatory parts (for reference check existing plugins): |
| 25 | + * Structure "init_info". Here you can identify which signals your plugin would provide, |
| 26 | + dependencies on other plugins, and os_version. If plugin generates signals, then |
| 27 | + they MUST be mentioned in "signals_list" field, otherwise automatic loading of plugins |
| 28 | + wouldn't work and needed plugins will have to be loaded manually. |
| 29 | + * Function "pi_start". Here you can subscribe to signals, define specific monitor commands |
| 30 | + for your plugin, register helper functions, and fill the table of functions that this plugin |
| 31 | + is providing in a straight-forward way, not through signals mechanism. |
| 32 | +Other parts of plugin are not obligatory, but are containing plugins' functionality. |
| 33 | + |
| 34 | +Basically, you perform instrumentation by subscribing to specific signal and providing |
| 35 | +function that will process gotten data. This would be performed during translation; if you |
| 36 | +want to process data during actual execution, you should use helper functions (look at function |
| 37 | +"tcg_context_register_helper" and "tcg_gen_callN"). |
| 38 | + |
| 39 | +To make plugin actually buildable, you should add corresponding info to plugins_src/Makefile |
| 40 | +and plugins_src/Makefile.plugins (again, check how it is done for existing plugins for |
| 41 | +reference). |
| 42 | + |
| 43 | +Use of signal-subscriber mechanism |
| 44 | +------------- |
| 45 | + |
| 46 | +To exchange the data between qemu and plugins, and between plugins themselves, we introduce |
| 47 | +signal-subsctiber mechanism. It works as following: firstly one of plugins registers signals |
| 48 | +which would be generated by it. Other plugin, that wishes to be notificated every time |
| 49 | +those signals emit, should subscribe to needed signals and set which function would process |
| 50 | +gotten data. At some place, that is specified in your plugin, a signal would be generated and |
| 51 | +data would be transfered to QEMU, which in it's turn would forward gotten data to all plugins, |
| 52 | +that were subscribed to this signal. |
| 53 | + |
| 54 | +How exactly these should be used: |
| 55 | + * First of all signals that would be provided by plugin should be mentioned in "init_info" |
| 56 | + structure (signal groups, to be more specific). |
| 57 | + * In "pi_start" those signals should be registered via "plugin_reg_signal(s1)" |
| 58 | + function, where s1 is a string identificator that identifies the group of signals (i.e. |
| 59 | + "syscalls"). This function will return pointer to "Signal_info", which should be used for |
| 60 | + signal generation. |
| 61 | + * To generate a signal you should use function "plugin_gen_signal(si, s2, data, env)", |
| 62 | + where si - is Signal_info that you got after signal registration, s2 - is a string |
| 63 | + identificator that identifies specific signal inside of group (i.e. "file_open"), data - |
| 64 | + data casted to void*, basically the useful info that signal is providing, and env - |
| 65 | + CPUArchState* var, that is widely used for analyses. The pair of s1 and s2 (signals group |
| 66 | + and specific signal inside of it) should be unique to your signal, and currently, this |
| 67 | + should be tracked by programmer himself. |
| 68 | + * To subscribe to a signal you should use a plugin_subscribe(func, s1, s2) function, where |
| 69 | + func - name of the function, that will process the signal, and s1 and s2 - are string ids, |
| 70 | + same as above. When you will try to subscribe to signal, mechanism would check whether |
| 71 | + corresponding plugins has already been loaded, and if not, would try to find and load them. |
| 72 | + That's exactly the reason why you should have all your signals mentioned in init_info |
| 73 | + structure, because that's the place where loader would look for them. If you wouldn't |
| 74 | + define signals there, you would have to load needed plugins (providers) by hand. |
| 75 | + * It also worth mentioning, that if you set "dependencies" in init_info structure, system |
| 76 | + will try to find and load mentioned dependency-plugins on load of your plugin. |
| 77 | + |
| 78 | + |
| 79 | +List of qemu-provided callbacks |
| 80 | +------------- |
| 81 | + |
| 82 | +I hope names are self-explanatory: |
| 83 | + |
| 84 | +PLUGIN_QEMU_BEFORE_GEN_TB, |
| 85 | +PLUGIN_QEMU_INSTR_TRANSLATE, |
| 86 | +PLUGIN_QEMU_EXCEPTION, |
| 87 | +PLUGIN_QEMU_EXCEPTION_HANDLER, |
| 88 | +PLUGIN_QEMU_INSTRUCTION_EXCEPTION, |
| 89 | +PLUGIN_QEMU_INTERRUPT, |
| 90 | +PLUGIN_QEMU_TLB_SET_PAGE, |
| 91 | +PLUGIN_QEMU_CPU_PAUSED, |
| 92 | +PLUGIN_QEMU_PAGE_DIR_UPD, |
| 93 | +PLUGIN_QEMU_CPUS_STOPPED |
0 commit comments