* [PATCH 0/3] plugins/execlog: add data address match and address range support @ 2024-02-29 15:07 Sven Schnelle 2024-02-29 15:07 ` [PATCH 2/3] plugins/execlog: add data address match Sven Schnelle ` (2 more replies) 0 siblings, 3 replies; 7+ messages in thread From: Sven Schnelle @ 2024-02-29 15:07 UTC (permalink / raw To: Alex Bennée, Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier Cc: qemu-devel, deller, Sven Schnelle Hi List, this patchset adds a new -dfilter option and address range matching. With this execlog can match only a certain range of address for both instruction and data adresses. Example usage: qemu-system-xxx <other options> -d plugin -plugin libexeclog.so,afilter=0x1000-0x2000,dfilter=0x388 This would only log instruction in the address range 0x1000 to 0x2000 and accessing data at address 0x388. Changes in v2: - rebased on top of latest master Sven Schnelle (3): plugins/execlog: pass matches array to parse_vaddr_match plugins/execlog: add data address match plugins/execlog: add address range matching contrib/plugins/execlog.c | 95 ++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 16 deletions(-) -- 2.43.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/3] plugins/execlog: add data address match 2024-02-29 15:07 [PATCH 0/3] plugins/execlog: add data address match and address range support Sven Schnelle @ 2024-02-29 15:07 ` Sven Schnelle 2024-02-29 15:07 ` [PATCH 3/3] plugins/execlog: add address range matching Sven Schnelle 2024-02-29 17:08 ` [PATCH 0/3] plugins/execlog: add data address match and address range support Alex Bennée 2 siblings, 0 replies; 7+ messages in thread From: Sven Schnelle @ 2024-02-29 15:07 UTC (permalink / raw To: Alex Bennée, Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier Cc: qemu-devel, deller, Sven Schnelle Add a match similar to the afilter address match, but for data addresses. When an address is specified with '-dfilter=0x12345' only load/stores to/from address 0x12345 are printed. All other instructions are hidden. Signed-off-by: Sven Schnelle <svens@stackframe.org> --- contrib/plugins/execlog.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index 934553e83d..c89ebc08b6 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -27,6 +27,8 @@ typedef struct CPU { GString *last_exec; /* Ptr array of Register */ GPtrArray *registers; + /* whether this instruction should be logged */ + bool log; } CPU; QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; @@ -36,6 +38,7 @@ static GRWLock expand_array_lock; static GPtrArray *imatches; static GArray *amatches; +static GArray *dmatches; static GPtrArray *rmatches; static bool disas_assist; static GMutex add_reg_name_lock; @@ -51,6 +54,17 @@ static CPU *get_cpu(int vcpu_index) return c; } +static bool match_vaddr(uint64_t vaddr) +{ + for (int i = 0; i < dmatches->len; i++) { + uint64_t v = g_array_index(dmatches, uint64_t, i); + if (v == vaddr) { + return true; + } + } + return false; +} + /** * Add memory read or write information to current instruction log */ @@ -62,6 +76,11 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info, /* Find vCPU in array */ + if (dmatches && !match_vaddr(vaddr)) { + return; + } + c->log = true; + /* Indicate type of memory access */ if (qemu_plugin_mem_is_store(info)) { g_string_append(s, ", store"); @@ -121,15 +140,17 @@ static void vcpu_insn_exec_with_regs(unsigned int cpu_index, void *udata) if (cpu->registers) { insn_check_regs(cpu); } - - qemu_plugin_outs(cpu->last_exec->str); - qemu_plugin_outs("\n"); + if (cpu->log) { + qemu_plugin_outs(cpu->last_exec->str); + qemu_plugin_outs("\n"); + } } /* Store new instruction in cache */ /* vcpu_mem will add memory access information to last_exec */ g_string_printf(cpu->last_exec, "%u, ", cpu_index); g_string_append(cpu->last_exec, (char *)udata); + cpu->log = dmatches ? false : true; } /* Log last instruction while checking registers, ignore next */ @@ -166,6 +187,7 @@ static void vcpu_insn_exec(unsigned int cpu_index, void *udata) /* vcpu_mem will add memory access information to last_exec */ g_string_printf(cpu->last_exec, "%u, ", cpu_index); g_string_append(cpu->last_exec, (char *)udata); + cpu->log = dmatches ? false : true; } /** @@ -381,7 +403,7 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) g_rw_lock_reader_lock(&expand_array_lock); for (i = 0; i < cpus->len; i++) { CPU *c = get_cpu(i); - if (c->last_exec && c->last_exec->str) { + if (c->log && c->last_exec && c->last_exec->str) { qemu_plugin_outs(c->last_exec->str); qemu_plugin_outs("\n"); } @@ -441,6 +463,8 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, parse_insn_match(tokens[1]); } else if (g_strcmp0(tokens[0], "afilter") == 0) { parse_vaddr_match(&amatches, tokens[1]); + } else if (g_strcmp0(tokens[0], "dfilter") == 0) { + parse_vaddr_match(&dmatches, tokens[1]); } else if (g_strcmp0(tokens[0], "reg") == 0) { add_regpat(tokens[1]); } else if (g_strcmp0(tokens[0], "rdisas") == 0) { -- 2.43.2 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] plugins/execlog: add address range matching 2024-02-29 15:07 [PATCH 0/3] plugins/execlog: add data address match and address range support Sven Schnelle 2024-02-29 15:07 ` [PATCH 2/3] plugins/execlog: add data address match Sven Schnelle @ 2024-02-29 15:07 ` Sven Schnelle 2024-02-29 17:12 ` Alex Bennée 2024-02-29 17:08 ` [PATCH 0/3] plugins/execlog: add data address match and address range support Alex Bennée 2 siblings, 1 reply; 7+ messages in thread From: Sven Schnelle @ 2024-02-29 15:07 UTC (permalink / raw To: Alex Bennée, Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier Cc: qemu-devel, deller, Sven Schnelle Allow to match memory ranges with the address matches. This allows to give a range of adresses like '-dfilter=0-0x400' which would only log memory accesses between 0 and 400. Signed-off-by: Sven Schnelle <svens@stackframe.org> --- contrib/plugins/execlog.c | 73 ++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index c89ebc08b6..b1b2a7baf1 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -44,6 +44,11 @@ static bool disas_assist; static GMutex add_reg_name_lock; static GPtrArray *all_reg_names; +struct address_match { + uint64_t low; + uint64_t high; +}; + static CPU *get_cpu(int vcpu_index) { CPU *c; @@ -54,11 +59,12 @@ static CPU *get_cpu(int vcpu_index) return c; } -static bool match_vaddr(uint64_t vaddr) +static bool match_address_range(GArray *match, uint64_t vaddr) { - for (int i = 0; i < dmatches->len; i++) { - uint64_t v = g_array_index(dmatches, uint64_t, i); - if (v == vaddr) { + for (int i = 0; i < match->len; i++) { + struct address_match *m = + g_array_index(match, struct address_match *, i); + if (vaddr >= m->low && vaddr <= m->high) { return true; } } @@ -74,9 +80,7 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info, CPU *c = get_cpu(cpu_index); GString *s = c->last_exec; - /* Find vCPU in array */ - - if (dmatches && !match_vaddr(vaddr)) { + if (dmatches && !match_address_range(dmatches, vaddr)) { return; } c->log = true; @@ -164,8 +168,10 @@ static void vcpu_insn_exec_only_regs(unsigned int cpu_index, void *udata) insn_check_regs(cpu); } - qemu_plugin_outs(cpu->last_exec->str); - qemu_plugin_outs("\n"); + if (cpu->log) { + qemu_plugin_outs(cpu->last_exec->str); + qemu_plugin_outs("\n"); + } } /* reset */ @@ -178,7 +184,7 @@ static void vcpu_insn_exec(unsigned int cpu_index, void *udata) CPU *cpu = get_cpu(cpu_index); /* Print previous instruction in cache */ - if (cpu->last_exec->len) { + if (cpu->log && cpu->last_exec->len) { qemu_plugin_outs(cpu->last_exec->str); qemu_plugin_outs("\n"); } @@ -239,8 +245,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) if (skip && amatches) { int j; for (j = 0; j < amatches->len && skip; j++) { - uint64_t v = g_array_index(amatches, uint64_t, j); - if (v == insn_vaddr) { + if (match_address_range(amatches, insn_vaddr)) { skip = false; } } @@ -394,6 +399,17 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) c->registers = registers_init(vcpu_index); } +static void free_matches(GArray *matches) +{ + if (!matches) { + return; + } + + for (int i = 0; i < matches->len; i++) { + g_free(g_array_index(matches, struct address_match *, i)); + } +} + /** * On plugin exit, print last instruction in cache */ @@ -409,6 +425,9 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) } } g_rw_lock_reader_unlock(&expand_array_lock); + + free_matches(amatches); + free_matches(dmatches); } /* Add a match to the array of matches */ @@ -420,14 +439,34 @@ static void parse_insn_match(char *match) g_ptr_array_add(imatches, g_strdup(match)); } -static void parse_vaddr_match(GArray **matches, char *match) +static void parse_vaddr_match(GArray **matches, char *token) { - uint64_t v = g_ascii_strtoull(match, NULL, 16); + uint64_t low, high; + gchar *endp; - if (!matches) { - *matches = g_array_new(false, true, sizeof(uint64_t)); + low = g_ascii_strtoull(token, &endp, 16); + if (endp == token) { + fprintf(stderr, "Invalid address(range) specified: %s\n", token); + return; + } + + if (*endp != '-') { + high = low; + } else { + high = g_ascii_strtoull(endp + 1, &endp, 16); + if (endp == token) { + fprintf(stderr, "Invalid address(range) specified: %s\n", token); + return; + } + } + + if (!*matches) { + *matches = g_array_new(false, true, sizeof(struct address_match)); } - g_array_append_val(*matches, v); + struct address_match *match = g_new(struct address_match, 1); + match->low = low; + match->high = high; + g_array_append_val(*matches, match); } /* -- 2.43.2 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] plugins/execlog: add address range matching 2024-02-29 15:07 ` [PATCH 3/3] plugins/execlog: add address range matching Sven Schnelle @ 2024-02-29 17:12 ` Alex Bennée 2024-02-29 18:04 ` Sven Schnelle 0 siblings, 1 reply; 7+ messages in thread From: Alex Bennée @ 2024-02-29 17:12 UTC (permalink / raw To: Sven Schnelle Cc: Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier, qemu-devel, deller Sven Schnelle <svens@stackframe.org> writes: > Allow to match memory ranges with the address matches. This > allows to give a range of adresses like '-dfilter=0-0x400' > which would only log memory accesses between 0 and 400. > > Signed-off-by: Sven Schnelle <svens@stackframe.org> > --- > contrib/plugins/execlog.c | 73 ++++++++++++++++++++++++++++++--------- > 1 file changed, 56 insertions(+), 17 deletions(-) > > diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c > index c89ebc08b6..b1b2a7baf1 100644 > --- a/contrib/plugins/execlog.c > +++ b/contrib/plugins/execlog.c > @@ -44,6 +44,11 @@ static bool disas_assist; > static GMutex add_reg_name_lock; > static GPtrArray *all_reg_names; > > +struct address_match { > + uint64_t low; > + uint64_t high; > +}; > + > static CPU *get_cpu(int vcpu_index) > { > CPU *c; > @@ -54,11 +59,12 @@ static CPU *get_cpu(int vcpu_index) > return c; > } > > -static bool match_vaddr(uint64_t vaddr) > +static bool match_address_range(GArray *match, uint64_t vaddr) > { > - for (int i = 0; i < dmatches->len; i++) { > - uint64_t v = g_array_index(dmatches, uint64_t, i); > - if (v == vaddr) { > + for (int i = 0; i < match->len; i++) { > + struct address_match *m = > + g_array_index(match, struct address_match *, i); > + if (vaddr >= m->low && vaddr <= m->high) { > return true; > } > } > @@ -74,9 +80,7 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info, > CPU *c = get_cpu(cpu_index); > GString *s = c->last_exec; > > - /* Find vCPU in array */ > - > - if (dmatches && !match_vaddr(vaddr)) { > + if (dmatches && !match_address_range(dmatches, vaddr)) { > return; > } > c->log = true; > @@ -164,8 +168,10 @@ static void vcpu_insn_exec_only_regs(unsigned int cpu_index, void *udata) > insn_check_regs(cpu); > } > > - qemu_plugin_outs(cpu->last_exec->str); > - qemu_plugin_outs("\n"); > + if (cpu->log) { > + qemu_plugin_outs(cpu->last_exec->str); > + qemu_plugin_outs("\n"); > + } > } > > /* reset */ > @@ -178,7 +184,7 @@ static void vcpu_insn_exec(unsigned int cpu_index, void *udata) > CPU *cpu = get_cpu(cpu_index); > > /* Print previous instruction in cache */ > - if (cpu->last_exec->len) { > + if (cpu->log && cpu->last_exec->len) { > qemu_plugin_outs(cpu->last_exec->str); > qemu_plugin_outs("\n"); > } > @@ -239,8 +245,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) > if (skip && amatches) { > int j; > for (j = 0; j < amatches->len && skip; j++) { > - uint64_t v = g_array_index(amatches, uint64_t, j); > - if (v == insn_vaddr) { > + if (match_address_range(amatches, insn_vaddr)) { > skip = false; > } > } > @@ -394,6 +399,17 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) > c->registers = registers_init(vcpu_index); > } > > +static void free_matches(GArray *matches) > +{ > + if (!matches) { > + return; > + } > + > + for (int i = 0; i < matches->len; i++) { > + g_free(g_array_index(matches, struct address_match *, i)); > + } > +} > + > /** > * On plugin exit, print last instruction in cache > */ > @@ -409,6 +425,9 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) > } > } > g_rw_lock_reader_unlock(&expand_array_lock); > + > + free_matches(amatches); > + free_matches(dmatches); > } > > /* Add a match to the array of matches */ > @@ -420,14 +439,34 @@ static void parse_insn_match(char *match) > g_ptr_array_add(imatches, g_strdup(match)); > } > > -static void parse_vaddr_match(GArray **matches, char *match) > +static void parse_vaddr_match(GArray **matches, char *token) > { > - uint64_t v = g_ascii_strtoull(match, NULL, 16); > + uint64_t low, high; > + gchar *endp; > > - if (!matches) { > - *matches = g_array_new(false, true, sizeof(uint64_t)); > + low = g_ascii_strtoull(token, &endp, 16); > + if (endp == token) { > + fprintf(stderr, "Invalid address(range) specified: %s\n", token); > + return; > + } > + > + if (*endp != '-') { > + high = low; > + } else { > + high = g_ascii_strtoull(endp + 1, &endp, 16); > + if (endp == token) { > + fprintf(stderr, "Invalid address(range) specified: %s\n", token); > + return; > + } > + } > + > + if (!*matches) { > + *matches = g_array_new(false, true, sizeof(struct address_match)); > } > - g_array_append_val(*matches, v); > + struct address_match *match = g_new(struct address_match, 1); > + match->low = low; > + match->high = high; > + g_array_append_val(*matches, match); This is almost but not quite qemu_set_dfilter_ranges(). I wonder if it would be worth a light re-factoring and then exposing the parser as a helper function? > } > > /* -- Alex Bennée Virtualisation Tech Lead @ Linaro ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] plugins/execlog: add address range matching 2024-02-29 17:12 ` Alex Bennée @ 2024-02-29 18:04 ` Sven Schnelle 0 siblings, 0 replies; 7+ messages in thread From: Sven Schnelle @ 2024-02-29 18:04 UTC (permalink / raw To: Alex Bennée Cc: Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier, qemu-devel, deller Hi Alex, Alex Bennée <alex.bennee@linaro.org> writes: > Sven Schnelle <svens@stackframe.org> writes: >> +static void parse_vaddr_match(GArray **matches, char *token) >> { >> - uint64_t v = g_ascii_strtoull(match, NULL, 16); >> + uint64_t low, high; >> + gchar *endp; >> >> - if (!matches) { >> - *matches = g_array_new(false, true, sizeof(uint64_t)); >> + low = g_ascii_strtoull(token, &endp, 16); >> + if (endp == token) { >> + fprintf(stderr, "Invalid address(range) specified: %s\n", token); >> + return; >> + } >> + >> + if (*endp != '-') { >> + high = low; >> + } else { >> + high = g_ascii_strtoull(endp + 1, &endp, 16); >> + if (endp == token) { >> + fprintf(stderr, "Invalid address(range) specified: %s\n", token); >> + return; >> + } >> + } >> + >> + if (!*matches) { >> + *matches = g_array_new(false, true, sizeof(struct address_match)); >> } >> - g_array_append_val(*matches, v); >> + struct address_match *match = g_new(struct address_match, 1); >> + match->low = low; >> + match->high = high; >> + g_array_append_val(*matches, match); > > This is almost but not quite qemu_set_dfilter_ranges(). I wonder if it > would be worth a light re-factoring and then exposing the parser as a > helper function? Thanks, I'll take a look. I wasn't aware of qemu_set_dfilter_ranges(). ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/3] plugins/execlog: add data address match and address range support 2024-02-29 15:07 [PATCH 0/3] plugins/execlog: add data address match and address range support Sven Schnelle 2024-02-29 15:07 ` [PATCH 2/3] plugins/execlog: add data address match Sven Schnelle 2024-02-29 15:07 ` [PATCH 3/3] plugins/execlog: add address range matching Sven Schnelle @ 2024-02-29 17:08 ` Alex Bennée 2024-02-29 19:40 ` Sven Schnelle 2 siblings, 1 reply; 7+ messages in thread From: Alex Bennée @ 2024-02-29 17:08 UTC (permalink / raw To: Sven Schnelle Cc: Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier, qemu-devel, deller Sven Schnelle <svens@stackframe.org> writes: > Hi List, > > this patchset adds a new -dfilter option and address range matching. With this > execlog can match only a certain range of address for both instruction and > data adresses. > > Example usage: > > qemu-system-xxx <other options> -d plugin -plugin libexeclog.so,afilter=0x1000-0x2000,dfilter=0x388 > > This would only log instruction in the address range 0x1000 to 0x2000 > and accessing data at address 0x388. > > Changes in v2: > - rebased on top of latest master > > Sven Schnelle (3): > plugins/execlog: pass matches array to parse_vaddr_match I think we've lost a patch in the re-posting. patchew hasn't seen it either: https://patchew.org/QEMU/20240229150729.1620410-1-svens@stackframe.org/ > plugins/execlog: add data address match > plugins/execlog: add address range matching > > contrib/plugins/execlog.c | 95 ++++++++++++++++++++++++++++++++------- > 1 file changed, 79 insertions(+), 16 deletions(-) -- Alex Bennée Virtualisation Tech Lead @ Linaro ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/3] plugins/execlog: add data address match and address range support 2024-02-29 17:08 ` [PATCH 0/3] plugins/execlog: add data address match and address range support Alex Bennée @ 2024-02-29 19:40 ` Sven Schnelle 0 siblings, 0 replies; 7+ messages in thread From: Sven Schnelle @ 2024-02-29 19:40 UTC (permalink / raw To: Alex Bennée Cc: Alexandre Iooss, Mahmoud Mandour, Pierrick Bouvier, qemu-devel, deller Hi Alex, Alex Bennée <alex.bennee@linaro.org> writes: > Sven Schnelle <svens@stackframe.org> writes: > I think we've lost a patch in the re-posting. patchew hasn't seen it > either: > > https://patchew.org/QEMU/20240229150729.1620410-1-svens@stackframe.org/ > >> plugins/execlog: add data address match >> plugins/execlog: add address range matching >> >> contrib/plugins/execlog.c | 95 ++++++++++++++++++++++++++++++++------- >> 1 file changed, 79 insertions(+), 16 deletions(-) Yes, i got a 550 mail. But i'll look into the qemu_set_dfilter_ranges() before resending. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-02-29 19:41 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-02-29 15:07 [PATCH 0/3] plugins/execlog: add data address match and address range support Sven Schnelle 2024-02-29 15:07 ` [PATCH 2/3] plugins/execlog: add data address match Sven Schnelle 2024-02-29 15:07 ` [PATCH 3/3] plugins/execlog: add address range matching Sven Schnelle 2024-02-29 17:12 ` Alex Bennée 2024-02-29 18:04 ` Sven Schnelle 2024-02-29 17:08 ` [PATCH 0/3] plugins/execlog: add data address match and address range support Alex Bennée 2024-02-29 19:40 ` Sven Schnelle
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.