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