xref: /qemu/plugins/api.c (revision 19f9c044)
1 /*
2  * QEMU Plugin API
3  *
4  * This provides the API that is available to the plugins to interact
5  * with QEMU. We have to be careful not to expose internal details of
6  * how QEMU works so we abstract out things like translation and
7  * instructions to anonymous data types:
8  *
9  *  qemu_plugin_tb
10  *  qemu_plugin_insn
11  *  qemu_plugin_register
12  *
13  * Which can then be passed back into the API to do additional things.
14  * As such all the public functions in here are exported in
15  * qemu-plugin.h.
16  *
17  * The general life-cycle of a plugin is:
18  *
19  *  - plugin is loaded, public qemu_plugin_install called
20  *    - the install func registers callbacks for events
21  *    - usually an atexit_cb is registered to dump info at the end
22  *  - when a registered event occurs the plugin is called
23  *     - some events pass additional info
24  *     - during translation the plugin can decide to instrument any
25  *       instruction
26  *  - when QEMU exits all the registered atexit callbacks are called
27  *
28  * Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
29  * Copyright (C) 2019, Linaro
30  *
31  * License: GNU GPL, version 2 or later.
32  *   See the COPYING file in the top-level directory.
33  *
34  * SPDX-License-Identifier: GPL-2.0-or-later
35  *
36  */
37 
38 #include "qemu/osdep.h"
39 #include "qemu/main-loop.h"
40 #include "qemu/plugin.h"
41 #include "qemu/log.h"
42 #include "tcg/tcg.h"
43 #include "exec/exec-all.h"
44 #include "exec/gdbstub.h"
45 #include "exec/ram_addr.h"
46 #include "disas/disas.h"
47 #include "plugin.h"
48 #ifndef CONFIG_USER_ONLY
49 #include "qemu/plugin-memory.h"
50 #include "hw/boards.h"
51 #else
52 #include "qemu.h"
53 #ifdef CONFIG_LINUX
54 #include "loader.h"
55 #endif
56 #endif
57 
58 /* Uninstall and Reset handlers */
59 
60 void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb)
61 {
62     plugin_reset_uninstall(id, cb, false);
63 }
64 
65 void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb)
66 {
67     plugin_reset_uninstall(id, cb, true);
68 }
69 
70 /*
71  * Plugin Register Functions
72  *
73  * This allows the plugin to register callbacks for various events
74  * during the translation.
75  */
76 
77 void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id,
78                                        qemu_plugin_vcpu_simple_cb_t cb)
79 {
80     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_INIT, cb);
81 }
82 
83 void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id,
84                                        qemu_plugin_vcpu_simple_cb_t cb)
85 {
86     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXIT, cb);
87 }
88 
89 void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb,
90                                           qemu_plugin_vcpu_udata_cb_t cb,
91                                           enum qemu_plugin_cb_flags flags,
92                                           void *udata)
93 {
94     if (!tb->mem_only) {
95         int index = flags == QEMU_PLUGIN_CB_R_REGS ||
96                     flags == QEMU_PLUGIN_CB_RW_REGS ?
97                     PLUGIN_CB_REGULAR_R : PLUGIN_CB_REGULAR;
98 
99         plugin_register_dyn_cb__udata(&tb->cbs[index],
100                                       cb, flags, udata);
101     }
102 }
103 
104 void qemu_plugin_register_vcpu_tb_exec_inline(struct qemu_plugin_tb *tb,
105                                               enum qemu_plugin_op op,
106                                               void *ptr, uint64_t imm)
107 {
108     if (!tb->mem_only) {
109         plugin_register_inline_op(&tb->cbs[PLUGIN_CB_INLINE], 0, op, ptr, imm);
110     }
111 }
112 
113 void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn,
114                                             qemu_plugin_vcpu_udata_cb_t cb,
115                                             enum qemu_plugin_cb_flags flags,
116                                             void *udata)
117 {
118     if (!insn->mem_only) {
119         int index = flags == QEMU_PLUGIN_CB_R_REGS ||
120                     flags == QEMU_PLUGIN_CB_RW_REGS ?
121                     PLUGIN_CB_REGULAR_R : PLUGIN_CB_REGULAR;
122 
123         plugin_register_dyn_cb__udata(&insn->cbs[PLUGIN_CB_INSN][index],
124                                       cb, flags, udata);
125     }
126 }
127 
128 void qemu_plugin_register_vcpu_insn_exec_inline(struct qemu_plugin_insn *insn,
129                                                 enum qemu_plugin_op op,
130                                                 void *ptr, uint64_t imm)
131 {
132     if (!insn->mem_only) {
133         plugin_register_inline_op(&insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_INLINE],
134                                   0, op, ptr, imm);
135     }
136 }
137 
138 
139 /*
140  * We always plant memory instrumentation because they don't finalise until
141  * after the operation has complete.
142  */
143 void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn,
144                                       qemu_plugin_vcpu_mem_cb_t cb,
145                                       enum qemu_plugin_cb_flags flags,
146                                       enum qemu_plugin_mem_rw rw,
147                                       void *udata)
148 {
149     plugin_register_vcpu_mem_cb(&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR],
150                                     cb, flags, rw, udata);
151 }
152 
153 void qemu_plugin_register_vcpu_mem_inline(struct qemu_plugin_insn *insn,
154                                           enum qemu_plugin_mem_rw rw,
155                                           enum qemu_plugin_op op, void *ptr,
156                                           uint64_t imm)
157 {
158     plugin_register_inline_op(&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE],
159                               rw, op, ptr, imm);
160 }
161 
162 void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id,
163                                            qemu_plugin_vcpu_tb_trans_cb_t cb)
164 {
165     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_TB_TRANS, cb);
166 }
167 
168 void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id,
169                                           qemu_plugin_vcpu_syscall_cb_t cb)
170 {
171     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL, cb);
172 }
173 
174 void
175 qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id,
176                                          qemu_plugin_vcpu_syscall_ret_cb_t cb)
177 {
178     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, cb);
179 }
180 
181 /*
182  * Plugin Queries
183  *
184  * These are queries that the plugin can make to gauge information
185  * from our opaque data types. We do not want to leak internal details
186  * here just information useful to the plugin.
187  */
188 
189 /*
190  * Translation block information:
191  *
192  * A plugin can query the virtual address of the start of the block
193  * and the number of instructions in it. It can also get access to
194  * each translated instruction.
195  */
196 
197 size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb)
198 {
199     return tb->n;
200 }
201 
202 uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb)
203 {
204     return tb->vaddr;
205 }
206 
207 struct qemu_plugin_insn *
208 qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx)
209 {
210     struct qemu_plugin_insn *insn;
211     if (unlikely(idx >= tb->n)) {
212         return NULL;
213     }
214     insn = g_ptr_array_index(tb->insns, idx);
215     insn->mem_only = tb->mem_only;
216     return insn;
217 }
218 
219 /*
220  * Instruction information
221  *
222  * These queries allow the plugin to retrieve information about each
223  * instruction being translated.
224  */
225 
226 const void *qemu_plugin_insn_data(const struct qemu_plugin_insn *insn)
227 {
228     return insn->data->data;
229 }
230 
231 size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn)
232 {
233     return insn->data->len;
234 }
235 
236 uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn)
237 {
238     return insn->vaddr;
239 }
240 
241 void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn)
242 {
243     return insn->haddr;
244 }
245 
246 char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn)
247 {
248     CPUState *cpu = current_cpu;
249     return plugin_disas(cpu, insn->vaddr, insn->data->len);
250 }
251 
252 const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn)
253 {
254     const char *sym = lookup_symbol(insn->vaddr);
255     return sym[0] != 0 ? sym : NULL;
256 }
257 
258 /*
259  * The memory queries allow the plugin to query information about a
260  * memory access.
261  */
262 
263 unsigned qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info)
264 {
265     MemOp op = get_memop(info);
266     return op & MO_SIZE;
267 }
268 
269 bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info)
270 {
271     MemOp op = get_memop(info);
272     return op & MO_SIGN;
273 }
274 
275 bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info)
276 {
277     MemOp op = get_memop(info);
278     return (op & MO_BSWAP) == MO_BE;
279 }
280 
281 bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info)
282 {
283     return get_plugin_meminfo_rw(info) & QEMU_PLUGIN_MEM_W;
284 }
285 
286 /*
287  * Virtual Memory queries
288  */
289 
290 #ifdef CONFIG_SOFTMMU
291 static __thread struct qemu_plugin_hwaddr hwaddr_info;
292 #endif
293 
294 struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info,
295                                                   uint64_t vaddr)
296 {
297 #ifdef CONFIG_SOFTMMU
298     CPUState *cpu = current_cpu;
299     unsigned int mmu_idx = get_mmuidx(info);
300     enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
301     hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0;
302 
303     assert(mmu_idx < NB_MMU_MODES);
304 
305     if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx,
306                            hwaddr_info.is_store, &hwaddr_info)) {
307         error_report("invalid use of qemu_plugin_get_hwaddr");
308         return NULL;
309     }
310 
311     return &hwaddr_info;
312 #else
313     return NULL;
314 #endif
315 }
316 
317 bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
318 {
319 #ifdef CONFIG_SOFTMMU
320     return haddr->is_io;
321 #else
322     return false;
323 #endif
324 }
325 
326 uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr)
327 {
328 #ifdef CONFIG_SOFTMMU
329     if (haddr) {
330         return haddr->phys_addr;
331     }
332 #endif
333     return 0;
334 }
335 
336 const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h)
337 {
338 #ifdef CONFIG_SOFTMMU
339     if (h && h->is_io) {
340         MemoryRegion *mr = h->mr;
341         if (!mr->name) {
342             unsigned maddr = (uintptr_t)mr;
343             g_autofree char *temp = g_strdup_printf("anon%08x", maddr);
344             return g_intern_string(temp);
345         } else {
346             return g_intern_string(mr->name);
347         }
348     } else {
349         return g_intern_static_string("RAM");
350     }
351 #else
352     return g_intern_static_string("Invalid");
353 #endif
354 }
355 
356 int qemu_plugin_num_vcpus(void)
357 {
358     return plugin_num_vcpus();
359 }
360 
361 /*
362  * Plugin output
363  */
364 void qemu_plugin_outs(const char *string)
365 {
366     qemu_log_mask(CPU_LOG_PLUGIN, "%s", string);
367 }
368 
369 bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret)
370 {
371     return name && value && qapi_bool_parse(name, value, ret, NULL);
372 }
373 
374 /*
375  * Binary path, start and end locations
376  */
377 const char *qemu_plugin_path_to_binary(void)
378 {
379     char *path = NULL;
380 #ifdef CONFIG_USER_ONLY
381     TaskState *ts = (TaskState *) current_cpu->opaque;
382     path = g_strdup(ts->bprm->filename);
383 #endif
384     return path;
385 }
386 
387 uint64_t qemu_plugin_start_code(void)
388 {
389     uint64_t start = 0;
390 #ifdef CONFIG_USER_ONLY
391     TaskState *ts = (TaskState *) current_cpu->opaque;
392     start = ts->info->start_code;
393 #endif
394     return start;
395 }
396 
397 uint64_t qemu_plugin_end_code(void)
398 {
399     uint64_t end = 0;
400 #ifdef CONFIG_USER_ONLY
401     TaskState *ts = (TaskState *) current_cpu->opaque;
402     end = ts->info->end_code;
403 #endif
404     return end;
405 }
406 
407 uint64_t qemu_plugin_entry_code(void)
408 {
409     uint64_t entry = 0;
410 #ifdef CONFIG_USER_ONLY
411     TaskState *ts = (TaskState *) current_cpu->opaque;
412     entry = ts->info->entry;
413 #endif
414     return entry;
415 }
416 
417 /*
418  * Create register handles.
419  *
420  * We need to create a handle for each register so the plugin
421  * infrastructure can call gdbstub to read a register. They are
422  * currently just a pointer encapsulation of the gdb_reg but in
423  * future may hold internal plugin state so its important plugin
424  * authors are not tempted to treat them as numbers.
425  *
426  * We also construct a result array with those handles and some
427  * ancillary data the plugin might find useful.
428  */
429 
430 static GArray *create_register_handles(GArray *gdbstub_regs)
431 {
432     GArray *find_data = g_array_new(true, true,
433                                     sizeof(qemu_plugin_reg_descriptor));
434 
435     for (int i = 0; i < gdbstub_regs->len; i++) {
436         GDBRegDesc *grd = &g_array_index(gdbstub_regs, GDBRegDesc, i);
437         qemu_plugin_reg_descriptor desc;
438 
439         /* skip "un-named" regs */
440         if (!grd->name) {
441             continue;
442         }
443 
444         /* Create a record for the plugin */
445         desc.handle = GINT_TO_POINTER(grd->gdb_reg);
446         desc.name = g_intern_string(grd->name);
447         desc.feature = g_intern_string(grd->feature_name);
448         g_array_append_val(find_data, desc);
449     }
450 
451     return find_data;
452 }
453 
454 GArray *qemu_plugin_get_registers(void)
455 {
456     g_assert(current_cpu);
457 
458     g_autoptr(GArray) regs = gdb_get_register_list(current_cpu);
459     return create_register_handles(regs);
460 }
461 
462 int qemu_plugin_read_register(struct qemu_plugin_register *reg, GByteArray *buf)
463 {
464     g_assert(current_cpu);
465 
466     return gdb_read_register(current_cpu, buf, GPOINTER_TO_INT(reg));
467 }
468