@@ -21,9 +21,11 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
21
21
/* Scoreboard to track executed instructions count */
22
22
typedef struct {
23
23
uint64_t insn_count ;
24
+ uint64_t current_pc ;
24
25
} InstructionsCount ;
25
26
static struct qemu_plugin_scoreboard * insn_count_sb ;
26
27
static qemu_plugin_u64 insn_count ;
28
+ static qemu_plugin_u64 current_pc ;
27
29
28
30
static uint64_t icount ;
29
31
static int icount_exit_code ;
@@ -34,6 +36,11 @@ static bool exit_on_address;
34
36
/* Map trigger addresses to exit code */
35
37
static GHashTable * addrs_ht ;
36
38
39
+ typedef struct {
40
+ uint64_t exit_addr ;
41
+ int exit_code ;
42
+ } ExitInfo ;
43
+
37
44
static void exit_emulation (int return_code , char * message )
38
45
{
39
46
qemu_plugin_outs (message );
@@ -43,47 +50,44 @@ static void exit_emulation(int return_code, char *message)
43
50
44
51
static void exit_icount_reached (unsigned int cpu_index , void * udata )
45
52
{
46
- uint64_t insn_vaddr = GPOINTER_TO_UINT ( udata );
53
+ uint64_t insn_vaddr = qemu_plugin_u64_get ( current_pc , cpu_index );
47
54
char * msg = g_strdup_printf ("icount reached at 0x%" PRIx64 ", exiting\n" ,
48
55
insn_vaddr );
49
-
50
56
exit_emulation (icount_exit_code , msg );
51
57
}
52
58
53
59
static void exit_address_reached (unsigned int cpu_index , void * udata )
54
60
{
55
- uint64_t insn_vaddr = GPOINTER_TO_UINT (udata );
56
- char * msg = g_strdup_printf ("0x%" PRIx64 " reached, exiting\n" , insn_vaddr );
57
- int exit_code ;
58
-
59
- exit_code = GPOINTER_TO_INT (
60
- g_hash_table_lookup (addrs_ht , GUINT_TO_POINTER (insn_vaddr )));
61
-
62
- exit_emulation (exit_code , msg );
61
+ ExitInfo * ei = udata ;
62
+ g_assert (ei );
63
+ char * msg = g_strdup_printf ("0x%" PRIx64 " reached, exiting\n" , ei -> exit_addr );
64
+ exit_emulation (ei -> exit_code , msg );
63
65
}
64
66
65
67
static void vcpu_tb_trans (qemu_plugin_id_t id , struct qemu_plugin_tb * tb )
66
68
{
67
69
size_t tb_n = qemu_plugin_tb_n_insns (tb );
68
70
for (size_t i = 0 ; i < tb_n ; i ++ ) {
69
71
struct qemu_plugin_insn * insn = qemu_plugin_tb_get_insn (tb , i );
70
- gpointer insn_vaddr = GUINT_TO_POINTER ( qemu_plugin_insn_vaddr (insn ) );
72
+ uint64_t insn_vaddr = qemu_plugin_insn_vaddr (insn );
71
73
72
74
if (exit_on_icount ) {
73
75
/* Increment and check scoreboard for each instruction */
74
76
qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu (
75
77
insn , QEMU_PLUGIN_INLINE_ADD_U64 , insn_count , 1 );
78
+ qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu (
79
+ insn , QEMU_PLUGIN_INLINE_STORE_U64 , current_pc , insn_vaddr );
76
80
qemu_plugin_register_vcpu_insn_exec_cond_cb (
77
81
insn , exit_icount_reached , QEMU_PLUGIN_CB_NO_REGS ,
78
- QEMU_PLUGIN_COND_EQ , insn_count , icount + 1 , insn_vaddr );
82
+ QEMU_PLUGIN_COND_EQ , insn_count , icount + 1 , NULL );
79
83
}
80
84
81
85
if (exit_on_address ) {
82
- if (g_hash_table_contains (addrs_ht , insn_vaddr )) {
86
+ ExitInfo * ei = g_hash_table_lookup (addrs_ht , & insn_vaddr );
87
+ if (ei ) {
83
88
/* Exit triggered by address */
84
89
qemu_plugin_register_vcpu_insn_exec_cb (
85
- insn , exit_address_reached , QEMU_PLUGIN_CB_NO_REGS ,
86
- insn_vaddr );
90
+ insn , exit_address_reached , QEMU_PLUGIN_CB_NO_REGS , ei );
87
91
}
88
92
}
89
93
}
@@ -99,11 +103,13 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
99
103
const qemu_info_t * info , int argc ,
100
104
char * * argv )
101
105
{
102
- addrs_ht = g_hash_table_new ( NULL , g_direct_equal );
106
+ addrs_ht = g_hash_table_new_full ( g_int64_hash , g_int64_equal , NULL , g_free );
103
107
104
108
insn_count_sb = qemu_plugin_scoreboard_new (sizeof (InstructionsCount ));
105
109
insn_count = qemu_plugin_scoreboard_u64_in_struct (
106
110
insn_count_sb , InstructionsCount , insn_count );
111
+ current_pc = qemu_plugin_scoreboard_u64_in_struct (
112
+ insn_count_sb , InstructionsCount , current_pc );
107
113
108
114
for (int i = 0 ; i < argc ; i ++ ) {
109
115
char * opt = argv [i ];
@@ -124,13 +130,13 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
124
130
exit_on_icount = true;
125
131
} else if (g_strcmp0 (tokens [0 ], "addr" ) == 0 ) {
126
132
g_auto (GStrv ) addr_tokens = g_strsplit (tokens [1 ], ":" , 2 );
127
- uint64_t exit_addr = g_ascii_strtoull (addr_tokens [0 ], NULL , 0 );
128
- int exit_code = 0 ;
133
+ ExitInfo * ei = g_malloc (sizeof (ExitInfo ));
134
+ ei -> exit_addr = g_ascii_strtoull (addr_tokens [0 ], NULL , 0 );
135
+ ei -> exit_code = 0 ;
129
136
if (addr_tokens [1 ]) {
130
- exit_code = g_ascii_strtoull (addr_tokens [1 ], NULL , 0 );
137
+ ei -> exit_code = g_ascii_strtoull (addr_tokens [1 ], NULL , 0 );
131
138
}
132
- g_hash_table_insert (addrs_ht , GUINT_TO_POINTER (exit_addr ),
133
- GINT_TO_POINTER (exit_code ));
139
+ g_hash_table_insert (addrs_ht , & ei -> exit_addr , ei );
134
140
exit_on_address = true;
135
141
} else {
136
142
fprintf (stderr , "option parsing failed: %s\n" , opt );
0 commit comments