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/translator.h" 46 #include "disas/disas.h" 47 #include "plugin.h" 48 #ifndef CONFIG_USER_ONLY 49 #include "exec/ram_addr.h" 50 #include "qemu/plugin-memory.h" 51 #include "hw/boards.h" 52 #else 53 #include "qemu.h" 54 #ifdef CONFIG_LINUX 55 #include "loader.h" 56 #endif 57 #endif 58 59 /* Uninstall and Reset handlers */ 60 61 void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb) 62 { 63 plugin_reset_uninstall(id, cb, false); 64 } 65 66 void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb) 67 { 68 plugin_reset_uninstall(id, cb, true); 69 } 70 71 /* 72 * Plugin Register Functions 73 * 74 * This allows the plugin to register callbacks for various events 75 * during the translation. 76 */ 77 78 void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id, 79 qemu_plugin_vcpu_simple_cb_t cb) 80 { 81 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_INIT, cb); 82 } 83 84 void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id, 85 qemu_plugin_vcpu_simple_cb_t cb) 86 { 87 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXIT, cb); 88 } 89 90 void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb, 91 qemu_plugin_vcpu_udata_cb_t cb, 92 enum qemu_plugin_cb_flags flags, 93 void *udata) 94 { 95 if (!tb->mem_only) { 96 plugin_register_dyn_cb__udata(&tb->cbs, cb, flags, udata); 97 } 98 } 99 100 void qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( 101 struct qemu_plugin_tb *tb, 102 enum qemu_plugin_op op, 103 qemu_plugin_u64 entry, 104 uint64_t imm) 105 { 106 if (!tb->mem_only) { 107 plugin_register_inline_op_on_entry(&tb->cbs, 0, op, entry, imm); 108 } 109 } 110 111 void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn, 112 qemu_plugin_vcpu_udata_cb_t cb, 113 enum qemu_plugin_cb_flags flags, 114 void *udata) 115 { 116 if (!insn->mem_only) { 117 plugin_register_dyn_cb__udata(&insn->insn_cbs, cb, flags, udata); 118 } 119 } 120 121 void qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( 122 struct qemu_plugin_insn *insn, 123 enum qemu_plugin_op op, 124 qemu_plugin_u64 entry, 125 uint64_t imm) 126 { 127 if (!insn->mem_only) { 128 plugin_register_inline_op_on_entry(&insn->insn_cbs, 0, op, entry, imm); 129 } 130 } 131 132 133 /* 134 * We always plant memory instrumentation because they don't finalise until 135 * after the operation has complete. 136 */ 137 void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn, 138 qemu_plugin_vcpu_mem_cb_t cb, 139 enum qemu_plugin_cb_flags flags, 140 enum qemu_plugin_mem_rw rw, 141 void *udata) 142 { 143 plugin_register_vcpu_mem_cb(&insn->mem_cbs, cb, flags, rw, udata); 144 } 145 146 void qemu_plugin_register_vcpu_mem_inline_per_vcpu( 147 struct qemu_plugin_insn *insn, 148 enum qemu_plugin_mem_rw rw, 149 enum qemu_plugin_op op, 150 qemu_plugin_u64 entry, 151 uint64_t imm) 152 { 153 plugin_register_inline_op_on_entry(&insn->mem_cbs, rw, op, entry, imm); 154 } 155 156 void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id, 157 qemu_plugin_vcpu_tb_trans_cb_t cb) 158 { 159 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_TB_TRANS, cb); 160 } 161 162 void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id, 163 qemu_plugin_vcpu_syscall_cb_t cb) 164 { 165 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL, cb); 166 } 167 168 void 169 qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id, 170 qemu_plugin_vcpu_syscall_ret_cb_t cb) 171 { 172 plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, cb); 173 } 174 175 /* 176 * Plugin Queries 177 * 178 * These are queries that the plugin can make to gauge information 179 * from our opaque data types. We do not want to leak internal details 180 * here just information useful to the plugin. 181 */ 182 183 /* 184 * Translation block information: 185 * 186 * A plugin can query the virtual address of the start of the block 187 * and the number of instructions in it. It can also get access to 188 * each translated instruction. 189 */ 190 191 size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb) 192 { 193 return tb->n; 194 } 195 196 uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb) 197 { 198 return tb->vaddr; 199 } 200 201 struct qemu_plugin_insn * 202 qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx) 203 { 204 struct qemu_plugin_insn *insn; 205 if (unlikely(idx >= tb->n)) { 206 return NULL; 207 } 208 insn = g_ptr_array_index(tb->insns, idx); 209 insn->mem_only = tb->mem_only; 210 return insn; 211 } 212 213 /* 214 * Instruction information 215 * 216 * These queries allow the plugin to retrieve information about each 217 * instruction being translated. 218 */ 219 220 size_t qemu_plugin_insn_data(const struct qemu_plugin_insn *insn, 221 void *dest, size_t len) 222 { 223 const DisasContextBase *db = tcg_ctx->plugin_db; 224 225 len = MIN(len, insn->len); 226 return translator_st(db, dest, insn->vaddr, len) ? len : 0; 227 } 228 229 size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn) 230 { 231 return insn->len; 232 } 233 234 uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn) 235 { 236 return insn->vaddr; 237 } 238 239 void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn) 240 { 241 return insn->haddr; 242 } 243 244 char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn) 245 { 246 CPUState *cpu = current_cpu; 247 return plugin_disas(cpu, insn->vaddr, insn->len); 248 } 249 250 const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn) 251 { 252 const char *sym = lookup_symbol(insn->vaddr); 253 return sym[0] != 0 ? sym : NULL; 254 } 255 256 /* 257 * The memory queries allow the plugin to query information about a 258 * memory access. 259 */ 260 261 unsigned qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info) 262 { 263 MemOp op = get_memop(info); 264 return op & MO_SIZE; 265 } 266 267 bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info) 268 { 269 MemOp op = get_memop(info); 270 return op & MO_SIGN; 271 } 272 273 bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info) 274 { 275 MemOp op = get_memop(info); 276 return (op & MO_BSWAP) == MO_BE; 277 } 278 279 bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info) 280 { 281 return get_plugin_meminfo_rw(info) & QEMU_PLUGIN_MEM_W; 282 } 283 284 /* 285 * Virtual Memory queries 286 */ 287 288 #ifdef CONFIG_SOFTMMU 289 static __thread struct qemu_plugin_hwaddr hwaddr_info; 290 #endif 291 292 struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, 293 uint64_t vaddr) 294 { 295 #ifdef CONFIG_SOFTMMU 296 CPUState *cpu = current_cpu; 297 unsigned int mmu_idx = get_mmuidx(info); 298 enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info); 299 hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0; 300 301 assert(mmu_idx < NB_MMU_MODES); 302 303 if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx, 304 hwaddr_info.is_store, &hwaddr_info)) { 305 error_report("invalid use of qemu_plugin_get_hwaddr"); 306 return NULL; 307 } 308 309 return &hwaddr_info; 310 #else 311 return NULL; 312 #endif 313 } 314 315 bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr) 316 { 317 #ifdef CONFIG_SOFTMMU 318 return haddr->is_io; 319 #else 320 return false; 321 #endif 322 } 323 324 uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr) 325 { 326 #ifdef CONFIG_SOFTMMU 327 if (haddr) { 328 return haddr->phys_addr; 329 } 330 #endif 331 return 0; 332 } 333 334 const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h) 335 { 336 #ifdef CONFIG_SOFTMMU 337 if (h && h->is_io) { 338 MemoryRegion *mr = h->mr; 339 if (!mr->name) { 340 unsigned maddr = (uintptr_t)mr; 341 g_autofree char *temp = g_strdup_printf("anon%08x", maddr); 342 return g_intern_string(temp); 343 } else { 344 return g_intern_string(mr->name); 345 } 346 } else { 347 return g_intern_static_string("RAM"); 348 } 349 #else 350 return g_intern_static_string("Invalid"); 351 #endif 352 } 353 354 int qemu_plugin_num_vcpus(void) 355 { 356 return plugin_num_vcpus(); 357 } 358 359 /* 360 * Plugin output 361 */ 362 void qemu_plugin_outs(const char *string) 363 { 364 qemu_log_mask(CPU_LOG_PLUGIN, "%s", string); 365 } 366 367 bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret) 368 { 369 return name && value && qapi_bool_parse(name, value, ret, NULL); 370 } 371 372 /* 373 * Binary path, start and end locations 374 */ 375 const char *qemu_plugin_path_to_binary(void) 376 { 377 char *path = NULL; 378 #ifdef CONFIG_USER_ONLY 379 TaskState *ts = get_task_state(current_cpu); 380 path = g_strdup(ts->bprm->filename); 381 #endif 382 return path; 383 } 384 385 uint64_t qemu_plugin_start_code(void) 386 { 387 uint64_t start = 0; 388 #ifdef CONFIG_USER_ONLY 389 TaskState *ts = get_task_state(current_cpu); 390 start = ts->info->start_code; 391 #endif 392 return start; 393 } 394 395 uint64_t qemu_plugin_end_code(void) 396 { 397 uint64_t end = 0; 398 #ifdef CONFIG_USER_ONLY 399 TaskState *ts = get_task_state(current_cpu); 400 end = ts->info->end_code; 401 #endif 402 return end; 403 } 404 405 uint64_t qemu_plugin_entry_code(void) 406 { 407 uint64_t entry = 0; 408 #ifdef CONFIG_USER_ONLY 409 TaskState *ts = get_task_state(current_cpu); 410 entry = ts->info->entry; 411 #endif 412 return entry; 413 } 414 415 /* 416 * Create register handles. 417 * 418 * We need to create a handle for each register so the plugin 419 * infrastructure can call gdbstub to read a register. They are 420 * currently just a pointer encapsulation of the gdb_reg but in 421 * future may hold internal plugin state so its important plugin 422 * authors are not tempted to treat them as numbers. 423 * 424 * We also construct a result array with those handles and some 425 * ancillary data the plugin might find useful. 426 */ 427 428 static GArray *create_register_handles(GArray *gdbstub_regs) 429 { 430 GArray *find_data = g_array_new(true, true, 431 sizeof(qemu_plugin_reg_descriptor)); 432 433 for (int i = 0; i < gdbstub_regs->len; i++) { 434 GDBRegDesc *grd = &g_array_index(gdbstub_regs, GDBRegDesc, i); 435 qemu_plugin_reg_descriptor desc; 436 437 /* skip "un-named" regs */ 438 if (!grd->name) { 439 continue; 440 } 441 442 /* Create a record for the plugin */ 443 desc.handle = GINT_TO_POINTER(grd->gdb_reg); 444 desc.name = g_intern_string(grd->name); 445 desc.feature = g_intern_string(grd->feature_name); 446 g_array_append_val(find_data, desc); 447 } 448 449 return find_data; 450 } 451 452 GArray *qemu_plugin_get_registers(void) 453 { 454 g_assert(current_cpu); 455 456 g_autoptr(GArray) regs = gdb_get_register_list(current_cpu); 457 return create_register_handles(regs); 458 } 459 460 int qemu_plugin_read_register(struct qemu_plugin_register *reg, GByteArray *buf) 461 { 462 g_assert(current_cpu); 463 464 return gdb_read_register(current_cpu, buf, GPOINTER_TO_INT(reg)); 465 } 466 467 struct qemu_plugin_scoreboard *qemu_plugin_scoreboard_new(size_t element_size) 468 { 469 return plugin_scoreboard_new(element_size); 470 } 471 472 void qemu_plugin_scoreboard_free(struct qemu_plugin_scoreboard *score) 473 { 474 plugin_scoreboard_free(score); 475 } 476 477 void *qemu_plugin_scoreboard_find(struct qemu_plugin_scoreboard *score, 478 unsigned int vcpu_index) 479 { 480 g_assert(vcpu_index < qemu_plugin_num_vcpus()); 481 /* we can't use g_array_index since entry size is not statically known */ 482 char *base_ptr = score->data->data; 483 return base_ptr + vcpu_index * g_array_get_element_size(score->data); 484 } 485 486 static uint64_t *plugin_u64_address(qemu_plugin_u64 entry, 487 unsigned int vcpu_index) 488 { 489 char *ptr = qemu_plugin_scoreboard_find(entry.score, vcpu_index); 490 return (uint64_t *)(ptr + entry.offset); 491 } 492 493 void qemu_plugin_u64_add(qemu_plugin_u64 entry, unsigned int vcpu_index, 494 uint64_t added) 495 { 496 *plugin_u64_address(entry, vcpu_index) += added; 497 } 498 499 uint64_t qemu_plugin_u64_get(qemu_plugin_u64 entry, 500 unsigned int vcpu_index) 501 { 502 return *plugin_u64_address(entry, vcpu_index); 503 } 504 505 void qemu_plugin_u64_set(qemu_plugin_u64 entry, unsigned int vcpu_index, 506 uint64_t val) 507 { 508 *plugin_u64_address(entry, vcpu_index) = val; 509 } 510 511 uint64_t qemu_plugin_u64_sum(qemu_plugin_u64 entry) 512 { 513 uint64_t total = 0; 514 for (int i = 0, n = qemu_plugin_num_vcpus(); i < n; ++i) { 515 total += qemu_plugin_u64_get(entry, i); 516 } 517 return total; 518 } 519