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