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